From bfffabe8fa3960b8e0616770a88f8bc1dafc8d59 Mon Sep 17 00:00:00 2001 From: Sergiu Deitsch Date: Fri, 6 Oct 2023 21:15:37 +0200 Subject: [PATCH] fix(demangle): limit ParseTemplateArg recursion depth --- src/demangle.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/demangle.cc b/src/demangle.cc index 39a462bf8..74dff7062 100644 --- a/src/demangle.cc +++ b/src/demangle.cc @@ -113,6 +113,7 @@ struct State { bool overflowed; // True if output gets overflowed. uint32 local_level; uint32 expr_level; + uint32 arg_level; }; // We don't use strlen() in libc since it's not guaranteed to be async @@ -159,6 +160,7 @@ static void InitState(State *state, const char *mangled, state->overflowed = false; state->local_level = 0; state->expr_level = 0; + state->arg_level = 0; } // Returns true and advances "mangled_cur" if we find "one_char_token" @@ -1095,22 +1097,33 @@ static bool ParseTemplateArgs(State *state) { // ::= J * E # argument pack // ::= X E static bool ParseTemplateArg(State *state) { + // Avoid recursion above max_levels + constexpr uint32 max_levels = 5; + + if (state->arg_level > max_levels) { + return false; + } + ++state->arg_level; + State copy = *state; if ((ParseOneCharToken(state, 'I') || ParseOneCharToken(state, 'J')) && ZeroOrMore(ParseTemplateArg, state) && ParseOneCharToken(state, 'E')) { + --state->arg_level; return true; } *state = copy; if (ParseType(state) || ParseExprPrimary(state)) { + --state->arg_level; return true; } *state = copy; if (ParseOneCharToken(state, 'X') && ParseExpression(state) && ParseOneCharToken(state, 'E')) { + --state->arg_level; return true; } *state = copy;