diff options
author | Nick Clifton <nickc@redhat.com> | 2021-07-15 16:51:56 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2021-07-15 16:51:56 +0100 |
commit | 25162c795b1a2becf936bb3581d86a307ea491eb (patch) | |
tree | 6e56b9ec6db3a1603ac60bf52aba281647f65d44 | |
parent | eb2839e6a5dac600ca4f6f30291f4f551386ac7b (diff) | |
download | gdb-25162c795b1a2becf936bb3581d86a307ea491eb.zip gdb-25162c795b1a2becf936bb3581d86a307ea491eb.tar.gz gdb-25162c795b1a2becf936bb3581d86a307ea491eb.tar.bz2 |
Fix a stack exhaustion problem in the Rust demangling code in the libiberty library.
PR 99935
* rust-demangle.c: Add recursion limit.
-rw-r--r-- | libiberty/ChangeLog | 5 | ||||
-rw-r--r-- | libiberty/rust-demangle.c | 31 |
2 files changed, 30 insertions, 6 deletions
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index bc1b35b..8e39fd2 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,8 @@ +2021-07-15 Nick Clifton <nickc@redhat.com> + + PR 99935 + * rust-demangle.c: Add recursion limit. + 2021-07-05 Nick Clifton <nickc@redhat.com> Reapply this change from commit: diff --git a/libiberty/rust-demangle.c b/libiberty/rust-demangle.c index 449941b..df09b7b 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). */ |