diff --git a/crates/bashkit/src/interpreter/mod.rs b/crates/bashkit/src/interpreter/mod.rs index aca72bdb..362b915e 100644 --- a/crates/bashkit/src/interpreter/mod.rs +++ b/crates/bashkit/src/interpreter/mod.rs @@ -3129,7 +3129,7 @@ impl Interpreter { if let Some(index_str) = &assignment.index { let resolved_name = self.resolve_nameref(&assignment.name).to_string(); if self.assoc_arrays.contains_key(&resolved_name) { - let key = self.expand_variable_or_literal(index_str); + let key = self.expand_assoc_key(index_str).await?; let is_new_entry = self .assoc_arrays .get(&resolved_name) @@ -7791,6 +7791,18 @@ impl Interpreter { s.to_string() } + /// Expand an associative array key with full word expansion. + /// Unlike `expand_variable_or_literal`, this handles command substitutions + /// (`$(...)`, backticks) and all other expansion types. (Issue #872) + async fn expand_assoc_key(&mut self, s: &str) -> Result { + if s.contains('$') || s.contains('`') { + let word = crate::parser::Parser::parse_word_string(s); + self.expand_word(&word).await + } else { + Ok(s.to_string()) + } + } + /// THREAT[TM-INJ-009]: Check if a variable name is an internal marker. fn is_internal_variable(name: &str) -> bool { is_internal_variable(name) diff --git a/crates/bashkit/tests/issue_872_test.rs b/crates/bashkit/tests/issue_872_test.rs new file mode 100644 index 00000000..76a55203 --- /dev/null +++ b/crates/bashkit/tests/issue_872_test.rs @@ -0,0 +1,66 @@ +//! Test for issue #872: Associative array keys with command substitutions +//! expand to empty string. + +use bashkit::Bash; + +#[tokio::test] +async fn assoc_key_command_substitution() { + let mut bash = Bash::new(); + let result = bash + .exec( + r#" +declare -A m=() +m["$(echo hello)"]="world" +echo "count: ${#m[@]}" +for k in "${!m[@]}"; do echo "key=[$k] val=[${m[$k]}]"; done +"#, + ) + .await + .unwrap(); + assert!( + result.stdout.contains("key=[hello] val=[world]"), + "expected key=[hello], got: {}", + result.stdout + ); +} + +#[tokio::test] +async fn assoc_key_variable_expansion() { + let mut bash = Bash::new(); + let result = bash + .exec( + r#" +declare -A m=() +key="mykey" +m[$key]="myval" +echo "${m[mykey]}" +"#, + ) + .await + .unwrap(); + assert!( + result.stdout.contains("myval"), + "expected myval, got: {}", + result.stdout + ); +} + +#[tokio::test] +async fn assoc_key_literal_unchanged() { + let mut bash = Bash::new(); + let result = bash + .exec( + r#" +declare -A m=() +m[literal]="val" +echo "${m[literal]}" +"#, + ) + .await + .unwrap(); + assert!( + result.stdout.contains("val"), + "expected val, got: {}", + result.stdout + ); +} diff --git a/supply-chain/config.toml b/supply-chain/config.toml index a7594112..93052b55 100644 --- a/supply-chain/config.toml +++ b/supply-chain/config.toml @@ -154,10 +154,6 @@ criteria = "safe-to-run" version = "0.2.4" criteria = "safe-to-deploy" -[[exemptions.cc]] -version = "1.2.57" -criteria = "safe-to-deploy" - [[exemptions.cc]] version = "1.2.58" criteria = "safe-to-deploy" @@ -206,10 +202,6 @@ criteria = "safe-to-deploy" version = "1.1.0" criteria = "safe-to-deploy" -[[exemptions.cmake]] -version = "0.1.57" -criteria = "safe-to-deploy" - [[exemptions.cmake]] version = "0.1.58" criteria = "safe-to-deploy" @@ -238,10 +230,6 @@ criteria = "safe-to-deploy" version = "0.9.0" criteria = "safe-to-deploy" -[[exemptions.console]] -version = "0.15.11" -criteria = "safe-to-run" - [[exemptions.console]] version = "0.16.3" criteria = "safe-to-run" @@ -578,10 +566,6 @@ criteria = "safe-to-deploy" version = "2.13.0" criteria = "safe-to-deploy" -[[exemptions.insta]] -version = "1.46.3" -criteria = "safe-to-run" - [[exemptions.insta]] version = "1.47.0" criteria = "safe-to-run" @@ -598,10 +582,6 @@ criteria = "safe-to-deploy" version = "2.12.0" criteria = "safe-to-deploy" -[[exemptions.iri-string]] -version = "0.7.10" -criteria = "safe-to-deploy" - [[exemptions.iri-string]] version = "0.7.11" criteria = "safe-to-deploy" @@ -642,10 +622,6 @@ criteria = "safe-to-deploy" version = "0.21.1" criteria = "safe-to-deploy" -[[exemptions.jni-sys]] -version = "0.3.0" -criteria = "safe-to-deploy" - [[exemptions.jni-sys]] version = "0.3.1" criteria = "safe-to-deploy" @@ -663,7 +639,7 @@ version = "0.1.34" criteria = "safe-to-deploy" [[exemptions.js-sys]] -version = "0.3.91" +version = "0.3.92" criteria = "safe-to-deploy" [[exemptions.leb128fmt]] @@ -726,10 +702,6 @@ criteria = "safe-to-deploy" version = "0.8.9" criteria = "safe-to-deploy" -[[exemptions.mio]] -version = "1.1.1" -criteria = "safe-to-deploy" - [[exemptions.mio]] version = "1.2.0" criteria = "safe-to-deploy" @@ -1190,10 +1162,6 @@ criteria = "safe-to-deploy" version = "0.9.1" criteria = "safe-to-deploy" -[[exemptions.simd-adler32]] -version = "0.3.8" -criteria = "safe-to-deploy" - [[exemptions.simd-adler32]] version = "0.3.9" criteria = "safe-to-deploy" @@ -1390,10 +1358,6 @@ criteria = "safe-to-deploy" version = "0.1.25" criteria = "safe-to-deploy" -[[exemptions.unicode-segmentation]] -version = "1.13.1" -criteria = "safe-to-deploy" - [[exemptions.unicode-segmentation]] version = "1.13.2" criteria = "safe-to-deploy" @@ -1463,23 +1427,23 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06" criteria = "safe-to-run" [[exemptions.wasm-bindgen]] -version = "0.2.114" +version = "0.2.115" criteria = "safe-to-deploy" [[exemptions.wasm-bindgen-futures]] -version = "0.4.64" +version = "0.4.65" criteria = "safe-to-deploy" [[exemptions.wasm-bindgen-macro]] -version = "0.2.114" +version = "0.2.115" criteria = "safe-to-deploy" [[exemptions.wasm-bindgen-macro-support]] -version = "0.2.114" +version = "0.2.115" criteria = "safe-to-deploy" [[exemptions.wasm-bindgen-shared]] -version = "0.2.114" +version = "0.2.115" criteria = "safe-to-deploy" [[exemptions.wasm-encoder]] @@ -1499,7 +1463,7 @@ version = "0.244.0" criteria = "safe-to-deploy" [[exemptions.web-sys]] -version = "0.3.91" +version = "0.3.92" criteria = "safe-to-deploy" [[exemptions.web-time]] @@ -1562,10 +1526,6 @@ criteria = "safe-to-deploy" version = "0.52.0" criteria = "safe-to-deploy" -[[exemptions.windows-sys]] -version = "0.59.0" -criteria = "safe-to-run" - [[exemptions.windows-sys]] version = "0.60.2" criteria = "safe-to-deploy"