diff --git a/absl/debugging/internal/demangle_rust.cc b/absl/debugging/internal/demangle_rust.cc index f7f671341f4..82e109023af 100644 --- a/absl/debugging/internal/demangle_rust.cc +++ b/absl/debugging/internal/demangle_rust.cc @@ -712,6 +712,11 @@ class RustSymbolParser { if (!ParseDecimalNumber(num_bytes)) return false; (void)Eat('_'); // optional separator, needed if a digit follows if (is_punycoded) { + // A length exceeding the remaining input would make punycode_end point + // past the end of the buffer, forming an out-of-bounds pointer. + if (static_cast(num_bytes) > std::strlen(&encoding_[pos_])) { + return false; + } DecodeRustPunycodeOptions options; options.punycode_begin = &encoding_[pos_]; options.punycode_end = &encoding_[pos_] + num_bytes; diff --git a/absl/debugging/internal/demangle_rust_test.cc b/absl/debugging/internal/demangle_rust_test.cc index 8ceb1fd7456..a67f013c8ee 100644 --- a/absl/debugging/internal/demangle_rust_test.cc +++ b/absl/debugging/internal/demangle_rust_test.cc @@ -118,6 +118,11 @@ TEST(DemangleRust, UnicodeIdentifiers) { "ice_cap::Eyjafjallajökull"); EXPECT_DEMANGLING("_RNvC7ice_caps_u19Eyjafjallajkull_jtb", "ice_cap::Eyjafjallajökull"); + + // A punycode byte count larger than the remaining input is rejected instead + // of running the decoder past the end of the buffer. + EXPECT_DEMANGLING_FAILS("_RNvC7ice_caps_u2000000000Eyjafjallajkull_jtb"); + EXPECT_DEMANGLING_FAILS("_RNvC7ice_caps_u99Eyj_a"); } TEST(DemangleRust, FunctionInModule) {