The annotations say "the bound of the pointer/array p is expression X", but if I subsequently do for (int i.....) { p[i]++; } you have to perform a bounds check unless you can prove that i never exceeds the expression given by the bounds.
e.g. (using the implemented and used in the real world bounds safety extension in clang[1])
void f1(int *ps __counted_by(N), int N) {
for (int j = 0; j < N; j++) ps[j]++;
}
void f2(int *ps __counted_by(N), int N) {
for (int j = 0; j < 10; j++) ps[j]++;
}
In the function f1 the compiler can in principle prove that the bounds checks aren't needed, but in f2 it cannot, and so failing to perform a bounds check would lead to unsafe code.
Making the bounds of a pointer explicit does not mean that you no longer need bounds checks, it just means that now you know what the bounds are, so you can most enforce those bounds. Then as an implementation detail you optimise the unnecessary checks out. The enforcement aspect is required for correctness, if you cannot prove at compile time that a pointer operation is in bounds a bounds check is mandatory.
Later it suggests changing just the declaration, adding a parameter annotation in this way:
int do_indexing(int *buf,
const size_t bufsize [[arraysize_of:buf]],
size_t index);
It suggests that, with this function declaration and the former function body, the compiler should emit a warning:
> Similarly the compiler can diagnose that the first example can lead to a buffer overflow, because the value of index can be anything.
This clashes with my understanding of why we would use the annotation in the first place. You seem to hold the same feelings, as this is analogous to your f1(), which you agree the compiler should consider safe.
Instead TFA seems to advocate that the correct function body should be:
> Now the compiler can in fact verify that the latter example is safe. When buf is dereferenced we know that the value of index is nonnegative and less than the size of the array.
The annotations say "the bound of the pointer/array p is expression X", but if I subsequently do for (int i.....) { p[i]++; } you have to perform a bounds check unless you can prove that i never exceeds the expression given by the bounds.
e.g. (using the implemented and used in the real world bounds safety extension in clang[1])
In the function f1 the compiler can in principle prove that the bounds checks aren't needed, but in f2 it cannot, and so failing to perform a bounds check would lead to unsafe code.Making the bounds of a pointer explicit does not mean that you no longer need bounds checks, it just means that now you know what the bounds are, so you can most enforce those bounds. Then as an implementation detail you optimise the unnecessary checks out. The enforcement aspect is required for correctness, if you cannot prove at compile time that a pointer operation is in bounds a bounds check is mandatory.
[1] https://discourse.llvm.org/t/rfc-enforcing-bounds-safety-in-...