summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-01-29 15:21:18 +0100
committerJason Zaugg <jzaugg@gmail.com>2014-01-29 15:30:15 +0100
commit0eefa77be199b1d8186a7a6978f8e01132f35cd9 (patch)
tree1a57eea6a9f6dab2b51b073e5ffbf9e70a434e88 /src/reflect
parent1e9dcc2ed603e7179b7b5eee9212e73f773b02fd (diff)
downloadscala-0eefa77be199b1d8186a7a6978f8e01132f35cd9.tar.gz
scala-0eefa77be199b1d8186a7a6978f8e01132f35cd9.tar.bz2
scala-0eefa77be199b1d8186a7a6978f8e01132f35cd9.zip
SI-8205 Avoid long, slow march to AIIOBE in SourceFile#lineContent
Fixing a regression from SI-8015. The failure mode is kind of amusing: a while loop in `lineToString` would count all the way to `Int.MaxValue`, and integer overflow would foil a bounds check when looking for the 'LF' in 'CR'-'LF'. Given that we're not a style checker to enforce that source files end in a new-line, this commit accounts for EOF, and fixed the overflow problem too. A JUnit test exercises the bug and a few other variations of `lineContent`. While i was in the neighbourhood, I opted for a more efficient means to slice out that line.
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/internal/util/SourceFile.scala6
1 files changed, 3 insertions, 3 deletions
diff --git a/src/reflect/scala/reflect/internal/util/SourceFile.scala b/src/reflect/scala/reflect/internal/util/SourceFile.scala
index 9866b043bb..add072aa71 100644
--- a/src/reflect/scala/reflect/internal/util/SourceFile.scala
+++ b/src/reflect/scala/reflect/internal/util/SourceFile.scala
@@ -40,8 +40,8 @@ abstract class SourceFile {
def lineToString(index: Int): String = {
val start = lineToOffset(index)
var end = start
- while (!isEndOfLine(end)) end += 1
- content.slice(start, end) mkString ""
+ while (!isEndOfLine(end) && end <= length) end += 1
+ new String(content, start, end - start)
}
@tailrec
@@ -136,7 +136,7 @@ class BatchSourceFile(val file : AbstractFile, val content0: Array[Char]) extend
private def charAtIsEOL(idx: Int)(p: Char => Boolean) = {
// don't identify the CR in CR LF as a line break, since LF will do.
- def notCRLF0 = content(idx) != CR || idx + 1 >= length || content(idx + 1) != LF
+ def notCRLF0 = content(idx) != CR || !content.isDefinedAt(idx + 1) || content(idx + 1) != LF
idx < length && notCRLF0 && p(content(idx))
}