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

[PATCH 1/6] hash-object: fix buffer reuse with --path in a subdirectory

From
Jeff King <peff@peff.net>
Date
Mar 21, 2017, 01:20 UTC
Message-ID
<20170321012042.jb5biz2min7a34gu@sigill.intra.peff.net>
In-Reply-To
<20170321011838.rdhnbfwbigm4s4e3@sigill.intra.peff.net>

The hash-object command uses prefix_filename() without duplicating its return value. Since that function returns a static buffer, the value is overwritten by subsequent calls.

This can cause incorrect results when we use --path along with hashing a file by its relative path, both of which need to call prefix_filename(). We overwrite the filename computed for --path, effectively ignoring it.

We can fix this by calling xstrdup on the return value. Note that we don't bother freeing the "vpath" instance, as it remains valid until the program exit.

Signed-off-by: Jeff King <peff@peff.net>
---
 builtin/hash-object.c  |  7 +++++--
 t/t1007-hash-object.sh | 10 ++++++++++
 2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index 9028e1fdc..56df77b0c 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -115,7 +115,7 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)
 
 	prefix_length = prefix ? strlen(prefix) : 0;
 	if (vpath && prefix)
-		vpath = prefix_filename(prefix, prefix_length, vpath);
+		vpath = xstrdup(prefix_filename(prefix, prefix_length, vpath));
 
 	git_config(git_default_config, NULL);
 
@@ -144,11 +144,14 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)
 
 	for (i = 0 ; i < argc; i++) {
 		const char *arg = argv[i];
+		char *to_free = NULL;
 
 		if (0 <= prefix_length)
-			arg = prefix_filename(prefix, prefix_length, arg);
+			arg = to_free =
+				xstrdup(prefix_filename(prefix, prefix_length, arg));
 		hash_object(arg, type, no_filters ? NULL : vpath ? vpath : arg,
 			    flags, literally);
+		free(to_free);
 	}
 
 	if (stdin_paths)
diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh
index c5245c5cb..532682f51 100755
--- a/t/t1007-hash-object.sh
+++ b/t/t1007-hash-object.sh
@@ -134,6 +134,16 @@ test_expect_success 'gitattributes also work in a subdirectory' '
 	)
 '
 
+test_expect_success '--path works in a subdirectory' '
+	(
+		cd subdir &&
+		path1_sha=$(git hash-object --path=../file1 ../file0) &&
+		path0_sha=$(git hash-object --path=../file0 ../file1) &&
+		test "$file0_sha" = "$path0_sha" &&
+		test "$file1_sha" = "$path1_sha"
+	)
+'
+
 test_expect_success 'check that --no-filters option works' '
 	nofilters_file1=$(git hash-object --no-filters file1) &&
 	test "$file0_sha" = "$nofilters_file1" &&
-- 
2.12.1.683.gcd02edfec
Previous: Jeff KingNext: Jeff King
Message 2 of 11 in “prefix_filename cleanups”
  1. 0/6 prefix_filename cleanupsJeff King, Mar 21, 2017
  2. 1/6 hash-object: fix buffer reuse with --path in a subdirectoryJeff King, Mar 21, 2017
  3. 2/6 prefix_filename: move docstring to header fileJeff King, Mar 21, 2017
  4. 3/6 prefix_filename: drop length parameterJeff King, Mar 21, 2017
  5. 4/6 prefix_filename: return newly allocated stringJeff King, Mar 21, 2017
  6. Junio C HamanoMar 21, 2017
  7. Jeff KingMar 21, 2017
  8. Jeff KingMar 21, 2017
  9. 5/6 prefix_filename: simplify windows #ifdefJeff King, Mar 21, 2017
  10. 6/6 bundle: use prefix_filename with bundle pathJeff King, Mar 21, 2017
  11. Junio C HamanoMar 21, 2017

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.