Merge branch 'zy/apply-abandoned-header-fix' into seen

A candidate 'git diff' header parsed by 'git apply' has been isolated
in a temporary structure, preventing any partially parsed state from
polluting the main patch structure and causing assertions to trip if
the header is ultimately rejected.

* zy/apply-abandoned-header-fix:
  apply: avoid leaking abandoned git-header state
seen
Junio C Hamano 2026-07-24 16:12:26 -07:00
commit 23198069bf
2 changed files with 47 additions and 7 deletions

29
apply.c
View File

@ -1374,6 +1374,9 @@ int parse_git_diff_header(struct strbuf *root,
* the default name from the header.
*/
patch->def_name = git_header_name(p_value, line, len);
if (patch->def_name && !*patch->def_name)
FREE_AND_NULL(patch->def_name);

if (patch->def_name && root->len) {
char *s = xstrfmt("%s%s", root->buf, patch->def_name);
free(patch->def_name);
@ -1644,15 +1647,27 @@ static int find_header(struct apply_state *state,
* or mode change, so we handle that specially
*/
if (!memcmp("diff --git ", line, 11)) {
int git_hdr_len = parse_git_diff_header(&state->root,
state->patch_input_file,
&state->linenr,
state->p_value, line, len,
size, patch);
if (git_hdr_len < 0)
struct patch git_patch = { 0 };
int git_linenr = state->linenr;
int git_hdr_len;

git_patch.inaccurate_eof = patch->inaccurate_eof;
git_patch.recount = patch->recount;
git_hdr_len = parse_git_diff_header(&state->root,
state->patch_input_file,
&git_linenr,
state->p_value, line, len,
size, &git_patch);
if (git_hdr_len < 0) {
release_patch(&git_patch);
return -128;
if (git_hdr_len <= len)
}
if (git_hdr_len <= len) {
release_patch(&git_patch);
continue;
}
*patch = git_patch;
state->linenr = git_linenr;
*hdrsize = git_hdr_len;
return offset;
}

View File

@ -113,6 +113,31 @@ test_expect_success 'applying a patch with a missing filename reports the input'
test_cmp expect err
'

test_expect_success 'empty default filename reports the input' '
cat >empty-name.patch <<-\EOF &&
diff --git "a/""b/"

--- /dev/null
+++ "
@@ -0,0 +1 @@
+
EOF
test_must_fail git apply empty-name.patch 2>err &&
test_grep "git diff header lacks filename information" err
'

test_expect_success 'abandoned git header does not reuse names' '
cat >abandoned-git-header.patch <<-\EOF &&
diff --git a/foo b/foo

--- /dev/null
+++ b/foo
@@ -0,0 +1 @@
+x
EOF
git apply --check abandoned-git-header.patch
'

test_expect_success 'applying a patch with an invalid mode reports the input' '
cat >mode.patch <<-\EOF &&
diff --git a/f b/f