summaryrefslogtreecommitdiff
path: root/bin/sh
diff options
context:
space:
mode:
authorJilles Tjoelker <jilles@FreeBSD.org>2019-02-10 22:23:05 +0000
committerJilles Tjoelker <jilles@FreeBSD.org>2019-02-10 22:23:05 +0000
commitaac5464b6108116bc4172b47f54854f6f85c7a64 (patch)
tree1151ffbe371a28cf932a79a8fa5e1934769b5385 /bin/sh
parent2a0f9d54162cfb8dbf1cd4cc5dd59aaa9f98a08e (diff)
downloadsrc-test-aac5464b6108116bc4172b47f54854f6f85c7a64.tar.gz
src-test-aac5464b6108116bc4172b47f54854f6f85c7a64.zip
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
Notes
Notes: svn path=/head/; revision=343981
Diffstat (limited to 'bin/sh')
-rw-r--r--bin/sh/arith_yacc.c2
-rw-r--r--bin/sh/arith_yacc.h1
-rw-r--r--bin/sh/arith_yylex.c30
-rw-r--r--bin/sh/shell.h1
-rw-r--r--bin/sh/tests/expansion/Makefile2
-rw-r--r--bin/sh/tests/expansion/arith16.026
-rw-r--r--bin/sh/tests/expansion/arith17.03
7 files changed, 62 insertions, 3 deletions
diff --git a/bin/sh/arith_yacc.c b/bin/sh/arith_yacc.c
index 5000c6b0d1bef..a08163bdc29be 100644
--- a/bin/sh/arith_yacc.c
+++ b/bin/sh/arith_yacc.c
@@ -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;
diff --git a/bin/sh/arith_yacc.h b/bin/sh/arith_yacc.h
index ca92e6f7fa175..7fdd99b75b574 100644
--- a/bin/sh/arith_yacc.h
+++ b/bin/sh/arith_yacc.h
@@ -90,4 +90,5 @@ union yystype {
extern union yystype yylval;
+arith_t strtoarith_t(const char *restrict nptr, char **restrict endptr);
int yylex(void);
diff --git a/bin/sh/arith_yylex.c b/bin/sh/arith_yylex.c
index f7eaf3e3fa6da..9f320dbcb5851 100644
--- a/bin/sh/arith_yylex.c
+++ b/bin/sh/arith_yylex.c
@@ -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':
diff --git a/bin/sh/shell.h b/bin/sh/shell.h
index 9e2f9ab6e7355..c06e737e658ff 100644
--- a/bin/sh/shell.h
+++ b/bin/sh/shell.h
@@ -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
diff --git a/bin/sh/tests/expansion/Makefile b/bin/sh/tests/expansion/Makefile
index 25cf218f40a2b..58df967304f58 100644
--- a/bin/sh/tests/expansion/Makefile
+++ b/bin/sh/tests/expansion/Makefile
@@ -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
diff --git a/bin/sh/tests/expansion/arith16.0 b/bin/sh/tests/expansion/arith16.0
new file mode 100644
index 0000000000000..b764e3c216f8d
--- /dev/null
+++ b/bin/sh/tests/expansion/arith16.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))
diff --git a/bin/sh/tests/expansion/arith17.0 b/bin/sh/tests/expansion/arith17.0
new file mode 100644
index 0000000000000..0a9260886ddb5
--- /dev/null
+++ b/bin/sh/tests/expansion/arith17.0
@@ -0,0 +1,3 @@
+# $FreeBSD$
+
+[ $((9223372036854775809)) -gt 0 ]