f4609b896f
This also bumps the stable nixpkgs to 20.09 as of 2020-11-21, because there is some breakage in the git build related to the netrc credentials helper which someone has taken care of in nixpkgs. The stable channel is not used for anything other than git, so this should be fine. Change-Id: I3575a19dab09e1e9556cf8231d717de9890484fb
194 lines
5.6 KiB
Bash
Executable file
194 lines
5.6 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
test_description='bounds-checking of access to mmapped on-disk file formats'
|
|
. ./test-lib.sh
|
|
|
|
clear_base () {
|
|
test_when_finished 'restore_base' &&
|
|
rm -f $base
|
|
}
|
|
|
|
restore_base () {
|
|
cp base-backup/* .git/objects/pack/
|
|
}
|
|
|
|
do_pack () {
|
|
pack_objects=$1; shift
|
|
sha1=$(
|
|
for i in $pack_objects
|
|
do
|
|
echo $i
|
|
done | git pack-objects "$@" .git/objects/pack/pack
|
|
) &&
|
|
pack=.git/objects/pack/pack-$sha1.pack &&
|
|
idx=.git/objects/pack/pack-$sha1.idx &&
|
|
chmod +w $pack $idx &&
|
|
test_when_finished 'rm -f "$pack" "$idx"'
|
|
}
|
|
|
|
munge () {
|
|
printf "$3" | dd of="$1" bs=1 conv=notrunc seek=$2
|
|
}
|
|
|
|
# Offset in a v2 .idx to its initial and extended offset tables. For an index
|
|
# with "nr" objects, this is:
|
|
#
|
|
# magic(4) + version(4) + fan-out(4*256) + sha1s(20*nr) + crc(4*nr),
|
|
#
|
|
# for the initial, and another ofs(4*nr) past that for the extended.
|
|
#
|
|
ofs_table () {
|
|
echo $((4 + 4 + 4*256 + $(test_oid rawsz)*$1 + 4*$1))
|
|
}
|
|
extended_table () {
|
|
echo $(($(ofs_table "$1") + 4*$1))
|
|
}
|
|
|
|
test_expect_success 'setup' '
|
|
test_oid_cache <<-EOF
|
|
oid000 sha1:1485
|
|
oid000 sha256:4222
|
|
|
|
oidfff sha1:74
|
|
oidfff sha256:1350
|
|
EOF
|
|
'
|
|
|
|
test_expect_success 'set up base packfile and variables' '
|
|
# the hash of this content starts with ff, which
|
|
# makes some later computations much simpler
|
|
echo $(test_oid oidfff) >file &&
|
|
git add file &&
|
|
git commit -m base &&
|
|
git repack -ad &&
|
|
base=$(echo .git/objects/pack/*) &&
|
|
chmod +w $base &&
|
|
mkdir base-backup &&
|
|
cp $base base-backup/ &&
|
|
object=$(git rev-parse HEAD:file)
|
|
'
|
|
|
|
test_expect_success 'pack/index object count mismatch' '
|
|
do_pack $object &&
|
|
munge $pack 8 "\377\0\0\0" &&
|
|
clear_base &&
|
|
|
|
# We enumerate the objects from the completely-fine
|
|
# .idx, but notice later that the .pack is bogus
|
|
# and fail to show any data.
|
|
echo "$object missing" >expect &&
|
|
git cat-file --batch-all-objects --batch-check >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
# ...and here fail to load the object (without segfaulting),
|
|
# but fallback to a good copy if available.
|
|
test_must_fail git cat-file blob $object &&
|
|
restore_base &&
|
|
git cat-file blob $object >actual &&
|
|
test_cmp file actual &&
|
|
|
|
# ...and make sure that index-pack --verify, which has its
|
|
# own reading routines, does not segfault.
|
|
test_must_fail git index-pack --verify $pack
|
|
'
|
|
|
|
test_expect_success 'matched bogus object count' '
|
|
do_pack $object &&
|
|
munge $pack 8 "\377\0\0\0" &&
|
|
munge $idx $((255 * 4)) "\377\0\0\0" &&
|
|
clear_base &&
|
|
|
|
# Unlike above, we should notice early that the .idx is totally
|
|
# bogus, and not even enumerate its contents.
|
|
git cat-file --batch-all-objects --batch-check >actual &&
|
|
test_must_be_empty actual &&
|
|
|
|
# But as before, we can do the same object-access checks.
|
|
test_must_fail git cat-file blob $object &&
|
|
restore_base &&
|
|
git cat-file blob $object >actual &&
|
|
test_cmp file actual &&
|
|
|
|
test_must_fail git index-pack --verify $pack
|
|
'
|
|
|
|
# Note that we cannot check the fallback case for these
|
|
# further .idx tests, as we notice the problem in functions
|
|
# whose interface doesn't allow an error return (like use_pack()),
|
|
# and thus we just die().
|
|
#
|
|
# There's also no point in doing enumeration tests, as
|
|
# we are munging offsets here, which are about looking up
|
|
# specific objects.
|
|
|
|
test_expect_success 'bogus object offset (v1)' '
|
|
do_pack $object --index-version=1 &&
|
|
munge $idx $((4 * 256)) "\377\0\0\0" &&
|
|
clear_base &&
|
|
test_must_fail git cat-file blob $object &&
|
|
test_must_fail git index-pack --verify $pack
|
|
'
|
|
|
|
test_expect_success 'bogus object offset (v2, no msb)' '
|
|
do_pack $object --index-version=2 &&
|
|
munge $idx $(ofs_table 1) "\0\377\0\0" &&
|
|
clear_base &&
|
|
test_must_fail git cat-file blob $object &&
|
|
test_must_fail git index-pack --verify $pack
|
|
'
|
|
|
|
test_expect_success 'bogus offset into v2 extended table' '
|
|
do_pack $object --index-version=2 &&
|
|
munge $idx $(ofs_table 1) "\377\0\0\0" &&
|
|
clear_base &&
|
|
test_must_fail git cat-file blob $object &&
|
|
test_must_fail git index-pack --verify $pack
|
|
'
|
|
|
|
test_expect_success 'bogus offset inside v2 extended table' '
|
|
# We need two objects here, so we can plausibly require
|
|
# an extended table (if the first object were larger than 2^31).
|
|
#
|
|
# Note that the value is important here. We want $object as
|
|
# the second entry in sorted-hash order. The hash of this object starts
|
|
# with "000", which sorts before that of $object (which starts
|
|
# with "fff").
|
|
second=$(test_oid oid000 | git hash-object -w --stdin) &&
|
|
do_pack "$object $second" --index-version=2 &&
|
|
|
|
# We have to make extra room for the table, so we cannot
|
|
# just munge in place as usual.
|
|
{
|
|
dd if=$idx bs=1 count=$(($(ofs_table 2) + 4)) &&
|
|
printf "\200\0\0\0" &&
|
|
printf "\377\0\0\0\0\0\0\0" &&
|
|
dd if=$idx bs=1 skip=$(extended_table 2)
|
|
} >tmp &&
|
|
mv tmp "$idx" &&
|
|
clear_base &&
|
|
test_must_fail git cat-file blob $object &&
|
|
test_must_fail git index-pack --verify $pack
|
|
'
|
|
|
|
test_expect_success 'bogus OFS_DELTA in packfile' '
|
|
# Generate a pack with a delta in it.
|
|
base=$(test-tool genrandom foo 3000 | git hash-object --stdin -w) &&
|
|
delta=$(test-tool genrandom foo 2000 | git hash-object --stdin -w) &&
|
|
do_pack "$base $delta" --delta-base-offset &&
|
|
rm -f .git/objects/??/* &&
|
|
|
|
# Double check that we have the delta we expect.
|
|
echo $base >expect &&
|
|
echo $delta | git cat-file --batch-check="%(deltabase)" >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
# Now corrupt it. We assume the varint size for the delta is small
|
|
# enough to fit in the first byte (which it should be, since it
|
|
# is a pure deletion from the base), and that original ofs_delta
|
|
# takes 2 bytes (which it should, as it should be ~3000).
|
|
ofs=$(git show-index <$idx | grep $delta | cut -d" " -f1) &&
|
|
munge $pack $(($ofs + 1)) "\177\377" &&
|
|
test_must_fail git cat-file blob $delta >/dev/null
|
|
'
|
|
|
|
test_done
|