1#!/bin/sh 2 3test_description='bounds-checking of access to mmapped on-disk file formats' 4. ./test-lib.sh 5 6clear_base () { 7 test_when_finished 'restore_base'&& 8rm-f$base 9} 10 11restore_base () { 12cp base-backup/* .git/objects/pack/ 13} 14 15do_pack () { 16 pack_objects=$1;shift 17 sha1=$( 18for i in$pack_objects 19do 20echo$i 21done| git pack-objects"$@" .git/objects/pack/pack 22) && 23 pack=.git/objects/pack/pack-$sha1.pack && 24 idx=.git/objects/pack/pack-$sha1.idx && 25chmod+w $pack $idx&& 26 test_when_finished 'rm -f "$pack" "$idx"' 27} 28 29munge () { 30printf"$3"|dd of="$1" bs=1 conv=notrunc seek=$2 31} 32 33# Offset in a v2 .idx to its initial and extended offset tables. For an index 34# with "nr" objects, this is: 35# 36# magic(4) + version(4) + fan-out(4*256) + sha1s(20*nr) + crc(4*nr), 37# 38# for the initial, and another ofs(4*nr) past that for the extended. 39# 40ofs_table () { 41echo$((4 + 4 + 4*256 + 20*$1 + 4*$1)) 42} 43extended_table () { 44echo$(($(ofs_table "$1")+4*$1)) 45} 46 47test_expect_success 'set up base packfile and variables'' 48 # the hash of this content starts with ff, which 49 # makes some later computations much simpler 50 echo 74 >file && 51 git add file && 52 git commit -m base && 53 git repack -ad && 54 base=$(echo .git/objects/pack/*)&& 55 chmod +w$base&& 56 mkdir base-backup && 57 cp$basebase-backup/ && 58 object=$(git rev-parse HEAD:file) 59' 60 61test_expect_success 'pack/index object count mismatch'' 62 do_pack$object&& 63 munge$pack8 "\377\0\0\0" && 64 clear_base && 65 66 # We enumerate the objects from the completely-fine 67 # .idx, but notice later that the .pack is bogus 68 # and fail to show any data. 69 echo "$objectmissing" >expect && 70 git cat-file --batch-all-objects --batch-check >actual && 71 test_cmp expect actual && 72 73 # ...and here fail to load the object (without segfaulting), 74 # but fallback to a good copy if available. 75 test_must_fail git cat-file blob$object&& 76 restore_base && 77 git cat-file blob$object>actual && 78 test_cmp file actual && 79 80 # ...and make sure that index-pack --verify, which has its 81 # own reading routines, does not segfault. 82 test_must_fail git index-pack --verify$pack 83' 84 85test_expect_success 'matched bogus object count'' 86 do_pack$object&& 87 munge$pack8 "\377\0\0\0" && 88 munge$idx$((255 * 4)) "\377\0\0\0" && 89 clear_base && 90 91 # Unlike above, we should notice early that the .idx is totally 92 # bogus, and not even enumerate its contents. 93 >expect && 94 git cat-file --batch-all-objects --batch-check >actual && 95 test_cmp expect actual && 96 97 # But as before, we can do the same object-access checks. 98 test_must_fail git cat-file blob$object&& 99 restore_base && 100 git cat-file blob$object>actual && 101 test_cmp file actual && 102 103 test_must_fail git index-pack --verify$pack 104' 105 106# Note that we cannot check the fallback case for these 107# further .idx tests, as we notice the problem in functions 108# whose interface doesn't allow an error return (like use_pack()), 109# and thus we just die(). 110# 111# There's also no point in doing enumeration tests, as 112# we are munging offsets here, which are about looking up 113# specific objects. 114 115test_expect_success 'bogus object offset (v1)'' 116 do_pack$object--index-version=1 && 117 munge$idx$((4 * 256)) "\377\0\0\0" && 118 clear_base && 119 test_must_fail git cat-file blob$object&& 120 test_must_fail git index-pack --verify$pack 121' 122 123test_expect_success 'bogus object offset (v2, no msb)'' 124 do_pack$object--index-version=2 && 125 munge$idx$(ofs_table 1)"\0\377\0\0" && 126 clear_base && 127 test_must_fail git cat-file blob$object&& 128 test_must_fail git index-pack --verify$pack 129' 130 131test_expect_success 'bogus offset into v2 extended table'' 132 do_pack$object--index-version=2 && 133 munge$idx$(ofs_table 1)"\377\0\0\0" && 134 clear_base && 135 test_must_fail git cat-file blob$object&& 136 test_must_fail git index-pack --verify$pack 137' 138 139test_expect_success 'bogus offset inside v2 extended table'' 140 # We need two objects here, so we can plausibly require 141 # an extended table (if the first object were larger than 2^31). 142 # 143 # Note that the value is important here. We want$objectas 144 # the second entry in sorted-sha1 order. The sha1 of 1485 starts 145 # with "000", which sorts before that of$object(which starts 146 # with "fff"). 147 second=$(echo 1485 | git hash-object -w --stdin)&& 148 do_pack "$object$second" --index-version=2 && 149 150 # We have to make extra room for the table, so we cannot 151 # just munge in place as usual. 152 { 153 dd if=$idxbs=1 count=$(($(ofs_table 2)+ 4)) && 154 printf "\200\0\0\0" && 155 printf "\377\0\0\0\0\0\0\0" && 156 dd if=$idxbs=1 skip=$(extended_table 2) 157 } >tmp && 158 mv tmp "$idx" && 159 clear_base && 160 test_must_fail git cat-file blob$object&& 161 test_must_fail git index-pack --verify$pack 162' 163 164test_expect_success 'bogus OFS_DELTA in packfile'' 165 # Generate a pack with a delta in it. 166 base=$(test-genrandom foo 3000 | git hash-object --stdin -w)&& 167 delta=$(test-genrandom foo 2000 | git hash-object --stdin -w)&& 168 do_pack "$base$delta" --delta-base-offset && 169 rm -f .git/objects/??/* && 170 171 # Double check that we have the delta we expect. 172 echo$base>expect && 173 echo$delta| git cat-file --batch-check="%(deltabase)" >actual && 174 test_cmp expect actual && 175 176 # Now corrupt it. We assume the varint size for the delta is small 177 # enough to fit in the first byte (which it should be, since it 178 # is a pure deletion from the base), and that original ofs_delta 179 # takes 2 bytes (which it should, as it should be ~3000). 180 ofs=$(git show-index <$idx | grep $delta | cut -d" " -f1)&& 181 munge$pack$(($ofs + 1)) "\177\377" && 182 test_must_fail git cat-file blob$delta>/dev/null 183' 184 185test_done