From 7b5b0a5d54ebce53226386d37cf34d5e514f6263 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Mon, 13 Sep 2021 04:23:50 +0200 Subject: [PATCH] Fix octal number arguments in printf integer arithmetic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug 1: POSIX requires numbers used as arguments for all the %d, %u... in printf to be interpreted as in the C language, so printf '%d\n' 010 should output 8 when the posix option is on. However, it outputs 10. This bug was introduced as a side effect of a change introduced in the 2012-02-07 version of ksh 93u+m, which caused the recognition of leading-zero numbers as octal in arithmetic expressions to be disabled outside ((...)) and $((...)). However, POSIX requires leading-zero octal numbers to be recognised for printf, too. The change in question introduced a sh.arith flag that is set while we're processing a POSIX arithmetic expression, i.e., one that recognises leading-zero octal numbers. Bug 2: Said flag is not reset in a command substitution used within an arithmetic expression. A command substitution should be a completely new context, so the following should both output 10: $ ksh -c 'integer x; x=010; echo $x' 10 # ok; it's outside ((…)) so octals are not recognised $ ksh -c 'echo $(( $(integer x; x=010; echo $x) ))' 8 # bad; $(comsub) should create new non-((…)) context src/cmd/ksh93/bltins/print.c: extend(): - For the u, d, i, o, x, and X conversion modifiers, set the POSIX arithmetic context flag before calling sh_strnum() to convert the argument. This fixes bug 1. src/cmd/ksh93/sh/subshell.c: sh_subshell(): - When invoking a command substitution, save and unset the POSIX arithmetic context flag. Restore it at the end. This fixes bug 2. Reported-by: @stephane-chazelas Resolves: https://github.com/ksh93/ksh/issues/326 --- NEWS | 12 ++++++++++++ src/cmd/ksh93/COMPATIBILITY | 5 +++++ src/cmd/ksh93/bltins/print.c | 2 ++ src/cmd/ksh93/data/builtins.c | 2 +- src/cmd/ksh93/include/defs.h | 2 +- src/cmd/ksh93/include/version.h | 2 +- src/cmd/ksh93/sh/subshell.c | 6 ++++++ src/cmd/ksh93/tests/arith.sh | 22 ++++++++++++++++++++++ 8 files changed, 50 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index a1ffbb7b5..37e6c276a 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,18 @@ For full details, see the git log at: https://github.com/ksh93/ksh Any uppercase BUG_* names are modernish shell bug IDs. +2021-09-13: + +- Fixed a bug introduced in 93u+ 2012-02-07 that caused the 'printf' builtin + (and its 'print -f' equivalent) to fail to recognise integer arguments with a + leading zero as octal numbers. For example, 'printf "%d\n" 010' now once + again outputs '8' instead of '10'. + +- Disable the POSIX arithmetic context while running a command substitution + invoked from within an arithmetic expression. This fixes a bug that caused + integer arguments with a leading zero to be incorrectly interpreted as octal + numbers in non-POSIX arithmetic contexts within such command substitutions. + 2021-09-12: - When invoking a script without an interpreter/hashbang path on Linux and diff --git a/src/cmd/ksh93/COMPATIBILITY b/src/cmd/ksh93/COMPATIBILITY index 94154d6b6..a029ed241 100644 --- a/src/cmd/ksh93/COMPATIBILITY +++ b/src/cmd/ksh93/COMPATIBILITY @@ -151,6 +151,11 @@ For more details, see the NEWS file and for complete details, see the git log. correctly negates another '!', e.g., [[ ! ! 1 -eq 1 ]] now returns 0/true. Note that this has always been the case for 'test'/'['. +28. In the 'printf' builtin (and the 'print -f' equivalent), numeric + arguments with a leading zero are now once again recognized as octal + numbers as in ksh93 versions before 2012-02-07, and as POSIX requires. + For example, 'printf "%d\n" 010' now once again outputs '8'. + ____________________________________________________________________________ KSH-93 VS. KSH-88 diff --git a/src/cmd/ksh93/bltins/print.c b/src/cmd/ksh93/bltins/print.c index 26808dc53..b65b4493e 100644 --- a/src/cmd/ksh93/bltins/print.c +++ b/src/cmd/ksh93/bltins/print.c @@ -882,7 +882,9 @@ static int extend(Sfio_t* sp, void* v, Sffmt_t* fe) } break; default: + shp->inarith = 1; /* POSIX compliance: recognize octal constants, e.g. printf '%d\n' 010 */ d = sh_strnum(argp,&lastchar,0); + shp->inarith = 0; if(doutpool); sh_sigcheck(shp); @@ -591,6 +592,9 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, volatile int flags, int comsub) { if(comsub) { + /* a comsub within an arithmetic expression must not itself be in an arithmetic context */ + save_inarith = shp->inarith; + shp->inarith = 0; /* disable job control */ shp->spid = 0; sp->jobcontrol = job.jobcontrol; @@ -734,6 +738,8 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, volatile int flags, int comsub) sh_close(sp->tmpfd); } shp->fdstatus[1] = sp->fdstatus; + /* restore POSIX arithmetic context flag */ + shp->inarith = save_inarith; } if(!shp->subshare) { diff --git a/src/cmd/ksh93/tests/arith.sh b/src/cmd/ksh93/tests/arith.sh index 8e33b2ce5..96171efc0 100755 --- a/src/cmd/ksh93/tests/arith.sh +++ b/src/cmd/ksh93/tests/arith.sh @@ -876,5 +876,27 @@ then fi unset got +# ====== +# https://github.com/ksh93/ksh/issues/326 +for m in u d i o x X +do + case $m in + o) exp="10;21;32;" ;; + x) exp="8;11;1a;" ;; + X) exp="8;11;1A;" ;; + *) exp="8;17;26;" ;; + esac + got=${ printf "%$m;" 010 021 032; } + [[ $got == "$exp" ]] || err_exit "printf %$m does not recognize octal arguments" \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" +done + +# https://github.com/ksh93/ksh/issues/326#issuecomment-917707463 +exp=18 +got=$(( $(integer x; x=010; echo $x) + 010 )) +# ^^^ decimal ^^^ octal +[[ $got == "$exp" ]] || err_exit 'Integer with leading zero incorrectly interpreted as octal in non-POSIX arith context' \ + "(expected $(printf %q "$exp"), got $(printf %q "$got"))" + # ====== exit $((Errors<125?Errors:125))