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 <meyering@redhat.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jim Meyering committed
May 20, 2011 at 19:20 UTC
42536dd9b9829b4eb4e3706e141b3c8bffa3e826
2 files changed
+36
-2
diff.c
+10
-2
@@ -1043,8 +1043,16 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
1043
emit_line(ecbdata->opt, plain, reset, line, len);
1044
fputs("~\n", ecbdata->opt->file);
1045
} 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);
1056
}
1057
return;
1058
}
t/t4034-diff-words.sh
+26
@@ -307,4 +307,30 @@ test_language_driver python
307
test_language_driver ruby
308
test_language_driver tex
309
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
+
336
test_done