cache-tree: detect mismatching number of index entries

In t4058 we have some tests that exercise git-read-tree(1) when used
with a tree that contains duplicate entries. While the expectation is
that we fail, we ideally should fail gracefully without a segfault.

But that is not the case: we never check that the number of entries in
the cache-tree is less than or equal to the number of entries in the
index. This can lead to an out-of-bounds read as we unconditionally
access `istate->cache[idx]`, where `idx` is controlled by the number of
cache-tree entries and the current position therein. The result is a
segfault.

Fix this segfault by adding a sanity check for the number of index
entries before dereferencing them.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Patrick Steinhardt 2024-10-07 06:38:18 +02:00 committed by Junio C Hamano
parent 9f119599a6
commit 2be7fc012e
2 changed files with 11 additions and 6 deletions

View File

@ -933,6 +933,11 @@ static int verify_one(struct repository *r,
pos = 0;
}

if (it->entry_count + pos > istate->cache_nr) {
ret = error(_("corrupted cache-tree has entries not present in index"));
goto out;
}

i = 0;
while (i < it->entry_count) {
struct cache_entry *ce = istate->cache[pos + i];

View File

@ -132,15 +132,15 @@ test_expect_success 'create a few commits' '
rm commit_id up final
'

test_expect_failure 'git read-tree does not segfault' '
test_when_finished rm .git/index.lock &&
test_might_fail git read-tree --reset base
test_expect_success 'git read-tree does not segfault' '
test_must_fail git read-tree --reset base 2>err &&
test_grep "error: corrupted cache-tree has entries not present in index" err
'

test_expect_failure 'reset --hard does not segfault' '
test_when_finished rm .git/index.lock &&
test_expect_success 'reset --hard does not segfault' '
git checkout base &&
test_might_fail git reset --hard
test_must_fail git reset --hard 2>err &&
test_grep "error: corrupted cache-tree has entries not present in index" err
'

test_expect_failure 'git diff HEAD does not segfault' '