Skip to content

Commit c17b18e

Browse files
committed
SI-9581 Fix overflow on Vector take and drop methods
Fixes the index/length comparison in `Vector#take` and `Vector#drop` so that they handle all possible integer values. Given the collection's invariants `startIndex >= endIndex` and `0 >= startIndex, endIndex`, it is sufficient to change the arithmetic in the comparison as done in this commit to avoid overflows. As cases when `n <= 0` are handled beforehand, `endIndex - n` cannot overflow, contrary to `startIndex + n`. If without the danger of overflows the condition yields true, on the other hand, `startIndex + n` cannot overflow as it is smaller than `endIndex` (as the previous formulation of the condition shows).
1 parent 5e99f82 commit c17b18e

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

src/library/scala/collection/immutable/Vector.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ override def companion: GenericCompanion[Vector] = Vector
156156
override def take(n: Int): Vector[A] = {
157157
if (n <= 0)
158158
Vector.empty
159-
else if (startIndex + n < endIndex)
159+
else if (startIndex < endIndex - n)
160160
dropBack0(startIndex + n)
161161
else
162162
this
@@ -165,7 +165,7 @@ override def companion: GenericCompanion[Vector] = Vector
165165
override def drop(n: Int): Vector[A] = {
166166
if (n <= 0)
167167
this
168-
else if (startIndex + n < endIndex)
168+
else if (startIndex < endIndex - n)
169169
dropFront0(startIndex + n)
170170
else
171171
Vector.empty
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package scala.collection.immutable
2+
3+
import org.junit.Assert._
4+
import org.junit.runner.RunWith
5+
import org.junit.runners.JUnit4
6+
import org.junit.Test
7+
8+
@RunWith(classOf[JUnit4])
9+
class VectorTest {
10+
11+
@Test
12+
def hasCorrectDropAndTakeMethods() {
13+
val v = Vector(0) ++ Vector(1 to 64: _*)
14+
15+
assertEquals(Vector(0, 1), v take 2)
16+
assertEquals(Vector(63, 64), v takeRight 2)
17+
assertEquals(Vector(2 to 64: _*), v drop 2)
18+
assertEquals(Vector(0 to 62: _*), v dropRight 2)
19+
20+
assertEquals(v, v take Int.MaxValue)
21+
assertEquals(v, v takeRight Int.MaxValue)
22+
assertEquals(Vector.empty[Int], v drop Int.MaxValue)
23+
assertEquals(Vector.empty[Int], v dropRight Int.MaxValue)
24+
25+
assertEquals(Vector.empty[Int], v take Int.MinValue)
26+
assertEquals(Vector.empty[Int], v takeRight Int.MinValue)
27+
assertEquals(v, v drop Int.MinValue)
28+
assertEquals(v, v dropRight Int.MinValue)
29+
}
30+
}

0 commit comments

Comments
 (0)