Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions core/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,11 @@ class Parser {
*/
ArgParams parseParams(const std::string &element_kind, bool &got_comma, Fodder &close_fodder, unsigned current_depth)
{
if (current_depth >= MAX_PARSER_DEPTH) {
throw StaticError(peek().location, "Exceeded maximum parse depth limit.");
}
ArgParams params;
Token paren_r = parseArgs(params, element_kind, got_comma, current_depth);
Token paren_r = parseArgs(params, element_kind, got_comma, current_depth + 1);

// Check they're all identifiers
// parseArgs returns f(x) with x as an expression. Convert it here.
Expand Down Expand Up @@ -259,7 +262,7 @@ class Parser {
if (peek().kind == Token::PAREN_L) {
Token paren_l = pop();
fodder_l = paren_l.fodder;
params = parseParams("function parameter", trailing_comma, fodder_r, current_depth);
params = parseParams("function parameter", trailing_comma, fodder_r, current_depth + 1);
is_function = true;
}
Token eq = popExpect(Token::OPERATOR, "=");
Expand Down Expand Up @@ -428,7 +431,7 @@ class Parser {
if (peek().kind == Token::PAREN_L) {
Token paren_l = pop();
fodder_l = paren_l.fodder;
params = parseParams("method parameter", meth_comma, fodder_r, current_depth);
params = parseParams("method parameter", meth_comma, fodder_r, current_depth + 1);
is_method = true;
}

Expand Down Expand Up @@ -519,7 +522,7 @@ class Parser {
Token paren_l = pop();
paren_l_fodder = paren_l.fodder;
is_method = true;
params = parseParams("function parameter", func_comma, paren_r_fodder, current_depth);
params = parseParams("function parameter", func_comma, paren_r_fodder, current_depth + 1);
}
Token eq = popExpect(Token::OPERATOR, "=");
AST *body = parse(MAX_PRECEDENCE, current_depth + 1);
Expand Down Expand Up @@ -879,7 +882,7 @@ class Parser {
std::vector<AST *> params_asts;
bool got_comma;
Fodder paren_r_fodder;
ArgParams params = parseParams("function parameter", got_comma, paren_r_fodder, current_depth);
ArgParams params = parseParams("function parameter", got_comma, paren_r_fodder, current_depth + 1);
AST *body = parse(MAX_PRECEDENCE, current_depth + 1);
return alloc->make<Function>(span(begin, body),
begin.fodder,
Expand Down Expand Up @@ -1129,7 +1132,7 @@ class Parser {
case Token::PAREN_L: {
ArgParams args;
bool got_comma;
Token end = parseArgs(args, "function argument", got_comma, current_depth);
Token end = parseArgs(args, "function argument", got_comma, current_depth + 1);
bool got_named = false;
for (const auto& arg : args) {
if (arg.id != nullptr) {
Expand Down
28 changes: 28 additions & 0 deletions core/parser_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,5 +343,33 @@ TEST(Parser, TestInvalidOverride)
testParseError("a{b c}", R"(test:1:5: expected token OPERATOR but got (IDENTIFIER, "c"))");
}

TEST(Parser, TestMaxDepthLimit)
{
// Test that deeply nested bracket expressions fail gracefully with depth limit error.
std::string deep_brackets = std::string(1000, '[') + "1" + std::string(1000, ']');
testParseError(deep_brackets.c_str(), "test:1:501: Exceeded maximum parse depth limit.");

// Test that deeply nested parens fail gracefully with depth limit error.
std::string deep_parens = std::string(1000, '(') + "1" + std::string(1000, ')');
testParseError(deep_parens.c_str(), "test:1:501: Exceeded maximum parse depth limit.");

// Test that deeply nested unary chains fail gracefully.
std::string deep_unary = std::string(1000, '!') + "true";
testParseError(deep_unary.c_str(), "test:1:501: Exceeded maximum parse depth limit.");

// Test that flat chained operations (binary +, indexing) parse fine without false positive depth errors.
std::string flat_binary = "1";
for (int i = 0; i < 1000; ++i) {
flat_binary += " + 1";
}
testParse(flat_binary.c_str());

std::string flat_index = "x";
for (int i = 0; i < 1000; ++i) {
flat_index += "[0]";
}
testParse(flat_index.c_str());
}

} // namespace
} // namespace jsonnet::internal
Loading