diff options
| author | Karpalo Toivonen <arktinenkarpalo@gmail.com> | 2025-11-08 15:51:46 +0200 |
|---|---|---|
| committer | Jonathan Wakely <redi@gcc.gnu.org> | 2025-11-14 13:08:52 +0000 |
| commit | e7ba197b19b37bb244b31c95f9c7f46749d06e48 (patch) | |
| tree | 11cbe75828d0163982ad57bf91789eb79d052fdd | |
| parent | c9fb483dbc880d0b109d73f80dffb5433eed179d (diff) | |
libstdc++: std::bitset<0>("zero") should throw std::invalid_argument [PR121054]
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>
| -rw-r--r-- | libstdc++-v3/include/std/bitset | 9 | ||||
| -rw-r--r-- | libstdc++-v3/testsuite/20_util/bitset/121054.cc | 233 | ||||
| -rw-r--r-- | libstdc++-v3/testsuite/20_util/bitset/cons/constexpr_c++23.cc | 2 |
3 files changed, 241 insertions, 3 deletions
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..0e8f32dc8ea --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bitset/121054.cc @@ -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(); +} 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; } |
