On Fri, Oct 2, 2026 at 11:41 AM Jonathan Wakely <[email protected]> wrote:

> The __builtin_alloca argument didn't account for the size or alignment
> of wide characters.
> Replace __builtin_alloca with an array _CharT[small ? N : 1] which is
> used for small, or a heap allocation otherwise.
>
> libstdc++-v3/ChangeLog:
>
>         PR libstdc++/124370
>         * include/std/bitset (operator>>): Use array inside _Buffer
>         instead of __builtin_alloca.
>         * testsuite/20_util/bitset/io/input.cc: Suppress pedwarn about
>         C++14 binary literal.
>         * testsuite/20_util/bitset/io/wchar_t.cc: New test.
> ---
>
> v2: replaced __builtin_alloca with _CharT array as suggested by Tomasz.
> Added pragmas to disable warnings about 0b literals in tests.  Added
> bitset<0> check to new test.
>
LGTM thanks. __use_local flags look more readable.

>
>  libstdc++-v3/include/std/bitset               | 31 ++++++++-------
>  .../testsuite/20_util/bitset/io/input.cc      |  2 +
>  .../testsuite/20_util/bitset/io/wchar_t.cc    | 39 +++++++++++++++++++
>  3 files changed, 57 insertions(+), 15 deletions(-)
>  create mode 100644 libstdc++-v3/testsuite/20_util/bitset/io/wchar_t.cc
>
> diff --git a/libstdc++-v3/include/std/bitset
> b/libstdc++-v3/include/std/bitset
> index d581606e7dde..469c8da9ece4 100644
> --- a/libstdc++-v3/include/std/bitset
> +++ b/libstdc++-v3/include/std/bitset
> @@ -1705,30 +1705,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
>        typedef std::basic_istream<_CharT, _Traits>  __istream_type;
>        typedef typename __istream_type::ios_base    __ios_base;
>
> -#pragma GCC diagnostic push
> -#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
> +      static const bool __use_local = _Nb * sizeof(_CharT) <= 256;
> +
>        struct _Buffer
>        {
> -       static _GLIBCXX_CONSTEXPR bool _S_use_alloca() { return _Nb <=
> 256; }
> -
> -       explicit _Buffer(_CharT* __p) : _M_ptr(__p) { }
> +#pragma GCC diagnostic push
> +#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
> +       _Buffer() : _M_ptr(_M_local)
> +       {
> +         if _GLIBCXX_CONSTEXPR (!__use_local)
> +           _M_ptr = new _CharT[_Nb];
> +       }
>
>         ~_Buffer()
>         {
> -         if _GLIBCXX_CONSTEXPR (!_S_use_alloca())
> +         if _GLIBCXX_CONSTEXPR (!__use_local)
>             delete[] _M_ptr;
>         }
> -
> -       _CharT* const _M_ptr;
> -      };
> -      _CharT* __ptr;
> -      if _GLIBCXX_CONSTEXPR (_Buffer::_S_use_alloca())
> -       __ptr = (_CharT*)__builtin_alloca(_Nb);
> -      else
> -       __ptr = new _CharT[_Nb];
> -      const _Buffer __buf(__ptr);
>  #pragma GCC diagnostic pop
>
> +       _CharT* _M_ptr;
> +       _CharT _M_local[__use_local && _Nb != 0 ? _Nb : 1];
> +      } __buf;
> +
> +      _CharT* __ptr = __buf._M_ptr;
> +
>        // _GLIBCXX_RESOLVE_LIB_DEFECTS
>        // 303. Bitset input operator underspecified
>        const char_type __zero = __is.widen('0');
> diff --git a/libstdc++-v3/testsuite/20_util/bitset/io/input.cc
> b/libstdc++-v3/testsuite/20_util/bitset/io/input.cc
> index b0e301a42b10..a01e48cf2847 100644
> --- a/libstdc++-v3/testsuite/20_util/bitset/io/input.cc
> +++ b/libstdc++-v3/testsuite/20_util/bitset/io/input.cc
> @@ -42,6 +42,8 @@ void test01()
>    VERIFY( ss.rdstate() == ios_base::goodbit ); // LWG 3199
>  }
>
> +#pragma GCC diagnostic ignored "-Wc++14-extensions" // 0b literals
> +
>  void
>  test02()
>  {
> diff --git a/libstdc++-v3/testsuite/20_util/bitset/io/wchar_t.cc
> b/libstdc++-v3/testsuite/20_util/bitset/io/wchar_t.cc
> new file mode 100644
> index 000000000000..6c7c496daa17
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/20_util/bitset/io/wchar_t.cc
> @@ -0,0 +1,39 @@
> +// { dg-do run }
> +
> +// C++98 23.3.5.3 bitset operators
> +
> +#include <bitset>
> +#include <sstream>
> +#include <testsuite_hooks.h>
> +
> +#pragma GCC diagnostic ignored "-Wc++14-extensions" // 0b literals
> +
> +// Bug 124370 - Out-of-bounds write for wistream >> bitset
> +void
> +test_pr124370()
> +{
> +  std::wistringstream input(L"10011011001101");
> +  std::bitset<10> b;
> +  input >> b;
> +  VERIFY( b == std::bitset<10>(0b1001101100) );
> +}
> +
> +// Round-trip through a wide stream.
> +template<int N>
> +void
> +test_round_trip()
> +{
> +  std::bitset<N> a(0b100110110011010101101010), b;
> +  std::wstringstream ss;
> +  ss << a;
> +  ss >> b;
> +  VERIFY( b == a );
> +}
> +
> +int main()
> +{
> +  test_pr124370();
> +  test_round_trip<0>();
> +  test_round_trip<24>();
> +  test_round_trip<1024>();
> +}
> --
> 2.55.0
>
>

Reply via email to