Skip site navigation (1)Skip section navigation (2)
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>