Skip to content

Commit

Permalink
Import patch from mainline GCC to fix an infinite recusion in the Rus…
Browse files Browse the repository at this point in the history
…t demangler.

	PR 98886
	PR 99935
	* rust-demangle.c (struct rust_demangler): Add a recursion
	counter.
	(demangle_path): Increment/decrement the recursion counter upon
	entry and exit.  Fail if the counter exceeds a fixed limit.
	(demangle_type): Likewise.
	(rust_demangle_callback): Initialise the recursion counter,
	disabling if requested by the option flags.
  • Loading branch information
nickclifton committed Jan 31, 2022
1 parent 9ff8aa7 commit f10f861
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 6 deletions.
12 changes: 12 additions & 0 deletions libiberty/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
2022-01-31 Nick Clifton <nickc@redhat.com>

PR 98886
PR 99935
* rust-demangle.c (struct rust_demangler): Add a recursion
counter.
(demangle_path): Increment/decrement the recursion counter upon
entry and exit. Fail if the counter exceeds a fixed limit.
(demangle_type): Likewise.
(rust_demangle_callback): Initialise the recursion counter,
disabling if requested by the option flags.

2022-01-15 Martin Sebor <msebor@redhat.com>

* regex.c: Suppress -Wuse-after-free.
Expand Down
47 changes: 41 additions & 6 deletions libiberty/rust-demangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ struct rust_demangler
/* Rust mangling version, with legacy mangling being -1. */
int version;

/* Recursion depth. */
unsigned int recursion;
/* Maximum number of times demangle_path may be called recursively. */
#define RUST_MAX_RECURSION_COUNT 1024
#define RUST_NO_RECURSION_LIMIT ((unsigned int) -1)

uint64_t bound_lifetime_depth;
};

Expand Down Expand Up @@ -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':
Expand All @@ -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);

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -870,6 +888,19 @@ demangle_type (struct rust_demangler *rdm)
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. */
{
rdm->errored = 1;
-- rdm->recursion;
return;
}
}

switch (tag)
{
case 'R':
Expand Down Expand Up @@ -1030,6 +1061,9 @@ demangle_type (struct rust_demangler *rdm)
rdm->next--;
demangle_path (rdm, 0);
}

if (rdm->recursion != RUST_NO_RECURSION_LIMIT)
-- rdm->recursion;
}

/* A trait in a trait object may have some "existential projections"
Expand Down Expand Up @@ -1320,6 +1354,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). */
Expand Down

0 comments on commit f10f861

Please sign in to comment.