Commit e1334ef
fix(interpreter): split command substitution output on IFS in list context (#374)
## Summary
- Fix word splitting for unquoted `$()` command substitution in list
contexts (e.g., `for x in $(cmd)`)
- Previously, the entire command substitution output was treated as a
single token; now it is split on IFS characters (space/tab/newline by
default)
- Add 3 spec tests covering for-loop with find, space-separated words,
and newline-separated output
## Details
The root cause was in `expand_word_to_fields()` in
`crates/bashkit/src/interpreter/mod.rs`. For words that weren't array
expansions, it called `expand_word()` which returns a single
concatenated string, then wrapped it in a single-element vec. There was
no IFS-based field splitting step for unquoted command substitutions.
The fix checks if the word is unquoted and contains a
`CommandSubstitution` part. If so, the expanded result is split on IFS
characters (defaulting to space/tab/newline), with consecutive
whitespace collapsed and empty results elided. This matches POSIX shell
semantics and real bash behavior.
## Test plan
- [x] Added 3 new spec tests in `command-subst.test.sh` (for-loop
splitting, space splitting, newline splitting)
- [x] All 1308 bash spec tests pass (1184 passed + 124 skipped, 0
failed)
- [x] 1084/1084 bash comparison tests match real bash (100%)
- [x] `cargo fmt --check` clean
- [x] `cargo clippy --all-targets --all-features -- -D warnings` clean
- [x] Unit tests and threat model tests pass
Closes #347
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 76be440 commit e1334ef
2 files changed
Lines changed: 71 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5288 | 5288 | | |
5289 | 5289 | | |
5290 | 5290 | | |
5291 | | - | |
| 5291 | + | |
| 5292 | + | |
| 5293 | + | |
5292 | 5294 | | |
5293 | | - | |
| 5295 | + | |
| 5296 | + | |
| 5297 | + | |
| 5298 | + | |
| 5299 | + | |
| 5300 | + | |
| 5301 | + | |
| 5302 | + | |
| 5303 | + | |
| 5304 | + | |
| 5305 | + | |
| 5306 | + | |
| 5307 | + | |
| 5308 | + | |
| 5309 | + | |
| 5310 | + | |
| 5311 | + | |
| 5312 | + | |
| 5313 | + | |
| 5314 | + | |
| 5315 | + | |
| 5316 | + | |
| 5317 | + | |
| 5318 | + | |
| 5319 | + | |
| 5320 | + | |
| 5321 | + | |
| 5322 | + | |
| 5323 | + | |
| 5324 | + | |
| 5325 | + | |
| 5326 | + | |
| 5327 | + | |
| 5328 | + | |
| 5329 | + | |
5294 | 5330 | | |
5295 | 5331 | | |
5296 | 5332 | | |
| |||
Lines changed: 33 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
152 | 152 | | |
153 | 153 | | |
154 | 154 | | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
0 commit comments