]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: std::bitset<0>("zero") should throw std::invalid_argument [PR121054]
authorKarpalo Toivonen <arktinenkarpalo@gmail.com>
Sat, 8 Nov 2025 13:51:46 +0000 (15:51 +0200)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 14 Nov 2025 13:08:52 +0000 (13:08 +0000)
According to the standard the first n characters of a bitset constructor
string need to be checked instead of only N.

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.

Co-authored-by: Jonathan Wakely <jwakely@redhat.com>
libstdc++-v3/include/std/bitset
libstdc++-v3/testsuite/20_util/bitset/121054.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/bitset/cons/constexpr_c++23.cc

index 92f11f19807a31741d54afe2ffd3a0b99e908edb..6fd32657863f4e0db02954018b712ac9931f85c6 100644 (file)
@@ -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 (file)
index 0000000..0e8f32d
--- /dev/null
@@ -0,0 +1,233 @@
+// { dg-do run }
+
+// PR libstdc++/121054 std::bitset<0>("zero") should throw std::invalid_argument
+#include <bitset>
+#include <stdexcept>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  try {
+    std::bitset<0>(std::string("x"));
+    VERIFY( false );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( true );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  try {
+    std::bitset<1>(std::string("0x"));
+    VERIFY( false );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( true );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  try {
+    std::bitset<0>(std::string("01"));
+    VERIFY( true );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( false );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  try {
+    std::bitset<1>(std::string("x0"), 1);
+    VERIFY( true );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( false );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+#if _GLIBCXX_USE_C99_WCHAR
+  try {
+    std::bitset<1>(std::wstring(L"0x"));
+    VERIFY( false );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( true );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  try {
+    std::bitset<1>(std::wstring(L"x0"), 1);
+    VERIFY( true );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( false );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+#endif
+}
+
+void
+test02()
+{
+#if __cplusplus >= 201103L
+  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 );
+  }
+
+#if _GLIBCXX_USE_C99_WCHAR
+  try {
+    std::bitset<1>(L"0x", 2);
+    VERIFY( false );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( true );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  try {
+    std::bitset<1>(L"0x", 1);
+    VERIFY( true );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( false );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+#endif
+#endif
+}
+
+void
+test03()
+{
+#if __cpp_lib_bitset >= 202202L
+  try {
+    std::bitset<0>(std::string_view("x"));
+    VERIFY( false );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( true );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  try {
+    std::bitset<1>(std::string_view("0x"));
+    VERIFY( false );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( true );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  try {
+    std::bitset<0>(std::string_view("01"));
+    VERIFY( true );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( false );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  try {
+    std::bitset<1>(std::string_view("x0"), 1);
+    VERIFY( true );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( false );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+#if _GLIBCXX_USE_C99_WCHAR
+  try {
+    std::bitset<1>(std::wstring_view(L"0x"));
+    VERIFY( false );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( true );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  try {
+    std::bitset<1>(std::wstring_view(L"x0"), 1);
+    VERIFY( true );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( false );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+#endif
+#endif
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+}
index 7e2eba5095d28a9450f8d6ad31346d1038e97b54..0a940949d846b857ce9e48086fc0361947ccf63b 100644 (file)
@@ -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;
 }