From: Nick Clifton Date: Thu, 15 Jul 2021 15:51:56 +0000 (+0100) Subject: Fix a stack exhaustion problem in the Rust demangling code in the libiberty library. X-Git-Tag: binutils-2_37~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=25162c795b1a2becf936bb3581d86a307ea491eb;p=thirdparty%2Fbinutils-gdb.git Fix a stack exhaustion problem in the Rust demangling code in the libiberty library. PR 99935 * rust-demangle.c: Add recursion limit. --- diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index bc1b35b97c4..8e39fd28eba 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,8 @@ +2021-07-15 Nick Clifton + + PR 99935 + * rust-demangle.c: Add recursion limit. + 2021-07-05 Nick Clifton Reapply this change from commit: diff --git a/libiberty/rust-demangle.c b/libiberty/rust-demangle.c index 449941b56dc..df09b7b8fdd 100644 --- a/libiberty/rust-demangle.c +++ b/libiberty/rust-demangle.c @@ -74,6 +74,12 @@ struct rust_demangler /* Rust mangling version, with legacy mangling being -1. */ int version; + /* Recursion depth. */ + uint recursion; + /* Maximum number of times demangle_path may be called recursively. */ +#define RUST_MAX_RECURSION_COUNT 1024 +#define RUST_NO_RECURSION_LIMIT ((uint) -1) + uint64_t bound_lifetime_depth; }; @@ -671,6 +677,15 @@ demangle_path (struct rust_demangler *rdm, int in_value) if (rdm->errored) return; + if (rdm->recursion != RUST_NO_RECURSION_LIMIT) + { + ++ rdm->recursion; + if (rdm->recursion > RUST_MAX_RECURSION_COUNT) + /* FIXME: There ought to be a way to report + that the recursion limit has been reached. */ + goto fail_return; + } + switch (tag = next (rdm)) { case 'C': @@ -688,10 +703,7 @@ demangle_path (struct rust_demangler *rdm, int in_value) case 'N': ns = next (rdm); if (!ISLOWER (ns) && !ISUPPER (ns)) - { - rdm->errored = 1; - return; - } + goto fail_return; demangle_path (rdm, in_value); @@ -776,9 +788,15 @@ demangle_path (struct rust_demangler *rdm, int in_value) } break; default: - rdm->errored = 1; - return; + goto fail_return; } + goto pass_return; + + fail_return: + rdm->errored = 1; + pass_return: + if (rdm->recursion != RUST_NO_RECURSION_LIMIT) + -- rdm->recursion; } static void @@ -1320,6 +1338,7 @@ rust_demangle_callback (const char *mangled, int options, rdm.skipping_printing = 0; rdm.verbose = (options & DMGL_VERBOSE) != 0; rdm.version = 0; + rdm.recursion = (options & DMGL_NO_RECURSE_LIMIT) ? RUST_NO_RECURSION_LIMIT : 0; rdm.bound_lifetime_depth = 0; /* Rust symbols always start with _R (v0) or _ZN (legacy). */