Thread (3 messages) flat view 3 messages, 3 authors, 2016-06-15

Re: [PATCH] Prevent git-upload-pack segfault if object cannot be found

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:42:20
Subsystem: the rest · Maintainer: Linus Torvalds

Possibly related (same subject, not in this thread)

Carl Worth [off-list ref] writes:
In the case in which I hit the original bug, this message is necessary
to provide information about where the actual problem is. Here is what
that scenario looks like with the message:

$ mkdir original;
$ (cd original; git-init-db; touch foo; git add foo; git commit -m "original")
defaulting to local storage area
Committing initial tree 4d5fcadc293a348e88f777dc0920f11e7d71441c
$ git clone -l -s original clone
$ mv original moved
$ git clone clone again
unable to open object pack directory: /tmp/original/.git/objects/pack: No such file or directory
fatal: git-upload-pack: cannot find object 0153d496df669cbe5cecb665dbe6f95b20461917:
fatal: unexpected EOF
clone-pack from '/tmp/clone/.git' failed.

Here the "cannot find object" message doesn't point to the core
problem, but the "unable to open object pack directory" does contain
the "/tmp/original" path of interest.
Updated patch.  The root cause of the problem you had was that
alternates was dangling, so we catch that.

-- >8 --
diff --git a/sha1_file.c b/sha1_file.c
index f08b1d6..c08da35 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -247,6 +247,7 @@ static void link_alt_odb_entries(const c
 		for ( ; cp < ep && *cp != sep; cp++)
 			;
 		if (last != cp) {
+			struct stat st;
 			struct alternate_object_database *alt;
 			/* 43 = 40-byte + 2 '/' + terminating NUL */
 			int pfxlen = cp - last;
@@ -269,9 +270,19 @@ static void link_alt_odb_entries(const c
 			}
 			else
 				memcpy(ent->base, last, pfxlen);
+
 			ent->name = ent->base + pfxlen + 1;
-			ent->base[pfxlen] = ent->base[pfxlen + 3] = '/';
-			ent->base[entlen-1] = 0;
+			ent->base[pfxlen + 3] = '/';
+			ent->base[pfxlen] = ent->base[entlen-1] = 0;
+
+			/* Detect cases where alternate disappeared */
+			if (stat(ent->base, &st) || !S_ISDIR(st.st_mode)) {
+				error("object directory %s does not exist; "
+				      "check .git/objects/info/alternates.",
+				      ent->base);
+				goto bad;
+			}
+			ent->base[pfxlen] = '/';
 
 			/* Prevent the common mistake of listing the same
 			 * thing twice, or object directory itself.
@@ -552,7 +563,9 @@ static void prepare_packed_git_one(char 
 	len = strlen(path);
 	dir = opendir(path);
 	if (!dir) {
-		fprintf(stderr, "unable to open object pack directory: %s: %s\n", path, strerror(errno));
+		if (errno != ENOENT)
+			error("unable to open object pack directory: %s: %s\n",
+			      path, strerror(errno));
 		return;
 	}
 	path[len++] = '/';
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help