From: Junio C Hamano Date: Thu, 6 Nov 2014 18:51:35 +0000 (-0800) Subject: Merge branch 'jk/cache-tree-protect-from-broken-libgit2' X-Git-Tag: v2.2.0-rc1~6 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/e44da1bbb83f8dac4ea2ae7c806383af470edd38?ds=inline;hp=-c Merge branch 'jk/cache-tree-protect-from-broken-libgit2' The code to use cache-tree trusted the on-disk data too much and fell into an infinite loop. * jk/cache-tree-protect-from-broken-libgit2: cache-tree: avoid infinite loop on zero-entry tree --- e44da1bbb83f8dac4ea2ae7c806383af470edd38 diff --combined cache-tree.c index 215202c42d,648e187491..32772b9564 --- a/cache-tree.c +++ b/cache-tree.c @@@ -1,5 -1,4 +1,5 @@@ #include "cache.h" +#include "lockfile.h" #include "tree.h" #include "tree-walk.h" #include "cache-tree.h" @@@ -247,12 -246,9 +247,12 @@@ static int update_one(struct cache_tre struct strbuf buffer; int missing_ok = flags & WRITE_TREE_MISSING_OK; int dryrun = flags & WRITE_TREE_DRY_RUN; + int repair = flags & WRITE_TREE_REPAIR; int to_invalidate = 0; int i; + assert(!(dryrun && repair)); + *skip_count = 0; if (0 <= it->entry_count && has_sha1_file(it->sha1)) @@@ -303,6 -299,8 +303,8 @@@ flags); if (subcnt < 0) return subcnt; + if (!subcnt) + die("index cache-tree records empty sub-tree"); i += subcnt; sub->count = subcnt; /* to be used in the next loop */ *skip_count += subskip; @@@ -324,7 -322,6 +326,7 @@@ int pathlen, entlen; const unsigned char *sha1; unsigned mode; + int expected_missing = 0; path = ce->name; pathlen = ce_namelen(ce); @@@ -341,10 -338,8 +343,10 @@@ i += sub->count; sha1 = sub->cache_tree->sha1; mode = S_IFDIR; - if (sub->cache_tree->entry_count < 0) + if (sub->cache_tree->entry_count < 0) { to_invalidate = 1; + expected_missing = 1; + } } else { sha1 = ce->sha1; @@@ -354,8 -349,6 +356,8 @@@ } if (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1)) { strbuf_release(&buffer); + if (expected_missing) + return -1; return error("invalid object %06o %s for '%.*s'", mode, sha1_to_hex(sha1), entlen+baselen, path); } @@@ -390,14 -383,7 +392,14 @@@ #endif } - if (dryrun) + if (repair) { + unsigned char sha1[20]; + hash_sha1_file(buffer.buf, buffer.len, tree_type, sha1); + if (has_sha1_file(sha1)) + hashcpy(it->sha1, sha1); + else + to_invalidate = 1; + } else if (dryrun) hash_sha1_file(buffer.buf, buffer.len, tree_type, it->sha1); else if (write_sha1_file(buffer.buf, buffer.len, tree_type, it->sha1)) { strbuf_release(&buffer);