aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Myers <ncm@cantrip.org>2026-03-04 13:08:41 -0500
committerNathan Myers <ncm@cantrip.org>2026-03-05 13:23:36 -0500
commit1b404c574450a48fee5f28f2acffafee7419fe38 (patch)
tree2fd40964af81a3c8accb775d6cd25d99f9dbd389
parentdae387d2c81eace093f3c9a2e6e3f027a615e23f (diff)
downloadgcc-master.zip
gcc-master.tar.gz
gcc-master.tar.bz2
libstdc++: bitset subscript check when _GLIBCXX_ASSERTIONS [PR118341]HEADtrunkmaster
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.
-rw-r--r--libstdc++-v3/include/std/bitset10
-rw-r--r--libstdc++-v3/testsuite/20_util/bitset/access/118341_neg1.cc14
-rw-r--r--libstdc++-v3/testsuite/20_util/bitset/access/118341_neg2.cc14
-rw-r--r--libstdc++-v3/testsuite/20_util/bitset/access/118341_smoke.cc31
-rw-r--r--libstdc++-v3/testsuite/20_util/bitset/access/subscript.cc26
-rw-r--r--libstdc++-v3/testsuite/20_util/bitset/access/subscript_const_neg.cc13
6 files changed, 106 insertions, 2 deletions
diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset
index 331d089..eb200ab 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 0000000..22991ff
--- /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 0000000..fa8942e
--- /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 0000000..0a525c1
--- /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 0000000..18d5155
--- /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 0000000..12d4f1e
--- /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();
+}