]> git.ipfire.org Git - thirdparty/git.git/blame - t/t5303-pack-corruption-resilience.sh
Merge branch 'jk/clone-allow-bare-and-o-together'
[thirdparty/git.git] / t / t5303-pack-corruption-resilience.sh
CommitLineData
29b0d019
NP
1#!/bin/sh
2#
3# Copyright (c) 2008 Nicolas Pitre
4#
5
6test_description='resilience to pack corruptions with redundant objects'
f40a6934
ÆAB
7
8TEST_PASSES_SANITIZE_LEAK=true
29b0d019
NP
9. ./test-lib.sh
10
11# Note: the test objects are created with knowledge of their pack encoding
12# to ensure good code path coverage, and to facilitate direct alteration
13# later on. The assumed characteristics are:
14#
15# 1) blob_2 is a delta with blob_1 for base and blob_3 is a delta with blob2
16# for base, such that blob_3 delta depth is 2;
17#
18# 2) the bulk of object data is uncompressible so the text part remains
19# visible;
20#
21# 3) object header is always 2 bytes.
22
23create_test_files() {
c680668d
NTND
24 test-tool genrandom "foo" 2000 > file_1 &&
25 test-tool genrandom "foo" 1800 > file_2 &&
26 test-tool genrandom "foo" 1800 > file_3 &&
29b0d019
NP
27 echo " base " >> file_1 &&
28 echo " delta1 " >> file_2 &&
29 echo " delta delta2 " >> file_3 &&
c680668d
NTND
30 test-tool genrandom "bar" 150 >> file_2 &&
31 test-tool genrandom "baz" 100 >> file_3
29b0d019
NP
32}
33
34create_new_pack() {
35 rm -rf .git &&
36 git init &&
a64d080f
EP
37 blob_1=$(git hash-object -t blob -w file_1) &&
38 blob_2=$(git hash-object -t blob -w file_2) &&
39 blob_3=$(git hash-object -t blob -w file_3) &&
40 pack=$(printf "$blob_1\n$blob_2\n$blob_3\n" |
41 git pack-objects $@ .git/objects/pack/pack) &&
29b0d019
NP
42 pack=".git/objects/pack/pack-${pack}" &&
43 git verify-pack -v ${pack}.pack
44}
45
538cf6b6 46do_repack() {
a64d080f
EP
47 pack=$(printf "$blob_1\n$blob_2\n$blob_3\n" |
48 git pack-objects $@ .git/objects/pack/pack) &&
538cf6b6
NP
49 pack=".git/objects/pack/pack-${pack}"
50}
51
29b0d019 52do_corrupt_object() {
a64d080f 53 ofs=$(git show-index < ${pack}.idx | grep $1 | cut -f1 -d" ") &&
29b0d019
NP
54 ofs=$(($ofs + $2)) &&
55 chmod +w ${pack}.pack &&
50b72ede 56 dd of=${pack}.pack bs=1 conv=notrunc seek=$ofs &&
29b0d019
NP
57 test_must_fail git verify-pack ${pack}.pack
58}
59
b689ccf6
JS
60printf '\0' > zero
61
29b0d019
NP
62test_expect_success \
63 'initial setup validation' \
64 'create_test_files &&
65 create_new_pack &&
66 git prune-packed &&
67 git cat-file blob $blob_1 > /dev/null &&
68 git cat-file blob $blob_2 > /dev/null &&
69 git cat-file blob $blob_3 > /dev/null'
70
71test_expect_success \
72 'create corruption in header of first object' \
b689ccf6 73 'do_corrupt_object $blob_1 0 < zero &&
29b0d019
NP
74 test_must_fail git cat-file blob $blob_1 > /dev/null &&
75 test_must_fail git cat-file blob $blob_2 > /dev/null &&
76 test_must_fail git cat-file blob $blob_3 > /dev/null'
77
78test_expect_success \
79 '... but having a loose copy allows for full recovery' \
80 'mv ${pack}.idx tmp &&
81 git hash-object -t blob -w file_1 &&
82 mv tmp ${pack}.idx &&
83 git cat-file blob $blob_1 > /dev/null &&
84 git cat-file blob $blob_2 > /dev/null &&
85 git cat-file blob $blob_3 > /dev/null'
86
87test_expect_success \
88 '... and loose copy of first delta allows for partial recovery' \
89 'git prune-packed &&
90 test_must_fail git cat-file blob $blob_2 > /dev/null &&
91 mv ${pack}.idx tmp &&
92 git hash-object -t blob -w file_2 &&
93 mv tmp ${pack}.idx &&
94 test_must_fail git cat-file blob $blob_1 > /dev/null &&
95 git cat-file blob $blob_2 > /dev/null &&
96 git cat-file blob $blob_3 > /dev/null'
97
98test_expect_success \
99 'create corruption in data of first object' \
100 'create_new_pack &&
101 git prune-packed &&
102 chmod +w ${pack}.pack &&
94221d22 103 perl -i.bak -pe "s/ base /abcdef/" ${pack}.pack &&
29b0d019
NP
104 test_must_fail git cat-file blob $blob_1 > /dev/null &&
105 test_must_fail git cat-file blob $blob_2 > /dev/null &&
106 test_must_fail git cat-file blob $blob_3 > /dev/null'
107
108test_expect_success \
109 '... but having a loose copy allows for full recovery' \
110 'mv ${pack}.idx tmp &&
111 git hash-object -t blob -w file_1 &&
112 mv tmp ${pack}.idx &&
113 git cat-file blob $blob_1 > /dev/null &&
114 git cat-file blob $blob_2 > /dev/null &&
115 git cat-file blob $blob_3 > /dev/null'
116
117test_expect_success \
118 '... and loose copy of second object allows for partial recovery' \
119 'git prune-packed &&
120 test_must_fail git cat-file blob $blob_2 > /dev/null &&
121 mv ${pack}.idx tmp &&
122 git hash-object -t blob -w file_2 &&
123 mv tmp ${pack}.idx &&
124 test_must_fail git cat-file blob $blob_1 > /dev/null &&
125 git cat-file blob $blob_2 > /dev/null &&
126 git cat-file blob $blob_3 > /dev/null'
127
128test_expect_success \
129 'create corruption in header of first delta' \
130 'create_new_pack &&
131 git prune-packed &&
b689ccf6 132 do_corrupt_object $blob_2 0 < zero &&
29b0d019
NP
133 git cat-file blob $blob_1 > /dev/null &&
134 test_must_fail git cat-file blob $blob_2 > /dev/null &&
135 test_must_fail git cat-file blob $blob_3 > /dev/null'
136
137test_expect_success \
138 '... but having a loose copy allows for full recovery' \
139 'mv ${pack}.idx tmp &&
140 git hash-object -t blob -w file_2 &&
141 mv tmp ${pack}.idx &&
142 git cat-file blob $blob_1 > /dev/null &&
143 git cat-file blob $blob_2 > /dev/null &&
144 git cat-file blob $blob_3 > /dev/null'
145
538cf6b6
NP
146test_expect_success \
147 '... and then a repack "clears" the corruption' \
148 'do_repack &&
149 git prune-packed &&
150 git verify-pack ${pack}.pack &&
151 git cat-file blob $blob_1 > /dev/null &&
152 git cat-file blob $blob_2 > /dev/null &&
153 git cat-file blob $blob_3 > /dev/null'
154
29b0d019
NP
155test_expect_success \
156 'create corruption in data of first delta' \
157 'create_new_pack &&
158 git prune-packed &&
159 chmod +w ${pack}.pack &&
94221d22 160 perl -i.bak -pe "s/ delta1 /abcdefgh/" ${pack}.pack &&
29b0d019
NP
161 git cat-file blob $blob_1 > /dev/null &&
162 test_must_fail git cat-file blob $blob_2 > /dev/null &&
163 test_must_fail git cat-file blob $blob_3 > /dev/null'
164
165test_expect_success \
166 '... but having a loose copy allows for full recovery' \
167 'mv ${pack}.idx tmp &&
168 git hash-object -t blob -w file_2 &&
169 mv tmp ${pack}.idx &&
170 git cat-file blob $blob_1 > /dev/null &&
171 git cat-file blob $blob_2 > /dev/null &&
172 git cat-file blob $blob_3 > /dev/null'
173
538cf6b6
NP
174test_expect_success \
175 '... and then a repack "clears" the corruption' \
176 'do_repack &&
177 git prune-packed &&
178 git verify-pack ${pack}.pack &&
179 git cat-file blob $blob_1 > /dev/null &&
180 git cat-file blob $blob_2 > /dev/null &&
181 git cat-file blob $blob_3 > /dev/null'
182
29b0d019
NP
183test_expect_success \
184 'corruption in delta base reference of first delta (OBJ_REF_DELTA)' \
185 'create_new_pack &&
186 git prune-packed &&
b689ccf6 187 do_corrupt_object $blob_2 2 < zero &&
29b0d019
NP
188 git cat-file blob $blob_1 > /dev/null &&
189 test_must_fail git cat-file blob $blob_2 > /dev/null &&
190 test_must_fail git cat-file blob $blob_3 > /dev/null'
191
192test_expect_success \
193 '... but having a loose copy allows for full recovery' \
194 'mv ${pack}.idx tmp &&
195 git hash-object -t blob -w file_2 &&
196 mv tmp ${pack}.idx &&
197 git cat-file blob $blob_1 > /dev/null &&
198 git cat-file blob $blob_2 > /dev/null &&
199 git cat-file blob $blob_3 > /dev/null'
200
201test_expect_success \
538cf6b6
NP
202 '... and then a repack "clears" the corruption' \
203 'do_repack &&
204 git prune-packed &&
205 git verify-pack ${pack}.pack &&
206 git cat-file blob $blob_1 > /dev/null &&
207 git cat-file blob $blob_2 > /dev/null &&
208 git cat-file blob $blob_3 > /dev/null'
209
210test_expect_success \
211 'corruption #0 in delta base reference of first delta (OBJ_OFS_DELTA)' \
29b0d019
NP
212 'create_new_pack --delta-base-offset &&
213 git prune-packed &&
b689ccf6 214 do_corrupt_object $blob_2 2 < zero &&
29b0d019
NP
215 git cat-file blob $blob_1 > /dev/null &&
216 test_must_fail git cat-file blob $blob_2 > /dev/null &&
217 test_must_fail git cat-file blob $blob_3 > /dev/null'
218
219test_expect_success \
538cf6b6 220 '... but having a loose copy allows for full recovery' \
29b0d019 221 'mv ${pack}.idx tmp &&
538cf6b6
NP
222 git hash-object -t blob -w file_2 &&
223 mv tmp ${pack}.idx &&
224 git cat-file blob $blob_1 > /dev/null &&
225 git cat-file blob $blob_2 > /dev/null &&
226 git cat-file blob $blob_3 > /dev/null'
227
228test_expect_success \
229 '... and then a repack "clears" the corruption' \
230 'do_repack --delta-base-offset &&
231 git prune-packed &&
232 git verify-pack ${pack}.pack &&
233 git cat-file blob $blob_1 > /dev/null &&
234 git cat-file blob $blob_2 > /dev/null &&
235 git cat-file blob $blob_3 > /dev/null'
236
237test_expect_success \
238 'corruption #1 in delta base reference of first delta (OBJ_OFS_DELTA)' \
239 'create_new_pack --delta-base-offset &&
240 git prune-packed &&
a2d2c478 241 printf "\001" | do_corrupt_object $blob_2 2 &&
538cf6b6
NP
242 git cat-file blob $blob_1 > /dev/null &&
243 test_must_fail git cat-file blob $blob_2 > /dev/null &&
244 test_must_fail git cat-file blob $blob_3 > /dev/null'
245
246test_expect_success \
247 '... but having a loose copy allows for full recovery' \
248 'mv ${pack}.idx tmp &&
249 git hash-object -t blob -w file_2 &&
250 mv tmp ${pack}.idx &&
251 git cat-file blob $blob_1 > /dev/null &&
252 git cat-file blob $blob_2 > /dev/null &&
253 git cat-file blob $blob_3 > /dev/null'
254
255test_expect_success \
256 '... and then a repack "clears" the corruption' \
257 'do_repack --delta-base-offset &&
258 git prune-packed &&
259 git verify-pack ${pack}.pack &&
260 git cat-file blob $blob_1 > /dev/null &&
261 git cat-file blob $blob_2 > /dev/null &&
262 git cat-file blob $blob_3 > /dev/null'
263
264test_expect_success \
265 '... and a redundant pack allows for full recovery too' \
b689ccf6 266 'do_corrupt_object $blob_2 2 < zero &&
538cf6b6
NP
267 git cat-file blob $blob_1 > /dev/null &&
268 test_must_fail git cat-file blob $blob_2 > /dev/null &&
269 test_must_fail git cat-file blob $blob_3 > /dev/null &&
270 mv ${pack}.idx tmp &&
29b0d019
NP
271 git hash-object -t blob -w file_1 &&
272 git hash-object -t blob -w file_2 &&
273 printf "$blob_1\n$blob_2\n" | git pack-objects .git/objects/pack/pack &&
274 git prune-packed &&
275 mv tmp ${pack}.idx &&
276 git cat-file blob $blob_1 > /dev/null &&
277 git cat-file blob $blob_2 > /dev/null &&
278 git cat-file blob $blob_3 > /dev/null'
279
1ee886c1
JK
280test_expect_success \
281 'corruption of delta base reference pointing to wrong object' \
282 'create_new_pack --delta-base-offset &&
283 git prune-packed &&
284 printf "\220\033" | do_corrupt_object $blob_3 2 &&
285 git cat-file blob $blob_1 >/dev/null &&
286 git cat-file blob $blob_2 >/dev/null &&
287 test_must_fail git cat-file blob $blob_3 >/dev/null'
288
289test_expect_success \
290 '... but having a loose copy allows for full recovery' \
291 'mv ${pack}.idx tmp &&
292 git hash-object -t blob -w file_3 &&
293 mv tmp ${pack}.idx &&
294 git cat-file blob $blob_1 > /dev/null &&
295 git cat-file blob $blob_2 > /dev/null &&
296 git cat-file blob $blob_3 > /dev/null'
297
298test_expect_success \
299 '... and then a repack "clears" the corruption' \
300 'do_repack --delta-base-offset --no-reuse-delta &&
301 git prune-packed &&
302 git verify-pack ${pack}.pack &&
303 git cat-file blob $blob_1 > /dev/null &&
304 git cat-file blob $blob_2 > /dev/null &&
305 git cat-file blob $blob_3 > /dev/null'
306
b3118bdc
SP
307test_expect_success \
308 'corrupting header to have too small output buffer fails unpack' \
309 'create_new_pack &&
310 git prune-packed &&
311 printf "\262\001" | do_corrupt_object $blob_1 0 &&
312 test_must_fail git cat-file blob $blob_1 > /dev/null &&
313 test_must_fail git cat-file blob $blob_2 > /dev/null &&
314 test_must_fail git cat-file blob $blob_3 > /dev/null'
315
9caf0107
JK
316# \0 - empty base
317# \1 - one byte in result
318# \1 - one literal byte (X)
319test_expect_success \
320 'apply good minimal delta' \
321 'printf "\0\1\1X" > minimal_delta &&
322 test-tool delta -p /dev/null minimal_delta /dev/null'
323
324# \0 - empty base
325# \1 - 1 byte in result
326# \2 - two literal bytes (one too many)
327test_expect_success \
328 'apply delta with too many literal bytes' \
329 'printf "\0\1\2XX" > too_big_literal &&
330 test_must_fail test-tool delta -p /dev/null too_big_literal /dev/null'
331
18f60f2d 332# \4 - four bytes in base
9caf0107
JK
333# \1 - one byte in result
334# \221 - copy, one byte offset, one byte size
335# \0 - copy from offset 0
336# \2 - copy two bytes (one too many)
337test_expect_success \
338 'apply delta with too many copied bytes' \
18f60f2d
JK
339 'printf "\4\1\221\0\2" > too_big_copy &&
340 printf base >base &&
9caf0107
JK
341 test_must_fail test-tool delta -p base too_big_copy /dev/null'
342
343# \0 - empty base
344# \2 - two bytes in result
345# \2 - two literal bytes (we are short one)
21870efc 346test_expect_success \
9caf0107
JK
347 'apply delta with too few literal bytes' \
348 'printf "\0\2\2X" > truncated_delta &&
349 test_must_fail test-tool delta -p /dev/null truncated_delta /dev/null'
350
351# \0 - empty base
352# \1 - one byte in result
353# \221 - copy, one byte offset, one byte size
354# \0 - copy from offset 0
355# \1 - copy one byte (we are short one)
356test_expect_success \
357 'apply delta with too few bytes in base' \
358 'printf "\0\1\221\0\1" > truncated_base &&
359 test_must_fail test-tool delta -p /dev/null truncated_base /dev/null'
360
18f60f2d
JK
361# \4 - four bytes in base
362# \2 - two bytes in result
9caf0107
JK
363# \1 - one literal byte (X)
364# \221 - copy, one byte offset, one byte size
365# (offset/size missing)
366#
367# Note that the literal byte is necessary to get past the uninteresting minimum
368# delta size check.
9514b0b2 369test_expect_success \
9caf0107 370 'apply delta with truncated copy parameters' \
18f60f2d
JK
371 'printf "\4\2\1X\221" > truncated_copy_delta &&
372 printf base >base &&
9caf0107
JK
373 test_must_fail test-tool delta -p base truncated_copy_delta /dev/null'
374
fa72f90e
JH
375# \0 - empty base
376# \1 - one byte in result
377# \1 - one literal byte (X)
378# \1 - trailing garbage command
379test_expect_success \
380 'apply delta with trailing garbage literal' \
381 'printf "\0\1\1X\1" > tail_garbage_literal &&
382 test_must_fail test-tool delta -p /dev/null tail_garbage_literal /dev/null'
383
18f60f2d 384# \4 - four bytes in base
fa72f90e
JH
385# \1 - one byte in result
386# \1 - one literal byte (X)
387# \221 - copy, one byte offset, one byte size
388# \0 - copy from offset 0
389# \1 - copy 1 byte
390test_expect_success \
391 'apply delta with trailing garbage copy' \
18f60f2d
JK
392 'printf "\4\1\1X\221\0\1" > tail_garbage_copy &&
393 printf base >base &&
fa72f90e
JH
394 test_must_fail test-tool delta -p /dev/null tail_garbage_copy /dev/null'
395
396# \0 - empty base
397# \1 - one byte in result
398# \1 - one literal byte (X)
399# \0 - bogus opcode
400test_expect_success \
401 'apply delta with trailing garbage opcode' \
402 'printf "\0\1\1X\0" > tail_garbage_opcode &&
403 test_must_fail test-tool delta -p /dev/null tail_garbage_opcode /dev/null'
404
29b0d019 405test_done