NationalSecurityAgency/ghidra · critical
%s: %s
Error message
%s: %s
What it means
cplus-dem's fatal(str) prints '<program_name>: <str>' to stderr and calls exit(1). It is the library's unrecoverable-error path; the one in-tree caller shown is xmalloc, which calls fatal("virtual memory exhausted") when malloc returns 0. So in practice this message means an allocation failed and the process is terminating immediately.
Solutions
- Run the demangler under a memory limit (ulimit -v, or container cgroup) to bound exposure, then reject inputs that exceed it.
- Inspect/sanitize the input mangled name for pathological patterns before demangling (size caps, depth caps).
- Increase available memory / reduce concurrent load if the host is genuinely constrained.
- Update the demangler/libiberty; some historical unbounded-allocation bugs in demangling are fixed in newer versions.
Example fix
// before - run demangler on unbounded untrusted input $ cat huge_symbols.txt | while read s; do c++filt "$s"; done // after - cap per-invocation memory and input size $ ulimit -v 262144 # 256 MB virtual cap $ awk 'length($0) < 4096' huge_symbols.txt | while read s; do c++filt "$s"; done
Defensive patterns
Strategy: fallback
Validate before calling
// Cap per-invocation memory and input size before demangling
// (shell) ulimit -v 262144 # 256 MB
// (input gate) skip lines longer than a safe bound before piping to the demangler
if (strlen(mangled) > MAX_SAFE_NAME) { /* skip or truncate */ } Type guard
boolean isPlausiblySafeInput(String s) {
return s != null && s.length() < 4096 && s.chars().filter(c -> c == 'N').count() < 1000; // crude depth/size guard
} Try / catch
// fatal() calls exit(1); cannot be caught inside the demangler process.
// Run it as a child and treat non-zero exit / 'virtual memory exhausted' as a hard reject:
int rc = run_child_with_limits({"c++filt", symbol}, memLimitBytes);
if (rc != 0) {
/* skip this symbol; treat as untrusted/pathological */
} Prevention
- Run the demangler under a memory cap (ulimit -v or container cgroup).
- Cap input name length and template-nesting depth before demangling.
- Process untrusted symbol streams one-at-a-time so one bad input cannot abort a batch.
- Keep the demangler/libiberty updated to pick up allocation-bug fixes.
When it happens
Trigger: Any allocation inside the demangler (xmalloc/xrealloc family) returning NULL/0, which routes to fatal(). With the standard caller this means the process ran out of memory while demangling (e.g. an adversarial/pathological mangled name causing huge allocation, or the host is genuinely OOM).
Common situations: Processing an extremely large or pathological mangled name that triggers a huge allocation; running the demangler on an untrusted input stream without memory limits; host under memory pressure or container memory cgroup hit; a bug causing unbounded allocation.
Related errors
- All trace memory is initialized
- At file ' ': Abnormal termination of 'pdb.exe' process.
- Attempt to create existing memory
- Byte arrays cannot exceed length of variable
- Cannot convert ' ' to address
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/17530a535a2dc17d.
Report an issue: GitHub.
Appendix: source
Thrown at GPL/DemanglerGnu/src/demangler_gnu_v2_24/c/cplus-dem.c:5303
fflush (stdout);
}
if (c == EOF)
break;
putchar (c);
if (c == '\n')
fflush (stdout);
}
}
return (0);
}
static void
fatal (str)
const char *str;
{
fprintf (stderr, "%s: %s\n", program_name, str);
exit (1);
}
PTR
xmalloc (size)
size_t size;
{
register PTR value = (PTR) malloc (size);
if (value == 0)
fatal ("virtual memory exhausted");
return value;
}
PTR
xrealloc (ptr, size)
PTR ptr;
size_t size;
{View on GitHub (pinned to d5f144c24d)