From 8f5e4eeaa5a441d6d82d4473196c8654ab375bf0 Mon Sep 17 00:00:00 2001 From: Defame1297 Date: Sat, 20 Jun 2026 22:16:49 +0000 Subject: [PATCH] fix(hooks): scope install traps to subshells to prevent RETURN trap leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit trap '...' RETURN inside a function is NOT local to that function in bash — it persists in the calling scope and fires on every subsequent function return. After install_shellcheck set the trap, it fired again when ensure_tool returned with $tmp_dir unbound, causing nounset abort. Fix: change install functions from {} to () (subshell bodies) and use trap EXIT instead of RETURN. The trap is now scoped to the subshell and cannot leak to callers. Also fixes double _os() call in install_jq and removes redundant local declarations (subshells don't need them). Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01TP4EGbBg3XMcyF28Lx78XJ --- scripts/setup-hooks.sh | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/scripts/setup-hooks.sh b/scripts/setup-hooks.sh index 56b33aa..2bdd258 100755 --- a/scripts/setup-hooks.sh +++ b/scripts/setup-hooks.sh @@ -39,49 +39,44 @@ _arch() { esac } -install_shellcheck() { - local os arch tarball url tmp_dir +install_shellcheck() ( os="$(_os)" arch="$(_arch)" tarball="shellcheck-v${SHELLCHECK_VERSION}.${os}.${arch}.tar.xz" url="https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/${tarball}" tmp_dir="$(mktemp -d)" - trap 'rm -rf "$tmp_dir"' RETURN + trap 'rm -rf "$tmp_dir"' EXIT echo "Installing shellcheck v${SHELLCHECK_VERSION}..." curl -fsSL "$url" -o "$tmp_dir/$tarball" tar -xJf "$tmp_dir/$tarball" -C "$tmp_dir" --strip-components=1 install -m 755 "$tmp_dir/shellcheck" "$TOOL_INSTALL_DIR/shellcheck" echo "Installed: $TOOL_INSTALL_DIR/shellcheck" -} +) -install_jq() { - local os arch binary url tmp_dir +install_jq() ( os="$(_os)" + [[ "$os" == "darwin" ]] && os="macos" arch="$(_arch | sed 's/x86_64/amd64/; s/aarch64/arm64/')" - [[ "$(_os)" == "darwin" ]] && os="macos" - binary="jq-${os}-${arch}" - url="https://github.com/jqlang/jq/releases/download/jq-${JQ_VERSION}/${binary}" + url="https://github.com/jqlang/jq/releases/download/jq-${JQ_VERSION}/jq-${os}-${arch}" tmp_dir="$(mktemp -d)" - trap 'rm -rf "$tmp_dir"' RETURN + trap 'rm -rf "$tmp_dir"' EXIT echo "Installing jq v${JQ_VERSION}..." curl -fsSL "$url" -o "$tmp_dir/jq" install -m 755 "$tmp_dir/jq" "$TOOL_INSTALL_DIR/jq" echo "Installed: $TOOL_INSTALL_DIR/jq" -} +) -install_yq() { - local os arch binary url tmp_dir +install_yq() ( os="$(_os)" arch="$(_arch | sed 's/x86_64/amd64/; s/aarch64/arm64/')" - binary="yq_${os}_${arch}" - url="https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/${binary}" + url="https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/yq_${os}_${arch}" tmp_dir="$(mktemp -d)" - trap 'rm -rf "$tmp_dir"' RETURN + trap 'rm -rf "$tmp_dir"' EXIT echo "Installing yq v${YQ_VERSION}..." curl -fsSL "$url" -o "$tmp_dir/yq" install -m 755 "$tmp_dir/yq" "$TOOL_INSTALL_DIR/yq" echo "Installed: $TOOL_INSTALL_DIR/yq" -} +) ensure_tool() { local tool="$1"