Date: Fri, 29 Aug 2025 11:28:04 +0100
On Fri, 29 Aug 2025 at 11:26, Jonathan Wakely <cxx_at_[hidden]> wrote:
>
>
> On Fri, 29 Aug 2025 at 11:20, Jonathan Wakely <cxx_at_[hidden]> wrote:
>
>>
>>
>> On Thu, 28 Aug 2025 at 23:44, Levo D via Std-Proposals <
>> std-proposals_at_[hidden]> wrote:
>>
>>>
>>> Why Not Span
>>>
>>> Span doesn't have special rules for bounds checking. The following would
>>> assert, but we're looking for a compile-time error, which does not happen.
>>>
>>
>> It could do though. std::span seems like the obvious solution for array
>> slices in C++.
>>
>> Why not work on improving static analysis in existing compilers so that
>> they detect out of bounds span accesses at compile time? Do we really need
>> changes to the type system to do that?
>>
>>
>>
>>
>>> The test1 and test2 only differ in the function signature.
>>>
>>> #include <span>
>>> int test1(std::span<int> file, int n) { // span<int>
>>> if (file[0] != 0x12 && file[2] != 0x34)
>>> return -1;
>>> return file[n] + file[100];
>>> }
>>> int test2(std::span<int, 32> file, int n) { // span<int, 32>
>>> if (file[0] != 0x12 && file[2] != 0x34)
>>> return -1;
>>> return file[n] + file[100];
>>> }
>>> int main() {
>>> int tooSmall[]={1};
>>> int fileBadHeader[64]={1,2,3,4,5,6,7,8,9};
>>> int fileOkHeader[64]={0x12,0x34,3,4,5,6,7,8,9};
>>>
>>> //test1({tooSmall}, 100); // will assert
>>> test1({fileBadHeader}, 100); // will not assert since header
>>> check fails
>>> //test1({fileOkHeader}, 100); // will assert
>>> test2(std::span{fileBadHeader}.subspan<10, 32>(), 100); // will
>>> not assert
>>> //test2(std::span{fileOkHeader}.subspan<0, 32>(), 100); // will
>>> assert
>>> }
>>>
>>> By using arrays, we can catch `file[100]` along with the
>>> problematic index `n` if the user opts into the non-literal bounds check.
>>>
>>
>> Nothing prevents compilers from checking the uses of std::span and
>> diagnosing provably out of bounds accesses.
>>
>
> And if we reach for a new hack in the type system every time there's a
> problem, and so *don't* work on improving the ergonomics and safety of
> std::span, then span will never get more safety benefits. We'll just need
> to keep adding more special case hacks to the type system to try to make
> arrays slightly less useless, one kludge at a time.
>
> We have std::span already. Let's make improvements there, not by trying to
> make arrays be both plain arrays and also slices of arrays.
>
And in case it's not obvious, your solution only helps arrays, not
std::array, or std::vector, contiguous ranges, or anything else that
std::span works with.
A good way to avoid out of bounds accesses on arrays is to stop using them
like that.
>
>
> On Fri, 29 Aug 2025 at 11:20, Jonathan Wakely <cxx_at_[hidden]> wrote:
>
>>
>>
>> On Thu, 28 Aug 2025 at 23:44, Levo D via Std-Proposals <
>> std-proposals_at_[hidden]> wrote:
>>
>>>
>>> Why Not Span
>>>
>>> Span doesn't have special rules for bounds checking. The following would
>>> assert, but we're looking for a compile-time error, which does not happen.
>>>
>>
>> It could do though. std::span seems like the obvious solution for array
>> slices in C++.
>>
>> Why not work on improving static analysis in existing compilers so that
>> they detect out of bounds span accesses at compile time? Do we really need
>> changes to the type system to do that?
>>
>>
>>
>>
>>> The test1 and test2 only differ in the function signature.
>>>
>>> #include <span>
>>> int test1(std::span<int> file, int n) { // span<int>
>>> if (file[0] != 0x12 && file[2] != 0x34)
>>> return -1;
>>> return file[n] + file[100];
>>> }
>>> int test2(std::span<int, 32> file, int n) { // span<int, 32>
>>> if (file[0] != 0x12 && file[2] != 0x34)
>>> return -1;
>>> return file[n] + file[100];
>>> }
>>> int main() {
>>> int tooSmall[]={1};
>>> int fileBadHeader[64]={1,2,3,4,5,6,7,8,9};
>>> int fileOkHeader[64]={0x12,0x34,3,4,5,6,7,8,9};
>>>
>>> //test1({tooSmall}, 100); // will assert
>>> test1({fileBadHeader}, 100); // will not assert since header
>>> check fails
>>> //test1({fileOkHeader}, 100); // will assert
>>> test2(std::span{fileBadHeader}.subspan<10, 32>(), 100); // will
>>> not assert
>>> //test2(std::span{fileOkHeader}.subspan<0, 32>(), 100); // will
>>> assert
>>> }
>>>
>>> By using arrays, we can catch `file[100]` along with the
>>> problematic index `n` if the user opts into the non-literal bounds check.
>>>
>>
>> Nothing prevents compilers from checking the uses of std::span and
>> diagnosing provably out of bounds accesses.
>>
>
> And if we reach for a new hack in the type system every time there's a
> problem, and so *don't* work on improving the ergonomics and safety of
> std::span, then span will never get more safety benefits. We'll just need
> to keep adding more special case hacks to the type system to try to make
> arrays slightly less useless, one kludge at a time.
>
> We have std::span already. Let's make improvements there, not by trying to
> make arrays be both plain arrays and also slices of arrays.
>
And in case it's not obvious, your solution only helps arrays, not
std::array, or std::vector, contiguous ranges, or anything else that
std::span works with.
A good way to avoid out of bounds accesses on arrays is to stop using them
like that.
Received on 2025-08-29 10:28:23