summaryrefslogtreecommitdiff
path: root/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c79
1 files changed, 61 insertions, 18 deletions
diff --git a/src/util.c b/src/util.c
index 964b0ab6a..1e7de93c3 100644
--- a/src/util.c
+++ b/src/util.c
@@ -64,12 +64,6 @@ int git_strarray_copy(git_strarray *tgt, const git_strarray *src)
return 0;
}
-int git__strtol64(int64_t *result, const char *nptr, const char **endptr, int base)
-{
-
- return git__strntol64(result, nptr, (size_t)-1, endptr, base);
-}
-
int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
{
const char *p;
@@ -128,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:
@@ -152,28 +156,26 @@ Return:
return 0;
}
-int git__strtol32(int32_t *result, const char *nptr, const char **endptr, int base)
-{
-
- return git__strntol32(result, nptr, (size_t)-1, endptr, base);
-}
-
int git__strntol32(int32_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
{
- int error;
+ const char *tmp_endptr;
int32_t tmp_int;
int64_t tmp_long;
+ int error;
- if ((error = git__strntol64(&tmp_long, nptr, nptr_len, endptr, base)) < 0)
+ if ((error = git__strntol64(&tmp_long, nptr, nptr_len, &tmp_endptr, base)) < 0)
return error;
tmp_int = tmp_long & 0xFFFFFFFF;
if (tmp_int != tmp_long) {
- giterr_set(GITERR_INVALID, "failed to convert: '%s' is too large", nptr);
+ int len = tmp_endptr - nptr;
+ giterr_set(GITERR_INVALID, "failed to convert: '%.*s' is too large", len, nptr);
return -1;
}
*result = tmp_int;
+ if (endptr)
+ *endptr = tmp_endptr;
return error;
}
@@ -351,6 +353,47 @@ size_t git__linenlen(const char *buffer, size_t buffer_len)
return nl ? (size_t)(nl - buffer) + 1 : buffer_len;
}
+/*
+ * Adapted Not So Naive algorithm from http://www-igm.univ-mlv.fr/~lecroq/string/
+ */
+const void * git__memmem(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen)
+{
+ const char *h, *n;
+ size_t j, k, l;
+
+ if (needlelen > haystacklen || !haystacklen || !needlelen)
+ return NULL;
+
+ h = (const char *) haystack,
+ n = (const char *) needle;
+
+ if (needlelen == 1)
+ return memchr(haystack, *n, haystacklen);
+
+ if (n[0] == n[1]) {
+ k = 2;
+ l = 1;
+ } else {
+ k = 1;
+ l = 2;
+ }
+
+ j = 0;
+ while (j <= haystacklen - needlelen) {
+ if (n[1] != h[j + 1]) {
+ j += k;
+ } else {
+ if (memcmp(n + 2, h + j + 2, needlelen - 2) == 0 &&
+ n[0] == h[j])
+ return h + j;
+ j += l;
+ }
+ }
+
+ return NULL;
+}
+
void git__hexdump(const char *buffer, size_t len)
{
static const size_t LINE_WIDTH = 16;