]> git.ipfire.org Git - thirdparty/git.git/commitdiff
cache-tree: detect mismatching number of index entries
authorPatrick Steinhardt <ps@pks.im>
Mon, 7 Oct 2024 04:38:18 +0000 (06:38 +0200)
committerJunio C Hamano <gitster@pobox.com>
Mon, 7 Oct 2024 22:08:11 +0000 (15:08 -0700)
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>
cache-tree.c
t/t4058-diff-duplicates.sh

index 4228b6fad486eb6c8f822876128c35999e158f0b..1e62567308622c57bd057f547ac0e65a1eb74b3c 100644 (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];
index 2501c89c1c91ec7ddc02f4e285aa4c10c32b98f6..3f602adb055b201c245412252a7f24f362b185fa 100755 (executable)
@@ -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' '