sh: Restore $((x)) error checking after fix for $((-9223372036854775808))

SVN r342880 was designed to fix $((-9223372036854775808)) and things like
$((0x8000000000000000)) but also broke error detection for values of
variables without dollar sign ($((x))).

For compatibility, overflow in plain literals continues to be ignored and
the value is clamped to the boundary (except 9223372036854775808 which is
changed to -9223372036854775808).

Reviewed by:	se (although he would like error checking to be removed)
MFC after:	2 weeks
X-MFC-with:	r342880
Differential Revision:	https://reviews.freebsd.org/D18926
This commit is contained in:
jilles 2019-02-10 22:23:05 +00:00
parent c757937316
commit bdbf8ff3c0
7 changed files with 62 additions and 3 deletions

View File

@ -104,7 +104,7 @@ static arith_t arith_lookupvarint(char *varname)
if (str == NULL || *str == '\0')
str = "0";
errno = 0;
result = strtoarith_t(str, &p, 0);
result = strtoarith_t(str, &p);
if (errno != 0 || *p != '\0')
yyerror("variable conversion error");
return result;

View File

@ -90,4 +90,5 @@ union yystype {
extern union yystype yylval;
arith_t strtoarith_t(const char *restrict nptr, char **restrict endptr);
int yylex(void);

View File

@ -35,6 +35,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
@ -50,6 +52,32 @@ __FBSDID("$FreeBSD$");
#error Arithmetic tokens are out of order.
#endif
arith_t
strtoarith_t(const char *restrict nptr, char **restrict endptr)
{
arith_t val;
while (isspace((unsigned char)*nptr))
nptr++;
switch (*nptr) {
case '-':
return strtoimax(nptr, endptr, 0);
case '0':
return (arith_t)strtoumax(nptr, endptr, 0);
default:
val = (arith_t)strtoumax(nptr, endptr, 0);
if (val >= 0)
return val;
else if (val == ARITH_MIN) {
errno = ERANGE;
return ARITH_MIN;
} else {
errno = ERANGE;
return ARITH_MAX;
}
}
}
int
yylex(void)
{
@ -78,7 +106,7 @@ yylex(void)
case '7':
case '8':
case '9':
yylval.val = strtoarith_t(buf, &end, 0);
yylval.val = strtoarith_t(buf, &end);
arith_buf = end;
return ARITH_NUM;
case 'A':

View File

@ -59,7 +59,6 @@
*/
typedef intmax_t arith_t;
#define ARITH_FORMAT_STR "%" PRIdMAX
#define strtoarith_t(nptr, endptr, base) (intmax_t)strtoumax(nptr, endptr, base)
#define ARITH_MIN INTMAX_MIN
#define ARITH_MAX INTMAX_MAX

View File

@ -22,6 +22,8 @@ ${PACKAGE}FILES+= arith12.0
${PACKAGE}FILES+= arith13.0
${PACKAGE}FILES+= arith14.0
${PACKAGE}FILES+= arith15.0
${PACKAGE}FILES+= arith16.0
${PACKAGE}FILES+= arith17.0
${PACKAGE}FILES+= assign1.0
${PACKAGE}FILES+= cmdsubst1.0
${PACKAGE}FILES+= cmdsubst2.0

View File

@ -0,0 +1,26 @@
# $FreeBSD$
failures=0
for x in \
0x10000000000000000 \
-0x8000000000000001 \
0xfffffffffffffffffffffffffffffffff \
-0xfffffffffffffffffffffffffffffffff \
02000000000000000000000 \
9223372036854775808 \
9223372036854775809 \
-9223372036854775809 \
9999999999999999999999999 \
-9999999999999999999999999
do
msg=$({
v=$((x)) || :
} 3>&1 >&2 2>&3 3>&-)
r=$?
if [ "$r" = 0 ] || [ -z "$msg" ]; then
printf 'Failed: %s\n' "$x"
: $((failures += 1))
fi
done
exit $((failures > 0))

View File

@ -0,0 +1,3 @@
# $FreeBSD$
[ $((9223372036854775809)) -gt 0 ]