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