From 923fc5ab4017801078a54310f94fd95c28b91ce0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 16 Jan 2015 13:54:52 -0800 Subject: apply.c: typofix Signed-off-by: Junio C Hamano --- builtin/apply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'builtin/apply.c') diff --git a/builtin/apply.c b/builtin/apply.c index 622ee1674a..31f873318c 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -2326,7 +2326,7 @@ static int match_fragment(struct image *img, /* * The hunk does not apply byte-by-byte, but the hash says - * it might with whitespace fuzz. We haven't been asked to + * it might with whitespace fuzz. We weren't asked to * ignore whitespace, we were asked to correct whitespace * errors, so let's try matching after whitespace correction. * -- cgit v1.2.3 From 2988289f2c5764605105037bfcb12f85b9971cf9 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 16 Jan 2015 11:54:47 -0800 Subject: 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" Signed-off-by: Junio C Hamano --- builtin/apply.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'builtin/apply.c') diff --git a/builtin/apply.c b/builtin/apply.c index 31f873318c..da6fb35545 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -2171,6 +2171,12 @@ static void update_pre_post_images(struct image *preimage, ctx++; } + if (postlen + ? postlen < new - postimage->buf + : postimage->len < new - postimage->buf) + die("BUG: caller miscounted postlen: asked %d, orig = %d, used = %d", + (int)postlen, (int) postimage->len, (int)(new - postimage->buf)); + /* Fix the length of the whole thing */ postimage->len = new - postimage->buf; postimage->nr -= reduced; -- cgit v1.2.3 From 407a792ef7e3c142a47c6b09a80f9ede4e14f444 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 16 Jan 2015 15:32:00 -0800 Subject: apply: count the size of postimage correctly Under --whitespace=fix option, match_fragment() function examines the preimage (the common context and the removed lines in the patch) and the file being patched and checks if they match after correcting all whitespace errors. When they are found to match, the common context lines in the preimage is replaced with the fixed copy, because these lines will then be copied to the corresponding place in the postimage by a later call to update_pre_post_images(). Lines that are added in the postimage, under --whitespace=fix, have their whitespace errors already fixed when apply_one_fragment() prepares the preimage and the postimage, so in the end, application of the patch can be done by replacing the block of text in the file being patched that matched the preimage with what is in the postimage that was updated by update_pre_post_images(). In the earlier days, fixing whitespace errors always resulted in reduction of size, either collapsing runs of spaces in the indent to a tab or removing the trailing whitespaces. These days, however, some whitespace error fix results in extending the size. 250b3c6c (apply --whitespace=fix: avoid running over the postimage buffer, 2013-03-22) tried to compute the final postimage size but its math was flawed. It counted the size of the block of text in the original being patched after fixing the whitespace errors on its lines that correspond to the preimage. That number does not have much to do with how big the final postimage would be. Instead count (1) the added lines in the postimage, whose size is the same as in the final patch result because their whitespace errors have already been corrected, and (2) the fixed size of the lines that are common. Signed-off-by: Junio C Hamano --- builtin/apply.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'builtin/apply.c') diff --git a/builtin/apply.c b/builtin/apply.c index da6fb35545..e8953404d2 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -2336,6 +2336,23 @@ static int match_fragment(struct image *img, * ignore whitespace, we were asked to correct whitespace * errors, so let's try matching after whitespace correction. * + * While checking the preimage against the target, whitespace + * errors in both fixed, we count how large the corresponding + * postimage needs to be. The postimage prepared by + * apply_one_fragment() has whitespace errors fixed on added + * lines already, but the common lines were propagated as-is, + * which may become longer when their whitespace errors are + * fixed. + */ + + /* First count added lines in postimage */ + postlen = 0; + for (i = 0; i < postimage->nr; i++) { + if (!(postimage->line[i].flag & LINE_COMMON)) + postlen += postimage->line[i].len; + } + + /* * The preimage may extend beyond the end of the file, * but in this loop we will only handle the part of the * preimage that falls within the file. @@ -2343,7 +2360,6 @@ static int match_fragment(struct image *img, strbuf_init(&fixed, preimage->len + 1); orig = preimage->buf; target = img->buf + try; - postlen = 0; for (i = 0; i < preimage_limit; i++) { size_t oldlen = preimage->line[i].len; size_t tgtlen = img->line[try_lno + i].len; @@ -2371,7 +2387,10 @@ static int match_fragment(struct image *img, match = (tgtfix.len == fixed.len - fixstart && !memcmp(tgtfix.buf, fixed.buf + fixstart, fixed.len - fixstart)); - postlen += tgtfix.len; + + /* Add the length if this is common with the postimage */ + if (preimage->line[i].flag & LINE_COMMON) + postlen += tgtfix.len; strbuf_release(&tgtfix); if (!match) -- cgit v1.2.3