Date: Tue, 4 Jul 2000 12:23:45 +0200 From: Stefan Esser <se@freebsd.org> To: freebsd-arch@FreeBSD.org Cc: Stefan Esser <se@freebsd.org> Subject: [Patch] make test,expr,printf support 64bit integers Message-ID: <20000703184219.A7587@StefanEsser.FreeBSD.org>
next in thread | raw e-mail | index | archive | help
I want to commit the following changes to test, expr and printf, which extend the integer range supported by them from 32bit signed to 64bit signed. The patches that are appended to this message have been tested (I rebuilt the world a number of times with them and performed some regression tests). The binaries grow by only a few bytes ... The original reason to extend the range was a shell script, which used test on the result of cksum, which generates an unsigned 32bit number. The result can't be passed to expr, test or printf, since it will be out of range of a signed 32bit number, half of the time. The patches do in no way change the normal behaviour of the programs (i.e. if valid 32bit integers are passed as argument). According to Bruce Evans, there is no Posix requirement regarding test and expr, besides that at least 32 bit signed integers be supported. There were replies to my earlier message to -current from Bruce Evans and Sheldon Hearn. Sheldon told me to check with NetBSD, what they think about the patches. Since I am not on any NetBSD list and do not know whom to ask there, I'd prefer, if somebody else asked them (or forwarded this message or named a NetBSD person to contact). Regards, STefan PS: I also fixed a potential buffer overflow in printf, when I was there ... Index: /usr/src/bin/test/test.c =================================================================== RCS file: /usr/cvs/src/bin/test/test.c,v retrieving revision 1.29 diff -u -2 -r1.29 test.c --- /usr/src/bin/test/test.c 1999/12/28 09:34:57 1.29 +++ /usr/src/bin/test/test.c 2000/06/23 15:56:26 @@ -154,4 +154,6 @@ static int isoperand __P((void)); static int getn __P((const char *)); +static quad_t getq __P((const char *)); +static int intcmp __P((const char *, const char *)); static int newerf __P((const char *, const char *)); static int olderf __P((const char *, const char *)); @@ -299,15 +301,15 @@ 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); @@ -442,4 +444,46 @@ return (int) r; +} + +/* atoi with error detection and 64 bit range */ +static quad_t +getq(s) + const char *s; +{ + char *p; + quad_t r; + + errno = 0; + r = strtoq(s, &p, 10); + + if (errno != 0) + errx(2, "%s: out of range", s); + + while (isspace((unsigned char)*p)) + p++; + + if (*p) + errx(2, "%s: bad number", s); + + return r; +} + +static int +intcmp (s1, s2) + const char *s1, *s2; +{ + quad_t q1, q2; + + + q1 = getq(s1); + q2 = getq(s2); + + if (q1 > q2) + return 1; + + if (q1 < q2) + return -1; + + return 0; } Index: /usr/src/bin/expr/expr.y =================================================================== RCS file: /usr/cvs/src/bin/expr/expr.y,v retrieving revision 1.14 diff -u -2 -r1.14 expr.y --- /usr/src/bin/expr/expr.y 1999/08/27 23:14:22 1.14 +++ /usr/src/bin/expr/expr.y 2000/06/24 12:20:59 @@ -8,4 +8,5 @@ */ +#include <sys/types.h> #include <stdio.h> #include <stdlib.h> @@ -14,4 +15,5 @@ #include <ctype.h> #include <err.h> +#include <regex.h> enum valtype { @@ -23,5 +25,5 @@ union { char *s; - int i; + quad_t i; } u; } ; @@ -88,5 +90,5 @@ struct val * make_integer (i) -int i; +quad_t i; { struct val *vp; @@ -140,9 +142,9 @@ -int +quad_t to_integer (vp) struct val *vp; { - int i; + quad_t i; if (vp->type == integer) @@ -153,5 +155,5 @@ /* vp->type == numeric_string, make it numeric */ - i = atoi(vp->u.s); + i = strtoq(vp->u.s, (char**)NULL, 10); free (vp->u.s); vp->u.i = i; @@ -174,5 +176,5 @@ } - sprintf (tmp, "%d", vp->u.i); + sprintf (tmp, "%lld", vp->u.i); vp->type = string; vp->u.s = tmp; @@ -240,5 +242,5 @@ if (result->type == integer) - printf ("%d\n", result->u.i); + printf ("%lld\n", result->u.i); else printf ("%s\n", result->u.s); @@ -275,5 +277,5 @@ free_value (a); free_value (b); - return (make_integer (0)); + return (make_integer ((quad_t)0)); } else { free_value (b); @@ -291,9 +293,9 @@ to_string (a); to_string (b); - r = make_integer (strcoll (a->u.s, b->u.s) == 0); + r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) == 0)); } else { (void)to_integer(a); (void)to_integer(b); - r = make_integer (a->u.i == b->u.i); + r = make_integer ((quad_t)(a->u.i == b->u.i)); } @@ -312,9 +314,9 @@ to_string (a); to_string (b); - r = make_integer (strcoll (a->u.s, b->u.s) > 0); + r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) > 0)); } else { (void)to_integer(a); (void)to_integer(b); - r= make_integer (a->u.i > b->u.i); + r = make_integer ((quad_t)(a->u.i > b->u.i)); } @@ -333,9 +335,9 @@ to_string (a); to_string (b); - r = make_integer (strcoll (a->u.s, b->u.s) < 0); + r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) < 0)); } else { (void)to_integer(a); (void)to_integer(b); - r = make_integer (a->u.i < b->u.i); + r = make_integer ((quad_t)(a->u.i < b->u.i)); } @@ -354,9 +356,9 @@ to_string (a); to_string (b); - r = make_integer (strcoll (a->u.s, b->u.s) >= 0); + r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) >= 0)); } else { (void)to_integer(a); (void)to_integer(b); - r = make_integer (a->u.i >= b->u.i); + r = make_integer ((quad_t)(a->u.i >= b->u.i)); } @@ -375,9 +377,9 @@ to_string (a); to_string (b); - r = make_integer (strcoll (a->u.s, b->u.s) <= 0); + r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) <= 0)); } else { (void)to_integer(a); (void)to_integer(b); - r = make_integer (a->u.i <= b->u.i); + r = make_integer ((quad_t)(a->u.i <= b->u.i)); } @@ -396,9 +398,9 @@ to_string (a); to_string (b); - r = make_integer (strcoll (a->u.s, b->u.s) != 0); + r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) != 0)); } else { (void)to_integer(a); (void)to_integer(b); - r = make_integer (a->u.i != b->u.i); + r = make_integer ((quad_t)(a->u.i != b->u.i)); } @@ -418,5 +420,5 @@ } - r = make_integer (a->u.i + b->u.i); + r = make_integer ((quad_t)(a->u.i + b->u.i)); free_value (a); free_value (b); @@ -434,5 +436,5 @@ } - r = make_integer (a->u.i - b->u.i); + r = make_integer ((quad_t)(a->u.i - b->u.i)); free_value (a); free_value (b); @@ -450,5 +452,5 @@ } - r = make_integer (a->u.i * b->u.i); + r = make_integer ((quad_t)(a->u.i * b->u.i)); free_value (a); free_value (b); @@ -470,5 +472,5 @@ } - r = make_integer (a->u.i / b->u.i); + r = make_integer ((quad_t)(a->u.i / b->u.i)); free_value (a); free_value (b); @@ -490,5 +492,5 @@ } - r = make_integer (a->u.i % b->u.i); + r = make_integer ((quad_t)(a->u.i % b->u.i)); free_value (a); free_value (b); @@ -496,7 +498,4 @@ } -#include <sys/types.h> -#include <regex.h> - struct val * op_colon (a, b) @@ -527,9 +526,9 @@ } else { - v = make_integer (rm[0].rm_eo - rm[0].rm_so); + v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so)); } } else { if (rp.re_nsub == 0) { - v = make_integer (0); + v = make_integer ((quad_t)0); } else { v = make_str (""); Index: /usr/src/usr.bin/printf/printf.c =================================================================== RCS file: /usr/cvs/src/usr.bin/printf/printf.c,v retrieving revision 1.13 diff -u -2 -r1.13 printf.c --- /usr/src/usr.bin/printf/printf.c 2000/04/20 09:31:54 1.13 +++ /usr/src/usr.bin/printf/printf.c 2000/07/03 16:21:25 @@ -87,5 +87,5 @@ static double getdouble __P((void)); static int getint __P((int *)); -static int getlong __P((long *)); +static int getlong __P((quad_t *)); static char *getstr __P((void)); static char *mklong __P((char *, int)); @@ -215,5 +215,5 @@ } case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': { - long p; + quad_t p; char *f; @@ -250,6 +250,9 @@ len = strlen(str) + 2; + if (len > sizeof copy) + return NULL; + memmove(copy, str, len - 3); - copy[len - 3] = 'l'; + copy[len - 3] = 'q'; copy[len - 2] = ch; copy[len - 1] = '\0'; @@ -339,13 +342,13 @@ int *ip; { - long val; + quad_t val; if (getlong(&val)) return (1); - if (val > INT_MAX) { + if (val < INT_MIN || val > INT_MAX) { warnx3("%s: %s", *gargv, strerror(ERANGE)); return (1); } - *ip = val; + *ip = (int)val; return (0); } @@ -353,7 +356,7 @@ static int getlong(lp) - long *lp; + quad_t *lp; { - long val; + quad_t val; char *ep; @@ -364,5 +367,5 @@ if (strchr(Number, **gargv)) { errno = 0; - val = strtol(*gargv, &ep, 0); + val = strtoq(*gargv, &ep, 0); if (*ep != '\0') { warnx2("%s: illegal number", *gargv, NULL); @@ -370,9 +373,9 @@ } if (errno == ERANGE) - if (val == LONG_MAX) { + if (val == QUAD_MAX) { warnx3("%s: %s", *gargv, strerror(ERANGE)); return (1); } - if (val == LONG_MIN) { + if (val == QUAD_MIN) { warnx3("%s: %s", *gargv, strerror(ERANGE)); return (1); To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-arch" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000703184219.A7587>