Summary: Stack-based buffer overflow in libiberty C++ demangler via unbounded VLA allocation when DMGL_NO_RECURSE_LIMIT flag is set Requirements to exploit: 1. Target application requirements: The target application must link against libiberty and call one of the vulnerable demangling functions: cplus_demangle_v3(), cplus_demangle(), or __cxa_demangle() The application must pass the DMGL_NO_RECURSE_LIMIT flag (0x40000 or 1 << 18) in the options parameter Without this flag, a built-in guard rejects symbols that would cause excessive stack allocation 2. Attacker capabilities: The attacker must be able to supply a crafted mangled C++ symbol name to the vulnerable application The malicious symbol must be at least ~111,000 characters to exceed the default 8 MB stack limit (72 bytes per character of stack allocation) The symbol must begin with "_Z" (Itanium C++ ABI mangling prefix) to reach the vulnerable code path 3. Common attack vectors: Malicious ELF object files: Symbol names in .symtab or .dynsym sections are demangled by nm, objdump, addr2line, and readelf Malicious PE/COFF files: Windows binaries processed by cross-platform binutils tools Malicious Mach-O files: macOS binaries with crafted symbol tables Direct input: c++filt reads symbol names from stdin or command-line arguments Debug information: DWARF debug info containing mangled names Core dumps: Post-mortem analysis tools demangling symbols from crashed processes 4. Affected tools (when compiled with DMGL_NO_RECURSE_LIMIT): c++filt: Historically used DMGL_NO_RECURSE_LIMIT as default nm: Demangles symbols when displaying symbol tables objdump: Demangles symbols in disassembly output addr2line: Demangles function names in stack traces readelf: Demangles symbols in ELF analysis GDB: Uses libiberty for C++ symbol demangling Custom applications: Any software using libiberty's demangler API 5. Exploitation constraints: The attacker does NOT need code execution - only the ability to provide a crafted input file or string No authentication or privileges required User interaction required (victim must process the malicious input) The vulnerability triggers during stack allocation, before any parsing, so the symbol content after "_Z" is irrelevant Component affected: libiberty (cp-demangle.c) Version affected: All versions (vulnerability exists in current trunk) Patch available: yes Proposed patch: — a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -6876,8 +6876,7 @@ d_demangle_callback (const char *mangled, int options, /* PR 87675 - Check for a mangled string that is so long that we do not have enough stack space to demangle it. */ if (((options & DMGL_NO_RECURSE_LIMIT) == 0) /* This check is a bit arbitrary, since what we really want to do is to + if (/* This check is a bit arbitrary, since what we really want to do is to compare the sizes of the di.comps and di.subs arrays against the amount of stack space remaining. But there is no portable way to do this, so instead we use the recursion limit as a guide to the maximum This patch removes the DMGL_NO_RECURSE_LIMIT bypass from the stack size guard, making the check unconditional. The flag's intended purpose is to disable recursion depth limits during parsing, not to allow unbounded stack allocations before parsing begins. Version fixed (if any already): N/A CVSS: 6.2 (Medium) - CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H Based on: Local attack vector (requires processing malicious file), low complexity, no privileges required, user interaction required (user must run tool on malicious input), no confidentiality/integrity impact, high availability impact (crash/DoS). Impact: Moderate. The vulnerability causes a denial of service (application crash) when processing maliciously crafted symbol names. On systems without stack guard pages, there is potential for arbitrary write via stack pivot, which could elevate this to Important. Embargo: no Reason: This is a moderate severity DoS vulnerability with straightforward mitigation (avoid DMGL_NO_RECURSE_LIMIT flag or validate symbol length before demangling). Minimal delay to public disclosure is appropriate. Acknowledgement: Nathaniel Oh (@calysteon) Steps to reproduce: Prerequisites: GCC compiler with AddressSanitizer support GCC/binutils source tree (tested on trunk as of February 2026) Step 1: Clone or obtain the GCC source tree git clone git://gcc.gnu.org/git/gcc.git cd gcc Step 2: Build libiberty with AddressSanitizer instrumentation cd libiberty make clean CFLAGS="-fsanitize=address -g -O0" ./configure make -j$(nproc) cd .. Step 3: Save the proof-of-concept code to poc_demangler_stack_overflow.c (See "Proof-of-concept source code" section below) Step 4: Compile the proof-of-concept gcc -fsanitize=address -g -O0 \ -I include -I libiberty \ poc_demangler_stack_overflow.c libiberty/libiberty.a \ -o poc_demangler_stack_overflow Step 5: Run the proof-of-concept ./poc_demangler_stack_overflow Step 6: Observe the ASan crash output Expected output: --------------------------------------------------------------- Symbol length : 200002 bytes Estimated VLA : 25.9 MB on stack Calling cplus_demangle_v3(..., DMGL_NO_RECURSE_LIMIT) AddressSanitizer:DEADLYSIGNAL ================================================================= ==PID==ERROR: AddressSanitizer: stack-overflow on address 0x... #0 ... in __asan_alloca_poison #1 ... in d_demangle cp-demangle.c:6967 #2 ... in cplus_demangle_v3 cp-demangle.c:7124 #3 ... in main poc_demangler_stack_overflow.c:92 SUMMARY: AddressSanitizer: stack-overflow cp-demangle.c:6967 in d_demangle ==PID==ABORTING --------------------------------------------------------------- Mitigation: For application developers using libiberty: 1. Do not use the DMGL_NO_RECURSE_LIMIT flag unless absolutely necessary. 2. If DMGL_NO_RECURSE_LIMIT is required, validate input symbol length before calling demangling functions: #define MAX_SAFE_SYMBOL_LEN 1024 if (strlen(symbol) > MAX_SAFE_SYMBOL_LEN) { // Reject or truncate the symbol return NULL; } result = cplus_demangle_v3(symbol, options | DMGL_NO_RECURSE_LIMIT); 3. Consider using setrlimit(RLIMIT_STACK, ...) to increase stack size if processing untrusted symbols is unavoidable (not recommended for security-sensitive contexts). For library maintainers: Apply the proposed patch above to remove the DMGL_NO_RECURSE_LIMIT bypass from the stack size guard.
This is a bogus CVE, compiler (and linker) crashes may be bugs but they're not security issues. Please see the security policies of the projects for information: https://gcc.gnu.org/git/?p=gcc.git;a=blob_plain;f=SECURITY.txt https://sourceware.org/git/?p=binutils-gdb.git;a=blob_plain;f=binutils/SECURITY.txt;hb=HEAD