in src/util.c [71:181]
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;
p = nptr;
neg = 0;
n = 0;
ndig = 0;
ovfl = 0;
/*
* White space
*/
while (nptr_len && git__isspace(*p))
p++, nptr_len--;
if (!nptr_len)
goto Return;
/*
* Sign
*/
if (*p == '-' || *p == '+') {
if (*p == '-')
neg = 1;
p++;
nptr_len--;
}
if (!nptr_len)
goto Return;
/*
* Automatically detect the base if none was given to us.
* Right now, we assume that a number starting with '0x'
* is hexadecimal and a number starting with '0' is
* octal.
*/
if (base == 0) {
if (*p != '0')
base = 10;
else if (nptr_len > 2 && (p[1] == 'x' || p[1] == 'X'))
base = 16;
else
base = 8;
}
if (base < 0 || 36 < base)
goto Return;
/*
* Skip prefix of '0x'-prefixed hexadecimal numbers. There is no
* need to do the same for '0'-prefixed octal numbers as a
* leading '0' does not have any impact. Also, if we skip a
* leading '0' in such a string, then we may end up with no
* digits left and produce an error later on which isn't one.
*/
if (base == 16 && nptr_len > 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
p += 2;
nptr_len -= 2;
}
/*
* Non-empty sequence of digits
*/
for (; nptr_len > 0; p++,ndig++,nptr_len--) {
c = *p;
v = base;
if ('0'<=c && c<='9')
v = c - '0';
else if ('a'<=c && c<='z')
v = c - 'a' + 10;
else if ('A'<=c && c<='Z')
v = c - 'A' + 10;
if (v >= base)
break;
v = neg ? -v : v;
if (n > INT64_MAX / base || n < INT64_MIN / base) {
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:
if (ndig == 0) {
git_error_set(GIT_ERROR_INVALID, "failed to convert string to long: not a number");
return -1;
}
if (endptr)
*endptr = p;
if (ovfl) {
git_error_set(GIT_ERROR_INVALID, "failed to convert string to long: overflow error");
return -1;
}
*result = n;
return 0;
}