On Sat, 8 Nov 2025 at 13:52, ArktinenKarpalo <[email protected]> wrote:
>
> From: Karpalo Toivonen <[email protected]>
>
> 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 @@

This test fails when run as C++98, because the bitset(const char*)
constructor didn't exist until C++11.

That also points out another problem with the test, which is that it
only checks the const char* constructor, and not the basic_string and
basic_string_view constructors. I'll add tests for those.

> +// PR libstdc++/121054 std::bitset<0>("zero") should throw 
> std::invalid_argument
> +#include <bitset>
> +#include <stdexcept>
> +#include <testsuite_hooks.h>
> +
> +void test01(void)

We don't use the (void) abomination in libstdc++, we just write ().
It's used in the 20_util/bitset/cons/1.cc test but that's very old and
is setting a bad example.

> +{
> +  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
>

Reply via email to