git: f44ac8cc9c10 - main - sh: Fix job pointer invalidation with trapsasync

From: Jilles Tjoelker <jilles_at_FreeBSD.org>
Date: Wed, 19 Nov 2025 20:32:18 UTC
The branch main has been updated by jilles:

URL: https://cgit.FreeBSD.org/src/commit/?id=f44ac8cc9c10d7305223a10b8dbd8e234388cc73

commit f44ac8cc9c10d7305223a10b8dbd8e234388cc73
Author:     Jilles Tjoelker <jilles@FreeBSD.org>
AuthorDate: 2025-11-17 17:42:01 +0000
Commit:     Jilles Tjoelker <jilles@FreeBSD.org>
CommitDate: 2025-11-19 20:30:39 +0000

    sh: Fix job pointer invalidation with trapsasync
    
    Calling dotrap() can do almost anything, including reallocating the
    jobtab array. Convert the job pointer to an index before calling
    dotrap() and then restore a proper job pointer afterwards.
    
    PR:             290330
    Reported by:    bdrewery
    Reviewed by:    bdrewery
    Differential Revision:  https://reviews.freebsd.org/D53793
---
 bin/sh/jobs.c                   | 6 +++++-
 bin/sh/tests/execution/Makefile | 1 +
 bin/sh/tests/execution/bg14.0   | 9 +++++++++
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c
index 0aaff5e1e140..a4cd76473921 100644
--- a/bin/sh/jobs.c
+++ b/bin/sh/jobs.c
@@ -1078,6 +1078,7 @@ waitforjob(struct job *jp, int *signaled)
 #if JOBS
 	int propagate_int = jp->jobctl && jp->foreground;
 #endif
+	int jobindex;
 	int status;
 	int st;
 
@@ -1085,8 +1086,11 @@ waitforjob(struct job *jp, int *signaled)
 	TRACE(("waitforjob(%%%td) called\n", jp - jobtab + 1));
 	while (jp->state == 0)
 		if (dowait(DOWAIT_BLOCK | (Tflag ? DOWAIT_SIG |
-		    DOWAIT_SIG_TRAP : 0), jp) == -1)
+		    DOWAIT_SIG_TRAP : 0), jp) == -1) {
+			jobindex = jp - jobtab;
 			dotrap();
+			jp = jobtab + jobindex;
+		}
 #if JOBS
 	if (jp->jobctl) {
 		if (ttyfd >= 0 && tcsetpgrp(ttyfd, rootpid) < 0)
diff --git a/bin/sh/tests/execution/Makefile b/bin/sh/tests/execution/Makefile
index 53cb97db9393..dde562a082cd 100644
--- a/bin/sh/tests/execution/Makefile
+++ b/bin/sh/tests/execution/Makefile
@@ -18,6 +18,7 @@ ${PACKAGE}FILES+=		bg10.0 bg10.0.stdout
 ${PACKAGE}FILES+=		bg11.0
 ${PACKAGE}FILES+=		bg12.0
 ${PACKAGE}FILES+=		bg13.0
+${PACKAGE}FILES+=		bg14.0
 ${PACKAGE}FILES+=		env1.0
 ${PACKAGE}FILES+=		fork1.0
 ${PACKAGE}FILES+=		fork2.0
diff --git a/bin/sh/tests/execution/bg14.0 b/bin/sh/tests/execution/bg14.0
new file mode 100644
index 000000000000..e27f77e9b7b3
--- /dev/null
+++ b/bin/sh/tests/execution/bg14.0
@@ -0,0 +1,9 @@
+T=`mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXXXX`
+trap 'rm -rf "$T"' 0
+cd "$T" || exit 3
+mkfifo fifo1 || exit 3
+set -T
+trap "for i in 1 2 3 4; do sleep 1 & done" USR1
+sleep 1 &
+{ kill -USR1 "$$"; echo .; } >fifo1 &
+(read dummy <fifo1)