Reputation: 56342
In an algorithm I'm writing, I can have the following (simplified of course)
int a[3] = {1,2,3};
int b = a[3];
when the index used to fill b
overflows, I never use the value of b. Is the code still incorrect? Do I have to make an explicit boundary check?
Upvotes: 6
Views: 505
Reputation: 385325
Yes.
You are using the value, by copying it into b
.
More specifically, dereferencing (a+3)
is not allowed since the expression (a+3)
is not a valid pointer... and the expression a[3]
is equivalent to *(a+3)
(where a
has decayed to a pointer-expression).
Upvotes: 1
Reputation: 133082
This code has Undefined Behavior whether or not you use b
. Why? Because a[3]
is equivalent to *(a+3)
by definition. And here's a quote from the standard that proved that *(a+3)
is in itself undefined, regardless of whether the value is stored, used, or left alone.
When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integral expression. In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i+n-th and i−n-th elements of the array object, provided they exist. Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
Upvotes: 5
Reputation: 46647
Reading a[3]
already causes undefined behaviour. As undefined behaviour is never locally limited, this can already lead to your harddisk drive being formatted or your computer emerging to a giant, flesh-eating zombie.
In reality, it will usually just work. But it's easy to make up a case where the end of the array marks the end of a mapped memory region, so accessing one element beyond would cause a segmentation fault. This is certainly not the case for an array of int
on the stack and neither with most heap implementations, but you shouldn't rely on it.
(Whether taking the address of &a[3]
is undefined behaviour as well is heavily disputed.)
Upvotes: 3
Reputation: 16243
It's still incorrect yes, because you access the out-of-bounds memory location to get the value a[3]
and store it in the variable b
.
The fact that you never use b
could mean that the compiler optimizes out that line of code, so you might not ever see any adverse effects from that line being there.
However, the compiler is not required to do so, and the code itself still has undefined behavior.
Upvotes: 2
Reputation: 131847
Still incorrect, still undefined behaviour. Do the bounds check.
int b = *(a + 3); // dereferencing beyond the array bound.
Upvotes: 3
Reputation: 92341
Yes, it is wrong to read a[3]
which doesn't exits.
Using b
would be wrong too, but it is already too late.
Upvotes: 0