Date: Sat, 23 Aug 2025 09:47:14 +0100
On Fri, 22 Aug 2025, 21:04 Levo D via Std-Proposals, <
std-proposals_at_[hidden]> wrote:
> I'd be happy to work on this proposal with others.
>
> This document is about bound-checking on arrays, not containers,
> which can be added in the future after a successful implementation.
>
> If we look at the following program, we'll notice several problems.
> Comments will explicitly explain them.
> The two biggest issues are
> 1) no easy way to convert a large array into a smaller array
> 2) Compilers don't need to error when the size is known and a
> literal index is outside of it
>
> #include <cstddef>
>
> void test16(char (&arr)[16]) { arr[15] = 0x12; }
> void test32(char (&arr)[32]) { arr[31] = 0x34; }
>
> // Sanitizers won't catch this if you change 257 to 255
> void test256(char (&arr)[256]) { arr[257] = 0x56; }
>
Is your comment backwards? Do you mean sanitizers don't catch it if you
accidentally write past the end of the array? I disagree, and compilers can
warn about the index being out of bounds.
prog.cc: In function 'void test256(char (&)[256])':
prog.cc:7:41: warning: array subscript 257 is above array bounds of 'char
[256]' [-Warray-bounds=]
7 | void test256(char (&arr)[256]) { arr[257] = 0x56; }
| ~~~~~~~^
prog.cc:7:21: note: while referencing 'arr'
7 | void test256(char (&arr)[256]) { arr[257] = 0x56; }
| ~~~~~~~^~~~~~~~~
You can is -Werror=array-bounds to get the error you want.
> template <size_t N> void testN(char (&arr)[N]) {
> //test16(arr); // error because size is not exact
> test32(arr); // exact, compiles
> // Typecasting is bad, as we know
> test16(reinterpret_cast<char (&)[16]>(arr)); // compiles
>
So don't do this, it's obviously wrong and should never be used.
test256(reinterpret_cast<char (&)[256]>(arr)); // compiles and will
> overwrite memory
>
Same here.
}
>
> int main() {
> char buf[32]{};
> testN(buf); // two problems, 32 is smaller than 256 and
> // test256 writes to 257, which is clearly out of range
> // the below doesn't cause a warning (or error) in some compilers
> buf[-1] = 0x78;
I'm not sure why GCC doesn't warn here, probably because it's just silly
code that nobody writes.
ubsan catches it:
prog.cc:22:15: runtime error: index -1 out of bounds for type 'char [32]'
> // I much rather the previous line be written as
> *(buf-1) = 0x78;
> }
>
>
> By having 'arr[257]' and 'buf[-1]' become an error, obvious mistakes will
> be caught immediately.
>
They're both undefined and can be diagnosed at compile time, including by
failure to compile the code.
std-proposals_at_[hidden]> wrote:
> I'd be happy to work on this proposal with others.
>
> This document is about bound-checking on arrays, not containers,
> which can be added in the future after a successful implementation.
>
> If we look at the following program, we'll notice several problems.
> Comments will explicitly explain them.
> The two biggest issues are
> 1) no easy way to convert a large array into a smaller array
> 2) Compilers don't need to error when the size is known and a
> literal index is outside of it
>
> #include <cstddef>
>
> void test16(char (&arr)[16]) { arr[15] = 0x12; }
> void test32(char (&arr)[32]) { arr[31] = 0x34; }
>
> // Sanitizers won't catch this if you change 257 to 255
> void test256(char (&arr)[256]) { arr[257] = 0x56; }
>
Is your comment backwards? Do you mean sanitizers don't catch it if you
accidentally write past the end of the array? I disagree, and compilers can
warn about the index being out of bounds.
prog.cc: In function 'void test256(char (&)[256])':
prog.cc:7:41: warning: array subscript 257 is above array bounds of 'char
[256]' [-Warray-bounds=]
7 | void test256(char (&arr)[256]) { arr[257] = 0x56; }
| ~~~~~~~^
prog.cc:7:21: note: while referencing 'arr'
7 | void test256(char (&arr)[256]) { arr[257] = 0x56; }
| ~~~~~~~^~~~~~~~~
You can is -Werror=array-bounds to get the error you want.
> template <size_t N> void testN(char (&arr)[N]) {
> //test16(arr); // error because size is not exact
> test32(arr); // exact, compiles
> // Typecasting is bad, as we know
> test16(reinterpret_cast<char (&)[16]>(arr)); // compiles
>
So don't do this, it's obviously wrong and should never be used.
test256(reinterpret_cast<char (&)[256]>(arr)); // compiles and will
> overwrite memory
>
Same here.
}
>
> int main() {
> char buf[32]{};
> testN(buf); // two problems, 32 is smaller than 256 and
> // test256 writes to 257, which is clearly out of range
> // the below doesn't cause a warning (or error) in some compilers
> buf[-1] = 0x78;
I'm not sure why GCC doesn't warn here, probably because it's just silly
code that nobody writes.
ubsan catches it:
prog.cc:22:15: runtime error: index -1 out of bounds for type 'char [32]'
> // I much rather the previous line be written as
> *(buf-1) = 0x78;
> }
>
>
> By having 'arr[257]' and 'buf[-1]' become an error, obvious mistakes will
> be caught immediately.
>
They're both undefined and can be diagnosed at compile time, including by
failure to compile the code.
Received on 2025-08-23 08:47:31