Skip to content

Commit d70e9c5

Browse files
rscharfegitster
authored andcommitted
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 <[email protected]> Signed-off-by: Rene Scharfe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 44e5471 commit d70e9c5

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

apply.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ struct patch {
210210
unsigned ws_rule;
211211
int lines_added, lines_deleted;
212212
int score;
213+
int extension_linenr; /* first line specifying delete/new/rename/copy */
213214
unsigned int is_toplevel_relative:1;
214215
unsigned int inaccurate_eof:1;
215216
unsigned int is_binary:1;
@@ -1329,6 +1330,18 @@ static char *git_header_name(struct apply_state *state,
13291330
}
13301331
}
13311332

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+
13321345
/* Verify that we recognize the lines following a git header */
13331346
static int parse_git_header(struct apply_state *state,
13341347
const char *line,
@@ -1395,6 +1408,8 @@ static int parse_git_header(struct apply_state *state,
13951408
res = p->fn(state, line + oplen, patch);
13961409
if (res < 0)
13971410
return -1;
1411+
if (check_header_line(state, patch))
1412+
return -1;
13981413
if (res > 0)
13991414
return offset;
14001415
break;

t/t4136-apply-check.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,22 @@ test_expect_success 'apply exits non-zero with no-op patch' '
2929
test_must_fail git apply --check input
3030
'
3131

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+
3250
test_done

0 commit comments

Comments
 (0)