git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] do not read beyond end of malloc'd buffer

From
Jim Meyering <jim@meyering.net>
Date
May 20, 2011, 17:20 UTC
Message-ID
<877h9lb86r.fsf@rho.meyering.net>

I was surprised to see "git diff --word-diff" output a ton of garbage, and tracked it down to a bug that's triggered when the diff.suppress-blank-empty config option to true and when at least one of the context lines is empty.

Here's a quick demo you can run in an empty directory:
    printf 'a\n\n[-b-]{+c+}\n' > exp
    git init && git config diff.suppress-blank-empty true
    printf 'a\n\nb\n' > f && git add . && git commit -m. .
    printf 'a\n\nc\n' > f
    git diff --word-diff | tail -3 > out
    diff out exp

Before the patch, the git diff ... command would read from beyond the end of a heap buffer, and "out" would contain far more than the expected 5 bytes.

Here's the patch:
-- >8 --
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 <meyering@redhat.com>
---
 diff.c |    9 +++++++--
 1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/diff.c b/diff.c
index ba5f7aa..57eea74 100644
--- a/diff.c
+++ b/diff.c
@@ -1117,8 +1117,13 @@ 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);
+			/* If there is a prefix character, skip it.
+			   With diff_suppress_blank_empty, there may be none. */
+			if (line[0] != '\n') {
+			      line++;
+			      len--;
+			}
+			emit_line(ecbdata->opt, plain, reset, line, len);
 		}
 		return;
 	}
--
1.7.5.2.316.gbcebc8b
Next: Junio C Hamano
Message 1 of 3 in “do not read beyond end of malloc'd buffer”
  1. do not read beyond end of malloc'd bufferJim Meyering, May 20, 2011
  2. Junio C HamanoMay 20, 2011
  3. Jim MeyeringMay 21, 2011

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.