Skip to content

Commit 250b3c6

Browse files
committed
apply --whitespace=fix: avoid running over the postimage buffer
Originally update-pre-post-images could assume that any whitespace fixing will make the result only shorter by unexpanding runs of leading SPs into HTs and removing trailing whitespaces at the end of lines. Updating the post-image we read from the patch to match the actual result can be performed in-place under this assumption. These days, however, we have tab-in-indent (aka Python) rule whose result can be longer than the original, and we do need to allocate a larger buffer than the input and replace the result. Fortunately the support for lengthening rewrite was already added when we began supporting "match while ignoring whitespace differences" mode in 86c91f9 (git apply: option to ignore whitespace differences, 2009-08-04). We only need to correctly count the number of bytes necessary to hold the updated result and tell the function to allocate a new buffer. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1599999 commit 250b3c6

File tree

4 files changed

+39
-9
lines changed

4 files changed

+39
-9
lines changed

builtin/apply.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2113,10 +2113,10 @@ static void update_pre_post_images(struct image *preimage,
21132113

21142114
/*
21152115
* Adjust the common context lines in postimage. This can be
2116-
* done in-place when we are just doing whitespace fixing,
2117-
* which does not make the string grow, but needs a new buffer
2118-
* when ignoring whitespace causes the update, since in this case
2119-
* we could have e.g. tabs converted to multiple spaces.
2116+
* done in-place when we are shrinking it with whitespace
2117+
* fixing, but needs a new buffer when ignoring whitespace or
2118+
* expanding leading tabs to spaces.
2119+
*
21202120
* We trust the caller to tell us if the update can be done
21212121
* in place (postlen==0) or not.
21222122
*/
@@ -2172,7 +2172,7 @@ static int match_fragment(struct image *img,
21722172
int i;
21732173
char *fixed_buf, *buf, *orig, *target;
21742174
struct strbuf fixed;
2175-
size_t fixed_len;
2175+
size_t fixed_len, postlen;
21762176
int preimage_limit;
21772177

21782178
if (preimage->nr + try_lno <= img->nr) {
@@ -2322,6 +2322,7 @@ static int match_fragment(struct image *img,
23222322
strbuf_init(&fixed, preimage->len + 1);
23232323
orig = preimage->buf;
23242324
target = img->buf + try;
2325+
postlen = 0;
23252326
for (i = 0; i < preimage_limit; i++) {
23262327
size_t oldlen = preimage->line[i].len;
23272328
size_t tgtlen = img->line[try_lno + i].len;
@@ -2349,6 +2350,7 @@ static int match_fragment(struct image *img,
23492350
match = (tgtfix.len == fixed.len - fixstart &&
23502351
!memcmp(tgtfix.buf, fixed.buf + fixstart,
23512352
fixed.len - fixstart));
2353+
postlen += tgtfix.len;
23522354

23532355
strbuf_release(&tgtfix);
23542356
if (!match)
@@ -2386,8 +2388,10 @@ static int match_fragment(struct image *img,
23862388
* hunk match. Update the context lines in the postimage.
23872389
*/
23882390
fixed_buf = strbuf_detach(&fixed, &fixed_len);
2391+
if (postlen < postimage->len)
2392+
postlen = 0;
23892393
update_pre_post_images(preimage, postimage,
2390-
fixed_buf, fixed_len, 0);
2394+
fixed_buf, fixed_len, postlen);
23912395
return 1;
23922396

23932397
unmatch_exit:

t/t4124-apply-ws-rule.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,4 +486,30 @@ test_expect_success 'same, but with CR-LF line endings && cr-at-eol unset' '
486486
test_cmp one expect
487487
'
488488

489+
test_expect_success 'whitespace=fix to expand' '
490+
qz_to_tab_space >preimage <<-\EOF &&
491+
QQa
492+
QQb
493+
QQc
494+
ZZZZZZZZZZZZZZZZd
495+
QQe
496+
QQf
497+
QQg
498+
EOF
499+
qz_to_tab_space >patch <<-\EOF &&
500+
diff --git a/preimage b/preimage
501+
--- a/preimage
502+
+++ b/preimage
503+
@@ -1,7 +1,6 @@
504+
QQa
505+
QQb
506+
QQc
507+
-QQd
508+
QQe
509+
QQf
510+
QQg
511+
EOF
512+
git -c core.whitespace=tab-in-indent apply --whitespace=fix patch
513+
'
514+
489515
test_done

t/t4150-am.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ test_expect_success 'setup: messages' '
1717
vero eos et accusam et justo duo dolores et ea rebum.
1818
1919
EOF
20-
q_to_tab <<-\EOF >>msg &&
20+
qz_to_tab_space <<-\EOF >>msg &&
2121
QDuis autem vel eum iriure dolor in hendrerit in vulputate velit
2222
Qesse molestie consequat, vel illum dolore eu feugiat nulla facilisis
2323
Qat vero eros et accumsan et iusto odio dignissim qui blandit

t/test-lib-functions.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ q_to_cr () {
8787
tr Q '\015'
8888
}
8989

90-
q_to_tab () {
91-
tr Q '\011'
90+
qz_to_tab_space () {
91+
tr QZ '\011\040'
9292
}
9393

9494
append_cr () {

0 commit comments

Comments
 (0)