[PATCH] libiberty: fix resource exhaustion in rust demangler (PR 33878)
Andrew Pinski
andrew.pinski@oss.qualcomm.com
Thu Feb 26 17:51:44 GMT 2026
On Thu, Feb 26, 2026 at 8:27 AM Ruslan Valiyev <linuxoid@gmail.com> wrote:
>
> demangle_binder() parses the bound_lifetimes count as a base-62
> integer with no upper bound. A crafted symbol can encode a huge
> lifetime count in very few bytes, causing OOM or CPU hang.
>
> Cap bound_lifetimes at 1024 and check rdm->errored in the loop
> so it bails out early on errors during iteration.
First thanks for this patch.
Second I think this is also GCC PR 106641
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106641). Can you double
check?
>
> libiberty/ChangeLog:
>
> PR binutils/33878
Currently only GCC bug #s can go into this changelog like this. This
is why I pointed to PR 106641.
If it is that bug report, please replace the above with `PR demangler/106641`.
> * rust-demangle.c (demangle_binder): Reject bound_lifetimes
> above 1024 to prevent resource exhaustion from crafted symbols.
> Add rdm->errored check in the loop condition.
> * testsuite/rust-demangle-expected: Add regression test.
>
> Signed-off-by: Ruslan Valiyev <linuxoid@gmail.com>
> ---
> libiberty/rust-demangle.c | 9 ++++++++-
> libiberty/testsuite/rust-demangle-expected | 6 ++++++
> 2 files changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/libiberty/rust-demangle.c b/libiberty/rust-demangle.c
> index 19070999654..2995333a3cf 100644
> --- a/libiberty/rust-demangle.c
> +++ b/libiberty/rust-demangle.c
> @@ -651,10 +651,17 @@ demangle_binder (struct rust_demangler *rdm)
> return;
>
> bound_lifetimes = parse_opt_integer_62 (rdm, 'G');
> + /* Reject implausibly large lifetime counts to prevent
> + resource exhaustion from crafted symbols (PR 33878). */
> + if (bound_lifetimes > 1024)
> + {
> + rdm->errored = 1;
> + return;
> + }
> if (bound_lifetimes > 0)
> {
> PRINT ("for<");
> - for (i = 0; i < bound_lifetimes; i++)
> + for (i = 0; i < bound_lifetimes && !rdm->errored; i++)
> {
> if (i > 0)
> PRINT (", ");
> diff --git a/libiberty/testsuite/rust-demangle-expected b/libiberty/testsuite/rust-demangle-expected
> index b565084cfef..d1eecb826ef 100644
> --- a/libiberty/testsuite/rust-demangle-expected
> +++ b/libiberty/testsuite/rust-demangle-expected
> @@ -321,3 +321,9 @@ foo
> --format=rust
> _RNvC9backtrace3foo.llvm.A5310EB9
> backtrace::foo
> +#
> +# PR binutils/33878: crafted symbol with huge lifetime count
Likewise here with the GCC PR #.
Otherwise, ok. Do you have write access to GCC and binutils git or do
you need someone to push it for you?
Thanks,
Andrew
> +# should not cause resource exhaustion.
> +--format=rust
> +_RINvC4te_C4tokpppppppppppFFFFFFGFpppppppppKj2_FFFFFFFFFFFFFE
> +_RINvC4te_C4tokpppppppppppFFFFFFGFpppppppppKj2_FFFFFFFFFFFFFE
> --
> 2.43.0
>
More information about the Binutils
mailing list