summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2019-11-10 18:44:56 +0100
committerPatrick Steinhardt <ps@pks.im>2020-03-26 22:12:59 +0100
commit8ff44c2ac8b767fe9145bb44dbbd1434184bea2e (patch)
tree20424b3c3c0df031b53a09c0e02bd9776c9a9d87
parent128230ba391c77c7dc774f98453618d601812d58 (diff)
downloadlibgit2-8ff44c2ac8b767fe9145bb44dbbd1434184bea2e.tar.gz
patch_parse: use paths from "---"/"+++" lines for binary patches
For some patches, it is not possible to derive the old and new file paths from the patch header's first line, most importantly when they contain spaces. In such a case, we derive both paths from the "---" and "+++" lines, which allow for non-ambiguous parsing. We fail to use these paths when parsing binary patches without data, though, as we always expect the header paths to be filled in. Fix this by using the "---"/"+++" paths by default and only fall back to header paths if they aren't set. If neither of those paths are set, we just return an error. Add two tests to verify this behaviour, one of which would have previously caused a segfault.
-rw-r--r--src/patch_parse.c16
-rw-r--r--tests/patch/parse.c14
-rw-r--r--tests/patch/patch_common.h12
3 files changed, 37 insertions, 5 deletions
diff --git a/src/patch_parse.c b/src/patch_parse.c
index 2f18b8786..e6406fc86 100644
--- a/src/patch_parse.c
+++ b/src/patch_parse.c
@@ -866,12 +866,18 @@ static int parse_patch_binary_nodata(
git_patch_parsed *patch,
git_patch_parse_ctx *ctx)
{
+ const char *old = patch->old_path ? patch->old_path : patch->header_old_path;
+ const char *new = patch->new_path ? patch->new_path : patch->header_new_path;
+
+ if (!old || !new)
+ return git_parse_err("corrupt binary data without paths at line %"PRIuZ, ctx->parse_ctx.line_num);
+
if (git_parse_advance_expected_str(&ctx->parse_ctx, "Binary files ") < 0 ||
- git_parse_advance_expected_str(&ctx->parse_ctx, patch->header_old_path) < 0 ||
- git_parse_advance_expected_str(&ctx->parse_ctx, " and ") < 0 ||
- git_parse_advance_expected_str(&ctx->parse_ctx, patch->header_new_path) < 0 ||
- git_parse_advance_expected_str(&ctx->parse_ctx, " differ") < 0 ||
- git_parse_advance_nl(&ctx->parse_ctx) < 0)
+ git_parse_advance_expected_str(&ctx->parse_ctx, old) < 0 ||
+ git_parse_advance_expected_str(&ctx->parse_ctx, " and ") < 0 ||
+ git_parse_advance_expected_str(&ctx->parse_ctx, new) < 0 ||
+ git_parse_advance_expected_str(&ctx->parse_ctx, " differ") < 0 ||
+ git_parse_advance_nl(&ctx->parse_ctx) < 0)
return git_parse_err("corrupt git binary header at line %"PRIuZ, ctx->parse_ctx.line_num);
patch->base.binary.contains_data = 0;
diff --git a/tests/patch/parse.c b/tests/patch/parse.c
index c18b63ab7..0c4eccc52 100644
--- a/tests/patch/parse.c
+++ b/tests/patch/parse.c
@@ -170,6 +170,20 @@ void test_patch_parse__binary_file_with_empty_quoted_paths(void)
strlen(PATCH_BINARY_FILE_WITH_QUOTED_EMPTY_PATHS), NULL));
}
+void test_patch_parse__binary_file_path_with_spaces(void)
+{
+ git_patch *patch;
+ cl_git_fail(git_patch_from_buffer(&patch, PATCH_BINARY_FILE_PATH_WITH_SPACES,
+ strlen(PATCH_BINARY_FILE_PATH_WITH_SPACES), NULL));
+}
+
+void test_patch_parse__binary_file_path_without_body_paths(void)
+{
+ git_patch *patch;
+ cl_git_fail(git_patch_from_buffer(&patch, PATCH_BINARY_FILE_PATH_WITHOUT_BODY_PATHS,
+ strlen(PATCH_BINARY_FILE_PATH_WITHOUT_BODY_PATHS), NULL));
+}
+
void test_patch_parse__memory_leak_on_multiple_paths(void)
{
git_patch *patch;
diff --git a/tests/patch/patch_common.h b/tests/patch/patch_common.h
index 4f2141dbe..92ab7692e 100644
--- a/tests/patch/patch_common.h
+++ b/tests/patch/patch_common.h
@@ -924,6 +924,18 @@
"+++ \"\"\n" \
"Binary files "
+#define PATCH_BINARY_FILE_PATH_WITH_SPACES \
+ "diff --git a b c d e f\n" \
+ "--- a b c\n" \
+ "+++ d e f\n" \
+ "Binary files a b c and d e f differ"
+
+#define PATCH_BINARY_FILE_PATH_WITHOUT_BODY_PATHS \
+ "diff --git a b c d e f\n" \
+ "--- \n" \
+ "+++ \n" \
+ "Binary files a b c and d e f differ"
+
#define PATCH_MULTIPLE_OLD_PATHS \
"diff --git \n" \
"--- \n" \