diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2020-12-13 13:46:16 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-13 13:46:16 +0000 |
commit | 851e778ec7b1a7d9e3a072322b2e9b976a5241f6 (patch) | |
tree | 884289a61693e8594cf96b57a594bfe1581b194e | |
parent | 86a1cdd38ee1cad0c578373a3888b92dbcb30106 (diff) | |
parent | e99e833f4808e027de8e984b9b99544ca41e28e2 (diff) | |
download | libgit2-851e778ec7b1a7d9e3a072322b2e9b976a5241f6.tar.gz |
Merge pull request #5735 from lhchavez/faster-strntol64
Make git__strntol64() ~70%* faster
-rw-r--r-- | src/integer.h | 31 | ||||
-rw-r--r-- | src/util.c | 14 |
2 files changed, 34 insertions, 11 deletions
diff --git a/src/integer.h b/src/integer.h index 067c0be1f..026a1fac0 100644 --- a/src/integer.h +++ b/src/integer.h @@ -77,6 +77,11 @@ GIT_INLINE(int) git__is_int(long long p) # define git__sub_int_overflow(out, one, two) \ __builtin_ssub_overflow(one, two, out) +# define git__add_int64_overflow(out, one, two) \ + __builtin_add_overflow(one, two, out) +# define git__multiply_int64_overflow(out, one, two) \ + __builtin_mul_overflow(one, two, out) + /* Use Microsoft's safe integer handling functions where available */ #elif defined(_MSC_VER) @@ -87,11 +92,17 @@ GIT_INLINE(int) git__is_int(long long p) (SizeTAdd(one, two, out) != S_OK) # define git__multiply_sizet_overflow(out, one, two) \ (SizeTMult(one, two, out) != S_OK) + #define git__add_int_overflow(out, one, two) \ (IntAdd(one, two, out) != S_OK) #define git__sub_int_overflow(out, one, two) \ (IntSub(one, two, out) != S_OK) +#define git__add_int64_overflow(out, one, two) \ + (LongLongAdd(one, two, out) != S_OK) +#define git__multiply_int64_overflow(out, one, two) \ + (LongLongMult(one, two, out) != S_OK) + #else /** @@ -136,6 +147,26 @@ GIT_INLINE(bool) git__sub_int_overflow(int *out, int one, int two) return false; } +GIT_INLINE(bool) git__add_int64_overflow(int64_t *out, int64_t one, int64_t two) +{ + if ((two > 0 && one > (INT64_MAX - two)) || + (two < 0 && one < (INT64_MIN - two))) + return true; + *out = one + two; + return false; +} + +GIT_INLINE(bool) git__multiply_int64_overflow(int64_t *out, int64_t one, int64_t two) +{ + if ((one == -1 && two == INT_MIN) || + (two == -1 && one == INT_MIN) || + (one && INT64_MAX / one < two) || + (one && INT64_MIN / one > two)) + return true; + *out = one * two; + return false; +} + #endif #endif diff --git a/src/util.c b/src/util.c index 87ccf32af..af825e4d2 100644 --- a/src/util.c +++ b/src/util.c @@ -34,8 +34,8 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base) { const char *p; - int64_t n, nn; - int c, ovfl, v, neg, ndig; + int64_t n, nn, v; + int c, ovfl, neg, ndig; p = nptr; neg = 0; @@ -110,19 +110,11 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const cha if (v >= base) break; v = neg ? -v : v; - if (n > INT64_MAX / base || n < INT64_MIN / base) { + if (git__multiply_int64_overflow(&nn, n, base) || git__add_int64_overflow(&n, nn, v)) { ovfl = 1; /* 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: |