path: root/builtin/fsck.c
diff options
authorÆvar Arnfjörð Bjarmason <>2021-10-01 09:16:52 (GMT)
committerJunio C Hamano <>2021-10-01 22:06:01 (GMT)
commit31deb28f5e0c85e8bd556ba135e5f0e0926bad7a (patch)
treec28a1ab72e65ecf5acedb6b278722985cc645adf /builtin/fsck.c
parentdccb32bf01411213297cde63cf689e476673a8ec (diff)
fsck: don't hard die on invalid object types
Change the error fsck emits on invalid object types, such as: $ git hash-object --stdin -w -t garbage --literally </dev/null <OID> From the very ungraceful error of: $ git fsck fatal: invalid object type $ To: $ git fsck error: <OID>: object is of unknown type 'garbage': <OID_PATH> [ other fsck output ] We'll still exit with non-zero, but now we'll finish the rest of the traversal. The tests that's being added here asserts that we'll still complain about other fsck issues (e.g. an unrelated dangling blob). To do this we need to pass down the "OBJECT_INFO_ALLOW_UNKNOWN_TYPE" flag from read_loose_object() through to parse_loose_header(). Since the read_loose_object() function is only used in builtin/fsck.c we can simply change it to accept a "struct object_info" (which contains the OBJECT_INFO_ALLOW_UNKNOWN_TYPE in its flags). See f6371f92104 (sha1_file: add read_loose_object() function, 2017-01-13) for the introduction of read_loose_object(). Since we'll need a "struct strbuf" to hold the "type_name" let's pass it to the for_each_loose_file_in_objdir() callback to avoid allocating a new one for each loose object in the iteration. It also makes the memory management simpler than sticking it in fsck_loose() itself, as we'll only need to strbuf_reset() it, with no need to do a strbuf_release() before each "return". Before this commit we'd never check the "type" if read_loose_object() failed, but now we do. We therefore need to initialize it to OBJ_NONE to be able to tell the difference between e.g. its unpack_loose_header() having failed, and us getting past that and into parse_loose_header(). Signed-off-by: Ævar Arnfjörð Bjarmason <> Signed-off-by: Junio C Hamano <>
Diffstat (limited to 'builtin/fsck.c')
1 files changed, 31 insertions, 6 deletions
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 87a99b0..f47b923 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -592,18 +592,36 @@ static void get_default_heads(void)
+struct for_each_loose_cb
+ struct progress *progress;
+ struct strbuf obj_type;
static int fsck_loose(const struct object_id *oid, const char *path, void *data)
+ struct for_each_loose_cb *cb_data = data;
struct object *obj;
- enum object_type type;
+ enum object_type type = OBJ_NONE;
unsigned long size;
void *contents;
int eaten;
+ struct object_info oi = OBJECT_INFO_INIT;
+ int err = 0;
- if (read_loose_object(path, oid, &type, &size, &contents) < 0) {
+ strbuf_reset(&cb_data->obj_type);
+ oi.type_name = &cb_data->obj_type;
+ oi.sizep = &size;
+ oi.typep = &type;
+ if (read_loose_object(path, oid, &contents, &oi) < 0)
+ err = error(_("%s: object corrupt or missing: %s"),
+ oid_to_hex(oid), path);
+ if (type != OBJ_NONE && type < 0)
+ err = error(_("%s: object is of unknown type '%s': %s"),
+ oid_to_hex(oid), cb_data->obj_type.buf, path);
+ if (err < 0) {
errors_found |= ERROR_OBJECT;
- error(_("%s: object corrupt or missing: %s"),
- oid_to_hex(oid), path);
return 0; /* keep checking other objects */
@@ -639,8 +657,10 @@ static int fsck_cruft(const char *basename, const char *path, void *data)
return 0;
-static int fsck_subdir(unsigned int nr, const char *path, void *progress)
+static int fsck_subdir(unsigned int nr, const char *path, void *data)
+ struct for_each_loose_cb *cb_data = data;
+ struct progress *progress = cb_data->progress;
display_progress(progress, nr + 1);
return 0;
@@ -648,6 +668,10 @@ static int fsck_subdir(unsigned int nr, const char *path, void *progress)
static void fsck_object_dir(const char *path)
struct progress *progress = NULL;
+ struct for_each_loose_cb cb_data = {
+ .obj_type = STRBUF_INIT,
+ .progress = progress,
+ };
if (verbose)
fprintf_ln(stderr, _("Checking object directory"));
@@ -656,9 +680,10 @@ static void fsck_object_dir(const char *path)
progress = start_progress(_("Checking object directories"), 256);
for_each_loose_file_in_objdir(path, fsck_loose, fsck_cruft, fsck_subdir,
- progress);
+ &cb_data);
display_progress(progress, 256);
+ strbuf_release(&cb_data.obj_type);
static int fsck_head_link(const char *head_ref_name,