{"thread":{"id":"5473","subject":"Fix git-fsck-objects SIGSEGV/divide-by-zero","startedAt":"2006-09-04T15:34:12Z","lastAt":"2006-09-04T15:34:12Z","messageCount":1,"participants":["Linus Torvalds"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"26304","messageId":"Pine.LNX.4.64.0609040821520.27779@g5.osdl.org","threadId":"5473","inReplyTo":null,"subject":"Fix git-fsck-objects SIGSEGV/divide-by-zero","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-09-04T15:34:12Z","receivedAt":"2006-09-04T15:34:12Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nIf you try to fsck a repository that isn't entirely empty, but that has no \ninter-object references (ie all the objects are blobs, and don't refer to \nanything else), git-fsck-objects currently fails.\n\nThis probably cannot happen in practice, but can be tested with something \nlike\n\n\tgit init-db\n\ttouch dummy\n\tgit add dummy\n\tgit fsck-objects\n\nwhere the fsck will die by a divide-by-zero when it tries to look up the \nreferences from the one object it found (hash_obj() will do a modulus by \nrefs_hash_size).\n\nOn some other archiectures (ppc, sparc) the divide-by-zero will go \nunnoticed, and we'll instead SIGSEGV when we hit the \"refs_hash[j]\" \naccess.\n\nSo move the test that should protect against this from mark_reachable() \ninto lookup_object_refs(), which incidentally in the process also fixes \nmark_reachable() itself (it used to not mark the one object that _was_ \nreachable, because it decided that it had no refs too early).\n\nSigned-off-by: Linus Torvalds <torvalds@osdl.org>\n---\n\ndiff --git a/object-refs.c b/object-refs.c\nindex b0034e4..98ea100 100644\n--- a/object-refs.c\n+++ b/object-refs.c\n@@ -55,9 +55,13 @@ static void add_object_refs(struct objec\n \n struct object_refs *lookup_object_refs(struct object *obj)\n {\n-\tint j = hash_obj(obj, refs_hash_size);\n \tstruct object_refs *ref;\n+\tint j;\n \n+\t/* nothing to lookup */\n+\tif (!refs_hash_size)\n+\t\treturn NULL;\n+\tj = hash_obj(obj, refs_hash_size);\n \twhile ((ref = refs_hash[j]) != NULL) {\n \t\tif (ref->base == obj)\n \t\t\tbreak;\n@@ -125,9 +129,6 @@ void mark_reachable(struct object *obj, \n \n \tif (!track_object_refs)\n \t\tdie(\"cannot do reachability with object refs turned off\");\n-\t/* nothing to lookup */\n-\tif (!refs_hash_size)\n-\t\treturn;\n \t/* If we've been here already, don't bother */\n \tif (obj->flags & mask)\n \t\treturn;\n"}]}