Skip to content

Commit 42536dd

Browse files
meyeringgitster
authored andcommitted
do not read beyond end of malloc'd buffer
With diff.suppress-blank-empty=true, "git diff --word-diff" would output data that had been read from uninitialized heap memory. The problem was that fn_out_consume did not account for the possibility of a line with length 1, i.e., the empty context line that diff.suppress-blank-empty=true converts from " \n" to "\n". Since it assumed there would always be a prefix character (the space), it decremented "len" unconditionally, thus passing len=0 to emit_line, which would then blindly call emit_line_0 with len=-1 which would pass that value on to fwrite as SIZE_MAX. Boom. Signed-off-by: Jim Meyering <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5269edf commit 42536dd

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

diff.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,8 +1043,16 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
10431043
emit_line(ecbdata->opt, plain, reset, line, len);
10441044
fputs("~\n", ecbdata->opt->file);
10451045
} else {
1046-
/* don't print the prefix character */
1047-
emit_line(ecbdata->opt, plain, reset, line+1, len-1);
1046+
/*
1047+
* Skip the prefix character, if any. With
1048+
* diff_suppress_blank_empty, there may be
1049+
* none.
1050+
*/
1051+
if (line[0] != '\n') {
1052+
line++;
1053+
len--;
1054+
}
1055+
emit_line(ecbdata->opt, plain, reset, line, len);
10481056
}
10491057
return;
10501058
}

t/t4034-diff-words.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,4 +307,30 @@ test_language_driver python
307307
test_language_driver ruby
308308
test_language_driver tex
309309
310+
test_expect_success 'word-diff with diff.sbe' '
311+
cat >expect <<-\EOF &&
312+
diff --git a/pre b/post
313+
index a1a53b5..bc8fe6d 100644
314+
--- a/pre
315+
+++ b/post
316+
@@ -1,3 +1,3 @@
317+
a
318+
319+
[-b-]{+c+}
320+
EOF
321+
cat >pre <<-\EOF &&
322+
a
323+
324+
b
325+
EOF
326+
cat >post <<-\EOF &&
327+
a
328+
329+
c
330+
EOF
331+
test_when_finished "git config --unset diff.suppress-blank-empty" &&
332+
git config diff.suppress-blank-empty true &&
333+
word_diff --word-diff=plain
334+
'
335+
310336
test_done

0 commit comments

Comments
 (0)