Skip to content

Commit 44c713f

Browse files
authored
fix: check func names against reserved words (reubeno#978)
1 parent aaab1cf commit 44c713f

2 files changed

Lines changed: 27 additions & 1 deletion

File tree

brush-parser/src/parser/peg.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,8 +412,14 @@ peg::parser! {
412412
}
413413

414414
// N.B. Non-sh extensions allows use of the 'function' word to indicate a function definition.
415+
// N.B. Without the 'function' keyword, reserved words cannot be used as function names
416+
// (bash rejects e.g. `for (){ :; }`). With the 'function' keyword, reserved words are
417+
// allowed as function names (bash accepts e.g. `function for { :; }`).
415418
rule function_definition() -> ast::FunctionDefinition =
416-
specific_word("function")? fname:fname() body:function_parens_and_body() {
419+
specific_word("function") fname:fname() body:function_parens_and_body() {
420+
ast::FunctionDefinition { fname, body }
421+
} /
422+
fname:non_reserved_fname() body:function_parens_and_body() {
417423
ast::FunctionDefinition { fname, body }
418424
} /
419425
specific_word("function") fname:fname() linebreak() body:function_body() {
@@ -433,6 +439,9 @@ peg::parser! {
433439
// TODO(parser): Find a way to make this still work without requiring this targeted exception.
434440
w:[Token::Word(word, l) if !word.ends_with('=')] { ast::Word::with_location(word, l) }
435441

442+
rule non_reserved_fname() -> ast::Word =
443+
!reserved_word() w:fname() { w }
444+
436445
rule brace_group() -> ast::BraceGroupCommand =
437446
start:specific_word("{") list:compound_list() end:specific_word("}") {
438447
let loc = SourceSpan::within(start.location(), end.location());

brush-shell/tests/cases/compat/functions.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,23 @@ cases:
120120
.
121121
echo "Call result: $?"
122122
123+
- name: "Reserved words cannot be used as function names without function keyword"
124+
ignore_stderr: true
125+
stdin: |
126+
for (){ :; }
127+
echo "exit: $?"
128+
129+
- name: "Reserved words can be used as function names with function keyword"
130+
stdin: |
131+
function for { echo "custom for"; }
132+
for x in 1; do echo "normal for: $x"; done
133+
134+
- name: "Reserved words can be used as function names with function keyword and parens"
135+
stdin: |
136+
function while() { echo "custom while"; }
137+
while false; do echo "nope"; done
138+
echo "done"
139+
123140
- name: "Functions shadowing builtins (POSIX mode)"
124141
ignore_stderr: true
125142
stdin: |

0 commit comments

Comments
 (0)