Skip to content

Commit 2720f6d

Browse files
rscharfegitster
authored andcommitted
fsck: handle NULL return of lookup_blob() and lookup_tree()
lookup_blob() and lookup_tree() can return NULL if they find an object of an unexpected type. Accessing the object member is undefined in that case. Cast the result to a struct object pointer instead; we can do that because object is the first member of all object types. This trick is already used in other places in the code. An error message is already shown by object_as_type(), which is called by the lookup functions. The walk callback functions are expected to handle NULL object pointers passed to them, but put_object_name() needs a valid object, so avoid calling it without one. Suggested-by: SZEDER Gábor <[email protected]> Helped-by: Junio C Hamano <[email protected]> Signed-off-by: Rene Scharfe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 4010f1d commit 2720f6d

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

fsck.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -358,15 +358,15 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op
358358
continue;
359359

360360
if (S_ISDIR(entry.mode)) {
361-
obj = &lookup_tree(entry.oid)->object;
362-
if (name)
361+
obj = (struct object *)lookup_tree(entry.oid);
362+
if (name && obj)
363363
put_object_name(options, obj, "%s%s/", name,
364364
entry.path);
365365
result = options->walk(obj, OBJ_TREE, data, options);
366366
}
367367
else if (S_ISREG(entry.mode) || S_ISLNK(entry.mode)) {
368-
obj = &lookup_blob(entry.oid)->object;
369-
if (name)
368+
obj = (struct object *)lookup_blob(entry.oid);
369+
if (name && obj)
370370
put_object_name(options, obj, "%s%s", name,
371371
entry.path);
372372
result = options->walk(obj, OBJ_BLOB, data, options);

t/t1450-fsck.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,28 @@ test_expect_success 'unparseable tree object' '
222222
test_i18ngrep ! "fatal: empty filename in tree entry" out
223223
'
224224

225+
hex2oct() {
226+
perl -ne 'printf "\\%03o", hex for /../g'
227+
}
228+
229+
test_expect_success 'tree entry with type mismatch' '
230+
test_when_finished "remove_object \$blob" &&
231+
test_when_finished "remove_object \$tree" &&
232+
test_when_finished "remove_object \$commit" &&
233+
test_when_finished "git update-ref -d refs/heads/type_mismatch" &&
234+
blob=$(echo blob | git hash-object -w --stdin) &&
235+
blob_bin=$(echo $blob | hex2oct) &&
236+
tree=$(
237+
printf "40000 dir\0${blob_bin}100644 file\0${blob_bin}" |
238+
git hash-object -t tree --stdin -w --literally
239+
) &&
240+
commit=$(git commit-tree $tree) &&
241+
git update-ref refs/heads/type_mismatch $commit &&
242+
test_must_fail git fsck >out 2>&1 &&
243+
test_i18ngrep "is a blob, not a tree" out &&
244+
test_i18ngrep ! "dangling blob" out
245+
'
246+
225247
test_expect_success 'tag pointing to nonexistent' '
226248
cat >invalid-tag <<-\EOF &&
227249
object ffffffffffffffffffffffffffffffffffffffff

0 commit comments

Comments
 (0)