[gcc r17-4837] libstdc++: Fix stack corruption in std::bitset stream extraction [PR124370]
Jonathan Wakely
redi@gcc.gnu.org
Fri Oct 2 13:52:07 GMT 2026
https://gcc.gnu.org/g:5d419c69ce2e6b86d7da75f18736904885674219
commit r17-4837-g5d419c69ce2e6b86d7da75f18736904885674219
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Thu Oct 1 22:50:13 2026 +0100
libstdc++: Fix stack corruption in std::bitset stream extraction [PR124370]
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.
Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
Diff:
---
libstdc++-v3/include/std/bitset | 31 ++++++++---------
libstdc++-v3/testsuite/20_util/bitset/io/input.cc | 2 ++
.../testsuite/20_util/bitset/io/wchar_t.cc | 39 ++++++++++++++++++++++
3 files changed, 57 insertions(+), 15 deletions(-)
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>();
+}
More information about the Libstdc++-cvs
mailing list