Skip to content

Commit

Permalink
Merge pull request #209 from ashawley/issue-4520
Browse files Browse the repository at this point in the history
Fix OOM for ConstructingParser
  • Loading branch information
ashawley authored Jun 26, 2018
2 parents e6c490e + e696ee6 commit db03589
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 7 deletions.
63 changes: 62 additions & 1 deletion jvm/src/test/scala/scala/xml/XMLTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ class XMLTestJVM {
import scala.xml.parsing._
@UnitTest
def dontLoop: Unit = {
val xml = "<!DOCTYPE xmeml SYSTEM> <xmeml> <sequence> </sequence> </xmeml> "
val xml = "<!DOCTYPE xmeml SYSTEM 'uri'> <xmeml> <sequence> </sequence> </xmeml> "
val sink = new PrintStream(new ByteArrayOutputStream())
(Console withOut sink) {
(Console withErr sink) {
Expand Down Expand Up @@ -765,4 +765,65 @@ class XMLTestJVM {
val formatted = pp.format(x)
assertEquals(x, XML.loadString(formatted))
}

def toSource(s: String) = new scala.io.Source {
val iter = s.iterator
override def reportError(pos: Int, msg: String, out: java.io.PrintStream = Console.err): Unit = {}
}

@UnitTest
def xTokenTest {
val x = xml.parsing.ConstructingParser.fromSource(toSource("a"), false)
assertEquals((): Unit, x.xToken('b'))
}

@UnitTest(expected = classOf[FatalError])
def xCharDataFailure {
val x = xml.parsing.ConstructingParser.fromSource(toSource(""), false)

x.xCharData
}

@UnitTest(expected = classOf[FatalError])
def xCommentFailure {
val x = xml.parsing.ConstructingParser.fromSource(toSource(""), false)

x.xComment
}

@UnitTest
def xmlProcInstrTest {
val x = xml.parsing.ConstructingParser.fromSource(toSource("aa"), false)

assertEquals(new UnprefixedAttribute("aa", Text(""), Null), x.xmlProcInstr)
}

@UnitTest(expected = classOf[FatalError])
def notationDeclFailure {
val x = xml.parsing.ConstructingParser.fromSource(toSource(""), false)

x.notationDecl
}

@UnitTest
def pubidLiteralTest {
val x = xml.parsing.ConstructingParser.fromSource(toSource(""), false)

assertEquals("", x.pubidLiteral)
}

@UnitTest
def xAttributeValueTest {
val x = xml.parsing.ConstructingParser.fromSource(toSource("'"), false)

assertEquals("", x.xAttributeValue)
}

@UnitTest
def xEntityValueTest {
val x = xml.parsing.ConstructingParser.fromSource(toSource(""), false)

assertEquals("", x.xEntityValue)
}

}
4 changes: 2 additions & 2 deletions shared/src/main/scala/scala/xml/parsing/MarkupParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ trait MarkupParser extends MarkupParserCommon with TokenTests {
} else sb.append(ch)
nextch()
}
throw truncatedError("broken comment")
truncatedError("broken comment")
}

/* todo: move this into the NodeBuilder class */
Expand Down Expand Up @@ -928,7 +928,7 @@ trait MarkupParser extends MarkupParserCommon with TokenTests {
new PublicID(pubID, sysID)
} else {
reportSyntaxError("PUBLIC or SYSTEM expected")
scala.sys.error("died parsing notationdecl")
truncatedError("died parsing notationdecl")
}
xSpaceOpt()
xToken('>')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import Utility.SU
* All members should be accessed through those.
*/
private[scala] trait MarkupParserCommon extends TokenTests {
protected def unreachable = scala.sys.error("Cannot be reached.")
protected def unreachable = truncatedError("Cannot be reached.")

// type HandleType // MarkupHandler, SymbolicXMLBuilder
type InputType // Source, CharArrayReader
Expand Down Expand Up @@ -62,7 +62,7 @@ private[scala] trait MarkupParserCommon extends TokenTests {
val buf = new StringBuilder
while (ch != endCh && !eof) {
// well-formedness constraint
if (ch == '<') return errorAndResult("'<' not allowed in attrib value", "")
if (ch == '<') reportSyntaxError("'<' not allowed in attrib value")
else if (ch == SU) truncatedError("")
else buf append ch_returning_nextch
}
Expand Down Expand Up @@ -241,11 +241,11 @@ private[scala] trait MarkupParserCommon extends TokenTests {
val head = until.head
val rest = until.tail

while (true) {
while (!eof) {
if (ch == head && peek(rest))
return handler(positioner(), sb.toString)
else if (ch == SU || eof)
truncatedError("") // throws TruncatedXMLControl in compiler
truncatedError(s"died parsing until $until") // throws TruncatedXMLControl in compiler

sb append ch
nextch()
Expand Down

0 comments on commit db03589

Please sign in to comment.