https://gcc.gnu.org/g:1b404c574450a48fee5f28f2acffafee7419fe38
commit r16-7919-g1b404c574450a48fee5f28f2acffafee7419fe38 Author: Nathan Myers <[email protected]> Date: Wed Mar 4 13:08:41 2026 -0500 libstdc++: bitset subscript check when _GLIBCXX_ASSERTIONS [PR118341] Changes in v3: - Delete redundant "dg" annotations. Changes in v2: - Rejigger testing. - Add tests for regular bitset<>::op[]. Perform __glibcxx_assert bounds check on indices to bitset<>::op[] for const and non-const overloads. Also, add previously neglected regular tests for bitset<>::op[]. libstdc++-v3/ChangeLog PR libstdc++/118341 * include/std/bitset (operator[] (2x)): Add assertion. * testsuite/20_util/bitset/access/118341_neg1.cc: New test. * testsuite/20_util/bitset/access/118341_neg2.cc: Same. * testsuite/20_util/bitset/access/118341_smoke.cc: Same. * testsuite/20_util/bitset/access/subscript.cc: Same. * testsuite/20_util/bitset/access/subscript_const_neg.cc: Same. Diff: --- libstdc++-v3/include/std/bitset | 10 +++++-- .../testsuite/20_util/bitset/access/118341_neg1.cc | 14 ++++++++++ .../testsuite/20_util/bitset/access/118341_neg2.cc | 14 ++++++++++ .../20_util/bitset/access/118341_smoke.cc | 31 ++++++++++++++++++++++ .../testsuite/20_util/bitset/access/subscript.cc | 26 ++++++++++++++++++ .../20_util/bitset/access/subscript_const_neg.cc | 13 +++++++++ 6 files changed, 106 insertions(+), 2 deletions(-) diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset index 331d0894342f..eb200ab9246c 100644 --- a/libstdc++-v3/include/std/bitset +++ b/libstdc++-v3/include/std/bitset @@ -1290,11 +1290,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX23_CONSTEXPR reference operator[](size_t __position) - { return reference(*this, __position); } + { + __glibcxx_assert(__position < _Nb); + return reference(*this, __position); + } _GLIBCXX_CONSTEXPR bool operator[](size_t __position) const - { return _Unchecked_test(__position); } + { + __glibcxx_assert(__position < _Nb); + return _Unchecked_test(__position); + } ///@} /** diff --git a/libstdc++-v3/testsuite/20_util/bitset/access/118341_neg1.cc b/libstdc++-v3/testsuite/20_util/bitset/access/118341_neg1.cc new file mode 100644 index 000000000000..22991ffac91c --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bitset/access/118341_neg1.cc @@ -0,0 +1,14 @@ +// { dg-do run { xfail *-*-* } } +// { dg-options "-D_GLIBCXX_ASSERTIONS" } + +#include <bitset> +#include <testsuite_hooks.h> + +// Check bitset<>::op[] hardening, non-const. + +int main() +{ + std::bitset<13> bs(0x1555ull); + bs[12]; // OK + bs[13]; // aborts, 13 > 12, non-const +} diff --git a/libstdc++-v3/testsuite/20_util/bitset/access/118341_neg2.cc b/libstdc++-v3/testsuite/20_util/bitset/access/118341_neg2.cc new file mode 100644 index 000000000000..fa8942ec5108 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bitset/access/118341_neg2.cc @@ -0,0 +1,14 @@ +// { dg-do run { xfail *-*-* } } +// { dg-options "-D_GLIBCXX_ASSERTIONS" } + +#include <bitset> +#include <testsuite_hooks.h> + +// Check bitset<>::op[] hardening, const. + +int main() +{ + const std::bitset<13> bs(0x1555ull); + bs[12]; // OK + bs[13]; // aborts, 13 > 12, const +} diff --git a/libstdc++-v3/testsuite/20_util/bitset/access/118341_smoke.cc b/libstdc++-v3/testsuite/20_util/bitset/access/118341_smoke.cc new file mode 100644 index 000000000000..0a525c1b3fac --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bitset/access/118341_smoke.cc @@ -0,0 +1,31 @@ +// { dg-do run } +// { dg-options "-D_GLIBCXX_ASSERTIONS" } + +// Smoke test, op[] hardening. + +#include <bitset> +#include <testsuite_hooks.h> + +void test_non_const_subscript() +{ + std::bitset<13> bs(0x1555ull); + for (int i = 0; i < 13; ++i) + { + VERIFY(bs[i] != (i & 1)); // Check op[] proxy result rvalue. + bs[i] = not bs[i]; // Assign via op[] proxy result lvalue. + VERIFY(bs[i] == (i & 1)); // Check modified. + } +} + +void test_const_subscript() +{ + const std::bitset<13> cbs(0x1555ull); + for (int i = 0; i < 13; ++i) + VERIFY(cbs[i] != (i & 1)); // Check op[] proxy result const rvalue. +} + +int main() +{ + test_non_const_subscript(); + test_const_subscript(); +} diff --git a/libstdc++-v3/testsuite/20_util/bitset/access/subscript.cc b/libstdc++-v3/testsuite/20_util/bitset/access/subscript.cc new file mode 100644 index 000000000000..18d5155ed085 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bitset/access/subscript.cc @@ -0,0 +1,26 @@ +#include <bitset> +#include <testsuite_hooks.h> + +void test_non_const_subscript() +{ + std::bitset<13> bs(0x1555ull); + for (int i = 0; i < 13; ++i) + { + VERIFY(bs[i] != (i & 1)); // Check op[] proxy result rvalue. + bs[i] = not bs[i]; // Assign via op[] proxy result lvalue. + VERIFY(bs[i] == (i & 1)); // Check modified. + } +} + +void test_const_subscript() +{ + const std::bitset<13> cbs(0x1555ull); + for (int i = 0; i < 13; ++i) + VERIFY(cbs[i] != (i & 1)); // Check op[] proxy result const rvalue. +} + +int main() +{ + test_non_const_subscript(); + test_const_subscript(); +} diff --git a/libstdc++-v3/testsuite/20_util/bitset/access/subscript_const_neg.cc b/libstdc++-v3/testsuite/20_util/bitset/access/subscript_const_neg.cc new file mode 100644 index 000000000000..12d4f1eaf308 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bitset/access/subscript_const_neg.cc @@ -0,0 +1,13 @@ +#include <bitset> + +void test_const_subscript_assignment() +{ + const std::bitset<13> bs(0x1555ull); + for (int i = 0; i < 13; ++i) + bs[i] = not bs[i]; // { dg-error "lvalue required" } +} + +int main() +{ + test_const_subscript_assignment(); +}
