On Thu, 5 Mar 2026 at 18:11, Nathan Myers <[email protected]> wrote:
>
> Changes in v3:
> - Delete redundant (and also broken) "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[].
OK for trunk, thanks.
>
> 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.
> ---
> libstdc++-v3/include/std/bitset | 10 ++++--
> .../20_util/bitset/access/118341_neg1.cc | 14 +++++++++
> .../20_util/bitset/access/118341_neg2.cc | 14 +++++++++
> .../20_util/bitset/access/118341_smoke.cc | 31 +++++++++++++++++++
> .../20_util/bitset/access/subscript.cc | 26 ++++++++++++++++
> .../bitset/access/subscript_const_neg.cc | 13 ++++++++
> 6 files changed, 106 insertions(+), 2 deletions(-)
> create mode 100644
> libstdc++-v3/testsuite/20_util/bitset/access/118341_neg1.cc
> create mode 100644
> libstdc++-v3/testsuite/20_util/bitset/access/118341_neg2.cc
> create mode 100644
> libstdc++-v3/testsuite/20_util/bitset/access/118341_smoke.cc
> create mode 100644 libstdc++-v3/testsuite/20_util/bitset/access/subscript.cc
> create mode 100644
> libstdc++-v3/testsuite/20_util/bitset/access/subscript_const_neg.cc
>
> diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset
> index 331d0894342..eb200ab9246 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 00000000000..22991ffac91
> --- /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 00000000000..fa8942ec510
> --- /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 00000000000..0a525c1b3fa
> --- /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 00000000000..18d5155ed08
> --- /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 00000000000..12d4f1eaf30
> --- /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();
> +}
> --
> 2.52.0
>