summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2018-10-18 14:37:55 +0200
committerPatrick Steinhardt <ps@pks.im>2018-10-19 13:52:43 +0200
commitfdb4d3a1fa75ec5b6c984b7d155b8f041a820306 (patch)
tree97f789ed3401f8def572d7d05ccc7675bc2bed53
parent8172b4d5fb0e4e15e4428569c3ae79ad836b828e (diff)
downloadlibgit2-fdb4d3a1fa75ec5b6c984b7d155b8f041a820306.tar.gz
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)
-rw-r--r--src/util.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/src/util.c b/src/util.c
index d47b18ae5..62290f311 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: