git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Gregoire Geis <opensource@gregoirege.is>
To: git@vger.kernel.org
Cc: Junio C Hamano <gitster@pobox.com>,
	Gregoire Geis <opensource@gregoirege.is>
Subject: [PATCH] diff-no-index: fix stdin path in subdirectory
Date: Fri,  8 Aug 2025 00:06:13 +0900	[thread overview]
Message-ID: <20250807150613.32177-1-opensource@gregoirege.is> (raw)

`git diff --no-index` tried to normalize paths before printing them,
skipping a prefix before reading a string. However, `-` doesn't start
with this prefix, leading to a buffer overflow:

$ make SANITIZE=address
$ mkdir a && cd a
$ echo a | ../git diff --no-index /dev/null -
=================================================================
==14536==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60b000001f92 at pc 0x000102612a30 bp 0x00016db386d0 sp 0x00016db386c8
READ of size 1 at 0x60b000001f92 thread T0
    #0 0x102612a2c in diff_flush_patch diff.c:6154
    #1 0x10260dbfc in diff_flush diff.c:6829
    #2 0x1025f218c in diff_no_index diff-no-index.c:422
    #3 0x102356338 in cmd_diff diff.c:501
    #4 0x1022cc780 in run_builtin git.c:480
    #5 0x1022c9bec in handle_builtin git.c:746
    #6 0x1022c8670 in cmd_main git.c:953
    #7 0x1024fe230 in main common-main.c:9

Signed-off-by: Gregoire Geis <opensource@gregoirege.is>
---
Hello!

I noticed that running `git diff --no-index /dev/null -` in a
subdirectory leads to garbage file names (instead of `a/-` and `b/-`).

Valgrind and ASAN confirmed that this is a heap buffer overflow. I
fixed it by checking against "-" when writing the file names in the
patch, which leads to results similar to using an absolute path (e.g.
`a/dev/stdin`, `a/-`, no matter the working directory). "-" is a
special input for `git diff --no-index`, so I don't think we need any
kind of normalization before this check.

I added a test which currently fails on `master`. I chose a
subdirectory `aa/bb/cc` to make sure that the path is long enough for
garbage to appear even if git is compiled without ASAN.

 diff.c                        |  4 ++--
 t/meson.build                 |  1 +
 t/t4072-diff-no-index-dash.sh | 17 +++++++++++++++++
 3 files changed, 20 insertions(+), 2 deletions(-)
 create mode 100755 t/t4072-diff-no-index-dash.sh

diff --git a/diff.c b/diff.c
index dca87e1..88e93e5 100644
--- a/diff.c
+++ b/diff.c
@@ -4626,12 +4626,12 @@ static void diff_fill_oid_info(struct diff_filespec *one, struct index_state *is
 static void strip_prefix(int prefix_length, const char **namep, const char **otherp)
 {
 	/* Strip the prefix but do not molest /dev/null and absolute paths */
-	if (*namep && !is_absolute_path(*namep)) {
+	if (*namep && !is_absolute_path(*namep) && strcmp(*namep, "-")) {
 		*namep += prefix_length;
 		if (**namep == '/')
 			++*namep;
 	}
-	if (*otherp && !is_absolute_path(*otherp)) {
+	if (*otherp && !is_absolute_path(*otherp) && strcmp(*otherp, "-")) {
 		*otherp += prefix_length;
 		if (**otherp == '/')
 			++*otherp;
diff --git a/t/meson.build b/t/meson.build
index bbeba1a..9042f3f 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -486,6 +486,7 @@ integration_tests = [
   't4069-remerge-diff.sh',
   't4070-diff-pairs.sh',
   't4071-diff-minimal.sh',
+  't4072-diff-no-index-dash.sh',
   't4100-apply-stat.sh',
   't4101-apply-nonl.sh',
   't4102-apply-rename.sh',
diff --git a/t/t4072-diff-no-index-dash.sh b/t/t4072-diff-no-index-dash.sh
new file mode 100755
index 0000000..35170a4
--- /dev/null
+++ b/t/t4072-diff-no-index-dash.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+test_description='`git diff file -` does not crash'
+
+. ./test-lib.sh
+
+test_expect_success '`git diff --no-index /dev/null -` works in root' '
+  echo foo | git diff --no-index /dev/null - | grep "a/- b/-"
+'
+
+test_expect_success '`git diff --no-index /dev/null -` works in subdirectory' '
+  mkdir -p aa/bb/cc &&
+  cd aa/bb/cc &&
+  echo foo | git diff --no-index /dev/null - | grep "a/- b/-"
+'
+
+test_done

base-commit: 64cbe5e2e8a7b0f92c780b210e602496bd5cad0f
-- 
2.48.1


             reply	other threads:[~2025-08-07 15:06 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-07 15:06 Gregoire Geis [this message]
2025-08-07 18:36 ` [PATCH] diff-no-index: fix stdin path in subdirectory Junio C Hamano
2025-08-08 11:25   ` opensource
2025-08-08 16:09     ` Junio C Hamano
2025-08-09  2:12       ` opensource

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250807150613.32177-1-opensource@gregoirege.is \
    --to=opensource@gregoirege.is \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).