diff --git a/packages/mosaic/framework/tools/wake/_wake-common.sh b/packages/mosaic/framework/tools/wake/_wake-common.sh index fc659711..ad7b2342 100755 --- a/packages/mosaic/framework/tools/wake/_wake-common.sh +++ b/packages/mosaic/framework/tools/wake/_wake-common.sh @@ -239,9 +239,45 @@ _wake_init_dir() { # silencing every abort thereafter. The fd is allocated dynamically (>= 10), # so it cannot collide with the wake lock fds (8) or the detector run-loop # lock (9). +# +# Init also PINS the BASH_LINENO convention the site coordinates depend on: +# a helper call written across a backslash continuation must report at its +# FIRST physical line (the denominator artifact's convention). That was +# measured on a developer bash (5.3.x); CI runs whatever bash its base image +# baked in, and that version floats silently between image rebuilds. A bash +# that disagrees would shift every continuation-site coordinate by one line +# UNDER the validation instead of in front of it — so the convention is +# asserted at runtime, in the same bash binary that runs the suite, and a +# disagreeing bash aborts the suite loudly instead of skewing coordinates. +_wake_assert_lineno_pin() { + local _wa_pin_tmp _wa_pin_got + _wa_pin_tmp="$(mktemp)" || { + _wake_assert_err_note "WAKE-ASSERT INIT ABORT: mktemp failed; cannot pin the BASH_LINENO convention — a pin that silently does not run is not a pin (#973)" + exit 97 + } + cat >"$_wa_pin_tmp" <<'WAKE_ASSERT_PIN' +_wap() { printf '%s\n' "${BASH_LINENO[0]}"; } +( + _wap simple + _wap \ + continuation +) +WAKE_ASSERT_PIN + # WAKE_ASSERT_PIN_BASH: test-only interpreter override so the pin's abort + # arm can be PROVEN to fire (microtest C10) — bash resets $BASH at startup, + # so the real probe interpreter cannot be spoofed from the environment. + _wa_pin_got="$("${WAKE_ASSERT_PIN_BASH:-${BASH:-bash}}" "$_wa_pin_tmp" 2>/dev/null)" + rm -f "$_wa_pin_tmp" + if [ "$_wa_pin_got" != "$(printf '3\n4')" ]; then + _wake_assert_err_note "WAKE-ASSERT INIT ABORT: BASH_LINENO convention violated on bash ${BASH_VERSION}: probe reported [${_wa_pin_got:-}], expected [3 4] (simple call at own line, continuation call at FIRST physical line) — site coordinates are untrustworthy on this bash (#973)" + exit 97 + fi +} + wake_assert_init() { if [ -z "${_wake_assert_err_fd:-}" ]; then exec {_wake_assert_err_fd}>&2 + _wake_assert_lineno_pin fi } diff --git a/packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh b/packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh index cee0e51b..7b043eed 100755 --- a/packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh +++ b/packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh @@ -30,6 +30,10 @@ # broken (ARMED line, no abort). C3..C6 require the ARMED line AND the # aborting site's ledger row (append lands BEFORE the grep runs, so an # abort can never shorten the count it is part of). +# C10 the BASH_LINENO pin's abort arm fires: under a probe interpreter that +# misreports the continuation line, wake_assert_init aborts loudly and +# nothing past init executes — a pin whose failure arm was never seen +# firing is an undertaking, not a control. set -uo pipefail HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -225,6 +229,24 @@ else check C9 1 "rc=$rc out=$(printf '%s' "$out" | tail -n 3 | tr '\n' ' ')" fi +# --- C10: lineno pin aborts under an interpreter that breaks the convention - +cat >"$TMP/fake-bash" <<'FAKE' +#!/usr/bin/env bash +# stand-in for a bash whose BASH_LINENO convention differs: misreports the +# continuation call one line low (the exact skew the pin exists to catch) +printf '3\n5\n' +FAKE +chmod +x "$TMP/fake-bash" +out="$(WAKE_ASSERT_PIN_BASH="$TMP/fake-bash" bash -c '. "$WAKE_COMMON" && wake_assert_init && echo REACHED-PAST-INIT' 2>&1)" +rc=$? +if [ "$rc" -ne 0 ] && + ! printf '%s' "$out" | grep -q 'REACHED-PAST-INIT' && + printf '%s' "$out" | grep -q 'WAKE-ASSERT INIT ABORT: BASH_LINENO convention violated'; then + check C10 0 "" +else + check C10 1 "rc=$rc out=$(printf '%s' "$out" | tail -n 2 | tr '\n' ' ')" +fi + echo if [ "$fails" -gt 0 ]; then echo "microtest-wake-assert: FAILED ($fails check(s))" >&2