Skip to content
Closed
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
17 changes: 11 additions & 6 deletions src/prism.c
Original file line number Diff line number Diff line change
Expand Up @@ -14568,10 +14568,15 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
* end
*
*
* It can recurse infinitely down, and splats are allowed to group arguments.
* The parentheses can be nested, and splats are allowed to group arguments.
*/
static pm_multi_target_node_t *
parse_required_destructured_parameter(pm_parser_t *parser) {
static pm_node_t *
parse_required_destructured_parameter(pm_parser_t *parser, uint16_t depth) {
if (PRISM_UNLIKELY(depth >= PRISM_DEPTH_MAXIMUM)) {
pm_parser_err_current(parser, PM_ERR_NESTING_TOO_DEEP);
return UP(pm_error_recovery_node_create(parser, PM_TOKEN_START(parser, &parser->current), PM_TOKEN_LENGTH(&parser->current)));
}

expect1(parser, PM_TOKEN_PARENTHESIS_LEFT_GROUPING, PM_ERR_EXPECT_LPAREN_REQ_PARAMETER);

pm_multi_target_node_t *node = pm_multi_target_node_create(parser);
Expand All @@ -14592,7 +14597,7 @@ parse_required_destructured_parameter(pm_parser_t *parser) {
}

if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT_GROUPING)) {
param = UP(parse_required_destructured_parameter(parser));
param = parse_required_destructured_parameter(parser, (uint16_t) (depth + 1));
} else if (accept1(parser, PM_TOKEN_USTAR)) {
pm_token_t star = parser->previous;
pm_node_t *value = NULL;
Expand Down Expand Up @@ -14625,7 +14630,7 @@ parse_required_destructured_parameter(pm_parser_t *parser) {
expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN_REQ_PARAMETER);
pm_multi_target_node_closing_set(parser, node, &parser->previous);

return node;
return UP(node);
}

/**
Expand Down Expand Up @@ -14762,7 +14767,7 @@ parse_parameters(
switch (parser->current.type) {
case PM_TOKEN_PARENTHESIS_LEFT_GROUPING: {
update_parameter_state(parser, &parser->current, &order);
pm_node_t *param = UP(parse_required_destructured_parameter(parser));
pm_node_t *param = parse_required_destructured_parameter(parser, (uint16_t) (depth + 1));

if (order > PM_PARAMETERS_ORDER_AFTER_OPTIONAL) {
pm_parameters_node_requireds_append(parser->arena, params, param);
Expand Down
8 changes: 8 additions & 0 deletions test/prism/errors_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,14 @@ def test_unclosed_heredoc_and_interpolation
assert_nil(statement.parts[0].statements)
end

def test_nested_destructured_parameters
nested = "#{"(" * 10_000}a#{")" * 10_000}"

["def foo(#{nested}); end", "foo { |#{nested}| }", "->(#{nested}) {}"].each do |source|
assert_includes Prism.parse(source).errors.map(&:type), :nesting_too_deep
end
end

private

def assert_errors(filepath, version)
Expand Down
Loading