summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/commit.c2
-rw-r--r--src/commit_list.c4
-rw-r--r--src/config.c2
-rw-r--r--src/curl_stream.c2
-rw-r--r--src/index.c2
-rw-r--r--src/rebase.c2
-rw-r--r--src/revparse.c5
-rw-r--r--src/signature.c8
-rw-r--r--src/tag.c10
-rw-r--r--src/transports/smart.c5
-rw-r--r--src/transports/smart_pkt.c2
-rw-r--r--src/transports/winhttp.c3
-rw-r--r--src/tree-cache.c4
-rw-r--r--src/util.c79
-rw-r--r--src/util.h5
15 files changed, 95 insertions, 40 deletions
diff --git a/src/commit.c b/src/commit.c
index 4a340058a..0ec989421 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -442,7 +442,7 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
while (eoln < buffer_end && *eoln != '\n')
++eoln;
- if (git__prefixcmp(buffer, "encoding ") == 0) {
+ if (git__prefixncmp(buffer, buffer_end - buffer, "encoding ") == 0) {
buffer += strlen("encoding ");
commit->message_encoding = git__strndup(buffer, eoln - buffer);
diff --git a/src/commit_list.c b/src/commit_list.c
index 3bba58c27..7df79bfd6 100644
--- a/src/commit_list.c
+++ b/src/commit_list.c
@@ -171,7 +171,9 @@ static int commit_quick_parse(
buffer--;
}
- if ((buffer == committer_start) || (git__strtol64(&commit_time, (char *)(buffer + 1), NULL, 10) < 0))
+ if ((buffer == committer_start) ||
+ (git__strntol64(&commit_time, (char *)(buffer + 1),
+ buffer_end - buffer + 1, NULL, 10) < 0))
return commit_error(commit, "cannot parse commit time");
commit->time = commit_time;
diff --git a/src/config.c b/src/config.c
index 169a62880..b0cb2c117 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1298,7 +1298,7 @@ int git_config_parse_int64(int64_t *out, const char *value)
const char *num_end;
int64_t num;
- if (!value || git__strtol64(&num, value, &num_end, 0) < 0)
+ if (!value || git__strntol64(&num, value, strlen(value), &num_end, 0) < 0)
goto fail_parse;
switch (*num_end) {
diff --git a/src/curl_stream.c b/src/curl_stream.c
index f07370f21..4e34ae2b9 100644
--- a/src/curl_stream.c
+++ b/src/curl_stream.c
@@ -328,7 +328,7 @@ int git_curl_stream_new(git_stream **out, const char *host, const char *port)
return -1;
}
- if ((error = git__strtol32(&iport, port, NULL, 10)) < 0) {
+ if ((error = git__strntol32(&iport, port, strlen(port), NULL, 10)) < 0) {
git__free(st);
return error;
}
diff --git a/src/index.c b/src/index.c
index c5f6550d6..d7952ac6e 100644
--- a/src/index.c
+++ b/src/index.c
@@ -2202,7 +2202,7 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
for (i = 0; i < 3; i++) {
int64_t tmp;
- if (git__strtol64(&tmp, buffer, &endptr, 8) < 0 ||
+ if (git__strntol64(&tmp, buffer, size, &endptr, 8) < 0 ||
!endptr || endptr == buffer || *endptr ||
tmp < 0 || tmp > UINT32_MAX) {
index_entry_reuc_free(lost);
diff --git a/src/rebase.c b/src/rebase.c
index f528031b3..6d31bf3ba 100644
--- a/src/rebase.c
+++ b/src/rebase.c
@@ -151,7 +151,7 @@ GIT_INLINE(int) rebase_readint(
if ((error = rebase_readfile(asc_out, state_path, filename)) < 0)
return error;
- if (git__strtol32(&num, asc_out->ptr, &eol, 10) < 0 || num < 0 || *eol) {
+ if (git__strntol32(&num, asc_out->ptr, asc_out->size, &eol, 10) < 0 || num < 0 || *eol) {
giterr_set(GITERR_REBASE, "the file '%s' contains an invalid numeric value", filename);
return -1;
}
diff --git a/src/revparse.c b/src/revparse.c
index fd6bd1ea6..927e83073 100644
--- a/src/revparse.c
+++ b/src/revparse.c
@@ -127,7 +127,8 @@ static int try_parse_numeric(int *n, const char *curly_braces_content)
int32_t content;
const char *end_ptr;
- if (git__strtol32(&content, curly_braces_content, &end_ptr, 10) < 0)
+ if (git__strntol32(&content, curly_braces_content, strlen(curly_braces_content),
+ &end_ptr, 10) < 0)
return -1;
if (*end_ptr != '\0')
@@ -577,7 +578,7 @@ static int extract_how_many(int *n, const char *spec, size_t *pos)
} while (spec[(*pos)] == kind && kind == '~');
if (git__isdigit(spec[*pos])) {
- if (git__strtol32(&parsed, spec + *pos, &end_ptr, 10) < 0)
+ if (git__strntol32(&parsed, spec + *pos, strlen(spec + *pos), &end_ptr, 10) < 0)
return GIT_EINVALIDSPEC;
accumulated += (parsed - 1);
diff --git a/src/signature.c b/src/signature.c
index 25e0ee723..2e0cfe01a 100644
--- a/src/signature.c
+++ b/src/signature.c
@@ -228,7 +228,8 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
const char *time_start = email_end + 2;
const char *time_end;
- if (git__strtol64(&sig->when.time, time_start, &time_end, 10) < 0) {
+ if (git__strntol64(&sig->when.time, time_start,
+ buffer_end - time_start, &time_end, 10) < 0) {
git__free(sig->name);
git__free(sig->email);
sig->name = sig->email = NULL;
@@ -243,8 +244,9 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
tz_start = time_end + 1;
if ((tz_start[0] != '-' && tz_start[0] != '+') ||
- git__strtol32(&offset, tz_start + 1, &tz_end, 10) < 0) {
- //malformed timezone, just assume it's zero
+ git__strntol32(&offset, tz_start + 1,
+ buffer_end - tz_start + 1, &tz_end, 10) < 0) {
+ /* malformed timezone, just assume it's zero */
offset = 0;
}
diff --git a/src/tag.c b/src/tag.c
index 2bf23fc3c..a0e968f38 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -70,10 +70,9 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
static const char *tag_types[] = {
NULL, "commit\n", "tree\n", "blob\n", "tag\n"
};
-
- unsigned int i;
size_t text_len, alloc_len;
- char *search;
+ const char *search;
+ unsigned int i;
if (git_oid__parse(&tag->target, &buffer, buffer_end, "object ") < 0)
return tag_error("object field invalid");
@@ -138,8 +137,9 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
tag->message = NULL;
if (buffer < buffer_end) {
/* If we're not at the end of the header, search for it */
- if( *buffer != '\n' ) {
- search = strstr(buffer, "\n\n");
+ if(*buffer != '\n') {
+ search = git__memmem(buffer, buffer_end - buffer,
+ "\n\n", 2);
if (search)
buffer = search + 1;
else
diff --git a/src/transports/smart.c b/src/transports/smart.c
index a96fdf6fb..5cf107dd9 100644
--- a/src/transports/smart.c
+++ b/src/transports/smart.c
@@ -43,6 +43,11 @@ GIT_INLINE(int) git_smart__reset_stream(transport_smart *t, bool close_subtransp
t->current_stream = NULL;
}
+ if (t->url) {
+ git__free(t->url);
+ t->url = NULL;
+ }
+
if (close_subtransport &&
t->wrapped->close(t->wrapped) < 0)
return -1;
diff --git a/src/transports/smart_pkt.c b/src/transports/smart_pkt.c
index e726d0777..0e05ff861 100644
--- a/src/transports/smart_pkt.c
+++ b/src/transports/smart_pkt.c
@@ -391,7 +391,7 @@ static int parse_len(size_t *out, const char *line, size_t linelen)
}
}
- if ((error = git__strtol32(&len, num, &num_end, 16)) < 0)
+ if ((error = git__strntol32(&len, num, PKT_LEN_SIZE, &num_end, 16)) < 0)
return error;
if (len < 0)
diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c
index cf6445f53..c54e16d0f 100644
--- a/src/transports/winhttp.c
+++ b/src/transports/winhttp.c
@@ -764,7 +764,8 @@ static int winhttp_connect(
t->connection = NULL;
/* Prepare port */
- if (git__strtol32(&port, t->connection_data.port, NULL, 10) < 0)
+ if (git__strntol32(&port, t->connection_data.port,
+ strlen(t->connection_data.port), NULL, 10) < 0)
return -1;
/* Prepare host */
diff --git a/src/tree-cache.c b/src/tree-cache.c
index 548054136..17f235977 100644
--- a/src/tree-cache.c
+++ b/src/tree-cache.c
@@ -90,7 +90,7 @@ static int read_tree_internal(git_tree_cache **out,
return -1;
/* Blank-terminated ASCII decimal number of entries in this tree */
- if (git__strtol32(&count, buffer, &buffer, 10) < 0)
+ if (git__strntol32(&count, buffer, buffer_end - buffer, &buffer, 10) < 0)
goto corrupted;
tree->entry_count = count;
@@ -99,7 +99,7 @@ static int read_tree_internal(git_tree_cache **out,
goto corrupted;
/* Number of children of the tree, newline-terminated */
- if (git__strtol32(&count, buffer, &buffer, 10) < 0 || count < 0)
+ if (git__strntol32(&count, buffer, buffer_end - buffer, &buffer, 10) < 0 || count < 0)
goto corrupted;
tree->children_count = count;
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;
diff --git a/src/util.h b/src/util.h
index 8e666f9de..2ac118d8f 100644
--- a/src/util.h
+++ b/src/util.h
@@ -263,9 +263,7 @@ GIT_INLINE(int) git__signum(int val)
return ((val > 0) - (val < 0));
}
-extern int git__strtol32(int32_t *n, const char *buff, const char **end_buf, int base);
extern int git__strntol32(int32_t *n, const char *buff, size_t buff_len, const char **end_buf, int base);
-extern int git__strtol64(int64_t *n, const char *buff, const char **end_buf, int base);
extern int git__strntol64(int64_t *n, const char *buff, size_t buff_len, const char **end_buf, int base);
@@ -318,6 +316,9 @@ GIT_INLINE(const void *) git__memrchr(const void *s, int c, size_t n)
return NULL;
}
+extern const void * git__memmem(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen);
+
typedef int (*git__tsort_cmp)(const void *a, const void *b);
extern void git__tsort(void **dst, size_t size, git__tsort_cmp cmp);