xref: /netbsd-src/external/public-domain/xz/dist/tests/test_index.c (revision 75cbb3d6e4fac2c8c149ebd3a1104dd4ac8c9b3a)
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       test_index.c
4 /// \brief      Tests functions handling the lzma_index structure
5 //
6 //  Author:     Lasse Collin
7 //
8 //  This file has been put into the public domain.
9 //  You can do whatever you want with this file.
10 //
11 ///////////////////////////////////////////////////////////////////////////////
12 
13 #include "tests.h"
14 
15 #define MEMLIMIT (LZMA_VLI_C(1) << 20)
16 
17 #define SMALL_COUNT 3
18 #define BIG_COUNT 5555
19 
20 
21 static lzma_index *
create_empty(void)22 create_empty(void)
23 {
24 	lzma_index *i = lzma_index_init(NULL);
25 	expect(i != NULL);
26 	return i;
27 }
28 
29 
30 static lzma_index *
create_small(void)31 create_small(void)
32 {
33 	lzma_index *i = lzma_index_init(NULL);
34 	expect(i != NULL);
35 	expect(lzma_index_append(i, NULL, 101, 555) == LZMA_OK);
36 	expect(lzma_index_append(i, NULL, 602, 777) == LZMA_OK);
37 	expect(lzma_index_append(i, NULL, 804, 999) == LZMA_OK);
38 	return i;
39 }
40 
41 
42 static lzma_index *
create_big(void)43 create_big(void)
44 {
45 	lzma_index *i = lzma_index_init(NULL);
46 	expect(i != NULL);
47 
48 	lzma_vli total_size = 0;
49 	lzma_vli uncompressed_size = 0;
50 
51 	// Add pseudo-random sizes (but always the same size values).
52 	uint32_t n = 11;
53 	for (size_t j = 0; j < BIG_COUNT; ++j) {
54 		n = 7019 * n + 7607;
55 		const uint32_t t = n * 3011;
56 		expect(lzma_index_append(i, NULL, t, n) == LZMA_OK);
57 		total_size += (t + 3) & ~LZMA_VLI_C(3);
58 		uncompressed_size += n;
59 	}
60 
61 	expect(lzma_index_block_count(i) == BIG_COUNT);
62 	expect(lzma_index_total_size(i) == total_size);
63 	expect(lzma_index_uncompressed_size(i) == uncompressed_size);
64 	expect(lzma_index_total_size(i) + lzma_index_size(i)
65 				+ 2 * LZMA_STREAM_HEADER_SIZE
66 			== lzma_index_stream_size(i));
67 
68 	return i;
69 }
70 
71 
72 static bool
is_equal(const lzma_index * a,const lzma_index * b)73 is_equal(const lzma_index *a, const lzma_index *b)
74 {
75 	// Compare only the Stream and Block sizes and offsets.
76 	lzma_index_iter ra, rb;
77 	lzma_index_iter_init(&ra, a);
78 	lzma_index_iter_init(&rb, b);
79 
80 	while (true) {
81 		bool reta = lzma_index_iter_next(&ra, LZMA_INDEX_ITER_ANY);
82 		bool retb = lzma_index_iter_next(&rb, LZMA_INDEX_ITER_ANY);
83 		if (reta)
84 			return !(reta ^ retb);
85 
86 		if (ra.stream.number != rb.stream.number
87 				|| ra.stream.block_count
88 					!= rb.stream.block_count
89 				|| ra.stream.compressed_offset
90 					!= rb.stream.compressed_offset
91 				|| ra.stream.uncompressed_offset
92 					!= rb.stream.uncompressed_offset
93 				|| ra.stream.compressed_size
94 					!= rb.stream.compressed_size
95 				|| ra.stream.uncompressed_size
96 					!= rb.stream.uncompressed_size
97 				|| ra.stream.padding
98 					!= rb.stream.padding)
99 			return false;
100 
101 		if (ra.stream.block_count == 0)
102 			continue;
103 
104 		if (ra.block.number_in_file != rb.block.number_in_file
105 				|| ra.block.compressed_file_offset
106 					!= rb.block.compressed_file_offset
107 				|| ra.block.uncompressed_file_offset
108 					!= rb.block.uncompressed_file_offset
109 				|| ra.block.number_in_stream
110 					!= rb.block.number_in_stream
111 				|| ra.block.compressed_stream_offset
112 					!= rb.block.compressed_stream_offset
113 				|| ra.block.uncompressed_stream_offset
114 					!= rb.block.uncompressed_stream_offset
115 				|| ra.block.uncompressed_size
116 					!= rb.block.uncompressed_size
117 				|| ra.block.unpadded_size
118 					!= rb.block.unpadded_size
119 				|| ra.block.total_size
120 					!= rb.block.total_size)
121 			return false;
122 	}
123 }
124 
125 
126 static void
test_equal(void)127 test_equal(void)
128 {
129 	lzma_index *a = create_empty();
130 	lzma_index *b = create_small();
131 	lzma_index *c = create_big();
132 	expect(a && b && c);
133 
134 	expect(is_equal(a, a));
135 	expect(is_equal(b, b));
136 	expect(is_equal(c, c));
137 
138 	expect(!is_equal(a, b));
139 	expect(!is_equal(a, c));
140 	expect(!is_equal(b, c));
141 
142 	lzma_index_end(a, NULL);
143 	lzma_index_end(b, NULL);
144 	lzma_index_end(c, NULL);
145 }
146 
147 
148 static void
test_overflow(void)149 test_overflow(void)
150 {
151 	// Integer overflow tests
152 	lzma_index *i = create_empty();
153 
154 	expect(lzma_index_append(i, NULL, LZMA_VLI_MAX - 5, 1234)
155 			== LZMA_DATA_ERROR);
156 
157 	// TODO
158 
159 	lzma_index_end(i, NULL);
160 }
161 
162 
163 static void
test_copy(const lzma_index * i)164 test_copy(const lzma_index *i)
165 {
166 	lzma_index *d = lzma_index_dup(i, NULL);
167 	expect(d != NULL);
168 	expect(is_equal(i, d));
169 	lzma_index_end(d, NULL);
170 }
171 
172 
173 static void
test_read(lzma_index * i)174 test_read(lzma_index *i)
175 {
176 	lzma_index_iter r;
177 	lzma_index_iter_init(&r, i);
178 
179 	// Try twice so we see that rewinding works.
180 	for (size_t j = 0; j < 2; ++j) {
181 		lzma_vli total_size = 0;
182 		lzma_vli uncompressed_size = 0;
183 		lzma_vli stream_offset = LZMA_STREAM_HEADER_SIZE;
184 		lzma_vli uncompressed_offset = 0;
185 		uint32_t count = 0;
186 
187 		while (!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)) {
188 			++count;
189 
190 			total_size += r.block.total_size;
191 			uncompressed_size += r.block.uncompressed_size;
192 
193 			expect(r.block.compressed_file_offset
194 					== stream_offset);
195 			expect(r.block.uncompressed_file_offset
196 					== uncompressed_offset);
197 
198 			stream_offset += r.block.total_size;
199 			uncompressed_offset += r.block.uncompressed_size;
200 		}
201 
202 		expect(lzma_index_total_size(i) == total_size);
203 		expect(lzma_index_uncompressed_size(i) == uncompressed_size);
204 		expect(lzma_index_block_count(i) == count);
205 
206 		lzma_index_iter_rewind(&r);
207 	}
208 }
209 
210 
211 static void
test_code(lzma_index * i)212 test_code(lzma_index *i)
213 {
214 	const size_t alloc_size = 128 * 1024;
215 	uint8_t *buf = malloc(alloc_size);
216 	expect(buf != NULL);
217 
218 	// Encode
219 	lzma_stream strm = LZMA_STREAM_INIT;
220 	expect(lzma_index_encoder(&strm, i) == LZMA_OK);
221 	const lzma_vli index_size = lzma_index_size(i);
222 	succeed(coder_loop(&strm, NULL, 0, buf, index_size,
223 			LZMA_STREAM_END, LZMA_RUN));
224 
225 	// Decode
226 	lzma_index *d;
227 	expect(lzma_index_decoder(&strm, &d, MEMLIMIT) == LZMA_OK);
228 	expect(d == NULL);
229 	succeed(decoder_loop(&strm, buf, index_size));
230 
231 	expect(is_equal(i, d));
232 
233 	lzma_index_end(d, NULL);
234 	lzma_end(&strm);
235 
236 	// Decode with hashing
237 	lzma_index_hash *h = lzma_index_hash_init(NULL, NULL);
238 	expect(h != NULL);
239 	lzma_index_iter r;
240 	lzma_index_iter_init(&r, i);
241 	while (!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK))
242 		expect(lzma_index_hash_append(h, r.block.unpadded_size,
243 				r.block.uncompressed_size) == LZMA_OK);
244 	size_t pos = 0;
245 	while (pos < index_size - 1)
246 		expect(lzma_index_hash_decode(h, buf, &pos, pos + 1)
247 				== LZMA_OK);
248 	expect(lzma_index_hash_decode(h, buf, &pos, pos + 1)
249 			== LZMA_STREAM_END);
250 
251 	lzma_index_hash_end(h, NULL);
252 
253 	// Encode buffer
254 	size_t buf_pos = 1;
255 	expect(lzma_index_buffer_encode(i, buf, &buf_pos, index_size)
256 			== LZMA_BUF_ERROR);
257 	expect(buf_pos == 1);
258 
259 	succeed(lzma_index_buffer_encode(i, buf, &buf_pos, index_size + 1));
260 	expect(buf_pos == index_size + 1);
261 
262 	// Decode buffer
263 	buf_pos = 1;
264 	uint64_t memlimit = MEMLIMIT;
265 	expect(lzma_index_buffer_decode(&d, &memlimit, NULL, buf, &buf_pos,
266 			index_size) == LZMA_DATA_ERROR);
267 	expect(buf_pos == 1);
268 	expect(d == NULL);
269 
270 	succeed(lzma_index_buffer_decode(&d, &memlimit, NULL, buf, &buf_pos,
271 			index_size + 1));
272 	expect(buf_pos == index_size + 1);
273 	expect(is_equal(i, d));
274 
275 	lzma_index_end(d, NULL);
276 
277 	free(buf);
278 }
279 
280 
281 static void
test_many(lzma_index * i)282 test_many(lzma_index *i)
283 {
284 	test_copy(i);
285 	test_read(i);
286 	test_code(i);
287 }
288 
289 
290 static void
test_cat(void)291 test_cat(void)
292 {
293 	lzma_index *a, *b, *c;
294 	lzma_index_iter r;
295 
296 	// Empty Indexes
297 	a = create_empty();
298 	b = create_empty();
299 	expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
300 	expect(lzma_index_block_count(a) == 0);
301 	expect(lzma_index_stream_size(a) == 2 * LZMA_STREAM_HEADER_SIZE + 8);
302 	expect(lzma_index_file_size(a)
303 			== 2 * (2 * LZMA_STREAM_HEADER_SIZE + 8));
304 	lzma_index_iter_init(&r, a);
305 	expect(lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK));
306 
307 	b = create_empty();
308 	expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
309 	expect(lzma_index_block_count(a) == 0);
310 	expect(lzma_index_stream_size(a) == 2 * LZMA_STREAM_HEADER_SIZE + 8);
311 	expect(lzma_index_file_size(a)
312 			== 3 * (2 * LZMA_STREAM_HEADER_SIZE + 8));
313 
314 	b = create_empty();
315 	c = create_empty();
316 	expect(lzma_index_stream_padding(b, 4) == LZMA_OK);
317 	expect(lzma_index_cat(b, c, NULL) == LZMA_OK);
318 	expect(lzma_index_block_count(b) == 0);
319 	expect(lzma_index_stream_size(b) == 2 * LZMA_STREAM_HEADER_SIZE + 8);
320 	expect(lzma_index_file_size(b)
321 			== 2 * (2 * LZMA_STREAM_HEADER_SIZE + 8) + 4);
322 
323 	expect(lzma_index_stream_padding(a, 8) == LZMA_OK);
324 	expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
325 	expect(lzma_index_block_count(a) == 0);
326 	expect(lzma_index_stream_size(a) == 2 * LZMA_STREAM_HEADER_SIZE + 8);
327 	expect(lzma_index_file_size(a)
328 			== 5 * (2 * LZMA_STREAM_HEADER_SIZE + 8) + 4 + 8);
329 
330 	expect(lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK));
331 	lzma_index_iter_rewind(&r);
332 	expect(lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK));
333 	lzma_index_end(a, NULL);
334 
335 	// Small Indexes
336 	a = create_small();
337 	lzma_vli stream_size = lzma_index_stream_size(a);
338 	lzma_index_iter_init(&r, a);
339 	for (int i = SMALL_COUNT; i >= 0; --i)
340 		expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
341 				^ (i == 0));
342 
343 	b = create_small();
344 	expect(lzma_index_stream_padding(a, 4) == LZMA_OK);
345 	expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
346 	expect(lzma_index_file_size(a) == stream_size * 2 + 4);
347 	expect(lzma_index_stream_size(a) > stream_size);
348 	expect(lzma_index_stream_size(a) < stream_size * 2);
349 	for (int i = SMALL_COUNT; i >= 0; --i)
350 		expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
351 				^ (i == 0));
352 
353 	lzma_index_iter_rewind(&r);
354 	for (int i = SMALL_COUNT * 2; i >= 0; --i)
355 		expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
356 				^ (i == 0));
357 
358 	b = create_small();
359 	c = create_small();
360 	expect(lzma_index_stream_padding(b, 8) == LZMA_OK);
361 	expect(lzma_index_cat(b, c, NULL) == LZMA_OK);
362 	expect(lzma_index_stream_padding(a, 12) == LZMA_OK);
363 	expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
364 	expect(lzma_index_file_size(a) == stream_size * 4 + 4 + 8 + 12);
365 
366 	expect(lzma_index_block_count(a) == SMALL_COUNT * 4);
367 	for (int i = SMALL_COUNT * 2; i >= 0; --i)
368 		expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
369 				^ (i == 0));
370 
371 	lzma_index_iter_rewind(&r);
372 	for (int i = SMALL_COUNT * 4; i >= 0; --i)
373 		expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
374 				^ (i == 0));
375 
376 	lzma_index_end(a, NULL);
377 
378 	// Mix of empty and small
379 	a = create_empty();
380 	b = create_small();
381 	expect(lzma_index_stream_padding(a, 4) == LZMA_OK);
382 	expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
383 	lzma_index_iter_init(&r, a);
384 	for (int i = SMALL_COUNT; i >= 0; --i)
385 		expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
386 				^ (i == 0));
387 
388 	lzma_index_end(a, NULL);
389 
390 	// Big Indexes
391 	a = create_big();
392 	stream_size = lzma_index_stream_size(a);
393 	b = create_big();
394 	expect(lzma_index_stream_padding(a, 4) == LZMA_OK);
395 	expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
396 	expect(lzma_index_file_size(a) == stream_size * 2 + 4);
397 	expect(lzma_index_stream_size(a) > stream_size);
398 	expect(lzma_index_stream_size(a) < stream_size * 2);
399 
400 	b = create_big();
401 	c = create_big();
402 	expect(lzma_index_stream_padding(b, 8) == LZMA_OK);
403 	expect(lzma_index_cat(b, c, NULL) == LZMA_OK);
404 	expect(lzma_index_stream_padding(a, 12) == LZMA_OK);
405 	expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
406 	expect(lzma_index_file_size(a) == stream_size * 4 + 4 + 8 + 12);
407 
408 	lzma_index_iter_init(&r, a);
409 	for (int i = BIG_COUNT * 4; i >= 0; --i)
410 		expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
411 				^ (i == 0));
412 
413 	lzma_index_end(a, NULL);
414 }
415 
416 
417 static void
test_locate(void)418 test_locate(void)
419 {
420 	lzma_index *i = lzma_index_init(NULL);
421 	expect(i != NULL);
422 	lzma_index_iter r;
423 	lzma_index_iter_init(&r, i);
424 
425 	// Cannot locate anything from an empty Index.
426 	expect(lzma_index_iter_locate(&r, 0));
427 	expect(lzma_index_iter_locate(&r, 555));
428 
429 	// One empty Record: nothing is found since there's no uncompressed
430 	// data.
431 	expect(lzma_index_append(i, NULL, 16, 0) == LZMA_OK);
432 	expect(lzma_index_iter_locate(&r, 0));
433 
434 	// Non-empty Record and we can find something.
435 	expect(lzma_index_append(i, NULL, 32, 5) == LZMA_OK);
436 	expect(!lzma_index_iter_locate(&r, 0));
437 	expect(r.block.total_size == 32);
438 	expect(r.block.uncompressed_size == 5);
439 	expect(r.block.compressed_file_offset
440 			== LZMA_STREAM_HEADER_SIZE + 16);
441 	expect(r.block.uncompressed_file_offset == 0);
442 
443 	// Still cannot find anything past the end.
444 	expect(lzma_index_iter_locate(&r, 5));
445 
446 	// Add the third Record.
447 	expect(lzma_index_append(i, NULL, 40, 11) == LZMA_OK);
448 
449 	expect(!lzma_index_iter_locate(&r, 0));
450 	expect(r.block.total_size == 32);
451 	expect(r.block.uncompressed_size == 5);
452 	expect(r.block.compressed_file_offset
453 			== LZMA_STREAM_HEADER_SIZE + 16);
454 	expect(r.block.uncompressed_file_offset == 0);
455 
456 	expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK));
457 	expect(r.block.total_size == 40);
458 	expect(r.block.uncompressed_size == 11);
459 	expect(r.block.compressed_file_offset
460 			== LZMA_STREAM_HEADER_SIZE + 16 + 32);
461 	expect(r.block.uncompressed_file_offset == 5);
462 
463 	expect(!lzma_index_iter_locate(&r, 2));
464 	expect(r.block.total_size == 32);
465 	expect(r.block.uncompressed_size == 5);
466 	expect(r.block.compressed_file_offset
467 			== LZMA_STREAM_HEADER_SIZE + 16);
468 	expect(r.block.uncompressed_file_offset == 0);
469 
470 	expect(!lzma_index_iter_locate(&r, 5));
471 	expect(r.block.total_size == 40);
472 	expect(r.block.uncompressed_size == 11);
473 	expect(r.block.compressed_file_offset
474 			== LZMA_STREAM_HEADER_SIZE + 16 + 32);
475 	expect(r.block.uncompressed_file_offset == 5);
476 
477 	expect(!lzma_index_iter_locate(&r, 5 + 11 - 1));
478 	expect(r.block.total_size == 40);
479 	expect(r.block.uncompressed_size == 11);
480 	expect(r.block.compressed_file_offset
481 			== LZMA_STREAM_HEADER_SIZE + 16 + 32);
482 	expect(r.block.uncompressed_file_offset == 5);
483 
484 	expect(lzma_index_iter_locate(&r, 5 + 11));
485 	expect(lzma_index_iter_locate(&r, 5 + 15));
486 
487 	// Large Index
488 	lzma_index_end(i, NULL);
489 	i = lzma_index_init(NULL);
490 	expect(i != NULL);
491 	lzma_index_iter_init(&r, i);
492 
493 	for (size_t n = 4; n <= 4 * 5555; n += 4)
494 		expect(lzma_index_append(i, NULL, n + 8, n) == LZMA_OK);
495 
496 	expect(lzma_index_block_count(i) == 5555);
497 
498 	// First Record
499 	expect(!lzma_index_iter_locate(&r, 0));
500 	expect(r.block.total_size == 4 + 8);
501 	expect(r.block.uncompressed_size == 4);
502 	expect(r.block.compressed_file_offset == LZMA_STREAM_HEADER_SIZE);
503 	expect(r.block.uncompressed_file_offset == 0);
504 
505 	expect(!lzma_index_iter_locate(&r, 3));
506 	expect(r.block.total_size == 4 + 8);
507 	expect(r.block.uncompressed_size == 4);
508 	expect(r.block.compressed_file_offset == LZMA_STREAM_HEADER_SIZE);
509 	expect(r.block.uncompressed_file_offset == 0);
510 
511 	// Second Record
512 	expect(!lzma_index_iter_locate(&r, 4));
513 	expect(r.block.total_size == 2 * 4 + 8);
514 	expect(r.block.uncompressed_size == 2 * 4);
515 	expect(r.block.compressed_file_offset
516 			== LZMA_STREAM_HEADER_SIZE + 4 + 8);
517 	expect(r.block.uncompressed_file_offset == 4);
518 
519 	// Last Record
520 	expect(!lzma_index_iter_locate(
521 			&r, lzma_index_uncompressed_size(i) - 1));
522 	expect(r.block.total_size == 4 * 5555 + 8);
523 	expect(r.block.uncompressed_size == 4 * 5555);
524 	expect(r.block.compressed_file_offset == lzma_index_total_size(i)
525 			+ LZMA_STREAM_HEADER_SIZE - 4 * 5555 - 8);
526 	expect(r.block.uncompressed_file_offset
527 			== lzma_index_uncompressed_size(i) - 4 * 5555);
528 
529 	// Allocation chunk boundaries. See INDEX_GROUP_SIZE in
530 	// liblzma/common/index.c.
531 	const size_t group_multiple = 256 * 4;
532 	const size_t radius = 8;
533 	const size_t start = group_multiple - radius;
534 	lzma_vli ubase = 0;
535 	lzma_vli tbase = 0;
536 	size_t n;
537 	for (n = 1; n < start; ++n) {
538 		ubase += n * 4;
539 		tbase += n * 4 + 8;
540 	}
541 
542 	while (n < start + 2 * radius) {
543 		expect(!lzma_index_iter_locate(&r, ubase + n * 4));
544 
545 		expect(r.block.compressed_file_offset == tbase + n * 4 + 8
546 				+ LZMA_STREAM_HEADER_SIZE);
547 		expect(r.block.uncompressed_file_offset == ubase + n * 4);
548 
549 		tbase += n * 4 + 8;
550 		ubase += n * 4;
551 		++n;
552 
553 		expect(r.block.total_size == n * 4 + 8);
554 		expect(r.block.uncompressed_size == n * 4);
555 	}
556 
557 	// Do it also backwards.
558 	while (n > start) {
559 		expect(!lzma_index_iter_locate(&r, ubase + (n - 1) * 4));
560 
561 		expect(r.block.total_size == n * 4 + 8);
562 		expect(r.block.uncompressed_size == n * 4);
563 
564 		--n;
565 		tbase -= n * 4 + 8;
566 		ubase -= n * 4;
567 
568 		expect(r.block.compressed_file_offset == tbase + n * 4 + 8
569 				+ LZMA_STREAM_HEADER_SIZE);
570 		expect(r.block.uncompressed_file_offset == ubase + n * 4);
571 	}
572 
573 	// Test locating in concatenated Index.
574 	lzma_index_end(i, NULL);
575 	i = lzma_index_init(NULL);
576 	expect(i != NULL);
577 	lzma_index_iter_init(&r, i);
578 	for (n = 0; n < group_multiple; ++n)
579 		expect(lzma_index_append(i, NULL, 8, 0) == LZMA_OK);
580 	expect(lzma_index_append(i, NULL, 16, 1) == LZMA_OK);
581 	expect(!lzma_index_iter_locate(&r, 0));
582 	expect(r.block.total_size == 16);
583 	expect(r.block.uncompressed_size == 1);
584 	expect(r.block.compressed_file_offset
585 			== LZMA_STREAM_HEADER_SIZE + group_multiple * 8);
586 	expect(r.block.uncompressed_file_offset == 0);
587 
588 	lzma_index_end(i, NULL);
589 }
590 
591 
592 static void
test_corrupt(void)593 test_corrupt(void)
594 {
595 	const size_t alloc_size = 128 * 1024;
596 	uint8_t *buf = malloc(alloc_size);
597 	expect(buf != NULL);
598 	lzma_stream strm = LZMA_STREAM_INIT;
599 
600 	lzma_index *i = create_empty();
601 	expect(lzma_index_append(i, NULL, 0, 1) == LZMA_PROG_ERROR);
602 	lzma_index_end(i, NULL);
603 
604 	// Create a valid Index and corrupt it in different ways.
605 	i = create_small();
606 	expect(lzma_index_encoder(&strm, i) == LZMA_OK);
607 	succeed(coder_loop(&strm, NULL, 0, buf, 20,
608 			LZMA_STREAM_END, LZMA_RUN));
609 	lzma_index_end(i, NULL);
610 
611 	// Wrong Index Indicator
612 	buf[0] ^= 1;
613 	expect(lzma_index_decoder(&strm, &i, MEMLIMIT) == LZMA_OK);
614 	succeed(decoder_loop_ret(&strm, buf, 1, LZMA_DATA_ERROR));
615 	buf[0] ^= 1;
616 
617 	// Wrong Number of Records and thus CRC32 fails.
618 	--buf[1];
619 	expect(lzma_index_decoder(&strm, &i, MEMLIMIT) == LZMA_OK);
620 	succeed(decoder_loop_ret(&strm, buf, 10, LZMA_DATA_ERROR));
621 	++buf[1];
622 
623 	// Padding not NULs
624 	buf[15] ^= 1;
625 	expect(lzma_index_decoder(&strm, &i, MEMLIMIT) == LZMA_OK);
626 	succeed(decoder_loop_ret(&strm, buf, 16, LZMA_DATA_ERROR));
627 
628 	lzma_end(&strm);
629 	free(buf);
630 }
631 
632 
633 // Allocator that succeeds for the first two allocation but fails the rest.
634 static void *
my_alloc(void * opaque,size_t a,size_t b)635 my_alloc(void *opaque, size_t a, size_t b)
636 {
637 	(void)opaque;
638 
639 	static unsigned count = 0;
640 	if (++count > 2)
641 		return NULL;
642 
643 	return malloc(a * b);
644 }
645 
646 static const lzma_allocator my_allocator = { &my_alloc, NULL, NULL };
647 
648 
649 int
main(void)650 main(void)
651 {
652 	test_equal();
653 
654 	test_overflow();
655 
656 	lzma_index *i = create_empty();
657 	test_many(i);
658 	lzma_index_end(i, NULL);
659 
660 	i = create_small();
661 	test_many(i);
662 	lzma_index_end(i, NULL);
663 
664 	i = create_big();
665 	test_many(i);
666 	lzma_index_end(i, NULL);
667 
668 	test_cat();
669 
670 	test_locate();
671 
672 	test_corrupt();
673 
674 	// Test for the bug fix 21515d79d778b8730a434f151b07202d52a04611:
675 	// liblzma: Fix lzma_index_dup() for empty Streams.
676 	i = create_empty();
677 	expect(lzma_index_stream_padding(i, 4) == LZMA_OK);
678 	test_copy(i);
679 	lzma_index_end(i, NULL);
680 
681 	// Test for the bug fix 3bf857edfef51374f6f3fffae3d817f57d3264a0:
682 	// liblzma: Fix a memory leak in error path of lzma_index_dup().
683 	// Use Valgrind to see that there are no leaks.
684 	i = create_small();
685 	expect(lzma_index_dup(i, &my_allocator) == NULL);
686 	lzma_index_end(i, NULL);
687 
688 	return 0;
689 }
690