Skip to content

Commit 2764442

Browse files
committed
Merge branch 'jc/apply-ws-fix-expands' into maint
"git apply --whitespace=fix" used to under-allocate the memory when the fix resulted in a longer text than the original patch. * jc/apply-ws-fix-expands: apply: count the size of postimage correctly apply: make update_pre_post_images() sanity check the given postlen apply.c: typofix
2 parents 254a3eb + 407a792 commit 2764442

File tree

2 files changed

+149
-3
lines changed

2 files changed

+149
-3
lines changed

builtin/apply.c

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2230,6 +2230,12 @@ static void update_pre_post_images(struct image *preimage,
22302230
ctx++;
22312231
}
22322232

2233+
if (postlen
2234+
? postlen < new - postimage->buf
2235+
: postimage->len < new - postimage->buf)
2236+
die("BUG: caller miscounted postlen: asked %d, orig = %d, used = %d",
2237+
(int)postlen, (int) postimage->len, (int)(new - postimage->buf));
2238+
22332239
/* Fix the length of the whole thing */
22342240
postimage->len = new - postimage->buf;
22352241
postimage->nr -= reduced;
@@ -2385,18 +2391,34 @@ static int match_fragment(struct image *img,
23852391

23862392
/*
23872393
* The hunk does not apply byte-by-byte, but the hash says
2388-
* it might with whitespace fuzz. We haven't been asked to
2394+
* it might with whitespace fuzz. We weren't asked to
23892395
* ignore whitespace, we were asked to correct whitespace
23902396
* errors, so let's try matching after whitespace correction.
23912397
*
2398+
* While checking the preimage against the target, whitespace
2399+
* errors in both fixed, we count how large the corresponding
2400+
* postimage needs to be. The postimage prepared by
2401+
* apply_one_fragment() has whitespace errors fixed on added
2402+
* lines already, but the common lines were propagated as-is,
2403+
* which may become longer when their whitespace errors are
2404+
* fixed.
2405+
*/
2406+
2407+
/* First count added lines in postimage */
2408+
postlen = 0;
2409+
for (i = 0; i < postimage->nr; i++) {
2410+
if (!(postimage->line[i].flag & LINE_COMMON))
2411+
postlen += postimage->line[i].len;
2412+
}
2413+
2414+
/*
23922415
* The preimage may extend beyond the end of the file,
23932416
* but in this loop we will only handle the part of the
23942417
* preimage that falls within the file.
23952418
*/
23962419
strbuf_init(&fixed, preimage->len + 1);
23972420
orig = preimage->buf;
23982421
target = img->buf + try;
2399-
postlen = 0;
24002422
for (i = 0; i < preimage_limit; i++) {
24012423
size_t oldlen = preimage->line[i].len;
24022424
size_t tgtlen = img->line[try_lno + i].len;
@@ -2424,7 +2446,10 @@ static int match_fragment(struct image *img,
24242446
match = (tgtfix.len == fixed.len - fixstart &&
24252447
!memcmp(tgtfix.buf, fixed.buf + fixstart,
24262448
fixed.len - fixstart));
2427-
postlen += tgtfix.len;
2449+
2450+
/* Add the length if this is common with the postimage */
2451+
if (preimage->line[i].flag & LINE_COMMON)
2452+
postlen += tgtfix.len;
24282453

24292454
strbuf_release(&tgtfix);
24302455
if (!match)

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)