summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2019-11-10 18:44:56 +0100
committerPatrick Steinhardt <ps@pks.im>2019-11-10 18:54:01 +0100
commitde7659ccc8cacc4d375e47021a1d634a931c78e7 (patch)
tree3daa1e75327b89f665096777f80f4f4bf655ee89
parent01ea911b9e14a38f94a0018c13e5f308719aced6 (diff)
downloadlibgit2-de7659ccc8cacc4d375e47021a1d634a931c78e7.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 1bf0190c3..e4031f11d 100644
--- a/src/patch_parse.c
+++ b/src/patch_parse.c
@@ -878,12 +878,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" \