hash-object: fix buffer reuse with --path in a subdirectory
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> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Mar 20, 2017 at 21:20 UTC
a1be47e4ca65718ec239e4b86a44e45220237aee
2 files changed
+15
-2
builtin/hash-object.c
+5
-2
@@ -115,7 +115,7 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)
115
116
prefix_length = prefix ? strlen(prefix) : 0;
117
if (vpath && prefix)
118
- vpath = prefix_filename(prefix, prefix_length, vpath);
118
+ vpath = xstrdup(prefix_filename(prefix, prefix_length, vpath));
119
120
git_config(git_default_config, NULL);
121
@@ -144,11 +144,14 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)
144
145
for (i = 0 ; i < argc; i++) {
146
const char *arg = argv[i];
147
+ char *to_free = NULL;
148
149
if (0 <= prefix_length)
149
- arg = prefix_filename(prefix, prefix_length, arg);
150
+ arg = to_free =
151
+ xstrdup(prefix_filename(prefix, prefix_length, arg));
152
hash_object(arg, type, no_filters ? NULL : vpath ? vpath : arg,
153
flags, literally);
154
+ free(to_free);
155
}
156
157
if (stdin_paths)
t/t1007-hash-object.sh
+10
@@ -134,6 +134,16 @@ test_expect_success 'gitattributes also work in a subdirectory' '
134
)
135
'
136
137
+test_expect_success '--path works in a subdirectory' '
138
+ (
139
+ cd subdir &&
140
+ path1_sha=$(git hash-object --path=../file1 ../file0) &&
141
+ path0_sha=$(git hash-object --path=../file0 ../file1) &&
142
+ test "$file0_sha" = "$path0_sha" &&
143
+ test "$file1_sha" = "$path1_sha"
144
+ )
145
+'
146
+
147
test_expect_success 'check that --no-filters option works' '
148
nofilters_file1=$(git hash-object --no-filters file1) &&
149
test "$file0_sha" = "$nofilters_file1" &&