From c28e986c098ec1e6c13c3d3ebc73eeb75c133c46 Mon Sep 17 00:00:00 2001 From: Mykhailo Chalyi Date: Thu, 26 Mar 2026 16:56:34 +0000 Subject: [PATCH] fix(interpreter): resolve namerefs before nounset check Nameref variables are now followed to their target before checking if a variable is unbound under set -u. Previously, the nameref itself was checked, causing false 'unbound variable' errors. Closes #834 --- crates/bashkit/src/interpreter/mod.rs | 5 ++ .../tests/spec_cases/bash/nameref.test.sh | 58 +++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/crates/bashkit/src/interpreter/mod.rs b/crates/bashkit/src/interpreter/mod.rs index 8e896127..18ddadfb 100644 --- a/crates/bashkit/src/interpreter/mod.rs +++ b/crates/bashkit/src/interpreter/mod.rs @@ -8001,7 +8001,12 @@ impl Interpreter { } /// Check if a variable is set (for `set -u` / nounset). + /// Follows nameref indirection so that a nameref pointing to a defined + /// target is considered "set". fn is_variable_set(&self, name: &str) -> bool { + // Resolve nameref before checking — a nameref whose target exists is "set". + let name = self.resolve_nameref(name); + // Special variables are always "set" if matches!( name, diff --git a/crates/bashkit/tests/spec_cases/bash/nameref.test.sh b/crates/bashkit/tests/spec_cases/bash/nameref.test.sh index c0196100..86eb968f 100644 --- a/crates/bashkit/tests/spec_cases/bash/nameref.test.sh +++ b/crates/bashkit/tests/spec_cases/bash/nameref.test.sh @@ -206,3 +206,61 @@ echo $x hello world ### end + +### nameref_nounset_basic +# basic nameref under set -u (issue #834) +set -u +target="hello" +declare -n ref=target +echo "${ref}" +### expect +hello +### end + +### nameref_nounset_local_n +# local -n inside function under set -u +set -u +val="world" +f() { + local -n r=$1 + echo "$r" +} +f val +### expect +world +### end + +### nameref_nounset_array +# nameref to array under set -u +set -u +arr=(one two three) +declare -n ref=arr +echo "${ref[1]}" +### expect +two +### end + +### nameref_nounset_write_through +# nameref write-through under set -u +set -u +target="before" +declare -n ref=target +ref="after" +echo "$target" +### expect +after +### end + +### nameref_nounset_harness +# harness pattern: set -euo pipefail with nameref function +set -euo pipefail +get_value() { + local -n out=$1 + out="computed" +} +result="" +get_value result +echo "$result" +### expect +computed +### end