summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fuzzers/corpora/midx/666a779eed16847c6930a71c0547a34e52db409ebin0 -> 62 bytes
-rw-r--r--src/diff_print.c5
-rw-r--r--src/fetch.c7
-rw-r--r--src/midx.c11
-rw-r--r--src/remote.c7
-rw-r--r--tests/diff/parse.c26
-rw-r--r--tests/online/fetch.c29
-rw-r--r--tests/patch/patch_common.h9
8 files changed, 87 insertions, 7 deletions
diff --git a/fuzzers/corpora/midx/666a779eed16847c6930a71c0547a34e52db409e b/fuzzers/corpora/midx/666a779eed16847c6930a71c0547a34e52db409e
new file mode 100644
index 000000000..ed9e0d07a
--- /dev/null
+++ b/fuzzers/corpora/midx/666a779eed16847c6930a71c0547a34e52db409e
Binary files differ
diff --git a/src/diff_print.c b/src/diff_print.c
index 03d25b087..6c5a2cdc8 100644
--- a/src/diff_print.c
+++ b/src/diff_print.c
@@ -316,6 +316,11 @@ static int diff_print_oid_range(
static int diff_delta_format_path(
git_str *out, const char *prefix, const char *filename)
{
+ if (!filename) {
+ /* don't prefix "/dev/null" */
+ return git_str_puts(out, "/dev/null");
+ }
+
if (git_str_joinpath(out, prefix, filename) < 0)
return -1;
diff --git a/src/fetch.c b/src/fetch.c
index 03d38452c..e9f30d9bc 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -76,8 +76,11 @@ static int maybe_want_oid(git_remote *remote, git_refspec *spec)
GIT_ERROR_CHECK_ALLOC(oid_head);
git_oid_fromstr(&oid_head->oid, spec->src);
- oid_head->name = git__strdup(spec->dst);
- GIT_ERROR_CHECK_ALLOC(oid_head->name);
+
+ if (spec->dst) {
+ oid_head->name = git__strdup(spec->dst);
+ GIT_ERROR_CHECK_ALLOC(oid_head->name);
+ }
if (git_vector_insert(&remote->local_heads, oid_head) < 0 ||
git_vector_insert(&remote->refs, oid_head) < 0)
diff --git a/src/midx.c b/src/midx.c
index eb99e7373..0092601f6 100644
--- a/src/midx.c
+++ b/src/midx.c
@@ -225,8 +225,13 @@ int git_midx_parse(
chunk_hdr = data + sizeof(struct git_midx_header);
last_chunk = NULL;
for (i = 0; i < hdr->chunks; ++i, chunk_hdr += 12) {
- chunk_offset = ((off64_t)ntohl(*((uint32_t *)(chunk_hdr + 4)))) << 32 |
- ((off64_t)ntohl(*((uint32_t *)(chunk_hdr + 8))));
+ uint32_t chunk_id = ntohl(*((uint32_t *)(chunk_hdr + 0)));
+ uint64_t high_offset = ((uint64_t)ntohl(*((uint32_t *)(chunk_hdr + 4)))) & 0xffffffffu;
+ uint64_t low_offset = ((uint64_t)ntohl(*((uint32_t *)(chunk_hdr + 8)))) & 0xffffffffu;
+
+ if (high_offset >= INT32_MAX)
+ return midx_error("chunk offset out of range");
+ chunk_offset = (off64_t)(high_offset << 32 | low_offset);
if (chunk_offset < last_chunk_offset)
return midx_error("chunks are non-monotonic");
if (chunk_offset >= trailer_offset)
@@ -235,7 +240,7 @@ int git_midx_parse(
last_chunk->length = (size_t)(chunk_offset - last_chunk_offset);
last_chunk_offset = chunk_offset;
- switch (ntohl(*((uint32_t *)(chunk_hdr + 0)))) {
+ switch (chunk_id) {
case MIDX_PACKFILE_NAMES_ID:
chunk_packfile_names.offset = last_chunk_offset;
last_chunk = &chunk_packfile_names;
diff --git a/src/remote.c b/src/remote.c
index f6421b9eb..1a79faaab 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -1895,8 +1895,11 @@ static int update_tips_for_spec(
if (git_oid__is_hexstr(spec->src)) {
git_oid id;
- if ((error = git_oid_fromstr(&id, spec->src)) < 0 ||
- (error = update_ref(remote, spec->dst, &id, log_message, callbacks)) < 0)
+ if ((error = git_oid_fromstr(&id, spec->src)) < 0)
+ goto on_error;
+
+ if (spec->dst &&
+ (error = update_ref(remote, spec->dst, &id, log_message, callbacks)) < 0)
goto on_error;
git_oid_cpy(&oid_head.oid, &id);
diff --git a/tests/diff/parse.c b/tests/diff/parse.c
index d3a0c8de6..9c3f798e4 100644
--- a/tests/diff/parse.c
+++ b/tests/diff/parse.c
@@ -431,6 +431,32 @@ void test_diff_parse__new_file_with_space(void)
git_diff_free(diff);
}
+void test_diff_parse__new_file_with_space_and_regenerate_patch(void)
+{
+ const char *content = PATCH_ORIGINAL_NEW_FILE_WITH_SPACE;
+ git_diff *diff = NULL;
+ git_buf buf = GIT_BUF_INIT;
+
+ cl_git_pass(git_diff_from_buffer(&diff, content, strlen(content)));
+ cl_git_pass(git_diff_to_buf(&buf, diff, GIT_DIFF_FORMAT_PATCH));
+
+ git_buf_dispose(&buf);
+ git_diff_free(diff);
+}
+
+void test_diff_parse__delete_file_with_space_and_regenerate_patch(void)
+{
+ const char *content = PATCH_DELETE_FILE_WITH_SPACE;
+ git_diff *diff = NULL;
+ git_buf buf = GIT_BUF_INIT;
+
+ cl_git_pass(git_diff_from_buffer(&diff, content, strlen(content)));
+ cl_git_pass(git_diff_to_buf(&buf, diff, GIT_DIFF_FORMAT_PATCH));
+
+ git_buf_dispose(&buf);
+ git_diff_free(diff);
+}
+
void test_diff_parse__crlf(void)
{
const char *text = PATCH_CRLF;
diff --git a/tests/online/fetch.c b/tests/online/fetch.c
index 7334f7e8b..5beb5b618 100644
--- a/tests/online/fetch.c
+++ b/tests/online/fetch.c
@@ -321,3 +321,32 @@ void test_online_fetch__reachable_commit(void)
git_object_free(obj);
git_remote_free(remote);
}
+
+void test_online_fetch__reachable_commit_without_destination(void)
+{
+ git_remote *remote;
+ git_strarray refspecs;
+ git_object *obj;
+ git_oid expected_id;
+ git_str fetchhead = GIT_STR_INIT;
+ char *refspec = "2c349335b7f797072cf729c4f3bb0914ecb6dec9";
+
+ refspecs.strings = &refspec;
+ refspecs.count = 1;
+
+ git_oid_fromstr(&expected_id, "2c349335b7f797072cf729c4f3bb0914ecb6dec9");
+
+ cl_git_pass(git_remote_create(&remote, _repo, "test",
+ "https://github.com/libgit2/TestGitRepository"));
+ cl_git_pass(git_remote_fetch(remote, &refspecs, NULL, NULL));
+
+ cl_git_fail_with(GIT_ENOTFOUND, git_revparse_single(&obj, _repo, "refs/success"));
+
+ cl_git_pass(git_futils_readbuffer(&fetchhead, "./fetch/.git/FETCH_HEAD"));
+ cl_assert_equal_s(fetchhead.ptr,
+ "2c349335b7f797072cf729c4f3bb0914ecb6dec9\t\t'2c349335b7f797072cf729c4f3bb0914ecb6dec9' of https://github.com/libgit2/TestGitRepository\n");
+
+ git_str_dispose(&fetchhead);
+ git_object_free(obj);
+ git_remote_free(remote);
+}
diff --git a/tests/patch/patch_common.h b/tests/patch/patch_common.h
index 1e03889fc..7e2cb6a58 100644
--- a/tests/patch/patch_common.h
+++ b/tests/patch/patch_common.h
@@ -933,6 +933,15 @@
"@@ -0,0 +1 @@\n" \
"+a\n"
+#define PATCH_DELETE_FILE_WITH_SPACE \
+ "diff --git a/sp ace.txt b/sp ace.txt\n" \
+ "deleted file mode 100644\n" \
+ "index 789819226..000000000\n" \
+ "--- a/sp ace.txt\n" \
+ "+++ /dev/null\n" \
+ "@@ -1 +0,0 @@\n" \
+ "-a\n"
+
#define PATCH_CRLF \
"diff --git a/test-file b/test-file\r\n" \
"new file mode 100644\r\n" \