Commit 737df8b55e25f234685be03a7530bdd66f8489ee

Patrick Steinhardt 2018-10-18T14:37:55

util: avoid signed integer overflows in `git__strntol64` While `git__strntol64` tries to detect integer overflows when doing the necessary arithmetics to come up with the final result, it does the detection only after the fact. This check thus relies on undefined behavior of signed integer overflows. Fix this by instead checking up-front whether the multiplications or additions will overflow. Note that a detected overflow will not cause us to abort parsing the current sequence of digits. In the case of an overflow, previous behavior was to still set up the end pointer correctly to point to the first character immediately after the currently parsed number. We do not want to change this now as code may rely on the end pointer being set up correctly even if the parsed number is too big to be represented as 64 bit integer. (cherry picked from commit b09c1c7b636c4112e247adc24245c65f3f9478d0)

diff --git a/src/util.c b/src/util.c
index d47b18a..62290f3 100644
--- a/src/util.c
+++ b/src/util.c
@@ -122,10 +122,20 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const cha
 			v = c - 'A' + 10;
 		if (v >= base)
 			break;
-		nn = n * base + (neg ? -v : v);
-		if ((!neg && nn < n) || (neg && nn > n))
+		v = neg ? -v : v;
+		if (n > INT64_MAX / base || n < INT64_MIN / base) {
 			ovfl = 1;
-		n = nn;
+			/* Keep on iterating until the end of this number */
+			continue;
+		}
+		nn = n * base;
+		if ((v > 0 && nn > INT64_MAX - v) ||
+		    (v < 0 && nn < INT64_MIN - v)) {
+			ovfl = 1;
+			/* Keep on iterating until the end of this number */
+			continue;
+		}
+		n = nn + v;
 	}
 
 Return: