1
Fork 0
forked from gcc/gcc
TEST repository for https://forge.sourceware.org/ experimenting.
  • C++ 30.7%
  • C 30.2%
  • Ada 14.3%
  • D 6.1%
  • Go 5.7%
  • Other 12.5%
Find a file
Andrew Burgess bc4d9b6aeb libiberty: avoid exponential back reference issue in D demangler
We had a bug reported against Fedora GDB where a particular D symbol
was causing an out of memory error.  I believe that the symbol is
valid (see below for details), but I'm not sure if it is possible to
successfully demangle it, so this patch aims to avoid the out of
memory error.

The symbol in question can be found in the newly added test case.

The symbol in question makes heavy use of back references to compress
the demangled string.  The back references are nested to ~57 levels of
depth, but that's not the real problem.  The real issue is that many
of these nested levels of back reference refer, multiple times, to the
earlier levels.  If the innermost level of back reference results in a
1 byte string (it doesn't, the resulting string is longer), and each
level of back reference refers to the next inner level just twice
(it's usually more), then by 30 levels the resulting string is 1G in
size.  This is an absolute lower bound of the required size.  By 40
levels we have, at a minimum, a 1024G string.

My plan for fixing this is to count nested back references, resetting
the counter at the "top level", i.e. at a nesting depth of 0.  If we
see too many (based on some arbitrary limit) nested back references,
then we'll abort the demangle, and return NULL.

Now, this isn't purely a recursion problem.  The theoretical maximum
depth is just 57, but the problem is the cumulative work that ends up
being done due to the exponential growth of each level referencing the
earlier levels.

However, I wanted to avoid adding a separate flag for this to the
demangler, and I figured that this problem is close enough to
recursion that we can reuse the existing recursion limit flag here
too.

And so, the solution I propose is that each time we encounter a nested
back reference we increment a counter.  If we see more than
DEMANGLE_RECURSION_LIMIT nested back references then we abort the
demangle, even if these back references are not all nested one inside
the other.  A second counter tracks the current depth of nested back
references.  If we are at depth 0 then the first counter, the nested
back reference counter, is reset back to 0.

With this fix in place, when passed the problematic mangled symbol,
the demangler returns NULL.  The c++filt tool will just re-print the
mangled symbol.  The D demangler tests are extended to include the
problematic symbol.

Side note: I mentioned above that I think this symbol is valid.  To
reach this conclusion I implemented a hack where I cached the result
of evaluating a back reference.  The first time a back reference is
processed I actually processed the input to check the string demangled
correctly, but I never added this demangled string to the final
result.  The second time the same back reference is requested, I spot
the cached entry and return, again adding nothing to the result string.

Thus, the final result string contains only the content from the top
level.  None of the back referenced content is included.  The input
string (mangled) is 2695 bytes, while the output string was 42kB, but
this skips all the nested content.  However, we did get to the end of
the input string, and returned a non-NULL value.  The full string
would be multiple GB given the exponential growth.

Bug: https://bugzilla.redhat.com/show_bug.cgi?id=2368350

libiberty/ChangeLog:

	* d-demangle.c (struct dlang_info::options): New field,
	carries options passed to the demangler.
	(struct dlang_info::num_backrefs): Count total number of back
	referenced types that have been processed.
	(struct dlang_info::backref_depth): Count the depth of
	recursive back references.
	(dlang_type_backref): Track recursive back reference depth,
	and the total number of back references encountered.  Bail out
	early if the total number gets too high.
	(dlang_demangle_init_info): Initialise new 'struct dlang_info'
	fields.
	(dlang_demangle): Pass demangler options to
	dlang_demangle_init_info.
	* testsuite/d-demangle-expected: Add new test.
2026-06-07 19:25:00 +01:00
.forgejo forge: Add a prototype CODEOWNERS file 2026-06-05 17:58:58 +01:00
.github
c++tools Update copyright years. 2026-01-02 09:56:11 +01:00
config Daily bump. 2026-05-06 00:16:29 +00:00
contrib contrib: Use 'command -v' in download_prerequisites 2026-06-05 21:20:01 +01:00
fixincludes Daily bump. 2026-05-31 00:16:35 +00:00
gcc testsuite: Automatically add check_function_bodies options 2026-06-07 10:03:09 +01:00
gnattools Daily bump. 2026-05-11 00:16:22 +00:00
gotools
include Daily bump. 2026-06-02 00:16:46 +00:00
INSTALL
libada Update copyright years. 2026-01-02 09:56:11 +01:00
libatomic Daily bump. 2026-06-02 00:16:46 +00:00
libbacktrace Daily bump. 2026-06-04 08:18:58 +00:00
libcc1 Daily bump. 2026-01-16 00:16:30 +00:00
libcody Daily bump. 2026-05-31 00:16:35 +00:00
libcpp Daily bump. 2026-05-31 00:16:35 +00:00
libdecnumber Daily bump. 2026-05-31 00:16:35 +00:00
libffi Daily bump. 2026-05-27 00:16:33 +00:00
libga68 Daily bump. 2026-05-31 00:16:35 +00:00
libgcc Daily bump. 2026-06-02 00:16:46 +00:00
libgcobol cobol: Properly DISPLAY COMP-1/-2 variables when "-dialect ibm" is in effect. [PR125616] 2026-06-05 15:06:07 -04:00
libgfortran Daily bump. 2026-05-31 00:16:35 +00:00
libgm2 Daily bump. 2026-06-02 00:16:46 +00:00
libgo libgo: cmd/go: use 'gcloud storage cp' instead of 'gsutil cp' 2026-05-02 16:21:35 -07:00
libgomp openmp, fortran: Add support for iterators in OpenMP 'target update' constructs (Fortran) 2026-06-07 01:51:46 +00:00
libgrust Update copyright years. 2026-01-02 09:56:11 +01:00
libiberty libiberty: avoid exponential back reference issue in D demangler 2026-06-07 19:25:00 +01:00
libitm Daily bump. 2026-06-02 00:16:46 +00:00
libobjc Update copyright years. 2026-01-02 09:56:11 +01:00
libphobos Daily bump. 2026-04-22 00:16:28 +00:00
libquadmath Daily bump. 2026-05-31 00:16:35 +00:00
libsanitizer Daily bump. 2026-06-04 08:18:58 +00:00
libssp Daily bump. 2026-05-06 00:16:29 +00:00
libstdc++-v3 libstdc++: avoid ill-formed nested generator 2026-06-05 19:52:44 +08:00
libvtv Daily bump. 2026-05-31 00:16:35 +00:00
lto-plugin Daily bump. 2026-05-31 00:16:35 +00:00
maintainer-scripts Daily bump. 2026-04-23 00:16:32 +00:00
zlib Daily bump. 2025-12-30 00:16:33 +00:00
.b4-config Add config file so b4 uses inbox.sourceware.org automatically 2024-07-28 11:13:16 +01:00
.dir-locals.el dir-locals: apply our C settings in C++ also 2024-07-31 20:38:27 +02:00
.editorconfig Configure EditorConfig for Git commit messages 2026-05-15 23:32:16 +00:00
.gitattributes
.gitignore Rust: Move 'libformat_parser' build into the GCC build directory 2025-08-05 16:36:43 +02:00
ABOUT-NLS
ar-lib
ChangeLog Daily bump. 2026-06-04 08:18:58 +00:00
ChangeLog.jit
ChangeLog.tree-ssa
compile
config-ml.in toplevel: Unbreak Ada build [PR123490] 2026-01-10 11:36:25 +01:00
config.guess
config.rpath
config.sub
configure [PATCH v2 2/2] build: Set default for CPP_FOR_BUILD environment variable in all cases. 2026-05-01 11:39:05 -06:00
configure.ac [PATCH v2 2/2] build: Set default for CPP_FOR_BUILD environment variable in all cases. 2026-05-01 11:39:05 -06:00
COPYING
COPYING.LIB
COPYING.RUNTIME
COPYING3
COPYING3.LIB
depcomp
install-sh
libtool-ldflags
libtool.m4 build: Cherry-pick libtool.m4 support for GNU ld *_sol2 emulations 2025-12-29 12:09:35 +01:00
ltgcc.m4
ltmain.sh ltmain.sh: allow more flags at link-time 2024-09-25 19:05:24 +01:00
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4
MAINTAINERS MAINTAINERS: Add missing account names 2026-06-03 17:10:53 +01:00
Makefile.def toplevel: Fix typos in build files 2026-05-30 19:49:31 +05:30
Makefile.in toplevel: Fix typos in build files 2026-05-30 19:49:31 +05:30
Makefile.tpl toplevel: Fix typos in build files 2026-05-30 19:49:31 +05:30
missing
mkdep
mkinstalldirs
move-if-change
multilib.am
README
SECURITY.txt a68: top-level misc files 2025-11-30 01:52:24 +01:00
symlink-tree bugzilla: remove gcc-bugs@ mailing list address 2026-01-09 11:10:38 +01:00
test-driver
ylwrap

This directory contains the GNU Compiler Collection (GCC).

The GNU Compiler Collection is free software.  See the files whose
names start with COPYING for copying permission.  The manuals, and
some of the runtime libraries, are under different terms; see the
individual source files for details.

The directory INSTALL contains copies of the installation information
as HTML and plain text.  The source of this information is
gcc/doc/install.texi.  The installation information includes details
of what is included in the GCC sources and what files GCC installs.

See the file gcc/doc/gcc.texi (together with other files that it
includes) for usage and porting information.  An online readable
version of the manual is in the files gcc/doc/gcc.info*.

See http://gcc.gnu.org/bugs/ for how to report bugs usefully.

Copyright years on GCC source files may be listed using range
notation, e.g., 1987-2012, indicating that every year in the range,
inclusive, is a copyrightable year that could otherwise be listed
individually.