Skip to content

Commit ef3148a

Browse files
authored
fix(awk): check word boundary before emitting keyword tokens (#859)
Closes #852
1 parent ed0707a commit ef3148a

2 files changed

Lines changed: 44 additions & 14 deletions

File tree

crates/bashkit/src/builtins/awk.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -623,13 +623,10 @@ impl<'a> AwkParser<'a> {
623623
fn matches_keyword(&mut self, keyword: &str) -> bool {
624624
if self.input[self.pos..].starts_with(keyword) {
625625
let after = self.pos + keyword.len();
626-
if after >= self.input.len()
627-
|| !self.input[after..]
628-
.chars()
629-
.next()
630-
.unwrap()
631-
.is_alphanumeric()
632-
{
626+
if after >= self.input.len() || {
627+
let c = self.input[after..].chars().next().unwrap();
628+
!c.is_alphanumeric() && c != '_'
629+
} {
633630
self.pos = after;
634631
return true;
635632
}
@@ -1523,13 +1520,10 @@ impl<'a> AwkParser<'a> {
15231520
for kw in keywords {
15241521
if remaining.starts_with(kw) {
15251522
let after = self.pos + kw.len();
1526-
if after >= self.input.len()
1527-
|| !self.input[after..]
1528-
.chars()
1529-
.next()
1530-
.unwrap()
1531-
.is_alphanumeric()
1532-
{
1523+
if after >= self.input.len() || {
1524+
let c = self.input[after..].chars().next().unwrap();
1525+
!c.is_alphanumeric() && c != '_'
1526+
} {
15331527
return true;
15341528
}
15351529
}

crates/bashkit/tests/spec_cases/awk/eval-bugs.test.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,39 @@ printf 'feat(auth): add OAuth2\n' | awk 'match($0, /^([a-z]+)\(([^)]+)\): (.*)/,
1717
### expect
1818
feat auth add OAuth2
1919
### end
20+
21+
### awk_keyword_prefix_identifier
22+
# Bug #852: identifiers starting with keywords split incorrectly
23+
# e.g. print_sp parsed as keyword "print" + variable "_sp"
24+
echo test | awk 'BEGIN { print_sp=0; print_sp++; print print_sp }'
25+
### expect
26+
1
27+
### end
28+
29+
### awk_keyword_prefix_identifier_printf
30+
# Bug #852: printf_count must not split into printf + _count
31+
echo test | awk 'BEGIN { printf_count=5; print printf_count }'
32+
### expect
33+
5
34+
### end
35+
36+
### awk_keyword_prefix_identifier_delete
37+
# Bug #852: delete_flag must not split into delete + _flag
38+
echo test | awk 'BEGIN { delete_flag=42; print delete_flag }'
39+
### expect
40+
42
41+
### end
42+
43+
### awk_keyword_prefix_identifier_return_val
44+
# Bug #852: return_val must not split into return + _val
45+
echo test | awk 'function f() { return_val=99; return return_val } BEGIN { print f() }'
46+
### expect
47+
99
48+
### end
49+
50+
### awk_keyword_prefix_identifier_if_done
51+
# Bug #852: if_done must not split into if + _done
52+
echo test | awk 'BEGIN { if_done=1; while_running=2; for_each=3; print if_done, while_running, for_each }'
53+
### expect
54+
1 2 3
55+
### end

0 commit comments

Comments
 (0)