diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc index 5b2d62398bb..c82274fe56a 100644 --- a/absl/debugging/internal/demangle.cc +++ b/absl/debugging/internal/demangle.cc @@ -973,6 +973,7 @@ static bool ParseUnnamedTypeName(State *state) { // Unnamed type local to function or class. if (ParseTwoCharToken(state, "Ut") && Optional(ParseNumber(state, &which)) && + which >= -1 && // Don't print garbage. which <= std::numeric_limits::max() - 2 && // Don't overflow. ParseOneCharToken(state, '_')) { MaybeAppend(state, "{unnamed type#"); @@ -988,6 +989,7 @@ static bool ParseUnnamedTypeName(State *state) { ZeroOrMore(ParseTemplateParamDecl, state) && OneOrMore(ParseType, state) && RestoreAppend(state, copy.append) && ParseOneCharToken(state, 'E') && Optional(ParseNumber(state, &which)) && + which >= -1 && // Don't print garbage. which <= std::numeric_limits::max() - 2 && // Don't overflow. ParseOneCharToken(state, '_')) { MaybeAppend(state, "{lambda()#"); diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc index 7238fd023a2..50e4359cde3 100644 --- a/absl/debugging/internal/demangle_test.cc +++ b/absl/debugging/internal/demangle_test.cc @@ -471,6 +471,31 @@ TEST(Demangle, AvoidSignedOverflowForUnfortunateParameterNumbers) { EXPECT_STREQ(tmp, "S::f()::{default arg#1}::{lambda()#1}::operator()()"); } +TEST(Demangle, NegativeUnnamedTypeNumbers) { + char tmp[100]; + + // An omitted denotes index 1 and is left as the -1 sentinel. + ASSERT_TRUE(Demangle("_ZUt_", tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "{unnamed type#1}"); + ASSERT_TRUE(Demangle("_ZUlvE_", tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "{lambda()#1}"); + + // Reject an explicitly negative . Left unstrained, + 2 is + // negative, and MaybeAppendDecimal emits (val % 10) + '0' per digit, which + // for a negative val yields characters below '0'. + ASSERT_FALSE(Demangle("_ZUtn3_", tmp, sizeof(tmp))); + ASSERT_FALSE(Demangle("_ZUlvEn3_", tmp, sizeof(tmp))); + + // ParseNumber truncates to int, so an in-range-looking can also + // arrive negative. + ASSERT_FALSE(Demangle("_ZUt2147483648_", tmp, sizeof(tmp))); + ASSERT_FALSE(Demangle("_ZUlvE2147483648_", tmp, sizeof(tmp))); + + // The largest whose index still fits in an int is unaffected. + ASSERT_TRUE(Demangle("_ZUt2147483645_", tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "{unnamed type#2147483647}"); +} + TEST(Demangle, SubstpackNotationForTroublesomeTemplatePack) { char tmp[100];