apply: report the location of corrupt patches

When parsing a corrupt patch, git apply reports only the line number. That does not tell the user which input the line number refers to. Include the patch input path in the error message so the reported location is easier to use. Reset the line number for each patch input so the reported location stays correct when multiple input files are provided. Add tests for file input, standard input, multiple patch inputs, and existing binary-diff corrupt patch cases. Signed-off-by: Jialong Wang <jerrywang183@yahoo.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jialong Wang committed Mar 17, 2026 at 12:23 UTC c5e15c9a58c0b32ec8be3ae96434834124de175e
3 files changed +42 -4
apply.c
+3 -1
@@ -1875,7 +1875,8 @@ static int parse_single_patch(struct apply_state *state,
1875 len = parse_fragment(state, line, size, patch, fragment);
1876 if (len <= 0) {
1877 free(fragment);
1878 - return error(_("corrupt patch at line %d"), state->linenr);
1878 + return error(_("corrupt patch at %s:%d"),
1879 + state->patch_input_file, state->linenr);
1880 }
1881 fragment->patch = line;
1882 fragment->size = len;
@@ -4825,6 +4826,7 @@ static int apply_patch(struct apply_state *state,
4826 int flush_attributes = 0;
4827
4828 state->patch_input_file = filename;
4829 + state->linenr = 1;
4830 if (read_patch_file(&buf, fd) < 0)
4831 return -128;
4832 offset = 0;
t/t4012-diff-binary.sh
+2 -2
@@ -68,7 +68,7 @@ test_expect_success 'apply detecting corrupt patch correctly' '
68 sed -e "s/-CIT/xCIT/" <output >broken &&
69 test_must_fail git apply --stat --summary broken 2>detected &&
70 detected=$(cat detected) &&
71 - detected=$(expr "$detected" : "error.*at line \\([0-9]*\\)\$") &&
71 + detected=$(expr "$detected" : "error.*broken:\\([0-9]*\\)\$") &&
72 detected=$(sed -ne "${detected}p" broken) &&
73 test "$detected" = xCIT
74 '
@@ -77,7 +77,7 @@ test_expect_success 'apply detecting corrupt patch correctly' '
77 git diff --binary | sed -e "s/-CIT/xCIT/" >broken &&
78 test_must_fail git apply --stat --summary broken 2>detected &&
79 detected=$(cat detected) &&
80 - detected=$(expr "$detected" : "error.*at line \\([0-9]*\\)\$") &&
80 + detected=$(expr "$detected" : "error.*broken:\\([0-9]*\\)\$") &&
81 detected=$(sed -ne "${detected}p" broken) &&
82 test "$detected" = xCIT
83 '
t/t4100-apply-stat.sh
+37 -1
@@ -48,7 +48,43 @@ test_expect_success 'applying a hunk header which overflows fails' '
48 +b
49 EOF
50 test_must_fail git apply patch 2>err &&
51 - echo "error: corrupt patch at line 4" >expect &&
51 + echo "error: corrupt patch at patch:4" >expect &&
52 + test_cmp expect err
53 +'
54 +
55 +test_expect_success 'applying a hunk header which overflows from stdin fails' '
56 + cat >patch <<-\EOF &&
57 + diff -u a/file b/file
58 + --- a/file
59 + +++ b/file
60 + @@ -98765432109876543210 +98765432109876543210 @@
61 + -a
62 + +b
63 + EOF
64 + test_must_fail git apply <patch 2>err &&
65 + echo "error: corrupt patch at <stdin>:4" >expect &&
66 + test_cmp expect err
67 +'
68 +
69 +test_expect_success 'applying multiple patches reports the corrupted input' '
70 + cat >good.patch <<-\EOF &&
71 + diff -u a/file b/file
72 + --- a/file
73 + +++ b/file
74 + @@ -1 +1 @@
75 + -a
76 + +b
77 + EOF
78 + cat >bad.patch <<-\EOF &&
79 + diff -u a/file b/file
80 + --- a/file
81 + +++ b/file
82 + @@ -98765432109876543210 +98765432109876543210 @@
83 + -a
84 + +b
85 + EOF
86 + test_must_fail git apply --stat --summary good.patch bad.patch 2>err &&
87 + echo "error: corrupt patch at bad.patch:4" >expect &&
88 test_cmp expect err
89 '
90 test_done