Skip to content
Merged
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
19 changes: 18 additions & 1 deletion crates/bashkit/src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8371,7 +8371,8 @@ impl Interpreter {
cmd.push(c);
}
}
// Execute the command and substitute
// Execute the command and substitute in a subshell context:
// save/restore mutable state so mutations don't leak.
let parser = Parser::with_limits(
&cmd,
self.limits.max_ast_depth,
Expand All @@ -8382,8 +8383,24 @@ impl Interpreter {
if self.counters.push_function(&self.limits).is_err() {
result.push('0');
} else {
let saved_vars = self.variables.clone();
let saved_arrays = self.arrays.clone();
let saved_assoc = self.assoc_arrays.clone();
let saved_functions = self.functions.clone();
let saved_traps = self.traps.clone();
let saved_aliases = self.aliases.clone();
let saved_cwd = self.cwd.clone();
let saved_memory_budget = self.memory_budget.clone();
let cmd_result =
self.execute_command_sequence(&script.commands).await?;
self.variables = saved_vars;
self.arrays = saved_arrays;
self.assoc_arrays = saved_assoc;
self.functions = saved_functions;
self.traps = saved_traps;
self.aliases = saved_aliases;
self.cwd = saved_cwd;
self.memory_budget = saved_memory_budget;
self.counters.pop_function();
let trimmed = cmd_result.stdout.trim_end_matches('\n');
if trimmed.is_empty() {
Expand Down
36 changes: 36 additions & 0 deletions crates/bashkit/tests/spec_cases/bash/recursive-cmdsub.test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
### recursive_function_command_subst
# Recursive function calls inside $() should work
factorial() {
if (( $1 <= 1 )); then echo 1
else echo $(( $1 * $(factorial $(($1 - 1))) ))
fi
}
factorial 5
### expect
120
### end

### recursive_depth_3
# Recursive function with depth 3
f() {
if (( $1 <= 0 )); then echo "base"
else echo "depth=$1 $(f $(($1 - 1)))"
fi
}
f 3
### expect
depth=3 depth=2 depth=1 base
### end

### recursive_cmdsub_var_isolation
# Variable mutations inside $() in arithmetic should not leak to parent
x=100
inner() {
x=999
echo 42
}
result=$(( $(inner) + x ))
echo "$result $x"
### expect
142 100
### end
Loading