From 56c2e13e929e29c2da22e48eb5214b3881c9143a Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Mon, 15 Nov 2021 18:49:19 +0100 Subject: [PATCH] arith: Fix variables 'nan' and 'inf' in arithmetic for POSIX mode The --posix compliance option now disables the case-insensitive special floating point constants Inf and NaN so that all case variants of $((inf)) and $((nan)) refer to the variables by those names as the standard requires. (BUG_ARITHNAN) src/cmd/ksh93/sh/arith.c: arith(): - Only do case-insensitive checks for "Inf" and "NaN" if the POSIX option is off. --- NEWS | 6 ++++++ src/cmd/ksh93/include/version.h | 2 +- src/cmd/ksh93/sh.1 | 11 ++++++++--- src/cmd/ksh93/sh/arith.c | 4 ++-- src/cmd/ksh93/tests/arith.sh | 22 ++++++++++++++++++++++ 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 6ee8a9a33..47201fd49 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,12 @@ For full details, see the git log at: https://github.com/ksh93/ksh Any uppercase BUG_* names are modernish shell bug IDs. +2021-11-15: + +- In arithmetic evaluation, the --posix compliance option now disables the + special floating point constants Inf and NaN so that $((inf)) and $((nan)) + refer to the variables by those names as the standard requires. (BUG_ARITHNAN) + 2021-11-14: - Fixed: ksh crashed after unsetting .sh.match and then matching a pattern. diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index 0421443d4..56b722d5c 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -21,7 +21,7 @@ #define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */ #define SH_RELEASE_SVER "1.0.0-beta.2" /* semantic version number: https://semver.org */ -#define SH_RELEASE_DATE "2021-11-14" /* must be in this format for $((.sh.version)) */ +#define SH_RELEASE_DATE "2021-11-15" /* must be in this format for $((.sh.version)) */ #define SH_RELEASE_CPYR "(c) 2020-2021 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.1 b/src/cmd/ksh93/sh.1 index 608d1898c..4fda9fbe2 100644 --- a/src/cmd/ksh93/sh.1 +++ b/src/cmd/ksh93/sh.1 @@ -2924,11 +2924,12 @@ arithmetic or long double precision floating point for systems that provide this data type. Floating point constants follow the ANSI-C programming language floating point conventions. -The floating point constants -.B Nan +The case-insensitive floating point constants +.B NaN and .B Inf -can be used to represent "not a number" and infinity respectively. +can be used to represent "not a number" and infinity respectively, +unless the \fBposix\fR shell option is on. Integer constants follow the ANSI-C programming language integer constant conventions although only single byte character constants are recognized and character casts @@ -7245,6 +7246,10 @@ disables the \fB&>\fR redirection shorthand; makes the \fB<>\fR redirection operator default to redirecting standard input if no file descriptor number precedes it; .IP \[bu] +disables the special floating point constants \fBInf\fR and \fBNaN\fR in +arithmetic evaluation so that, e.g., \fB$((inf))\fR and \fB$((nan))\fR refer +to the variables by those names; +.IP \[bu] changes the \fBtest\fR/\fB[\fR built-in command to make its deprecated \fIexpr1\fR \fB-a\fR \fIexpr2\fR and \fIexpr1\fR \fB-o\fR \fIexpr2\fR operators work even if \fIexpr1\fR equals "\fB!\fR" or "\fb(\fR" (which means the diff --git a/src/cmd/ksh93/sh/arith.c b/src/cmd/ksh93/sh/arith.c index 2a9097609..0f59072f7 100644 --- a/src/cmd/ksh93/sh/arith.c +++ b/src/cmd/ksh93/sh/arith.c @@ -349,14 +349,14 @@ static Sfdouble_t arith(const char **ptr, struct lval *lvalue, int type, Sfdoubl } *str = 0; cp = (char*)*ptr; - if ((cp[0] == 'i' || cp[0] == 'I') && (cp[1] == 'n' || cp[1] == 'N') && (cp[2] == 'f' || cp[2] == 'F') && cp[3] == 0) + if(!sh_isoption(SH_POSIX) && (cp[0] == 'i' || cp[0] == 'I') && (cp[1] == 'n' || cp[1] == 'N') && (cp[2] == 'f' || cp[2] == 'F') && cp[3] == 0) { Inf = strtold("Inf", NiL); Infnod.nvalue.ldp = &Inf; np = &Infnod; nv_onattr(np,NV_NOFREE|NV_LDOUBLE|NV_RDONLY); } - else if ((cp[0] == 'n' || cp[0] == 'N') && (cp[1] == 'a' || cp[1] == 'A') && (cp[2] == 'n' || cp[2] == 'N') && cp[3] == 0) + else if(!sh_isoption(SH_POSIX) && (cp[0] == 'n' || cp[0] == 'N') && (cp[1] == 'a' || cp[1] == 'A') && (cp[2] == 'n' || cp[2] == 'N') && cp[3] == 0) { NaN = strtold("NaN", NiL); NaNnod.nvalue.ldp = &NaN; diff --git a/src/cmd/ksh93/tests/arith.sh b/src/cmd/ksh93/tests/arith.sh index 96171efc0..accf3091c 100755 --- a/src/cmd/ksh93/tests/arith.sh +++ b/src/cmd/ksh93/tests/arith.sh @@ -898,5 +898,27 @@ got=$(( $(integer x; x=010; echo $x) + 010 )) [[ $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"))" +# ====== +# BUG_ARITHNAN: In ksh <= 93u+m 2021-11-15 and zsh 5.6 - 5.8, the case-insensitive +# floating point constants Inf and NaN are recognised in arithmetic evaluation, +# overriding any variables with the names Inf, NaN, INF, nan, etc. +if (set --posix) 2>/dev/null +then set --posix + Inf=42 NaN=13 + inf=421 nan=137 + INF=429 NAN=937 + typeset -l v=$((Inf)),$((NaN)),$((inf)),$((nan)),$((INF)),$((NAN)) + case $v in + ( inf,nan,inf,nan,inf,nan ) + err_exit "posix: arith: inf/nan override variables" ;; + ( "$Inf,$NaN,$inf,$nan,$INF,$NAN" ) + : mustNotHave BUG_ARITHNAN ;; + ( * ) + err_exit "posix: arith: weird inf/nan problem: $(printf %q "$v")" ;; + esac + unset -v Inf NaN inf nan INF NAN v + set --noposix +fi + # ====== exit $((Errors<125?Errors:125))