summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRené Scharfe <l.s.r@web.de>2017-06-27 19:03:39 +0200
committerJunio C Hamano <gitster@pobox.com>2017-06-27 14:41:10 -0700
commitd70e9c5c8c865626b6e69c2bf9fd0e368543617b (patch)
tree309b7e2255b5467662d3f3b43f74a369469a874d
parent44e5471a8d8ec5f04058220f8b91513b5b5accaa (diff)
downloadgit-rs/apply-validate-input.tar.gz
apply: check git diffs for mutually exclusive header linesrs/apply-validate-input
A file can either be added, removed, copied, or renamed, but no two of these actions can be done by the same patch. Some of these combinations provoke error messages due to missing file names, and some are only caught by an assertion. Check git patches already as they are parsed and report conflicting lines on sight. Found by Vegard Nossum using AFL. Reported-by: Vegard Nossum <vegard.nossum@oracle.com> Signed-off-by: Rene Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--apply.c15
-rwxr-xr-xt/t4136-apply-check.sh18
2 files changed, 33 insertions, 0 deletions
diff --git a/apply.c b/apply.c
index 4b689d9bf7..574ada87c5 100644
--- a/apply.c
+++ b/apply.c
@@ -210,6 +210,7 @@ struct patch {
unsigned ws_rule;
int lines_added, lines_deleted;
int score;
+ int extension_linenr; /* first line specifying delete/new/rename/copy */
unsigned int is_toplevel_relative:1;
unsigned int inaccurate_eof:1;
unsigned int is_binary:1;
@@ -1329,6 +1330,18 @@ static char *git_header_name(struct apply_state *state,
}
}
+static int check_header_line(struct apply_state *state, struct patch *patch)
+{
+ int extensions = (patch->is_delete == 1) + (patch->is_new == 1) +
+ (patch->is_rename == 1) + (patch->is_copy == 1);
+ if (extensions > 1)
+ return error(_("inconsistent header lines %d and %d"),
+ patch->extension_linenr, state->linenr);
+ if (extensions && !patch->extension_linenr)
+ patch->extension_linenr = state->linenr;
+ return 0;
+}
+
/* Verify that we recognize the lines following a git header */
static int parse_git_header(struct apply_state *state,
const char *line,
@@ -1395,6 +1408,8 @@ static int parse_git_header(struct apply_state *state,
res = p->fn(state, line + oplen, patch);
if (res < 0)
return -1;
+ if (check_header_line(state, patch))
+ return -1;
if (res > 0)
return offset;
break;
diff --git a/t/t4136-apply-check.sh b/t/t4136-apply-check.sh
index 4b0a374b63..6d92872318 100755
--- a/t/t4136-apply-check.sh
+++ b/t/t4136-apply-check.sh
@@ -29,4 +29,22 @@ test_expect_success 'apply exits non-zero with no-op patch' '
test_must_fail git apply --check input
'
+test_expect_success 'invalid combination: create and copy' '
+ test_must_fail git apply --check - <<-\EOF
+ diff --git a/1 b/2
+ new file mode 100644
+ copy from 1
+ copy to 2
+ EOF
+'
+
+test_expect_success 'invalid combination: create and rename' '
+ test_must_fail git apply --check - <<-\EOF
+ diff --git a/1 b/2
+ new file mode 100644
+ rename from 1
+ rename to 2
+ EOF
+'
+
test_done