From acaac0ac48d19acf5f154bcb7930dc2e81957d02 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Tue, 23 Jan 2024 15:51:05 +0000 Subject: [PATCH] Fix use-after-free in tilde expansion disciplines (re: 936a1939) When compiling with AddressSanitizer/ASan, the regression tests on tests/tilde.sh line 163 occasionally aborts with a stack trace. In addition, the test on line 155 intermittently fails on a Linux armv7l system (without ASan). Something is wrong in my code here. The ASan stack trace shows a use after free in tilde_expand2() on macro.c line 2734, right after the stkseek() call that restores the stack state -- *and* that this space had been freed earlier via macro.c line 2722, the stkset() call that restores the stack after running a tilde discipline shell function. Evidently, stkfreeze() followed by stkset() is not correct here. The fix, as it turns out, is to simply write a 0 byte to the stack instead of freezing the stack adding a 0 byte, then restoring the stack state with stkseek() instead of stkset(), thus avoiding a potential rearranging of stack memory. --- NEWS | 5 +++++ src/cmd/ksh93/include/version.h | 2 +- src/cmd/ksh93/sh/macro.c | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index a7d8d93c9f69..cc38995e7a4f 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,11 @@ 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. +2024-01-23: + +- Fixed a rare crash or rare incorrect behaviour in .sh.tilde.{get,set} + discipline functions for ~ expansion (see 2021-03-16 below). + 2024-01-22: - Fixed a bug in the loop invariants optimizer (SHOPT_OPTIMIZE) that caused diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index dc55f4278de9..a686737b7c96 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -18,7 +18,7 @@ #define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */ #define SH_RELEASE_SVER "1.1.0-alpha" /* semantic version number: https://semver.org */ -#define SH_RELEASE_DATE "2024-01-22" /* must be in this format for $((.sh.version)) */ +#define SH_RELEASE_DATE "2024-01-23" /* must be in this format for $((.sh.version)) */ #define SH_RELEASE_CPYR "(c) 2020-2024 Contributors to ksh " SH_RELEASE_FORK /* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */ diff --git a/src/cmd/ksh93/sh/macro.c b/src/cmd/ksh93/sh/macro.c index 5533639273fe..6eadbfc2e0ce 100644 --- a/src/cmd/ksh93/sh/macro.c +++ b/src/cmd/ksh93/sh/macro.c @@ -2712,14 +2712,14 @@ static void tilde_expand2(int offset) */ if(!sh.tilde_block && SH_TILDENOD->nvfun && SH_TILDENOD->nvfun->disc) { - stkfreeze(sh.stk,1); /* terminate current stack object to avoid data corruption */ + sfputc(sh.stk,'\0'); /* terminate current stack object to avoid data corruption */ sh.tilde_block = 1; nv_putval(SH_TILDENOD, &stakp[offset], 0); cp = nv_getval(SH_TILDENOD); sh.tilde_block = 0; if(cp[0]=='\0' || cp[0]=='~') cp = NULL; /* do not use empty or unexpanded result */ - stkset(sh.stk,stakp,curoff); /* restore stack to state on function entry */ + stkseek(sh.stk,curoff); /* restore stack to state on function entry */ } /* * Perform default tilde expansion unless overridden.