summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2019-10-19 15:42:54 +0200
committerPatrick Steinhardt <ps@pks.im>2020-03-26 16:20:18 +0100
commitdb73191b7bc91f2ade9b6b1325033554f9e2b045 (patch)
tree0b800337e4e1b8bf75ca602a3c6bf42c33a6e9af
parentfc60777e31495543479bddba62615d9c27476424 (diff)
downloadlibgit2-db73191b7bc91f2ade9b6b1325033554f9e2b045.tar.gz
patch_parse: reject patches with multiple old/new paths
It's currently possible to have patches with multiple old path name headers. As we didn't check for this case, this resulted in a memory leak when overwriting the old old path with the new old path because we simply discarded the old pointer. Instead of fixing this by free'ing the old pointer, we should reject such patches altogether. It doesn't make any sense for the "---" or "+++" markers to occur multiple times within a patch n the first place. This also implicitly fixes the memory leak.
-rw-r--r--src/patch_parse.c19
-rw-r--r--tests/patch/parse.c6
-rw-r--r--tests/patch/patch_common.h7
3 files changed, 30 insertions, 2 deletions
diff --git a/src/patch_parse.c b/src/patch_parse.c
index 73f1eb11a..06d0fce94 100644
--- a/src/patch_parse.c
+++ b/src/patch_parse.c
@@ -79,10 +79,14 @@ done:
static int parse_header_path(char **out, git_patch_parse_ctx *ctx)
{
git_buf path = GIT_BUF_INIT;
- int error = parse_header_path_buf(&path, ctx, header_path_len(ctx));
+ int error;
+ if ((error = parse_header_path_buf(&path, ctx, header_path_len(ctx))) < 0)
+ goto out;
*out = git_buf_detach(&path);
+out:
+ git_buf_dispose(&path);
return error;
}
@@ -92,6 +96,12 @@ static int parse_header_git_oldpath(
git_buf old_path = GIT_BUF_INIT;
int error;
+ if (patch->old_path) {
+ error = git_parse_err("patch contains duplicate old path at line %"PRIuZ,
+ ctx->parse_ctx.line_num);
+ goto out;
+ }
+
if ((error = parse_header_path_buf(&old_path, ctx, ctx->parse_ctx.line_len - 1)) < 0)
goto out;
@@ -108,9 +118,14 @@ static int parse_header_git_newpath(
git_buf new_path = GIT_BUF_INIT;
int error;
- if ((error = parse_header_path_buf(&new_path, ctx, ctx->parse_ctx.line_len - 1)) < 0)
+ if (patch->new_path) {
+ error = git_parse_err("patch contains duplicate new path at line %"PRIuZ,
+ ctx->parse_ctx.line_num);
goto out;
+ }
+ if ((error = parse_header_path_buf(&new_path, ctx, ctx->parse_ctx.line_len - 1)) < 0)
+ goto out;
patch->new_path = git_buf_detach(&new_path);
out:
diff --git a/tests/patch/parse.c b/tests/patch/parse.c
index b89322ff3..fb185eb2a 100644
--- a/tests/patch/parse.c
+++ b/tests/patch/parse.c
@@ -148,3 +148,9 @@ void test_patch_parse__lifetime_of_patch_does_not_depend_on_buffer(void)
git_patch_free(patch);
}
+
+void test_patch_parse__memory_leak_on_multiple_paths(void)
+{
+ git_patch *patch;
+ cl_git_fail(git_patch_from_buffer(&patch, PATCH_MULTIPLE_OLD_PATHS, strlen(PATCH_MULTIPLE_OLD_PATHS), NULL));
+}
diff --git a/tests/patch/patch_common.h b/tests/patch/patch_common.h
index d730d142c..68b183d38 100644
--- a/tests/patch/patch_common.h
+++ b/tests/patch/patch_common.h
@@ -905,3 +905,10 @@
"-b\n" \
"+bb\n" \
" c\n"
+
+#define PATCH_MULTIPLE_OLD_PATHS \
+ "diff --git \n" \
+ "--- \n" \
+ "+++ \n" \
+ "index 0000..7DDb\n" \
+ "--- \n"