[PATCH] libstdc++: std::bitset<0>("zero") should throw std::invalid_argument [PR121054]

ArktinenKarpalo arktinenkarpalo@gmail.com
Sat Nov 8 13:51:46 GMT 2025


From: Karpalo Toivonen <arktinenkarpalo@gmail.com>

According to the standard the first n characters of a bitset constructor
string need to be checked instead of only N.

Tested on x86_64-linux.

libstdc++-v3/ChangeLog:
	PR libstdc++/121054
	* include/std/bitset: Add string check to constructor.
	* testsuite/20_util/bitset/121054.cc: New test.
	* testsuite/20_util/bitset/cons/constexpr_c++23.cc: Fix.
---
 libstdc++-v3/include/std/bitset               |  9 ++-
 .../testsuite/20_util/bitset/121054.cc        | 57 +++++++++++++++++++
 .../20_util/bitset/cons/constexpr_c++23.cc    |  2 -
 3 files changed, 65 insertions(+), 3 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/20_util/bitset/121054.cc

diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset
index 92f11f19807..6fd32657863 100644
--- a/libstdc++-v3/include/std/bitset
+++ b/libstdc++-v3/include/std/bitset
@@ -1549,7 +1549,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 		       size_t __pos, size_t __n, _CharT __zero, _CharT __one)
       {
 	reset();
-	const size_t __nbits = std::min(_Nb, std::min(__n, size_t(__len - __pos)));
+	const size_t __rlen = std::min(__n, size_t(__len - __pos));
+	const size_t __nbits = std::min(_Nb, __rlen);
+	for (size_t __i = __rlen - __nbits; __i > 0; --__i)
+	  {
+	    const _CharT __c = __s[__pos + __rlen - __i];
+	    if (!_Traits::eq(__c, __zero) && !_Traits::eq(__c, __one))
+	      __throw_invalid_argument(__N("bitset::_M_copy_from_ptr"));
+	  }
 	for (size_t __i = __nbits; __i > 0; --__i)
 	  {
 	    const _CharT __c = __s[__pos + __nbits - __i];
diff --git a/libstdc++-v3/testsuite/20_util/bitset/121054.cc b/libstdc++-v3/testsuite/20_util/bitset/121054.cc
new file mode 100644
index 00000000000..401d09d888b
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bitset/121054.cc
@@ -0,0 +1,57 @@
+// PR libstdc++/121054 std::bitset<0>("zero") should throw std::invalid_argument
+#include <bitset>
+#include <stdexcept>
+#include <testsuite_hooks.h>
+
+void test01(void)
+{
+  try {
+    std::bitset<0>("x");
+    VERIFY( false );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( true );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  try {
+    std::bitset<1>("0x", 2);
+    VERIFY( false );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( true );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  try {
+    std::bitset<1>("0x", 1);
+    VERIFY( true );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( false );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  try {
+    std::bitset<0>("01");
+    VERIFY( true );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( false );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/bitset/cons/constexpr_c++23.cc b/libstdc++-v3/testsuite/20_util/bitset/cons/constexpr_c++23.cc
index 7e2eba5095d..0a940949d84 100644
--- a/libstdc++-v3/testsuite/20_util/bitset/cons/constexpr_c++23.cc
+++ b/libstdc++-v3/testsuite/20_util/bitset/cons/constexpr_c++23.cc
@@ -18,8 +18,6 @@ constexpr bool test_ntbs()
   VERIFY( std::bitset<0>("000").all() );
   VERIFY( std::bitset<0>("000", 2).all() );
   VERIFY( std::bitset<1>("100", 2).all() );
-  VERIFY( std::bitset<1>("z00", 2, 'z').none() );
-  VERIFY( std::bitset<2>("ab0", 3, 'a', 'b').count() == 1 );
 
   return true;
 }
-- 
2.51.2



More information about the Libstdc++ mailing list