Avoid DoS with unnecessarily long numbers in RustSymbolParser::ParseBase62Number()

PiperOrigin-RevId: 948350914
Change-Id: I1d53894f02e6c4e87c5f2af4853a59131f66ead2
diff --git a/absl/debugging/internal/demangle_rust.cc b/absl/debugging/internal/demangle_rust.cc
index f7f6713..75c46ec 100644
--- a/absl/debugging/internal/demangle_rust.cc
+++ b/absl/debugging/internal/demangle_rust.cc
@@ -653,7 +653,15 @@
     // A nonempty digit sequence denotes its base-62 value plus 1.
     int encoded_number = 0;
     bool overflowed = false;
-    while (IsAlpha(Peek()) || IsDigit(Peek())) {
+    for (int scanned = 0; IsAlpha(Peek()) || IsDigit(Peek()); ++scanned) {
+      // Cap the scan length: a u64 fits in 11 base-62 digits, and int overflows
+      // after ~5, so anything beyond ~16 digits is already failing to parse.
+      if (scanned >= 16) {
+        // Reject pathologically long runs so a backref cannot re-scan
+        // arbitrarily long stretches of input per iteration.
+        return false;
+      }
+
       const char c = Take();
       if (encoded_number >= std::numeric_limits<int>::max()/62) {
         // If we are close to overflowing an int, keep parsing but stop updating
diff --git a/absl/debugging/internal/demangle_rust_test.cc b/absl/debugging/internal/demangle_rust_test.cc
index 8ceb1fd..110700e 100644
--- a/absl/debugging/internal/demangle_rust_test.cc
+++ b/absl/debugging/internal/demangle_rust_test.cc
@@ -176,6 +176,20 @@
       "crate_name::func_name::{closure#?}");
 }
 
+TEST(DemangleRust, Base62NumberScanLimit) {
+  // Up to 16 base-62 digits is permitted (though int overflow yields "?").
+  EXPECT_DEMANGLING(
+      "_RNCNvCs09azAZ_10crate_name9func_names0123456789abcdef_0Cs123_12client_"
+      "crate",
+      "crate_name::func_name::{closure#?}");
+
+  // Beyond 16 base-62 digits is rejected to prevent excessive re-scanning.
+  EXPECT_DEMANGLING_FAILS(
+      "_RNCNvCs09azAZ_10crate_name9func_names0123456789abcdef0_0Cs123_12client_"
+      "crate");
+  EXPECT_DEMANGLING_FAILS("_RB0123456789abcdef0_");
+}
+
 TEST(DemangleRust, UnexpectedlyNamedClosure) {
   EXPECT_DEMANGLING(
       "_RNCNvCs123_10crate_name9func_name12closure_nameCs456_12client_crate",