summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Osheim <d_m@plastic-idolatry.com>2012-12-17 23:28:08 -0500
committerAdriaan Moors <adriaan.moors@typesafe.com>2013-01-04 11:48:38 -0800
commit92cf0e354e38d450bfe34d4612f9f869faec2baf (patch)
tree989fc06d6b2c8e372e17e6ebefbba32770ae789c
parente112ac94d04be7ee715ebf8724709123b0f3e1f6 (diff)
downloadscala-92cf0e354e38d450bfe34d4612f9f869faec2baf.tar.gz
scala-92cf0e354e38d450bfe34d4612f9f869faec2baf.tar.bz2
scala-92cf0e354e38d450bfe34d4612f9f869faec2baf.zip
Fix Iterator#copyToArray (fixes SI-6827).
As pointed out in #scala, when using a non-zero start it's possible to get an ArrayIndexOutOfBoundsException due to an incorrect bounds check. This patch fixes this, as well as another potential bounds error, and adds test cases. Incorporates some other suggestions by Som-Snytt to ensure that callers will get useful error messages in cases where the start parameter is wrong (negative or out-of-array-bounds). Review by @som-snytt.
-rw-r--r--src/library/scala/collection/Iterator.scala5
-rw-r--r--test/files/run/t6827.check15
-rw-r--r--test/files/run/t6827.scala31
3 files changed, 49 insertions, 2 deletions
diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala
index cbf8cc4931..696bc4ab5c 100644
--- a/src/library/scala/collection/Iterator.scala
+++ b/src/library/scala/collection/Iterator.scala
@@ -1111,9 +1111,10 @@ trait Iterator[+A] extends TraversableOnce[A] {
* $willNotTerminateInf
*/
def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Unit = {
+ require(start >= 0 && start < xs.length, s"start $start out of range ${xs.length}")
var i = start
- val end = start + math.min(len, xs.length)
- while (hasNext && i < end) {
+ val end = start + math.min(len, xs.length - start)
+ while (i < end && hasNext) {
xs(i) = next()
i += 1
}
diff --git a/test/files/run/t6827.check b/test/files/run/t6827.check
new file mode 100644
index 0000000000..3a3a71c67d
--- /dev/null
+++ b/test/files/run/t6827.check
@@ -0,0 +1,15 @@
+start at -5: java.lang.IllegalArgumentException: requirement failed: start -5 out of range 10
+start at -1: java.lang.IllegalArgumentException: requirement failed: start -1 out of range 10
+start at limit: java.lang.IllegalArgumentException: requirement failed: start 10 out of range 10
+start at limit-1: ok
+first 10: ok
+read all: ok
+test huge len: ok
+5 from 5: ok
+20 from 5: ok
+test len overflow: ok
+start beyond limit: java.lang.IllegalArgumentException: requirement failed: start 30 out of range 10
+read 0: ok
+read -1: ok
+invalid read 0: java.lang.IllegalArgumentException: requirement failed: start 30 out of range 10
+invalid read -1: java.lang.IllegalArgumentException: requirement failed: start 30 out of range 10
diff --git a/test/files/run/t6827.scala b/test/files/run/t6827.scala
new file mode 100644
index 0000000000..7e8918e3dc
--- /dev/null
+++ b/test/files/run/t6827.scala
@@ -0,0 +1,31 @@
+object Test extends App {
+ val ns = (0 until 20)
+ val arr = new Array[Int](10)
+
+ def tryit(label: String, start: Int, len: Int): Unit = {
+ val status = try {
+ val it = ns.toIterator
+ it.copyToArray(arr, start, len)
+ "ok"
+ } catch {
+ case e: Exception => e.toString
+ }
+ println("%s: %s" format (label, status))
+ }
+
+ tryit("start at -5", -5, 10)
+ tryit("start at -1", -1, 10)
+ tryit("start at limit", 10, 10)
+ tryit("start at limit-1", 9, 10)
+ tryit("first 10", 0, 10)
+ tryit("read all", 0, 20)
+ tryit("test huge len", 0, Int.MaxValue)
+ tryit("5 from 5", 5, 10)
+ tryit("20 from 5", 5, 20)
+ tryit("test len overflow", 5, Int.MaxValue)
+ tryit("start beyond limit", 30, 10)
+ tryit("read 0", 0, 0)
+ tryit("read -1", 0, -1)
+ tryit("invalid read 0", 30, 0)
+ tryit("invalid read -1", 30, -1)
+}