You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
An index into a fixed-size array is not checked: a[4] on an int[3] writes past it #3113
A slice index is bounds-checked: s[i] outside 0 ..< s.len is a named panic (language reference, Slices). An index into a fixed-size array T[N] is not checked at all. The generated C is a plain a[i], so an index outside 0 ..< N reads and writes whatever memory lies past the array:
fn at(a: int[3], i: int) -> int {
return a[i]
}
main() {
a = [1, 2, 3]
b = [7, 8, 9]
i = 4
a[i] = 99 // writes past a, into the frame
println("${at(a, 5)} ${b[0]} ${b[1]}")
}
This prints 1089384752 7 8 and exits 0 (0.839.0 and the #3101 branch, Windows, gcc -O2). Nothing panics, and the write lands in the stack frame. The same holds for an array field (c.w[i] on w: long[80]), an array parameter, an actor's array state, and a const table (SIGMA[i]).
The reference says what a slice index does but never says what an array index does, so this reads as a gap rather than a decision. A language that panics on a bad slice index but corrupts memory on a bad array index gives a program no safety it can rely on.
Fix:
Every index into a T[N] is checked against N, as a slice index is. Outside 0 ..< N it is the same named panic, with the source line, the index and the length. The check covers reads, writes, compound assignments and ++/--, through locals, fields, parameters, actor state and const tables.
A constant index outside the range is a compile error.
The reference states the rule beside the slice rule.
Performance is measured before and after on the code that indexes arrays in hot loops: the cryptography modules (blake2's SIGMA, gost's 2048-entry table, the round constants) and the cross-language benchmarks. With a constant N and a loop bounded by it, the C compiler drops the check itself; any case where it does not is reported with its numbers.
Found on #3101, while moving #3107's crypto buffers onto arrays.
Activity
An index into a fixed-size array is checked against its length (#3113)
std.bignum and the cryptography modules hold their buffers as arrays …