'trap' commands in shell scripts present a dilemma:
- If we use double-quotes to delimit the command
trap "rmdir '$lockdir'; exit 1" 1 2 15
we get undefined behaviour if $lockdir contains a single-quote,
and also some backslashes might be needed here and there, for
quoting.
- If we use single-quotes to delimit the command
trap 'rmdir "$lockdir"; exit 1' 1 2 15
we soon get into a quoting trouble if the command contains single-quotes.
The best way out, for safety AND maintainability, is to move the bulk
of the command's body into a shell function and then just invoke that
shell function. Then, no unusual quoting is needed at all.
Here's a proposed patch.
From 3b488dd30879405759622d9ba66771119691b014 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Fri, 29 May 2026 15:55:27 +0200
Subject: [PATCH] compile, depcomp, ylwrap: Fix quoting bug in 'trap' command.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Reported by an AI tool in the name of Micha?? Majchrowicz.
Based on the idea from Autoconf commit 416b8f50c9bd4e38f9bc48b946505d2a18f6b1fd:
Use a shell function to avoid quoting hassles inside a 'trap' argument.
* lib/compile (cleanup): New function.
(trap): Use it.
* lib/depcomp (cleanup): New function.
(trap): Use it.
* lib/ylwrap (origdirname): New variable.
(cleanup): New function.
(do_exit): Use it.
---
lib/compile | 5 ++++-
lib/depcomp | 8 ++++----
lib/ylwrap | 6 +++++-
3 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/lib/compile b/lib/compile
index 02ff093c3..1feb2a2d2 100755
--- a/lib/compile
+++ b/lib/compile
@@ -338,7 +338,10 @@ while true; do
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
-trap "rmdir '$lockdir'; exit 1" 1 2 15
+cleanup () {
+ rmdir "$lockdir"
+}
+trap "cleanup; exit 1" 1 2 15
# Run the compile.
"$@"
diff --git a/lib/depcomp b/lib/depcomp
index 9f6725b9e..ed5bef5f0 100755
--- a/lib/depcomp
+++ b/lib/depcomp
@@ -383,11 +383,11 @@ pgcc)
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
- trap "
+ cleanup () {
echo '$0: caught signal, cleaning up...' >&2
- rmdir '$lockdir'
- exit 1
- " 1 2 13 15
+ rmdir "$lockdir"
+ }
+ trap "cleanup; exit 1" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
diff --git a/lib/ylwrap b/lib/ylwrap
index 62aed82da..1d3117bf9 100755
--- a/lib/ylwrap
+++ b/lib/ylwrap
@@ -159,8 +159,12 @@ case $prog in
*[\\/]*) prog=`pwd`/$prog ;;
esac
+origdirname=`pwd`
dirname=ylwrap$$
-do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret'
+cleanup () {
+ cd "$origdirname" && rm -rf $dirname > /dev/null 2>&1
+}
+do_exit='cleanup; (exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
--
2.54.0