diff options
| author | 2018-04-02 06:47:43 +0000 | |
|---|---|---|
| committer | 2018-04-02 06:47:43 +0000 | |
| commit | 2133b42eb22f6d83c07d97f9e3bc89be7a178410 (patch) | |
| tree | 5cf88f2b412c81eb7410a19a8004700f5374997d | |
| parent | In ssl.h rev. 1.151 2018/03/17 15:48:31, tb@ provided (diff) | |
| download | wireguard-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.c | 113 | ||||
| -rw-r--r-- | regress/bin/test/TEST.sh | 13 |
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 ""' |
