Make sure index and count do not overflow for long sequences
Throw an exception immediately before an overflow becomes observable. Place check to prevent negative index from indexOf, indexOfFirst. Do not insert overflow checks for arrays, lists, maps and char sequences. #KT-16097
This commit is contained in:
@@ -251,6 +251,7 @@ public fun <@kotlin.internal.OnlyInputTypes T> Iterable<T>.indexOf(element: T):
|
||||
if (this is List) return this.indexOf(element)
|
||||
var index = 0
|
||||
for (item in this) {
|
||||
checkIndexOverflow(index)
|
||||
if (element == item)
|
||||
return index
|
||||
index++
|
||||
@@ -272,6 +273,7 @@ public fun <@kotlin.internal.OnlyInputTypes T> List<T>.indexOf(element: T): Int
|
||||
public inline fun <T> Iterable<T>.indexOfFirst(predicate: (T) -> Boolean): Int {
|
||||
var index = 0
|
||||
for (item in this) {
|
||||
checkIndexOverflow(index)
|
||||
if (predicate(item))
|
||||
return index
|
||||
index++
|
||||
@@ -299,6 +301,7 @@ public inline fun <T> Iterable<T>.indexOfLast(predicate: (T) -> Boolean): Int {
|
||||
var lastIndex = -1
|
||||
var index = 0
|
||||
for (item in this) {
|
||||
checkIndexOverflow(index)
|
||||
if (predicate(item))
|
||||
lastIndex = index
|
||||
index++
|
||||
@@ -387,6 +390,7 @@ public fun <@kotlin.internal.OnlyInputTypes T> Iterable<T>.lastIndexOf(element:
|
||||
var lastIndex = -1
|
||||
var index = 0
|
||||
for (item in this) {
|
||||
checkIndexOverflow(index)
|
||||
if (element == item)
|
||||
lastIndex = index
|
||||
index++
|
||||
@@ -1258,7 +1262,7 @@ public inline fun <T, R : Any, C : MutableCollection<in R>> Iterable<T>.mapIndex
|
||||
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapIndexedTo(destination: C, transform: (index: Int, T) -> R): C {
|
||||
var index = 0
|
||||
for (item in this)
|
||||
destination.add(transform(index++, item))
|
||||
destination.add(transform(checkIndexOverflow(index++), item))
|
||||
return destination
|
||||
}
|
||||
|
||||
@@ -1407,7 +1411,7 @@ public inline fun <T> Iterable<T>.any(predicate: (T) -> Boolean): Boolean {
|
||||
public fun <T> Iterable<T>.count(): Int {
|
||||
if (this is Collection) return size
|
||||
var count = 0
|
||||
for (element in this) count++
|
||||
for (element in this) checkCountOverflow(++count)
|
||||
return count
|
||||
}
|
||||
|
||||
@@ -1425,7 +1429,7 @@ public inline fun <T> Collection<T>.count(): Int {
|
||||
public inline fun <T> Iterable<T>.count(predicate: (T) -> Boolean): Int {
|
||||
if (this is Collection && isEmpty()) return 0
|
||||
var count = 0
|
||||
for (element in this) if (predicate(element)) count++
|
||||
for (element in this) if (predicate(element)) checkCountOverflow(++count)
|
||||
return count
|
||||
}
|
||||
|
||||
@@ -1447,7 +1451,7 @@ public inline fun <T, R> Iterable<T>.fold(initial: R, operation: (acc: R, T) ->
|
||||
public inline fun <T, R> Iterable<T>.foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): R {
|
||||
var index = 0
|
||||
var accumulator = initial
|
||||
for (element in this) accumulator = operation(index++, accumulator, element)
|
||||
for (element in this) accumulator = operation(checkIndexOverflow(index++), accumulator, element)
|
||||
return accumulator
|
||||
}
|
||||
|
||||
@@ -1498,7 +1502,7 @@ public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
|
||||
*/
|
||||
public inline fun <T> Iterable<T>.forEachIndexed(action: (index: Int, T) -> Unit): Unit {
|
||||
var index = 0
|
||||
for (item in this) action(index++, item)
|
||||
for (item in this) action(checkIndexOverflow(index++), item)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1725,7 +1729,7 @@ public inline fun <S, T : S> Iterable<T>.reduceIndexed(operation: (index: Int, a
|
||||
var index = 1
|
||||
var accumulator: S = iterator.next()
|
||||
while (iterator.hasNext()) {
|
||||
accumulator = operation(index++, accumulator, iterator.next())
|
||||
accumulator = operation(checkIndexOverflow(index++), accumulator, iterator.next())
|
||||
}
|
||||
return accumulator
|
||||
}
|
||||
@@ -2238,7 +2242,7 @@ public fun Iterable<Byte>.average(): Double {
|
||||
var count: Int = 0
|
||||
for (element in this) {
|
||||
sum += element
|
||||
count += 1
|
||||
checkCountOverflow(++count)
|
||||
}
|
||||
return if (count == 0) Double.NaN else sum / count
|
||||
}
|
||||
@@ -2252,7 +2256,7 @@ public fun Iterable<Short>.average(): Double {
|
||||
var count: Int = 0
|
||||
for (element in this) {
|
||||
sum += element
|
||||
count += 1
|
||||
checkCountOverflow(++count)
|
||||
}
|
||||
return if (count == 0) Double.NaN else sum / count
|
||||
}
|
||||
@@ -2266,7 +2270,7 @@ public fun Iterable<Int>.average(): Double {
|
||||
var count: Int = 0
|
||||
for (element in this) {
|
||||
sum += element
|
||||
count += 1
|
||||
checkCountOverflow(++count)
|
||||
}
|
||||
return if (count == 0) Double.NaN else sum / count
|
||||
}
|
||||
@@ -2280,7 +2284,7 @@ public fun Iterable<Long>.average(): Double {
|
||||
var count: Int = 0
|
||||
for (element in this) {
|
||||
sum += element
|
||||
count += 1
|
||||
checkCountOverflow(++count)
|
||||
}
|
||||
return if (count == 0) Double.NaN else sum / count
|
||||
}
|
||||
@@ -2294,7 +2298,7 @@ public fun Iterable<Float>.average(): Double {
|
||||
var count: Int = 0
|
||||
for (element in this) {
|
||||
sum += element
|
||||
count += 1
|
||||
checkCountOverflow(++count)
|
||||
}
|
||||
return if (count == 0) Double.NaN else sum / count
|
||||
}
|
||||
@@ -2308,7 +2312,7 @@ public fun Iterable<Double>.average(): Double {
|
||||
var count: Int = 0
|
||||
for (element in this) {
|
||||
sum += element
|
||||
count += 1
|
||||
checkCountOverflow(++count)
|
||||
}
|
||||
return if (count == 0) Double.NaN else sum / count
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user