apply: check git diffs for mutually exclusive header lines
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>
René Scharfe committed
Jun 27, 2017 at 19:03 UTC
d70e9c5c8c865626b6e69c2bf9fd0e368543617b
2 files changed
+33
apply.c
+15
@@ -210,6 +210,7 @@ struct patch {
210
unsigned ws_rule;
211
int lines_added, lines_deleted;
212
int score;
213
+ int extension_linenr; /* first line specifying delete/new/rename/copy */
214
unsigned int is_toplevel_relative:1;
215
unsigned int inaccurate_eof:1;
216
unsigned int is_binary:1;
@@ -1329,6 +1330,18 @@ static char *git_header_name(struct apply_state *state,
1330
}
1331
}
1332
1333
+static int check_header_line(struct apply_state *state, struct patch *patch)
1334
+{
1335
+ int extensions = (patch->is_delete == 1) + (patch->is_new == 1) +
1336
+ (patch->is_rename == 1) + (patch->is_copy == 1);
1337
+ if (extensions > 1)
1338
+ return error(_("inconsistent header lines %d and %d"),
1339
+ patch->extension_linenr, state->linenr);
1340
+ if (extensions && !patch->extension_linenr)
1341
+ patch->extension_linenr = state->linenr;
1342
+ return 0;
1343
+}
1344
+
1345
/* Verify that we recognize the lines following a git header */
1346
static int parse_git_header(struct apply_state *state,
1347
const char *line,
@@ -1395,6 +1408,8 @@ static int parse_git_header(struct apply_state *state,
1408
res = p->fn(state, line + oplen, patch);
1409
if (res < 0)
1410
return -1;
1411
+ if (check_header_line(state, patch))
1412
+ return -1;
1413
if (res > 0)
1414
return offset;
1415
break;
t/t4136-apply-check.sh
+18
@@ -29,4 +29,22 @@ test_expect_success 'apply exits non-zero with no-op patch' '
29
test_must_fail git apply --check input
30
'
31
32
+test_expect_success 'invalid combination: create and copy' '
33
+ test_must_fail git apply --check - <<-\EOF
34
+ diff --git a/1 b/2
35
+ new file mode 100644
36
+ copy from 1
37
+ copy to 2
38
+ EOF
39
+'
40
+
41
+test_expect_success 'invalid combination: create and rename' '
42
+ test_must_fail git apply --check - <<-\EOF
43
+ diff --git a/1 b/2
44
+ new file mode 100644
45
+ rename from 1
46
+ rename to 2
47
+ EOF
48
+'
49
+
50
test_done