diff options
author | Paul Phillips <paulp@improving.org> | 2011-05-29 20:19:55 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-05-29 20:19:55 +0000 |
commit | 1125a9cfab5c5bacfd10bf1a559b97437339dbaf (patch) | |
tree | 5d5155cf1465d1796901773a156d4d9e94efb3b2 /src | |
parent | 75ec2ba72f17a57060ca5831ccc9e38167e957ae (diff) | |
download | scala-1125a9cfab5c5bacfd10bf1a559b97437339dbaf.tar.gz scala-1125a9cfab5c5bacfd10bf1a559b97437339dbaf.tar.bz2 scala-1125a9cfab5c5bacfd10bf1a559b97437339dbaf.zip |
Fixed a crasher in the scanner when unicode esc...
Fixed a crasher in the scanner when unicode escape sequences offered up
EOF before completion. Also made the repl a little more robust against
crashers in scalac. Treat it like a hostile witness! Closes #4584, no
review.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/interpreter/IMain.scala | 28 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/util/CharArrayReader.scala | 19 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/util/SourceFile.scala | 2 |
3 files changed, 32 insertions, 17 deletions
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index 0ef82351b1..517e6ee6d0 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -362,16 +362,14 @@ class IMain(val settings: Settings, protected val out: PrintWriter) extends Impo // warning about serially defining companions. It'd be easy // enough to just redefine them together but that may not always // be what people want so I'm waiting until I can do it better. - if (!settings.nowarnings.value) { - for { - name <- req.definedNames filterNot (x => req.definedNames contains x.companionName) - oldReq <- definedNameMap get name.companionName - newSym <- req.definedSymbols get name - oldSym <- oldReq.definedSymbols get name.companionName - } { - printMessage("warning: previously defined %s is not a companion to %s.".format(oldSym, newSym)) - printMessage("Companions must be defined together; you may wish to use :paste mode for this.") - } + for { + name <- req.definedNames filterNot (x => req.definedNames contains x.companionName) + oldReq <- definedNameMap get name.companionName + newSym <- req.definedSymbols get name + oldSym <- oldReq.definedSymbols get name.companionName + } { + replwarn("warning: previously defined %s is not a companion to %s.".format(oldSym, newSym)) + replwarn("Companions must be defined together; you may wish to use :paste mode for this.") } // Updating the defined name map @@ -404,12 +402,20 @@ class IMain(val settings: Settings, protected val out: PrintWriter) extends Impo } } + private[nsc] def replwarn(msg: => String): Unit = + if (!settings.nowarnings.value) + printMessage(msg) + def isParseable(line: String): Boolean = { beSilentDuring { - parse(line) match { + try parse(line) match { case Some(xs) => xs.nonEmpty // parses as-is case None => true // incomplete } + catch { case x: Exception => // crashed the compiler + replwarn("Exception in isParseable(\"" + line + "\"): " + x) + false + } } } diff --git a/src/compiler/scala/tools/nsc/util/CharArrayReader.scala b/src/compiler/scala/tools/nsc/util/CharArrayReader.scala index c79ac91f49..aee87d8ad9 100644 --- a/src/compiler/scala/tools/nsc/util/CharArrayReader.scala +++ b/src/compiler/scala/tools/nsc/util/CharArrayReader.scala @@ -15,7 +15,7 @@ abstract class CharArrayReader { self => def decodeUni: Boolean = true /** An error routine to call on bad unicode escapes \\uxxxx. */ - protected def error(offset: Int, msg: String) + protected def error(offset: Int, msg: String): Unit /** the last read character */ var ch: Char = _ @@ -68,10 +68,19 @@ abstract class CharArrayReader { self => (charOffset - p) % 2 == 0 } def udigit: Int = { - val d = digit2int(buf(charOffset), 16) - if (d >= 0) charOffset += 1 - else error(charOffset, "error in unicode escape") - d + if (charOffset >= buf.length) { + // Since the positioning code is very insistent about throwing exceptions, + // we have to decrement the position so our error message can be seen, since + // we are one past EOF. This happens with e.g. val x = \ u 1 <EOF> + error(charOffset - 1, "incomplete unicode escape") + SU + } + else { + val d = digit2int(buf(charOffset), 16) + if (d >= 0) charOffset += 1 + else error(charOffset, "error in unicode escape") + d + } } if (charOffset < buf.length && buf(charOffset) == 'u' && decodeUni && evenSlashPrefix) { do charOffset += 1 diff --git a/src/compiler/scala/tools/nsc/util/SourceFile.scala b/src/compiler/scala/tools/nsc/util/SourceFile.scala index f875ff549f..97aa08b183 100644 --- a/src/compiler/scala/tools/nsc/util/SourceFile.scala +++ b/src/compiler/scala/tools/nsc/util/SourceFile.scala @@ -22,7 +22,7 @@ abstract class SourceFile { def isSelfContained: Boolean def length : Int def position(offset: Int) : Position = { - assert(offset < length) + assert(offset < length, file + ": " + offset + " >= " + length) new OffsetPosition(this, offset) } def position(line: Int, column: Int) : Position = new OffsetPosition(this, lineToOffset(line) + column) |