Skip to content

Commit 3024bee

Browse files
st0012kddnewton
andcommitted
Prevent optional block parameter from accepting certain prefixed values
This commit prevents the following unary operators from being accepted as the value prefix of a block's optional parameter: - `+` - `-` - `~` - `!` For example, `f { |a = +b| }` will now raise a syntax error. Co-authored-by: Kevin Newton <[email protected]>
1 parent 8174aac commit 3024bee

File tree

4 files changed

+30
-0
lines changed

4 files changed

+30
-0
lines changed

config.yml

+1
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ errors:
261261
- TERNARY_COLON
262262
- TERNARY_EXPRESSION_FALSE
263263
- TERNARY_EXPRESSION_TRUE
264+
- UNARY_DISALLOWED
264265
- UNARY_RECEIVER
265266
- UNDEF_ARGUMENT
266267
- UNEXPECTED_BLOCK_ARGUMENT

src/prism.c

+17
Original file line numberDiff line numberDiff line change
@@ -17142,6 +17142,10 @@ pm_parser_err_prefix(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
1714217142
PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, diag_id, human, parser->previous.start[0]);
1714317143
break;
1714417144
}
17145+
case PM_ERR_UNARY_DISALLOWED: {
17146+
PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, diag_id, pm_token_type_human(parser->current.type));
17147+
break;
17148+
}
1714517149
default:
1714617150
pm_parser_err_previous(parser, diag_id);
1714717151
break;
@@ -19675,6 +19679,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1967519679
}
1967619680
}
1967719681
case PM_TOKEN_BANG: {
19682+
if (binding_power > PM_BINDING_POWER_UNARY) {
19683+
pm_parser_err_prefix(parser, PM_ERR_UNARY_DISALLOWED);
19684+
}
19685+
1967819686
parser_lex(parser);
1967919687

1968019688
pm_token_t operator = parser->previous;
@@ -19685,6 +19693,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1968519693
return (pm_node_t *) node;
1968619694
}
1968719695
case PM_TOKEN_TILDE: {
19696+
if (binding_power > PM_BINDING_POWER_UNARY) {
19697+
pm_parser_err_prefix(parser, PM_ERR_UNARY_DISALLOWED);
19698+
}
1968819699
parser_lex(parser);
1968919700

1969019701
pm_token_t operator = parser->previous;
@@ -19694,6 +19705,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1969419705
return (pm_node_t *) node;
1969519706
}
1969619707
case PM_TOKEN_UMINUS: {
19708+
if (binding_power > PM_BINDING_POWER_UNARY) {
19709+
pm_parser_err_prefix(parser, PM_ERR_UNARY_DISALLOWED);
19710+
}
1969719711
parser_lex(parser);
1969819712

1969919713
pm_token_t operator = parser->previous;
@@ -19810,6 +19824,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1981019824
return (pm_node_t *) pm_lambda_node_create(parser, &locals, &operator, &opening, &parser->previous, parameters, body);
1981119825
}
1981219826
case PM_TOKEN_UPLUS: {
19827+
if (binding_power > PM_BINDING_POWER_UNARY) {
19828+
pm_parser_err_prefix(parser, PM_ERR_UNARY_DISALLOWED);
19829+
}
1981319830
parser_lex(parser);
1981419831

1981519832
pm_token_t operator = parser->previous;

templates/src/diagnostic.c.erb

+1
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
344344
[PM_ERR_TERNARY_EXPRESSION_TRUE] = { "expected an expression after `?` in the ternary operator", PM_ERROR_LEVEL_SYNTAX },
345345
[PM_ERR_UNDEF_ARGUMENT] = { "invalid argument being passed to `undef`; expected a bare word, constant, or symbol argument", PM_ERROR_LEVEL_SYNTAX },
346346
[PM_ERR_UNARY_RECEIVER] = { "unexpected %s, expected a receiver for unary `%c`", PM_ERROR_LEVEL_SYNTAX },
347+
[PM_ERR_UNARY_DISALLOWED] = { "unexpected %s; unary calls are not allowed in this context", PM_ERROR_LEVEL_SYNTAX },
347348
[PM_ERR_UNEXPECTED_BLOCK_ARGUMENT] = { "block argument should not be given", PM_ERROR_LEVEL_SYNTAX },
348349
[PM_ERR_UNEXPECTED_INDEX_BLOCK] = { "unexpected block arg given in index assignment; blocks are not allowed in index assignment expressions", PM_ERROR_LEVEL_SYNTAX },
349350
[PM_ERR_UNEXPECTED_INDEX_KEYWORDS] = { "unexpected keyword arg given in index assignment; keywords are not allowed in index assignment expressions", PM_ERROR_LEVEL_SYNTAX },

test/prism/errors_test.rb

+11
Original file line numberDiff line numberDiff line change
@@ -1493,6 +1493,17 @@ def test_shadow_args_in_block
14931493
]
14941494
end
14951495

1496+
def test_optional_block_parameters_with_unary_operator
1497+
[
1498+
["foo { |a = +b| }", ["unexpected '+'; unary calls are not allowed in this context", 11..12]],
1499+
["foo { |a = -b| }", ["unexpected '-'; unary calls are not allowed in this context", 11..12]],
1500+
["foo { |a = !b| }", ["unexpected '!'; unary calls are not allowed in this context", 11..12]],
1501+
["foo { |a = ~b| }", ["unexpected '~'; unary calls are not allowed in this context", 11..12]],
1502+
].each do |source, *errors|
1503+
assert_errors expression(source), source, errors
1504+
end
1505+
end
1506+
14961507
def test_repeated_parameter_name_in_destructured_params
14971508
source = "def f(a, (b, (a))); end"
14981509

0 commit comments

Comments
 (0)