Permalink
Browse files

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

…08))

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
  • Loading branch information...
jillest committed Feb 10, 2019
1 parent c757937 commit bdbf8ff3c037e3ea0af749f43843000f2a9a88ed
@@ -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;
@@ -90,4 +90,5 @@ union yystype {

extern union yystype yylval;

arith_t strtoarith_t(const char *restrict nptr, char **restrict endptr);
int yylex(void);
@@ -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':
@@ -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

@@ -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
@@ -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))
@@ -0,0 +1,3 @@
# $FreeBSD$

[ $((9223372036854775809)) -gt 0 ]

0 comments on commit bdbf8ff

Please sign in to comment.