summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-05-29 20:19:55 +0000
committerPaul Phillips <paulp@improving.org>2011-05-29 20:19:55 +0000
commit1125a9cfab5c5bacfd10bf1a559b97437339dbaf (patch)
tree5d5155cf1465d1796901773a156d4d9e94efb3b2 /src/compiler
parent75ec2ba72f17a57060ca5831ccc9e38167e957ae (diff)
downloadscala-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/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala28
-rw-r--r--src/compiler/scala/tools/nsc/util/CharArrayReader.scala19
-rw-r--r--src/compiler/scala/tools/nsc/util/SourceFile.scala2
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)