changeset 17552:1d873182d5a8

lib: strnum - harden str_to_uintmax against overflows The invalid number "20496382304121724020" (2^64*10/9) will be parsed as valid. 2049638230412172402 * 10 does not noticably wrap, it becomes 2049638230412172404 Do not perform operations which might wrap, and then try to detect the issue, just compare with the known fixed bounds before doing the multiplication. Signed-off-by: Phil Carmody <phil@dovecot.fi>
author Phil Carmody <phil@dovecot.fi>
date Wed, 02 Jul 2014 18:21:24 +0300
parents 6c1e44033e60
children 59b6893fbf65
files src/lib/strnum.c
diffstat 1 files changed, 7 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/strnum.c	Wed Jul 02 18:21:24 2014 +0300
+++ b/src/lib/strnum.c	Wed Jul 02 18:21:24 2014 +0300
@@ -84,18 +84,19 @@
 
 int str_to_uintmax(const char *str, uintmax_t *num_r)
 {
-	uintmax_t next, n = 0;
+	uintmax_t n = 0;
 
 	if (*str < '0' || *str > '9')
 		return -1;
 
 	for (; *str >= '0' && *str <= '9'; str++) {
-		next = n*10;
-		if (next < n) {
-			/* overflow */
-			return -1;
+		if (n >= ((uintmax_t)-1 / 10)) {
+			if (n > (uintmax_t)-1 / 10)
+				return -1;
+			if ((uintmax_t)(*str - '0') > ((uintmax_t)-1 % 10))
+				return -1;
 		}
-		n = next + (*str - '0');
+		n = n * 10 + (*str - '0');
 	}
 	if (*str != '\0')
 		return -1;