From f18c97669ded347aa5fcfbe8008533f06ab8959f Mon Sep 17 00:00:00 2001 From: Mykhailo Chalyi Date: Fri, 27 Mar 2026 23:24:06 +0000 Subject: [PATCH] fix(interpreter): expand command substitutions in assoc array keys Associative array assignments where the key is a command substitution (e.g. m["$(echo hello)"]="world") silently produced an empty key. Add async expand_assoc_key() that parses the subscript as a full Word and expands it with expand_word() when it contains $( or backtick. Closes #872 --- crates/bashkit/src/interpreter/mod.rs | 15 +++++++++------ .../tests/spec_cases/bash/assoc-arrays.test.sh | 10 ++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/crates/bashkit/src/interpreter/mod.rs b/crates/bashkit/src/interpreter/mod.rs index 3657aaf3..caed1cb8 100644 --- a/crates/bashkit/src/interpreter/mod.rs +++ b/crates/bashkit/src/interpreter/mod.rs @@ -7714,15 +7714,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) + /// Fully expand an associative array key, including command substitutions. + /// Falls back to `expand_variable_or_literal` for keys without `$(` or backtick. async fn expand_assoc_key(&mut self, s: &str) -> Result { - if s.contains('$') || s.contains('`') { - let word = crate::parser::Parser::parse_word_string(s); + if s.contains("$(") || s.contains('`') { + let word = Parser::parse_word_string_with_limits( + s, + self.limits.max_ast_depth, + self.limits.max_parser_operations, + ); self.expand_word(&word).await } else { - Ok(s.to_string()) + Ok(self.expand_variable_or_literal(s)) } } diff --git a/crates/bashkit/tests/spec_cases/bash/assoc-arrays.test.sh b/crates/bashkit/tests/spec_cases/bash/assoc-arrays.test.sh index 1ed9c7bb..69b4e73d 100644 --- a/crates/bashkit/tests/spec_cases/bash/assoc-arrays.test.sh +++ b/crates/bashkit/tests/spec_cases/bash/assoc-arrays.test.sh @@ -202,6 +202,16 @@ result: [a b] ### end +### assoc_key_command_substitution +declare -A m=() +m["$(echo hello)"]="world" +echo "count: ${#m[@]}" +for k in "${!m[@]}"; do echo "key=[$k] val=[${m[$k]}]"; done +### expect +count: 1 +key=[hello] val=[world] +### end + ### assoc_iteration declare -A m m[a]="1"