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%
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. |
||
|---|---|---|
| .forgejo | ||
| .github | ||
| c++tools | ||
| config | ||
| contrib | ||
| fixincludes | ||
| gcc | ||
| gnattools | ||
| gotools | ||
| include | ||
| INSTALL | ||
| libada | ||
| libatomic | ||
| libbacktrace | ||
| libcc1 | ||
| libcody | ||
| libcpp | ||
| libdecnumber | ||
| libffi | ||
| libga68 | ||
| libgcc | ||
| libgcobol | ||
| libgfortran | ||
| libgm2 | ||
| libgo | ||
| libgomp | ||
| libgrust | ||
| libiberty | ||
| libitm | ||
| libobjc | ||
| libphobos | ||
| libquadmath | ||
| libsanitizer | ||
| libssp | ||
| libstdc++-v3 | ||
| libvtv | ||
| lto-plugin | ||
| maintainer-scripts | ||
| zlib | ||
| .b4-config | ||
| .dir-locals.el | ||
| .editorconfig | ||
| .gitattributes | ||
| .gitignore | ||
| ABOUT-NLS | ||
| ar-lib | ||
| ChangeLog | ||
| ChangeLog.jit | ||
| ChangeLog.tree-ssa | ||
| compile | ||
| config-ml.in | ||
| config.guess | ||
| config.rpath | ||
| config.sub | ||
| configure | ||
| configure.ac | ||
| COPYING | ||
| COPYING.LIB | ||
| COPYING.RUNTIME | ||
| COPYING3 | ||
| COPYING3.LIB | ||
| depcomp | ||
| install-sh | ||
| libtool-ldflags | ||
| libtool.m4 | ||
| ltgcc.m4 | ||
| ltmain.sh | ||
| ltoptions.m4 | ||
| ltsugar.m4 | ||
| ltversion.m4 | ||
| lt~obsolete.m4 | ||
| MAINTAINERS | ||
| Makefile.def | ||
| Makefile.in | ||
| Makefile.tpl | ||
| missing | ||
| mkdep | ||
| mkinstalldirs | ||
| move-if-change | ||
| multilib.am | ||
| README | ||
| SECURITY.txt | ||
| symlink-tree | ||
| 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.