summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortobias <tobias@openbsd.org>2018-04-02 06:47:43 +0000
committertobias <tobias@openbsd.org>2018-04-02 06:47:43 +0000
commit2133b42eb22f6d83c07d97f9e3bc89be7a178410 (patch)
tree5cf88f2b412c81eb7410a19a8004700f5374997d
parentIn ssl.h rev. 1.151 2018/03/17 15:48:31, tb@ provided (diff)
downloadwireguard-openbsd-2133b42eb22f6d83c07d97f9e3bc89be7a178410.tar.xz
wireguard-openbsd-2133b42eb22f6d83c07d97f9e3bc89be7a178410.zip
Support integers of arbitrary length.
Previously it was possible to overflow integers while parsing. With this diff, we support any kind of POSIX-compatible integers for comparisons. with input by and ok schwarze, ok tb
-rw-r--r--bin/test/test.c113
-rw-r--r--regress/bin/test/TEST.sh13
2 files changed, 104 insertions, 22 deletions
diff --git a/bin/test/test.c b/bin/test/test.c
index ca88f4846dd..64f58acc2fb 100644
--- a/bin/test/test.c
+++ b/bin/test/test.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: test.c,v 1.18 2017/07/24 22:15:52 jca Exp $ */
+/* $OpenBSD: test.c,v 1.19 2018/04/02 06:47:43 tobias Exp $ */
/* $NetBSD: test.c,v 1.15 1995/03/21 07:04:06 cgd Exp $ */
/*
@@ -16,6 +16,7 @@
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -145,6 +146,8 @@ static int aexpr(enum token n);
static int nexpr(enum token n);
static int binop(void);
static int primary(enum token n);
+static const char *getnstr(const char *, int *, size_t *);
+static int intcmp(const char *, const char *);
static int filstat(char *nm, enum token mode);
static int getn(const char *s);
static int newerf(const char *, const char *);
@@ -290,6 +293,70 @@ primary(enum token n)
return strlen(*t_wp) > 0;
}
+static const char *
+getnstr(const char *s, int *signum, size_t *len)
+{
+ const char *p, *start;
+
+ /* skip leading whitespaces */
+ p = s;
+ while (isspace((unsigned char)*p))
+ p++;
+
+ /* accept optional sign */
+ if (*p == '-') {
+ *signum = -1;
+ p++;
+ } else {
+ *signum = 1;
+ if (*p == '+')
+ p++;
+ }
+
+ /* skip leading zeros */
+ while (*p == '0' && isdigit((unsigned char)p[1]))
+ p++;
+
+ /* turn 0 always positive */
+ if (*p == '0')
+ *signum = 1;
+
+ start = p;
+ while (isdigit((unsigned char)*p))
+ p++;
+ *len = p - start;
+
+ /* allow trailing whitespaces */
+ while (isspace((unsigned char)*p))
+ p++;
+
+ /* validate number */
+ if (*p != '\0' || *start == '\0')
+ errx(2, "%s: invalid", s);
+
+ return start;
+}
+
+static int
+intcmp(const char *opnd1, const char *opnd2)
+{
+ const char *p1, *p2;
+ size_t len1, len2;
+ int c, sig1, sig2;
+
+ p1 = getnstr(opnd1, &sig1, &len1);
+ p2 = getnstr(opnd2, &sig2, &len2);
+
+ if (sig1 != sig2)
+ c = sig1;
+ else if (len1 != len2)
+ c = (len1 < len2) ? -sig1 : sig1;
+ else
+ c = strncmp(p1, p2, len1) * sig1;
+
+ return c;
+}
+
static int
binop(void)
{
@@ -313,17 +380,17 @@ binop(void)
case STRGT:
return strcmp(opnd1, opnd2) > 0;
case INTEQ:
- return getn(opnd1) == getn(opnd2);
+ return intcmp(opnd1, opnd2) == 0;
case INTNE:
- return getn(opnd1) != getn(opnd2);
+ return intcmp(opnd1, opnd2) != 0;
case INTGE:
- return getn(opnd1) >= getn(opnd2);
+ return intcmp(opnd1, opnd2) >= 0;
case INTGT:
- return getn(opnd1) > getn(opnd2);
+ return intcmp(opnd1, opnd2) > 0;
case INTLE:
- return getn(opnd1) <= getn(opnd2);
+ return intcmp(opnd1, opnd2) <= 0;
case INTLT:
- return getn(opnd1) < getn(opnd2);
+ return intcmp(opnd1, opnd2) < 0;
case FILNT:
return newerf(opnd1, opnd2);
case FILOT:
@@ -455,22 +522,26 @@ t_lex(char *s)
static int
getn(const char *s)
{
- char *p;
- long r;
-
- errno = 0;
- r = strtol(s, &p, 10);
-
- if (errno != 0)
- errx(2, "%s: out of range", s);
-
- while (isspace((unsigned char)*p))
- p++;
+ char buf[32];
+ const char *errstr, *p;
+ size_t len;
+ int r, sig;
+
+ p = getnstr(s, &sig, &len);
+ if (sig != 1)
+ errstr = "too small";
+ else if (len >= sizeof(buf))
+ errstr = "too large";
+ else {
+ strlcpy(buf, p, sizeof(buf));
+ buf[len] = '\0';
+ r = strtonum(buf, 0, INT_MAX, &errstr);
+ }
- if (*p)
- errx(2, "%s: bad number", s);
+ if (errstr != NULL)
+ errx(2, "%s: %s", s, errstr);
- return (int) r;
+ return r;
}
static int
diff --git a/regress/bin/test/TEST.sh b/regress/bin/test/TEST.sh
index eae6480a0ee..5493d86a06b 100644
--- a/regress/bin/test/TEST.sh
+++ b/regress/bin/test/TEST.sh
@@ -26,7 +26,7 @@
#
# TEST.sh - check if test(1) or builtin test works
#
-# $OpenBSD: TEST.sh,v 1.2 2014/11/25 23:09:22 daniel Exp $
+# $OpenBSD: TEST.sh,v 1.3 2018/04/02 06:47:43 tobias Exp $
# force a specified test program, e.g. `env test=/bin/test sh TEST.sh'
: ${test=test}
@@ -124,6 +124,17 @@ t 0 '0 -eq 0'
t 1 '-5 -eq 5'
t 0 '\( 0 -eq 0 \)'
t 1 '1 -eq 0 -o a = a -a 1 -eq 0 -o a = aa'
+t 0 '" +123 " -eq 123'
+t 1 '"-123 " -gt " -1"'
+t 0 '123 -gt -123'
+t 0 '-0 -eq +0'
+t 1 '+0 -gt 0'
+t 0 '0 -eq 0'
+t 0 '0000 -eq -0'
+t 0 '-1 -gt -2'
+t 1 '1 -gt 2'
+t 1 '4294967296 -eq 0'
+t 0 '12345678901234567890 -eq +0012345678901234567890'
t 1 '"" -o ""'
t 1 '"" -a ""'