From 38acc02e78ed403b093dd6672869d4887f2145eb Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Sun, 31 Jul 2022 04:02:03 +0200 Subject: [PATCH] nv_newattr(): Fix out-of-bounds read (re: bdb99741) When converting from -Z to another attribute, if the value of the -Z variable was empty (so -Z0 and an empty value), the loop that skips initial zeros may read before the beginning of the buffer: 2968: if(nv_isattr(np,NV_ZFILL)) 2969: { 2970: while(*sp=='0') sp++; /* skip initial zeros */ 2971: if(!*sp) sp--; /* if number was 0, leave one zero */ 2972: } If the *sp value is empty (just a terminating zero byte), line 2970 does nothing, but line 2971 still decrases the pointer, to before the beginning of the buffer. The fix is to check for an initial zero before running that block. Reproducer (fails intermittently, depending on garbage before *sp): typeset -Z foo= typeset -i foo --- src/cmd/ksh93/include/version.h | 4 ++-- src/cmd/ksh93/sh/name.c | 2 +- src/cmd/ksh93/tests/attributes.sh | 7 +++++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index 16b32300f..b4fc81296 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -17,8 +17,8 @@ #include #define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */ -#define SH_RELEASE_SVER "1.0.0-rc.4" /* semantic version number: https://semver.org */ -#define SH_RELEASE_DATE "2022-07-28" /* must be in this format for $((.sh.version)) */ +#define SH_RELEASE_SVER "1.0.0-rc.5" /* semantic version number: https://semver.org */ +#define SH_RELEASE_DATE "2022-07-31" /* must be in this format for $((.sh.version)) */ #define SH_RELEASE_CPYR "(c) 2020-2022 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/name.c b/src/cmd/ksh93/sh/name.c index 876ed153a..c3cd0e66c 100644 --- a/src/cmd/ksh93/sh/name.c +++ b/src/cmd/ksh93/sh/name.c @@ -2965,7 +2965,7 @@ void nv_newattr (register Namval_t *np, unsigned newatts, int size) np->nvflag = oldatts; if (sp = nv_getval(np)) { - if(nv_isattr(np,NV_ZFILL)) + if(nv_isattr(np,NV_ZFILL) && *sp=='0') { while(*sp=='0') sp++; /* skip initial zeros */ if(!*sp) sp--; /* if number was 0, leave one zero */ diff --git a/src/cmd/ksh93/tests/attributes.sh b/src/cmd/ksh93/tests/attributes.sh index 7a8978576..6134d174a 100755 --- a/src/cmd/ksh93/tests/attributes.sh +++ b/src/cmd/ksh93/tests/attributes.sh @@ -822,5 +822,12 @@ got=$(typeset -F5 num; num=3.25+4.5 eval 'typeset -p num') [[ $got == "$exp" ]] || err_exit 'assignment preceding special built-in command call does not honour pre-set attributes' \ "(expected $(printf %q "$exp"), got $(printf %q "$got"))" +# ====== +unset foo +( + typeset -Z foo= + typeset -i foo +) || err_exit 'failed to convert from -Z to -i' + # ====== exit $((Errors<125?Errors:125))