From b6ddc1c9aac1259a05cf4fc7c114e9757ee32cf5 Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Fri, 31 Jul 2026 10:10:06 +0200 Subject: [PATCH 1/4] configure discards a user-supplied BASH_SHELL AS_UNSET erased the variable before AC_PATH_PROGS could honour it, so "./configure BASH_SHELL=/path" had no effect and there was no way to point the build at a bash other than the first one on PATH. Nothing presets BASH_SHELL, which was the whole problem with BASH in #895, so declaring it precious is enough. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Xavier Roche --- configure.ac | 3 ++- tests/146_bash-shell.test | 28 ++++++++++++++++++++++++++++ tests/Makefile.am | 1 + 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 7ebd1d05..853b94eb 100644 --- a/configure.ac +++ b/configure.ac @@ -57,7 +57,8 @@ LT_INIT # A real bash, for "make deb" and the test harness. Not searched into BASH: bash presets # that to its own path, and macOS /bin/sh is a bash, so the macro never searches (#895). -AS_UNSET([BASH_SHELL]) +# Nothing presets BASH_SHELL, so it is safe to let the user point it at their own. +AC_ARG_VAR([BASH_SHELL], [path to a real (non-POSIX-mode) bash]) AC_PATH_PROGS([BASH_SHELL], [bash], [/bin/bash]) # Export LD_LIBRARY_PATH name or equivalent. diff --git a/tests/146_bash-shell.test b/tests/146_bash-shell.test index a753533e..a3c0da04 100644 --- a/tests/146_bash-shell.test +++ b/tests/146_bash-shell.test @@ -43,4 +43,32 @@ test "$out" = procsub || { exit 1 } +# Whatever configure picks, an absolute BASH_SHELL from the user must win over the search. +configure="${abs_top_srcdir:-}/configure" +test -r "$configure" || { + echo "no configure script at $configure; tests/Makefile.am must export abs_top_srcdir" >&2 + exit 1 +} + +help=$(bash "$configure" --help) +grep -q '^ *BASH_SHELL ' <<<"$help" || { + echo "configure --help does not advertise BASH_SHELL (AC_ARG_VAR missing)" >&2 + exit 1 +} + +tmp=$(mktemp -d) +trap 'set +e; rm -rf "$tmp"' EXIT +ln -s "$sh" "$tmp/mybash" +mkdir "$tmp/bld" +(cd "$tmp/bld" && BASH_SHELL="$tmp/mybash" bash "$configure" >conf.log 2>&1) || { + echo "configure BASH_SHELL=$tmp/mybash failed:" >&2 + tail -20 "$tmp/bld/conf.log" >&2 + exit 1 +} +got=$(sed -n 's/^BASH_SHELL = //p' "$tmp/bld/Makefile") +test "$got" = "$tmp/mybash" || { + echo "configure discarded BASH_SHELL=$tmp/mybash, kept: $got" >&2 + exit 1 +} + echo "configured bash is $sh ($version)" diff --git a/tests/Makefile.am b/tests/Makefile.am index ec2385a7..983e3e2b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -27,6 +27,7 @@ TESTS_ENVIRONMENT += V6_SUPPORT=$(V6_SUPPORT) # Asserted by 146_bash-shell.test. TESTS_ENVIRONMENT += BASH_SHELL=$(BASH_SHELL) TESTS_ENVIRONMENT += top_srcdir=$(top_srcdir) +TESTS_ENVIRONMENT += abs_top_srcdir=$(abs_top_srcdir) TESTS_ENVIRONMENT += abs_top_builddir=$(abs_top_builddir) TESTS_ENVIRONMENT += CONFIGURED_DATADIR=$(datadir) TESTS_ENVIRONMENT += RENAMEFAIL_LA=$(abs_builddir)/librenamefail.la From 63e24012d3b08c305ea3104a5794015125db60db Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Fri, 31 Jul 2026 11:11:36 +0200 Subject: [PATCH 2/4] Run the nested configure against a symlink farm An in-tree build leaves a config.status in srcdir, and autoconf then refuses the out-of-tree run the test needs. Every CI build leg builds in-tree, so the check failed there while passing on an out-of-tree tree. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Xavier Roche --- tests/146_bash-shell.test | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/146_bash-shell.test b/tests/146_bash-shell.test index a3c0da04..e57c47c7 100644 --- a/tests/146_bash-shell.test +++ b/tests/146_bash-shell.test @@ -58,9 +58,19 @@ grep -q '^ *BASH_SHELL ' <<<"$help" || { tmp=$(mktemp -d) trap 'set +e; rm -rf "$tmp"' EXIT +mkdir "$tmp/src" "$tmp/bld" ln -s "$sh" "$tmp/mybash" -mkdir "$tmp/bld" -(cd "$tmp/bld" && BASH_SHELL="$tmp/mybash" bash "$configure" >conf.log 2>&1) || { + +# Symlink farm rather than the real srcdir: autoconf refuses an out-of-tree run when +# srcdir holds a config.status, which is what an in-tree build leaves behind. +for f in "$abs_top_srcdir"/*; do + case "${f##*/}" in + config.status | config.log | config.h | stamp-h1 | Makefile) continue ;; + esac + ln -s "$f" "$tmp/src/" +done + +(cd "$tmp/bld" && BASH_SHELL="$tmp/mybash" bash "$tmp/src/configure" >conf.log 2>&1) || { echo "configure BASH_SHELL=$tmp/mybash failed:" >&2 tail -20 "$tmp/bld/conf.log" >&2 exit 1 From 531024be085870c09e01df53a62349f0c0d12b53 Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Fri, 31 Jul 2026 11:37:08 +0200 Subject: [PATCH 3/4] Read the resolved bash from the configure trace, not the Makefile The nested configure ran without the flags the outer one was given, so on macOS it died at the openssl check that Homebrew paths satisfy. BASH_SHELL is resolved long before that, so assert on the trace and let the run fail. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Xavier Roche --- tests/146_bash-shell.test | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/146_bash-shell.test b/tests/146_bash-shell.test index e57c47c7..4fe86a89 100644 --- a/tests/146_bash-shell.test +++ b/tests/146_bash-shell.test @@ -70,14 +70,14 @@ for f in "$abs_top_srcdir"/*; do ln -s "$f" "$tmp/src/" done -(cd "$tmp/bld" && BASH_SHELL="$tmp/mybash" bash "$tmp/src/configure" >conf.log 2>&1) || { - echo "configure BASH_SHELL=$tmp/mybash failed:" >&2 - tail -20 "$tmp/bld/conf.log" >&2 - exit 1 -} -got=$(sed -n 's/^BASH_SHELL = //p' "$tmp/bld/Makefile") +# Read the trace, not the generated Makefile, and ignore the exit status: BASH_SHELL is +# resolved long before the library checks, which need a build environment we cannot assume +# (macOS CI hands its own configure the Homebrew paths for openssl). +(cd "$tmp/bld" && BASH_SHELL="$tmp/mybash" bash "$tmp/src/configure" >conf.log 2>&1) || true +got=$(sed -n 's/^checking for bash\.\.\. //p' "$tmp/bld/conf.log") test "$got" = "$tmp/mybash" || { - echo "configure discarded BASH_SHELL=$tmp/mybash, kept: $got" >&2 + echo "configure discarded BASH_SHELL=$tmp/mybash, resolved: ${got:-}" >&2 + tail -20 "$tmp/bld/conf.log" >&2 exit 1 } From ee3895f2f3e8a004dc8f00d0d4326cbe11c86e15 Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Fri, 31 Jul 2026 12:23:22 +0200 Subject: [PATCH 4/4] Assert the value that reaches $(BASH_SHELL), not the macro's decision Reading the configure trace let a mutant through: resolve the override correctly, clobber BASH_SHELL one line later, and both assertions passed while every Makefile got the wrong shell. Prefer the generated Makefile and keep the trace only as a fallback for a configure that dies early. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Xavier Roche --- configure.ac | 2 +- tests/146_bash-shell.test | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index 853b94eb..f74c3179 100644 --- a/configure.ac +++ b/configure.ac @@ -57,7 +57,7 @@ LT_INIT # A real bash, for "make deb" and the test harness. Not searched into BASH: bash presets # that to its own path, and macOS /bin/sh is a bash, so the macro never searches (#895). -# Nothing presets BASH_SHELL, so it is safe to let the user point it at their own. +# BASH_SHELL isn't preset the way BASH is, so AC_ARG_VAR needs no guard. AC_ARG_VAR([BASH_SHELL], [path to a real (non-POSIX-mode) bash]) AC_PATH_PROGS([BASH_SHELL], [bash], [/bin/bash]) diff --git a/tests/146_bash-shell.test b/tests/146_bash-shell.test index 4fe86a89..4d83062d 100644 --- a/tests/146_bash-shell.test +++ b/tests/146_bash-shell.test @@ -61,8 +61,7 @@ trap 'set +e; rm -rf "$tmp"' EXIT mkdir "$tmp/src" "$tmp/bld" ln -s "$sh" "$tmp/mybash" -# Symlink farm rather than the real srcdir: autoconf refuses an out-of-tree run when -# srcdir holds a config.status, which is what an in-tree build leaves behind. +# Symlink farm, not the real srcdir: an in-tree config.status makes autoconf refuse it. for f in "$abs_top_srcdir"/*; do case "${f##*/}" in config.status | config.log | config.h | stamp-h1 | Makefile) continue ;; @@ -70,13 +69,20 @@ for f in "$abs_top_srcdir"/*; do ln -s "$f" "$tmp/src/" done -# Read the trace, not the generated Makefile, and ignore the exit status: BASH_SHELL is -# resolved long before the library checks, which need a build environment we cannot assume -# (macOS CI hands its own configure the Homebrew paths for openssl). -(cd "$tmp/bld" && BASH_SHELL="$tmp/mybash" bash "$tmp/src/configure" >conf.log 2>&1) || true -got=$(sed -n 's/^checking for bash\.\.\. //p' "$tmp/bld/conf.log") +# Prefer the Makefile: it proves the value that reaches $(BASH_SHELL), not just the macro's +# decision. configure may die on a library check before writing one, so fall back to the +# trace it printed earlier. +(cd "$tmp/bld" && BASH_SHELL="$tmp/mybash" bash "$tmp/src/configure" --disable-https >conf.log 2>&1) || true +if test -f "$tmp/bld/Makefile"; then + got=$(sed -n 's/^BASH_SHELL = //p' "$tmp/bld/Makefile") + from="Makefile" +else + got=$(sed -n 's/^checking for bash\.\.\. //p' "$tmp/bld/conf.log") + got=${got#"(cached) "} + from="trace" +fi test "$got" = "$tmp/mybash" || { - echo "configure discarded BASH_SHELL=$tmp/mybash, resolved: ${got:-}" >&2 + echo "configure discarded BASH_SHELL=$tmp/mybash, $from has: ${got:-}" >&2 tail -20 "$tmp/bld/conf.log" >&2 exit 1 }