]> git.ipfire.org Git - thirdparty/git.git/blame - t/t5313-pack-bounds-checks.sh
gitweb: correctly store previous rev in javascript-actions mode
[thirdparty/git.git] / t / t5313-pack-bounds-checks.sh
CommitLineData
a1283866
JK
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' &&
8 rm -f $base
9}
10
11restore_base () {
12 cp base-backup/* .git/objects/pack/
13}
14
15do_pack () {
16 pack_objects=$1; shift
17 sha1=$(
18 for i in $pack_objects
19 do
20 echo $i
21 done | git pack-objects "$@" .git/objects/pack/pack
22 ) &&
23 pack=.git/objects/pack/pack-$sha1.pack &&
24 idx=.git/objects/pack/pack-$sha1.idx &&
25 chmod +w $pack $idx &&
26 test_when_finished 'rm -f "$pack" "$idx"'
27}
28
29munge () {
30 printf "$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 () {
41 echo $((4 + 4 + 4*256 + 20*$1 + 4*$1))
42}
43extended_table () {
44 echo $(($(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 $base base-backup/ &&
58 object=$(git rev-parse HEAD:file)
59'
60
61test_expect_success 'pack/index object count mismatch' '
62 do_pack $object &&
63 munge $pack 8 "\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 "$object missing" >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 $pack 8 "\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.
a1283866 93 git cat-file --batch-all-objects --batch-check >actual &&
d3c6751b 94 test_must_be_empty actual &&
a1283866
JK
95
96 # But as before, we can do the same object-access checks.
97 test_must_fail git cat-file blob $object &&
98 restore_base &&
99 git cat-file blob $object >actual &&
100 test_cmp file actual &&
101
102 test_must_fail git index-pack --verify $pack
103'
104
105# Note that we cannot check the fallback case for these
106# further .idx tests, as we notice the problem in functions
107# whose interface doesn't allow an error return (like use_pack()),
108# and thus we just die().
109#
110# There's also no point in doing enumeration tests, as
111# we are munging offsets here, which are about looking up
112# specific objects.
113
114test_expect_success 'bogus object offset (v1)' '
115 do_pack $object --index-version=1 &&
116 munge $idx $((4 * 256)) "\377\0\0\0" &&
117 clear_base &&
118 test_must_fail git cat-file blob $object &&
119 test_must_fail git index-pack --verify $pack
120'
121
122test_expect_success 'bogus object offset (v2, no msb)' '
123 do_pack $object --index-version=2 &&
124 munge $idx $(ofs_table 1) "\0\377\0\0" &&
125 clear_base &&
126 test_must_fail git cat-file blob $object &&
127 test_must_fail git index-pack --verify $pack
128'
129
47fe3f6e 130test_expect_success 'bogus offset into v2 extended table' '
a1283866
JK
131 do_pack $object --index-version=2 &&
132 munge $idx $(ofs_table 1) "\377\0\0\0" &&
133 clear_base &&
134 test_must_fail git cat-file blob $object &&
135 test_must_fail git index-pack --verify $pack
136'
137
13e0b0d3 138test_expect_success 'bogus offset inside v2 extended table' '
a1283866
JK
139 # We need two objects here, so we can plausibly require
140 # an extended table (if the first object were larger than 2^31).
7c2115aa
JK
141 #
142 # Note that the value is important here. We want $object as
143 # the second entry in sorted-sha1 order. The sha1 of 1485 starts
144 # with "000", which sorts before that of $object (which starts
145 # with "fff").
146 second=$(echo 1485 | git hash-object -w --stdin) &&
147 do_pack "$object $second" --index-version=2 &&
a1283866
JK
148
149 # We have to make extra room for the table, so we cannot
150 # just munge in place as usual.
151 {
152 dd if=$idx bs=1 count=$(($(ofs_table 2) + 4)) &&
153 printf "\200\0\0\0" &&
154 printf "\377\0\0\0\0\0\0\0" &&
155 dd if=$idx bs=1 skip=$(extended_table 2)
156 } >tmp &&
157 mv tmp "$idx" &&
158 clear_base &&
159 test_must_fail git cat-file blob $object &&
160 test_must_fail git index-pack --verify $pack
161'
162
163test_expect_success 'bogus OFS_DELTA in packfile' '
164 # Generate a pack with a delta in it.
c680668d
NTND
165 base=$(test-tool genrandom foo 3000 | git hash-object --stdin -w) &&
166 delta=$(test-tool genrandom foo 2000 | git hash-object --stdin -w) &&
a1283866
JK
167 do_pack "$base $delta" --delta-base-offset &&
168 rm -f .git/objects/??/* &&
169
170 # Double check that we have the delta we expect.
171 echo $base >expect &&
172 echo $delta | git cat-file --batch-check="%(deltabase)" >actual &&
173 test_cmp expect actual &&
174
175 # Now corrupt it. We assume the varint size for the delta is small
176 # enough to fit in the first byte (which it should be, since it
177 # is a pure deletion from the base), and that original ofs_delta
178 # takes 2 bytes (which it should, as it should be ~3000).
179 ofs=$(git show-index <$idx | grep $delta | cut -d" " -f1) &&
180 munge $pack $(($ofs + 1)) "\177\377" &&
181 test_must_fail git cat-file blob $delta >/dev/null
182'
183
184test_done