From cbdb8bc85aa8c06bc481a30c6abbac5b8b4ee319 Mon Sep 17 00:00:00 2001 From: Johnothan King Date: Sat, 4 Jan 2025 19:01:30 -0800 Subject: [PATCH] Scope variables to subshell before setting their discipline (#811) Currently, running the tilde.sh tests under ASan will fail with a use after free. The crash occurs because the discipline function is assigned before .sh.tilde is scoped to the currently active virtual subshell. After this, sh_subshell() frees the discipline function by calling nv_delete() upon subshell completion, but because of improper scoping, .sh.tilde in the parent subshell now has an np->nvfun which points to freed memory. (As a side note, I'll note that this bug can be reproduced for any variable assigned a discipline function, not just .sh.tilde.) src/cmd/ksh93/sh/xec.c: sh_exec(): - Use sh_assignok to scope variables to subshells before assigning a new discipline function to them. --- NEWS | 7 +++++++ src/cmd/ksh93/include/version.h | 2 +- src/cmd/ksh93/sh/xec.c | 7 +++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 29bb035a6f07..c065459865b8 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,13 @@ This documents significant changes in the dev branch of ksh 93u+m. For full details, see the git log at: https://github.com/ksh93/ksh Uppercase BUG_* IDs are shell bug IDs as used by the Modernish shell library. +2025-01-05: + +- Fixed a crash that could occur if a discipline function was first assigned + to a variable in a virtual subshell before the variable was scoped to that + subshell, then upon subshell completion another discipline function of the + same type was assigned to that selfsame variable in the parent shell. + 2025-01-03: - The performance of virtual subshells has been significantly improved by diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index bfa197b5d931..a700f32711b9 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -18,7 +18,7 @@ #include #include "git.h" -#define SH_RELEASE_DATE "2025-01-03" /* must be in this format for $((.sh.version)) */ +#define SH_RELEASE_DATE "2025-01-05" /* must be in this format for $((.sh.version)) */ /* * This comment keeps SH_RELEASE_DATE a few lines away from SH_RELEASE_SVER to avoid * merge conflicts when cherry-picking dev branch commits onto a release branch. diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c index f8ab80fe5112..1ea9b56313ca 100644 --- a/src/cmd/ksh93/sh/xec.c +++ b/src/cmd/ksh93/sh/xec.c @@ -2382,7 +2382,14 @@ int sh_exec(const Shnode_t *t, int flags) if(npv) { if(!sh.mktype) + { /* + * Set the discipline function. If this is done in a subshell, the variable + * must be scoped to the subshell before nvfun is set to the discipline. + */ + if(sh.subshell && !sh.subshare) + sh_assignok(npv, 1); cp = nv_setdisc(npv,cp,np,(Namfun_t*)npv); + } if(!cp) { errormsg(SH_DICT,ERROR_exit(1),e_baddisc,fname);