diff options
author | Vicent Marti <tanoku@gmail.com> | 2011-04-10 02:22:11 +0400 |
---|---|---|
committer | Vicent Marti <tanoku@gmail.com> | 2011-04-10 02:22:11 +0400 |
commit | c6e65acae63bd9b251140184679ab4ea0ec5c1a9 (patch) | |
tree | 42e304af6ea9be7f4f35e3beca314fccc9fddd27 /src/util.c | |
parent | b918ae40d1dc5116d7631ef822d7b5b39a622c81 (diff) |
Properly check `strtol` for errors
We are now using a custom `strtol` implementation to make sure we're not
missing any overflow errors.
Diffstat (limited to 'src/util.c')
-rw-r--r-- | src/util.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/util.c b/src/util.c index 995daf314..55a7ab2a9 100644 --- a/src/util.c +++ b/src/util.c @@ -2,6 +2,7 @@ #include "common.h" #include <stdarg.h> #include <stdio.h> +#include <ctype.h> void git_strarray_free(git_strarray *array) { @@ -12,6 +13,84 @@ void git_strarray_free(git_strarray *array) free(array->strings); } +int git__strtol32(long *result, const char *nptr, const char **endptr, int base) +{ + const char *p; + long n, nn; + int c, ovfl, v, neg, ndig; + + p = nptr; + neg = 0; + n = 0; + ndig = 0; + ovfl = 0; + + /* + * White space + */ + while (isspace(*p)) + p++; + + /* + * Sign + */ + if (*p == '-' || *p == '+') + if (*p++ == '-') + neg = 1; + + /* + * Base + */ + if (base == 0) { + if (*p != '0') + base = 10; + else { + base = 8; + if (p[1] == 'x' || p[1] == 'X') { + p += 2; + base = 16; + } + } + } else if (base == 16 && *p == '0') { + if (p[1] == 'x' || p[1] == 'X') + p += 2; + } else if (base < 0 || 36 < base) + goto Return; + + /* + * Non-empty sequence of digits + */ + for (;; p++,ndig++) { + 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; + nn = n*base + v; + if (nn < n) + ovfl = 1; + n = nn; + } + +Return: + if (ndig == 0) + return GIT_ENOTNUM; + + if (endptr) + *endptr = p; + + if (ovfl) + return GIT_EOVERFLOW; + + *result = neg ? -n : n; + return GIT_SUCCESS; +} + int git__fmt(char *buf, size_t buf_sz, const char *fmt, ...) { va_list va; |