A flaw was found in GCC. When an application calls the eraseif function on a binary heap priority queue in libstdc++, the library reallocates storage but fails to update its internal entry pointer. An attacker capable of triggering this operation can exploit this use-after-free condition, leading to a Denial of Service (DoS) via an application crash or potential memory corruption.
AIONLYREPORT package: gcc-toolset-15-gcc-15.2.1-7.el10 ------ Summary: gnupbds::detail::binaryheap::eraseif use-after-free and stale-pointer free in reallocation path: calling eraseif on a binaryheaptag-backed pbds priority queue can leave the internal entry-array pointer dangling, leading to heap use-after-free during makeheap() and a later stale-pointer free during cleanup. Requirements to exploit: An attacker needs a path to make an application built from this SRPM instantiate gnupbds::priorityqueue<..., binaryheaptag> and call eraseif; once that public API path is exercised, subsequent heap operations or object teardown can act on freed storage. Component affected: gcc-toolset-15-gcc-15.2.1-7.el10, libstdc++-v3/include/ext/pbds/detail/binaryheap/erasefnimps.hpp, gnupbds::detail::binaryheap::eraseif Version affected: gcc-toolset-15-gcc-15.2.1-7.el10 Patch available: no released package fix established; proposed patch included below Version fixed: unknown Upstream coordination: Not notified. CVSS: CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:H - 7.8 (HIGH) AV:L - Exploitation requires reaching this local library API in a process using the affected pbds container path. AC:L - Once binaryheaptag and eraseif are in use, the vulnerable sequence is straightforward to trigger. PR:N - No privileges are required beyond reaching the affected call path in the target process. UI:N - No separate user interaction is required. S:U - The resulting corruption stays within the security scope of the calling process. C:L - In-process memory misuse could expose some data, but broader disclosure is not established here. I:L - Heap corruption can alter in-process state, but arbitrary code execution is not demonstrated by the available evidence. A:H - Use-after-free and stale-pointer free conditions are likely to crash or seriously destabilize the affected process. Impact: Moderate. This is a real memory-corruption flaw with likely process-level availability impact and some in-process integrity or confidentiality risk, but exploitability is limited to consumers that opt into the pbds binaryheaptag backend and invoke eraseif on that path. Under Red Hat's severity guidance, that narrower, non-default reachability fits Moderate more closely than Important or Critical. Embargo: no Reason: The issue is local and API-specific, with no evidence of default remote exposure in the shipped package. Public coordination without extended embargo is proportionate unless a broadly exposed consumer of this path is identified. Acknowledgement: Aisle Research Vulnerability Details: The pbds binary heap backend reallocates the entry array inside eraseif, but does not update maentries to the new allocation before continuing. The vulnerable block is: cpp const sizetype newsize = resizepolicy::getnewsizeforarbitrary(left); entrypointer newentries = sentryallocator.allocate(newsize); std::copy(maentries, maentries + left, newentries); sentryallocator.deallocate(maentries, mactualsize); mactualsize = newsize; resizepolicy::notifyarbitrary(mactualsize); After that, eraseif rebuilds the heap: cpp msize = left; makeheap(); makeheap() uses maentries directly: cpp entrypointer end = maentries + msize; std::makeheap(maentries, end, mcmp); Because maentries = newentries; is missing, makeheap() operates on freed storage after successful reallocation. Later cleanup may deallocate the stale maentries again, leading to an invalid free or double-free condition. Nearby reallocation paths in the same component do update maentries, which supports that this omission is unintended. Steps to reproduce: 1. Build a small C++ test with AddressSanitizer enabled and use pbds priorityqueue with binaryheaptag. 2. Insert enough elements to force dynamic storage growth. 3. Call eraseif with a predicate that removes entries. 4. Continue heap activity, or allow the object to destruct. 5. Observe invalid memory behavior, typically a use-after-free during heap repair and potentially an invalid free during teardown. Minimal PoC: cpp #include <ext/pbds/priorityqueue.hpp> using namespace gnupbds; int main() { priorityqueue<int, std::less<int>, binaryheaptag> q; for (int i = 0; i < 1000; ++i) q.push; q.eraseif( { return (v % 2) == 0; }); q.push(42); q.pop(); } Mitigation: Until a fixed package is available, avoid calling eraseif on gnupbds::priorityqueue instances that use binaryheaptag in code built from this SRPM. If predicate-based removal is required, use an alternative container or backend, or rebuild with the patch below applied. Proposed Fix: Store the replacement entry array in maentries before freeing the old array, and copy from the saved old pointer. diff diff --git a/libstdc++-v3/include/ext/pbds/detail/binaryheap/erasefnimps.hpp b/libstdc++-v3/include/ext/pbds/detail/binaryheap/erasefnimps.hpp @@ -118,9 +118,11 @@ PBDSCLASSCDEC::eraseif(Pred pred) const sizetype newsize = resizepolicy::getnewsizeforarbitrary(left); + entrypointer oldentries = maentries; entrypointer newentries = sentryallocator.allocate(newsize); std::copy(maentries, maentries + left, newentries);
sentryallocator.deallocate(maentries, mactualsize); + std::copy(oldentries, oldentries + left, newentries); + maentries = newentries; + sentryallocator.deallocate(oldentries, mactualsize); mactualsize = newsize; resizepolicy::notifyarbitrary(mactualsize);
------ This report was generated using AI technology. Always review AI-generated content prior to use