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
>

Reply via email to