Skip to content

Commit 6ec1977

Browse files
committed
fix(interpreter): shadow arrays for bare local declarations
1 parent 5d6cb63 commit 6ec1977

2 files changed

Lines changed: 50 additions & 2 deletions

File tree

crates/bashkit/src/interpreter/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6768,16 +6768,17 @@ impl Interpreter {
67686768
}
67696769
} else if !is_internal_variable(arg) {
67706770
if flags.assoc {
6771-
self.remember_local_assoc_array_binding(arg);
6771+
self.shadow_local_array_bindings(arg, false, true);
67726772
if self.insert_assoc_array_checked(arg.to_string(), HashMap::new()) {
67736773
self.insert_local_checked(arg.to_string(), String::new());
67746774
}
67756775
} else if flags.array {
6776-
self.remember_local_array_binding(arg);
6776+
self.shadow_local_array_bindings(arg, true, false);
67776777
if self.insert_array_checked(arg.to_string(), HashMap::new()) {
67786778
self.insert_local_checked(arg.to_string(), String::new());
67796779
}
67806780
} else {
6781+
self.shadow_local_array_bindings(arg, false, false);
67816782
self.insert_local_checked(arg.to_string(), String::new());
67826783
}
67836784
if flags.integer {

crates/bashkit/tests/integration/threat_model_tests.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3808,6 +3808,53 @@ f
38083808
assert_eq!(counts, vec![0, 0]);
38093809
}
38103810

3811+
/// TM-INF-023: bare local declarations must shadow stale global array bindings.
3812+
#[tokio::test]
3813+
async fn tm_inf_023_bare_local_declarations_shadow_global_arrays() {
3814+
let mut bash = Bash::builder()
3815+
.session_limits(SessionLimits::unlimited())
3816+
.build();
3817+
3818+
let script = r#"
3819+
scalar_shadow=(GLOBAL_INDEXED)
3820+
declare -A indexed_shadow=([k]=GLOBAL_ASSOC)
3821+
assoc_shadow=(GLOBAL_INDEXED)
3822+
f() {
3823+
local scalar_shadow
3824+
local -a indexed_shadow
3825+
local -A assoc_shadow
3826+
printf "scalar_star=<%s>\n" "${scalar_shadow[*]}"
3827+
printf "scalar_zero=<%s>\n" "${scalar_shadow[0]}"
3828+
printf "indexed_star=<%s>\n" "${indexed_shadow[*]}"
3829+
printf "indexed_key=<%s>\n" "${indexed_shadow[k]}"
3830+
printf "assoc_star=<%s>\n" "${assoc_shadow[*]}"
3831+
printf "assoc_zero=<%s>\n" "${assoc_shadow[0]}"
3832+
}
3833+
f
3834+
printf "after_scalar=<%s>\n" "${scalar_shadow[*]}"
3835+
printf "after_indexed=<%s>\n" "${indexed_shadow[*]}"
3836+
printf "after_assoc=<%s>\n" "${assoc_shadow[*]}"
3837+
"#;
3838+
let result = bash.exec(script).await.unwrap();
3839+
3840+
assert_eq!(result.exit_code, 0);
3841+
let lines: Vec<&str> = result.stdout.lines().collect();
3842+
assert_eq!(
3843+
lines,
3844+
vec![
3845+
"scalar_star=<>",
3846+
"scalar_zero=<>",
3847+
"indexed_star=<>",
3848+
"indexed_key=<>",
3849+
"assoc_star=<>",
3850+
"assoc_zero=<>",
3851+
"after_scalar=<GLOBAL_INDEXED>",
3852+
"after_indexed=<GLOBAL_ASSOC>",
3853+
"after_assoc=<GLOBAL_INDEXED>",
3854+
]
3855+
);
3856+
}
3857+
38113858
/// TM-INF-023: local compound arrays must not leak after a function returns.
38123859
#[tokio::test]
38133860
async fn tm_inf_023_function_local_arrays_do_not_leak() {

0 commit comments

Comments
 (0)