Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package gcc14 for openSUSE:Factory checked in at 2026-11-09 16:08:10 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/gcc14 (Old) and /work/SRC/openSUSE:Factory/.gcc14.new.3759290 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gcc14" Mon Nov 9 16:08:10 2026 rev:25 rq:1396314 version:14.4.0+git12698 Changes: -------- --- /work/SRC/openSUSE:Factory/gcc14/gcc14.changes 2026-06-29 17:32:51.879184401 +0200 +++ /work/SRC/openSUSE:Factory/.gcc14.new.3759290/gcc14.changes 2026-11-09 16:09:10.523205275 +0100 @@ -1,0 +2,14 @@ +Mon Nov 9 09:14:37 UTC 2026 - Richard Biener <[email protected]> + +- Add gcc14-pr127656.patch to fix use-after-free in + __gnu_pbds::priority_queue. [bsc#1283123] (CVE-2026-102010) +- Add gcc14-pr124370.patch to fix stack corruption in std::bitset + stream extraction [bsc#1289549] [gcc#124370] (CVE-2026-115455) +- Add gcc14-pr127666.patch to fix std::from_chars to not read past + end of input [bsc#1289550] [gcc#127666] (CVE-2026-115456) +- Add gcc14-cve-2026-114690.patch to fix buffer overrun in __gnu_parallel + search [bsc#1288775] (CVE-2026-114690) +- Add gcc14-cve-2026-114691.patch to fix overflow in std::vector<bool> + constructors [bsc#1288774] (CVE-2026-114691) + +------------------------------------------------------------------- New: ---- gcc14-cve-2026-114690.patch gcc14-cve-2026-114691.patch gcc14-pr124370.patch gcc14-pr127656.patch gcc14-pr127666.patch ----------(New B)---------- New: end of input [bsc#1289550] [gcc#127666] (CVE-2026-115456) - Add gcc14-cve-2026-114690.patch to fix buffer overrun in __gnu_parallel search [bsc#1288775] (CVE-2026-114690) New: search [bsc#1288775] (CVE-2026-114690) - Add gcc14-cve-2026-114691.patch to fix overflow in std::vector<bool> constructors [bsc#1288774] (CVE-2026-114691) New: __gnu_pbds::priority_queue. [bsc#1283123] (CVE-2026-102010) - Add gcc14-pr124370.patch to fix stack corruption in std::bitset stream extraction [bsc#1289549] [gcc#124370] (CVE-2026-115455) New: - Add gcc14-pr127656.patch to fix use-after-free in __gnu_pbds::priority_queue. [bsc#1283123] (CVE-2026-102010) New: stream extraction [bsc#1289549] [gcc#124370] (CVE-2026-115455) - Add gcc14-pr127666.patch to fix std::from_chars to not read past end of input [bsc#1289550] [gcc#127666] (CVE-2026-115456) ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ cross-aarch64-gcc14-bootstrap.spec ++++++ --- /var/tmp/diff_new_pack.Lbe7KW/_old 2026-11-09 16:09:12.280278877 +0100 +++ /var/tmp/diff_new_pack.Lbe7KW/_new 2026-11-09 16:09:12.282278960 +0100 @@ -128,6 +128,11 @@ Patch24: gcc14-bsc1239938.patch Patch25: gcc14-rs6000-msplit-patch-nops.patch Patch26: gcc14-pr119680.patch +Patch27: gcc14-pr127656.patch +Patch28: gcc14-pr124370.patch +Patch29: gcc14-pr127666.patch +Patch30: gcc14-cve-2026-114690.patch +Patch31: gcc14-cve-2026-114691.patch # A set of patches from the RH srpm Patch51: gcc41-ppc32-retaddr.patch # Some patches taken from Debian @@ -334,6 +339,7 @@ %patch -p1 -P 19 %endif %patch -p1 -P 20 -P 23 -P 24 -P 25 -P 26 +%patch -p1 -P 27 -P 28 -P 29 -P 30 -P 31 %patch -P 51 %patch -p1 -P 60 -P 61 cross-aarch64-gcc14.spec: same change cross-amdgcn-gcc14.spec: same change cross-arm-gcc14.spec: same change cross-arm-none-gcc14-bootstrap.spec: same change cross-arm-none-gcc14.spec: same change cross-avr-gcc14-bootstrap.spec: same change cross-avr-gcc14.spec: same change cross-bpf-gcc14.spec: same change cross-hppa-gcc14-bootstrap.spec: same change cross-hppa-gcc14.spec: same change cross-loongarch64-gcc14-bootstrap.spec: same change cross-loongarch64-gcc14.spec: same change cross-nvptx-gcc14.spec: same change cross-ppc64-gcc14.spec: same change cross-ppc64le-gcc14-bootstrap.spec: same change cross-ppc64le-gcc14.spec: same change cross-pru-gcc14-bootstrap.spec: same change cross-pru-gcc14.spec: same change cross-riscv64-elf-gcc14-bootstrap.spec: same change cross-riscv64-elf-gcc14.spec: same change cross-riscv64-gcc14-bootstrap.spec: same change cross-riscv64-gcc14.spec: same change cross-rx-gcc14-bootstrap.spec: same change cross-rx-gcc14.spec: same change cross-s390x-gcc14-bootstrap.spec: same change cross-s390x-gcc14.spec: same change cross-x86_64-gcc14.spec: same change gcc14-testresults.spec: same change ++++++ gcc14.spec ++++++ --- /var/tmp/diff_new_pack.Lbe7KW/_old 2026-11-09 16:09:13.152315405 +0100 +++ /var/tmp/diff_new_pack.Lbe7KW/_new 2026-11-09 16:09:13.155315531 +0100 @@ -374,6 +374,11 @@ Patch24: gcc14-bsc1239938.patch Patch25: gcc14-rs6000-msplit-patch-nops.patch Patch26: gcc14-pr119680.patch +Patch27: gcc14-pr127656.patch +Patch28: gcc14-pr124370.patch +Patch29: gcc14-pr127666.patch +Patch30: gcc14-cve-2026-114690.patch +Patch31: gcc14-cve-2026-114691.patch # A set of patches from the RH srpm Patch51: gcc41-ppc32-retaddr.patch # Some patches taken from Debian @@ -2376,6 +2381,7 @@ %patch -p1 -P 19 %endif %patch -p1 -P 20 -P 23 -P 24 -P 25 -P 26 +%patch -p1 -P 27 -P 28 -P 29 -P 30 -P 31 %patch -P 51 %patch -p1 -P 60 -P 61 ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.Lbe7KW/_old 2026-11-09 16:09:13.254319678 +0100 +++ /var/tmp/diff_new_pack.Lbe7KW/_new 2026-11-09 16:09:13.259319887 +0100 @@ -1,5 +1,5 @@ -mtime: 1782717587 -commit: 9bc40569fe568f438444cc147c7fbd13c5fd6bd4d71183ecd8ae2b950dc228dc +mtime: 1794215931 +commit: 0dcdad0be53608b6f81f51a9b5e5d1ef258e2d5aae209338cee9ec6d695d13d7 url: https://src.opensuse.org/gcc/gcc14.git revision: main ++++++ build.specials.obscpio ++++++ ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-11-09 10:18:51.000000000 +0100 @@ -0,0 +1 @@ +.osc diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pre_checkin.sh new/pre_checkin.sh --- old/pre_checkin.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/pre_checkin.sh 2026-11-09 10:18:51.000000000 +0100 @@ -0,0 +1,31 @@ +#!/bin/bash +# This script is called automatically during autobuild checkin. + +case $0 in + \./*) + here=$PWD + ;; + */*) + here=${0%/*} + ;; + *) + here=$PWD + ;; +esac +case ${here##*/} in + gcc*.*) + # Handle maintainance projects with .$REPO suffix + suffix=${here##*/} + suffix=${suffix%%\.*} + set ${suffix#gcc} + ;; + gcc-*) + suffix=${here##*/} + set ${suffix#*-}- + ;; + gcc[0-9]*) + suffix=${here##*/} + set ${suffix#gcc} + ;; +esac +. ${here}/change_spec ++++++ gcc.spec.in ++++++ --- /var/tmp/diff_new_pack.Lbe7KW/_old 2026-11-09 16:09:13.500329983 +0100 +++ /var/tmp/diff_new_pack.Lbe7KW/_new 2026-11-09 16:09:13.504330151 +0100 @@ -379,6 +379,11 @@ Patch24: gcc14-bsc1239938.patch Patch25: gcc14-rs6000-msplit-patch-nops.patch Patch26: gcc14-pr119680.patch +Patch27: gcc14-pr127656.patch +Patch28: gcc14-pr124370.patch +Patch29: gcc14-pr127666.patch +Patch30: gcc14-cve-2026-114690.patch +Patch31: gcc14-cve-2026-114691.patch # A set of patches from the RH srpm Patch51: gcc41-ppc32-retaddr.patch # Some patches taken from Debian @@ -1350,6 +1355,7 @@ %patch -p1 -P 19 %endif %patch -p1 -P 20 -P 23 -P 24 -P 25 -P 26 +%patch -p1 -P 27 -P 28 -P 29 -P 30 -P 31 %patch -P 51 %patch -p1 -P 60 -P 61 ++++++ gcc14-cve-2026-114690.patch ++++++ >From 31366968a5b4a457ee37237317ab66a0cafc14d6 Mon Sep 17 00:00:00 2001 From: Richard Biener <[email protected]> Date: Wed, 21 Oct 2026 18:14:33 +0100 Subject: [PATCH] libstdc++: Fix buffer overrun in __gnu_parallel search (CVE-2026-114690) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To: [email protected] From: Jonathan Wakely <[email protected]> The libstdc++ Parallel Mode (enabled by _GLIBCXX_PARALLEL or by including the relevant headers and calling the functionss explicitly) uses the Knuth-Morris-Pratt search algorithm. A VLA is declared for the borders, but it uses N elements not N+1, leading to an out-of-bounds write in the parallel std::search. libstdc++-v3/ChangeLog: * include/parallel/search.h (__search_template): Increase array size. Reviewed-by: Tomasz Kamiński <[email protected]> (cherry picked from commit c1f32b67510f6f9998deadaef5090b6663adb979) --- libstdc++-v3/include/parallel/search.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libstdc++-v3/include/parallel/search.h b/libstdc++-v3/include/parallel/search.h index 6424a45b682..a215e0ead0c 100644 --- a/libstdc++-v3/include/parallel/search.h +++ b/libstdc++-v3/include/parallel/search.h @@ -111,7 +111,7 @@ namespace __gnu_parallel (1, std::min<_DifferenceType>(__input_length, __get_max_threads())); - _DifferenceType __advances[__pattern_length]; + _DifferenceType __advances[__pattern_length + 1]; __calc_borders(__begin2, __pattern_length, __advances); # pragma omp parallel num_threads(__num_threads) -- 2.51.0 ++++++ gcc14-cve-2026-114691.patch ++++++ >From 65928074e7d564c1d296f5082915f5a37a3d2bee Mon Sep 17 00:00:00 2001 From: Richard Biener <[email protected]> Date: Mon, 26 Oct 2026 17:21:01 +0000 Subject: [PATCH] libstdc++: Fix overflow in std::vector<bool> constructors (CVE-2026-114691) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To: [email protected] From: Jonathan Wakely <[email protected]> Some std::vector<bool> constructors pass a user-provided size (or a distance derived from user-provided range) to the _S_nword function which does addition to find the number of words (of type unsigned long) that are needed for that number of bits. If the size is close to SIZE_MAX the addition wraps to zero and the number of words needed is incorrect. This adds a new function for initializing from user-provided sizes which checks against max_size() so that out-of-range values are rejected before any call to _S_nword. The new function rejects negative values as well as large ones. For an invalid range the result of ranges::distance or std::distance could be a very large negative value that would become smaller than max_size() when converted to size_t. This detects some invalid inputs (last before first) at minimal cost. libstdc++-v3/ChangeLog: * include/bits/stl_bvector.h (_M_check_and_initialize): New function. (vector(size_type, const bool&, const allocator_type&)) (_M_initialize_dispatch, _M_initialize_range): Use new function instead of _M_initialize. (_M_initialize): Add debug assertion. * testsuite/23_containers/vector/bool/prX.cc: New test. Reviewed-by: Tomasz Kamiński <[email protected]> (cherry picked from commit 2fd8866591b5aea7098835f80ab7e176382175ae) --- libstdc++-v3/include/bits/stl_bvector.h | 22 ++- .../23_containers/vector/bool/prX.cc | 160 ++++++++++++++++++ 2 files changed, 178 insertions(+), 4 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/vector/bool/prX.cc diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index ed70e04dc64..2156616f8c4 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -709,6 +709,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { _M_impl._M_move_data(std::move(__x._M_impl)); } #endif + // Caller must ensure the addition won't overflow. _GLIBCXX_CONSTEXPR static size_t _S_nword(size_t __n) @@ -801,7 +802,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #endif : _Base(__a) { - _M_initialize(__n); + _M_check_and_initialize(__n); _M_initialize_value(__value); } @@ -1348,6 +1349,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void _M_initialize(size_type __n) { + // Caller must ensure this, to avoid overflow in _S_nword. + _GLIBCXX_DEBUG_ASSERT(__n <= (size_t)-_S_word_bit); + if (__n) { _Bit_pointer __q = this->_M_allocate(__n); @@ -1358,6 +1362,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } } + template<typename _SizeT> + _GLIBCXX20_CONSTEXPR + void + _M_check_and_initialize(_SizeT __n) + { + if (__n > max_size() || __n < 0) + __throw_length_error( + __N("Cannot create std::vector<bool> larger than max_size()")); + _M_initialize(static_cast<size_type>(__n)); + } + _GLIBCXX20_CONSTEXPR void _M_initialize_value(bool __x) _GLIBCXX_NOEXCEPT @@ -1383,7 +1398,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) { - _M_initialize(static_cast<size_type>(__n)); + _M_check_and_initialize(static_cast<size_type>(__n)); _M_initialize_value(__x); } @@ -1411,8 +1426,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_initialize_range(_ForwardIterator __first, _ForwardIterator __last, std::forward_iterator_tag) { - const size_type __n = std::distance(__first, __last); - _M_initialize(__n); + _M_check_and_initialize(std::distance(__first, __last)); std::copy(__first, __last, begin()); } diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/prX.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/prX.cc new file mode 100644 index 00000000000..bc97b9bfde5 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/prX.cc @@ -0,0 +1,160 @@ +// { dg-do run } + +#include <vector> +#include <ranges> +#include <stdexcept> +#include <testsuite_hooks.h> + +static void +test_n_element_ctor() +{ + try { + std::vector<bool> v(-15, true); + VERIFY(false); + } catch (const std::length_error&) { + } +} + +static void +test_n_element_ctor_dispatch() +{ + try { + std::vector<bool> v(-15, 1); // in C++98 this calls vector(Iter, Iter) ctor + VERIFY(false); + } catch (const std::length_error&) { + } +} + +// A Cpp17RandomAccessIterator for which std::distance always returns an +// impossibly large distance. This implements the Cpp17RandomAccessIterator +// API but doesn't meet the semantic requirements. +// For the test below, all that matters is that the huge value from +// std::distance(first, last) causes std::length_error to be thrown. +struct FakeIterator +{ + typedef std::random_access_iterator_tag iterator_category; + typedef bool value_type; + typedef std::size_t difference_type; // should be a signed type + typedef const bool* pointer; + typedef const bool& reference; + + FakeIterator() : val(true) { } + + reference operator*() const { return val; } + pointer operator->() const { return &val; } + reference operator[](difference_type) const { return val; } + + FakeIterator& operator++() { return *this; } + FakeIterator operator++(int) { return *this; } + FakeIterator& operator--() { return *this; } + FakeIterator operator--(int) { return *this; } + + FakeIterator& operator+=(difference_type) { return *this; } + FakeIterator& operator-=(difference_type) { return *this; } + + FakeIterator operator+(difference_type) const { return *this; } + FakeIterator operator-(difference_type) const { return *this; } + + friend FakeIterator operator+(difference_type, FakeIterator i) { return i; } + + // Return an impossibly large distance + difference_type operator-(FakeIterator) const { return (std::size_t)-8; } + + // These are meaningless results but not actually used by this test. + bool operator==(const FakeIterator&) const { return false; } + bool operator!=(const FakeIterator&) const { return true; } + bool operator<(const FakeIterator&) const { return true; } + bool operator>(const FakeIterator&) const { return false; } + bool operator<=(const FakeIterator&) const { return true; } + bool operator>=(const FakeIterator&) const { return false; } + +private: + bool val; +}; + +#ifdef __cpp_lib_ranges +// Wraps a std::random_access_iterator as a Cpp17RandomAccessIterator +// except for having an integer-like class type as difference_type. +// This one is _almost_ a real Cpp17RandomAccessIterator, except for the +// difference_type. Again, we only care that the huge distance is +// detected and std::length_error is thrown. +class Iterator +{ + using View = std::ranges::iota_view<std::size_t, std::size_t>; + using ViewIter = std::ranges::iterator_t<View>; + +public: + using iterator_category = std::random_access_iterator_tag; + using value_type = bool; + using difference_type = std::iter_difference_t<ViewIter>; + + Iterator() = default; + + explicit Iterator(ViewIter iter) : iter(iter) { } + + const bool& operator*() const { return val; } + const bool* operator->() const { return &val; } + const bool& operator[](difference_type n) const { return *(*this + n); } + + Iterator& operator++() { ++iter; return *this; } + Iterator operator++(int) { return Iterator(iter++); } + Iterator& operator--() { --iter; return *this; } + Iterator operator--(int) { return Iterator(iter--); } + + Iterator& operator+=(difference_type n) { iter += n; return *this; } + Iterator& operator-=(difference_type n) { iter -= n; return *this; } + + Iterator operator+(difference_type n) const { return Iterator(iter + n); } + Iterator operator-(difference_type n) const { return Iterator(iter - n); } + + friend Iterator operator+(difference_type n, Iterator i) { return i + n; } + difference_type operator-(Iterator i) const { return iter - i.iter; } + + bool operator==(const Iterator& i) const { return iter == i.iter; } + auto operator<=>(const Iterator& i) const { return iter <=> i.iter; } + +private: + ViewIter iter = ViewIter(); + bool val = true; +}; + +static_assert( std::random_access_iterator<Iterator> ); +#endif + +static void +test_range_ctors() +{ + try { + FakeIterator x; + std::vector<bool> v(x, x); + VERIFY(false); + } catch (const std::length_error&) { + } + +#ifdef __cpp_lib_ranges + const std::size_t min = 0, max = -8; + auto i = std::views::iota(min, max); + try { + Iterator first(std::ranges::begin(i)); + Iterator last(std::ranges::end(i)); + std::vector<bool> v(first, last); + VERIFY(false); + } catch (const std::length_error&) { + } + +#ifdef __cpp_lib_containers_ranges + try { + std::vector<bool> v(std::from_range, i); + VERIFY(false); + } catch (const std::length_error&) { + } +#endif +#endif +} + +int main() +{ + test_n_element_ctor(); + test_n_element_ctor_dispatch(); + test_range_ctors(); +} -- 2.51.0 ++++++ gcc14-pr124370.patch ++++++ >From 3a1e569268c866369a66173d1959cee50aef340d Mon Sep 17 00:00:00 2001 From: Richard Biener <[email protected]> Date: Thu, 1 Oct 2026 22:50:13 +0100 Subject: [PATCH] libstdc++: Fix stack corruption in std::bitset stream extraction [PR124370] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To: [email protected] From: Jonathan Wakely <[email protected]> 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 <[email protected]> (cherry picked from commit 5d419c69ce2e6b86d7da75f18736904885674219) --- libstdc++-v3/include/std/bitset | 25 ++++++------ .../testsuite/20_util/bitset/io/input.cc | 2 + .../testsuite/20_util/bitset/io/wchar_t.cc | 39 +++++++++++++++++++ 3 files changed, 54 insertions(+), 12 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 acd5768d6f6..71beaacac32 100644 --- a/libstdc++-v3/include/std/bitset +++ b/libstdc++-v3/include/std/bitset @@ -1596,26 +1596,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef std::basic_istream<_CharT, _Traits> __istream_type; typedef typename __istream_type::ios_base __ios_base; + 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) { } + _Buffer() : _M_ptr(_M_local) + { + if _GLIBCXX17_CONSTEXPR (!__use_local) + _M_ptr = new _CharT[_Nb]; + } ~_Buffer() { - if _GLIBCXX17_CONSTEXPR (!_S_use_alloca()) + if _GLIBCXX17_CONSTEXPR (!__use_local) delete[] _M_ptr; } - _CharT* const _M_ptr; - }; - _CharT* __ptr; - if _GLIBCXX17_CONSTEXPR (_Buffer::_S_use_alloca()) - __ptr = (_CharT*)__builtin_alloca(_Nb); - else - __ptr = new _CharT[_Nb]; - const _Buffer __buf(__ptr); + _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 diff --git a/libstdc++-v3/testsuite/20_util/bitset/io/input.cc b/libstdc++-v3/testsuite/20_util/bitset/io/input.cc index de0ea07e56a..6b11bf0e487 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 00000000000..6c7c496daa1 --- /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.51.0 ++++++ gcc14-pr127656.patch ++++++ >From 1d1b3c2f214345a98570ed6b095b8df305db2363 Mon Sep 17 00:00:00 2001 From: Richard Biener <[email protected]> Date: Fri, 25 Sep 2026 18:14:34 +0100 Subject: [PATCH] libstdc++: Fix use-after-free in pbds binary heap (CVE-2026-102010) [PR127656] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To: [email protected] From: Jonathan Wakely <[email protected]> After reallocating the storage the m_a_entries pointer is left dangling and the new storage is leaked. libstdc++-v3/ChangeLog: PR libstdc++/127656 * include/ext/pb_ds/detail/binary_heap_/erase_fn_imps.hpp (erase_if): Update m_a_entries after reallocation. * testsuite/ext/pb_ds/regression/priority_queues_erase_if.cc: New test. Reviewed-by: Tomasz Kamiński <[email protected]> (cherry picked from commit aaa8351f4d2e636f9680a1f0a8ebc2f0a60611e6) --- .../detail/binary_heap_/erase_fn_imps.hpp | 1 + .../regression/priority_queues_erase_if.cc | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 libstdc++-v3/testsuite/ext/pb_ds/regression/priority_queues_erase_if.cc diff --git a/libstdc++-v3/include/ext/pb_ds/detail/binary_heap_/erase_fn_imps.hpp b/libstdc++-v3/include/ext/pb_ds/detail/binary_heap_/erase_fn_imps.hpp index 8710b40ea01..fc20db4d67c 100644 --- a/libstdc++-v3/include/ext/pb_ds/detail/binary_heap_/erase_fn_imps.hpp +++ b/libstdc++-v3/include/ext/pb_ds/detail/binary_heap_/erase_fn_imps.hpp @@ -121,6 +121,7 @@ erase_if(Pred pred) entry_pointer new_entries = s_entry_allocator.allocate(new_size); std::copy(m_a_entries, m_a_entries + left, new_entries); s_entry_allocator.deallocate(m_a_entries, m_actual_size); + m_a_entries = new_entries; m_actual_size = new_size; resize_policy::notify_arbitrary(m_actual_size); } diff --git a/libstdc++-v3/testsuite/ext/pb_ds/regression/priority_queues_erase_if.cc b/libstdc++-v3/testsuite/ext/pb_ds/regression/priority_queues_erase_if.cc new file mode 100644 index 00000000000..30b8452eff9 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/pb_ds/regression/priority_queues_erase_if.cc @@ -0,0 +1,19 @@ +// { dg-do run } + +// CVE-2026-201020 use-after-free in binary heap erase_if + +#include <ext/pb_ds/priority_queue.hpp> + +bool is_odd(int v) { return v & 1; } + +int main() +{ + using __gnu_pbds::priority_queue; + using __gnu_pbds::binary_heap_tag; + priority_queue<int, std::less<int>, binary_heap_tag> q; + q.push(1); + q.push(2); + q.push(3); + q.erase_if(&is_odd); + q.clear(); +} -- 2.51.0 ++++++ gcc14-pr127666.patch ++++++ >From f0cba688b7b5a68819e7d1c9af97fcf22b24fdfd Mon Sep 17 00:00:00 2001 From: Richard Biener <[email protected]> Date: Thu, 1 Oct 2026 17:39:33 +0100 Subject: [PATCH] libstdc++: Fix std::from_chars to not read past end of input [PR127666] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To: [email protected] From: Jonathan Wakely <[email protected]> The bug report points out one out-of-bounds read and the second was found by an LLM. The testcase was generated by an LLM. The code fixes are artisanal handwritten code. Assisted-by: LLM libstdc++-v3/ChangeLog: PR libstdc++/127666 * src/c++17/floating_from_chars.cc (pattern): Avoid reading past the end of the input. Remove unused variable. * testsuite/20_util/from_chars/127666.cc: New test. Reviewed-by: Tomasz Kamiński <[email protected]> (cherry picked from commit 524847fec983eaedca147840ce46fcbb0cd38952) --- libstdc++-v3/src/c++17/floating_from_chars.cc | 9 ++- .../testsuite/20_util/from_chars/127666.cc | 70 +++++++++++++++++++ 2 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 libstdc++-v3/testsuite/20_util/from_chars/127666.cc diff --git a/libstdc++-v3/src/c++17/floating_from_chars.cc b/libstdc++-v3/src/c++17/floating_from_chars.cc index b3061bdca01..5e3e183680f 100644 --- a/libstdc++-v3/src/c++17/floating_from_chars.cc +++ b/libstdc++-v3/src/c++17/floating_from_chars.cc @@ -452,13 +452,16 @@ namespace // fmt has the value of one of the enumerators of chars_format. __glibcxx_assert(valid_fmt(fmt)); - string_view res; - + // Fail if the input is empty or starts with '+' if (first == last || *first == '+') [[unlikely]] return nullptr; const int neg = (*first == '-'); + // Fail if the input consists of a lone '-' + if (first + neg == last) + return nullptr; + if (std::memchr("iInN", (unsigned char)first[neg], 4)) { ptrdiff_t len = last - first; @@ -490,7 +493,7 @@ namespace else // Only need 4 chars for "-NAN" len = neg + 3; - buf.assign(first, 0, len); + buf.assign(first, len); // prevent make_result correcting for "0x" fmt = chars_format::general; return buf.c_str(); diff --git a/libstdc++-v3/testsuite/20_util/from_chars/127666.cc b/libstdc++-v3/testsuite/20_util/from_chars/127666.cc new file mode 100644 index 00000000000..25989f2cfee --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/from_chars/127666.cc @@ -0,0 +1,70 @@ +// { dg-do run { target c++17 } } +// { dg-require-effective-target mmap } +// { dg-require-effective-target sysconf } +// { dg-add-options ieee } +// { dg-additional-options "-DSKIP_LONG_DOUBLE" { target aarch64-*-rtems* aarch64-*-vxworks* x86_64-*-vxworks* } } + +// Bug 127666 +// std::from_chars(first, last, long double&) reads past 'last' for "inf"/"nan" + +#include <charconv> +#include <string_view> +#include <cstring> +#include <sys/mman.h> +#include <unistd.h> +#include <testsuite_hooks.h> + +using namespace std::string_view_literals; + +// One past the last writable byte; the guard page starts here, so reading +// at or beyond this address faults. +static char* buf_end; + +template<typename T> +void +check(std::string_view input, std::errc ec, std::size_t len) +{ + // Position the input against the guard page so an over-read faults. + char* const first = buf_end - input.size(); + std::memcpy(first, input.data(), input.size()); + T value = 1; + auto res = std::from_chars(first, buf_end, value); + VERIFY( res.ec == ec ); + VERIFY( res.ptr == first + len ); +} + +template<typename T> +void +test_type() +{ + // The inf/nan forms used to read past the end via strlen. + check<T>("inf"sv, std::errc{}, 3); + check<T>("infinity"sv, std::errc{}, 8); + check<T>("nan"sv, std::errc{}, 3); + check<T>("nan(1)"sv, std::errc{}, 6); + check<T>("-nan(ab)"sv, std::errc{}, 8); + + // A lone sign used to read one byte past the end. + check<T>("-"sv, std::errc::invalid_argument, 0); + check<T>("+"sv, std::errc::invalid_argument, 0); +} + +int +main() +{ + const long pg = ::sysconf(_SC_PAGESIZE); + VERIFY( pg > 0 ); + char* const base = (char*) ::mmap(nullptr, 2 * pg, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + VERIFY( base != MAP_FAILED ); + VERIFY( ::mprotect(base + pg, pg, PROT_NONE) == 0 ); + buf_end = base + pg; + + test_type<float>(); + test_type<double>(); +#ifndef SKIP_LONG_DOUBLE + test_type<long double>(); +#endif + + ::munmap(base, 2 * pg); +} -- 2.51.0
