summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <gitster@pobox.com>2014-09-19 11:38:34 -0700
committerLibravatar Junio C Hamano <gitster@pobox.com>2014-09-19 11:38:34 -0700
commit04631848c4bd66bf802983482b7b99021da85c9f (patch)
tree6780c16454a9453ec1dbe87e27f6779a523f8918
parentMerge branch 'jk/index-pack-threading-races' (diff)
parentread_index_unmerged(): remove unnecessary loop index adjustment (diff)
downloadtgif-04631848c4bd66bf802983482b7b99021da85c9f.tar.xz
Merge branch 'jp/index-with-corrupt-stages'
A broken reimplementation of Git could write an invalid index that records both stage #0 and higher stage entries for the same path. Notice and reject such an index, as there is no sensible fallback (we do not know if the broken tool wanted to resolve and forgot to remove higher stage entries, or if it wanted to unresolve and forgot to remove the stage#0 entry). * jp/index-with-corrupt-stages: read_index_unmerged(): remove unnecessary loop index adjustment read_index_from(): catch out of order entries when reading an index file
-rw-r--r--read-cache.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/read-cache.c b/read-cache.c
index b5917e0c07..2fc1182f22 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1465,6 +1465,21 @@ static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk,
return ce;
}
+static void check_ce_order(struct cache_entry *ce, struct cache_entry *next_ce)
+{
+ int name_compare = strcmp(ce->name, next_ce->name);
+ if (0 < name_compare)
+ die("unordered stage entries in index");
+ if (!name_compare) {
+ if (!ce_stage(ce))
+ die("multiple stage entries for merged file '%s'",
+ ce->name);
+ if (ce_stage(ce) > ce_stage(next_ce))
+ die("unordered stage entries for '%s'",
+ ce->name);
+ }
+}
+
/* remember to discard_cache() before reading a different cache! */
int do_read_index(struct index_state *istate, const char *path, int must_exist)
{
@@ -1526,6 +1541,9 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
ce = create_from_disk(disk_ce, &consumed, previous_name);
set_index_entry(istate, i, ce);
+ if (i > 0)
+ check_ce_order(istate->cache[i - 1], ce);
+
src_offset += consumed;
}
strbuf_release(&previous_name_buf);
@@ -2172,7 +2190,6 @@ int read_index_unmerged(struct index_state *istate)
if (add_index_entry(istate, new_ce, 0))
return error("%s: cannot drop to stage #0",
new_ce->name);
- i = index_name_pos(istate, new_ce->name, len);
}
return unmerged;
}