Skip to content

Commit 2988289

Browse files
committed
apply: make update_pre_post_images() sanity check the given postlen
"git apply --whitespace=fix" used to be able to assume that fixing errors will always reduce the size by e.g. stripping whitespaces at the end of lines or collapsing runs of spaces into tabs at the beginning of lines. An update to accomodate fixes that lengthens the result by e.g. expanding leading tabs into spaces were made long time ago but the logic miscounted the necessary space after such whitespace fixes, leading to either under-allocation or over-usage of already allocated space. Illustrate this with a runtime sanity-check to protect us from future breakage. The test was stolen from Kyle McKay who helped to identify the problem. Helped-by: "Kyle J. McKay" <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 923fc5a commit 2988289

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed

builtin/apply.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2171,6 +2171,12 @@ static void update_pre_post_images(struct image *preimage,
21712171
ctx++;
21722172
}
21732173

2174+
if (postlen
2175+
? postlen < new - postimage->buf
2176+
: postimage->len < new - postimage->buf)
2177+
die("BUG: caller miscounted postlen: asked %d, orig = %d, used = %d",
2178+
(int)postlen, (int) postimage->len, (int)(new - postimage->buf));
2179+
21742180
/* Fix the length of the whole thing */
21752181
postimage->len = new - postimage->buf;
21762182
postimage->nr -= reduced;

t/t4138-apply-ws-expansion.sh

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#!/bin/sh
2+
#
3+
# Copyright (C) 2015 Kyle J. McKay
4+
#
5+
6+
test_description='git apply test patches with whitespace expansion.'
7+
8+
. ./test-lib.sh
9+
10+
test_expect_success setup '
11+
#
12+
## create test-N, patchN.patch, expect-N files
13+
#
14+
15+
# test 1
16+
printf "\t%s\n" 1 2 3 4 5 6 >before &&
17+
printf "\t%s\n" 1 2 3 >after &&
18+
printf "%64s\n" a b c >>after &&
19+
printf "\t%s\n" 4 5 6 >>after &&
20+
git diff --no-index before after |
21+
sed -e "s/before/test-1/" -e "s/after/test-1/" >patch1.patch &&
22+
printf "%64s\n" 1 2 3 4 5 6 >test-1 &&
23+
printf "%64s\n" 1 2 3 a b c 4 5 6 >expect-1 &&
24+
25+
# test 2
26+
printf "\t%s\n" a b c d e f >before &&
27+
printf "\t%s\n" a b c >after &&
28+
n=10 &&
29+
x=1 &&
30+
while test $x -lt $n
31+
do
32+
printf "%63s%d\n" "" $x >>after
33+
x=$(( $x + 1 ))
34+
done &&
35+
printf "\t%s\n" d e f >>after &&
36+
git diff --no-index before after |
37+
sed -e "s/before/test-2/" -e "s/after/test-2/" >patch2.patch &&
38+
printf "%64s\n" a b c d e f >test-2 &&
39+
printf "%64s\n" a b c >expect-2 &&
40+
x=1 &&
41+
while test $x -lt $n
42+
do
43+
printf "%63s%d\n" "" $x >>expect-2
44+
x=$(( $x + 1 ))
45+
done &&
46+
printf "%64s\n" d e f >>expect-2 &&
47+
48+
# test 3
49+
printf "\t%s\n" a b c d e f >before &&
50+
printf "\t%s\n" a b c >after &&
51+
n=100 &&
52+
x=0 &&
53+
while test $x -lt $n
54+
do
55+
printf "%63s%02d\n" "" $x >>after
56+
x=$(( $x + 1 ))
57+
done &&
58+
printf "\t%s\n" d e f >>after &&
59+
git diff --no-index before after |
60+
sed -e "s/before/test-3/" -e "s/after/test-3/" >patch3.patch &&
61+
printf "%64s\n" a b c d e f >test-3 &&
62+
printf "%64s\n" a b c >expect-3 &&
63+
x=0 &&
64+
while test $x -lt $n
65+
do
66+
printf "%63s%02d\n" "" $x >>expect-3
67+
x=$(( $x + 1 ))
68+
done &&
69+
printf "%64s\n" d e f >>expect-3 &&
70+
71+
# test 4
72+
>before &&
73+
x=0 &&
74+
while test $x -lt 50
75+
do
76+
printf "\t%02d\n" $x >>before
77+
x=$(( $x + 1 ))
78+
done &&
79+
cat before >after &&
80+
printf "%64s\n" a b c >>after &&
81+
while test $x -lt 100
82+
do
83+
printf "\t%02d\n" $x >>before
84+
printf "\t%02d\n" $x >>after
85+
x=$(( $x + 1 ))
86+
done &&
87+
git diff --no-index before after |
88+
sed -e "s/before/test-4/" -e "s/after/test-4/" >patch4.patch &&
89+
>test-4 &&
90+
x=0 &&
91+
while test $x -lt 50
92+
do
93+
printf "%63s%02d\n" "" $x >>test-4
94+
x=$(( $x + 1 ))
95+
done &&
96+
cat test-4 >expect-4 &&
97+
printf "%64s\n" a b c >>expect-4 &&
98+
while test $x -lt 100
99+
do
100+
printf "%63s%02d\n" "" $x >>test-4
101+
printf "%63s%02d\n" "" $x >>expect-4
102+
x=$(( $x + 1 ))
103+
done &&
104+
105+
git config core.whitespace tab-in-indent,tabwidth=63 &&
106+
git config apply.whitespace fix
107+
108+
'
109+
110+
# Note that `patch` can successfully apply all patches when run
111+
# with the --ignore-whitespace option.
112+
113+
for t in 1 2 3 4
114+
do
115+
test_expect_success 'apply with ws expansion (t=$t)' '
116+
git apply patch$t.patch &&
117+
test_cmp test-$t expect-$t
118+
'
119+
done
120+
121+
test_done

0 commit comments

Comments
 (0)