From 42536dd9b9829b4eb4e3706e141b3c8bffa3e826 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Fri, 20 May 2011 19:20:12 +0200 Subject: [PATCH] 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 Signed-off-by: Junio C Hamano --- diff.c | 12 ++++++++++-- t/t4034-diff-words.sh | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/diff.c b/diff.c index 5422c43882..f90c7a896b 100644 --- a/diff.c +++ b/diff.c @@ -1043,8 +1043,16 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) emit_line(ecbdata->opt, plain, reset, line, len); fputs("~\n", ecbdata->opt->file); } else { - /* don't print the prefix character */ - emit_line(ecbdata->opt, plain, reset, line+1, len-1); + /* + * Skip the prefix character, if any. With + * diff_suppress_blank_empty, there may be + * none. + */ + if (line[0] != '\n') { + line++; + len--; + } + emit_line(ecbdata->opt, plain, reset, line, len); } return; } diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh index 37aeab0d5c..c374aa4c1c 100755 --- a/t/t4034-diff-words.sh +++ b/t/t4034-diff-words.sh @@ -307,4 +307,30 @@ test_language_driver python test_language_driver ruby test_language_driver tex +test_expect_success 'word-diff with diff.sbe' ' + cat >expect <<-\EOF && + diff --git a/pre b/post + index a1a53b5..bc8fe6d 100644 + --- a/pre + +++ b/post + @@ -1,3 +1,3 @@ + a + + [-b-]{+c+} + EOF + cat >pre <<-\EOF && + a + + b + EOF + cat >post <<-\EOF && + a + + c + EOF + test_when_finished "git config --unset diff.suppress-blank-empty" && + git config diff.suppress-blank-empty true && + word_diff --word-diff=plain +' + test_done