[binutils-gdb] libiberty: fix resource exhaustion in rust demangler (PR demangler/106641)

Alan Modra via Binutils-cvs <[email protected]>
Newsgroups gmane.comp.gnu.binutils.cvs
Message-ID <20260308220505.060BE4BA2E13__34656.7340706073$1773007513$gmane$org@sourceware.org>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=74b48014179ed612ed0ea6ee4abf3b2102ef764d

commit 74b48014179ed612ed0ea6ee4abf3b2102ef764d
Author: Ruslan Valiyev <[email protected]>
Date:   Thu Feb 26 19:15:06 2026 +0000

    libiberty: fix resource exhaustion in rust demangler (PR demangler/106641)
    
    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.
    
    libiberty/ChangeLog:
    
            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 <[email protected]>

Diff:
---
 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..013f14eebac 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 demangler/106641).  */
+  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..acadf7c9b83 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 demangler/106641: crafted symbol with huge lifetime count
+# should not cause resource exhaustion.
+--format=rust
+_RINvC4te_C4tokpppppppppppFFFFFFGFpppppppppKj2_FFFFFFFFFFFFFE
+_RINvC4te_C4tokpppppppppppFFFFFFGFpppppppppKj2_FFFFFFFFFFFFFE
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.