xref: /netbsd-src/external/public-domain/xz/dist/tests/test_bcj_exact_size.c (revision 75cbb3d6e4fac2c8c149ebd3a1104dd4ac8c9b3a)
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       test_bcj_exact_size.c
4 /// \brief      Tests BCJ decoding when the output size is known
5 ///
6 /// These tests fail with XZ Utils 5.0.3 and earlier.
7 //
8 //  Author:     Lasse Collin
9 //
10 //  This file has been put into the public domain.
11 //  You can do whatever you want with this file.
12 //
13 ///////////////////////////////////////////////////////////////////////////////
14 
15 #include "tests.h"
16 
17 
18 /// Something to be compressed
19 static const uint8_t in[16] = "0123456789ABCDEF";
20 
21 /// in[] after compression
22 static uint8_t compressed[1024];
23 static size_t compressed_size = 0;
24 
25 /// Output buffer for decompressing compressed[]
26 static uint8_t out[sizeof(in)];
27 
28 
29 static void
compress(void)30 compress(void)
31 {
32 	// Compress with PowerPC BCJ and LZMA2. PowerPC BCJ is used because
33 	// it has fixed 4-byte alignment which makes triggering the potential
34 	// bug easy.
35 	lzma_options_lzma opt_lzma2;
36 	succeed(lzma_lzma_preset(&opt_lzma2, 0));
37 
38 	lzma_filter filters[3] = {
39 		{ .id = LZMA_FILTER_POWERPC, .options = NULL },
40 		{ .id = LZMA_FILTER_LZMA2, .options = &opt_lzma2 },
41 		{ .id = LZMA_VLI_UNKNOWN, .options = NULL },
42 	};
43 
44 	expect(lzma_stream_buffer_encode(filters, LZMA_CHECK_CRC32, NULL,
45 			in, sizeof(in),
46 			compressed, &compressed_size, sizeof(compressed))
47 			== LZMA_OK);
48 }
49 
50 
51 static void
decompress(void)52 decompress(void)
53 {
54 	lzma_stream strm = LZMA_STREAM_INIT;
55 	expect(lzma_stream_decoder(&strm, 10 << 20, 0) == LZMA_OK);
56 
57 	strm.next_in = compressed;
58 	strm.next_out = out;
59 
60 	while (true) {
61 		if (strm.total_in < compressed_size)
62 			strm.avail_in = 1;
63 
64 		const lzma_ret ret = lzma_code(&strm, LZMA_RUN);
65 		if (ret == LZMA_STREAM_END) {
66 			expect(strm.total_in == compressed_size);
67 			expect(strm.total_out == sizeof(in));
68 			lzma_end(&strm);
69 			return;
70 		}
71 
72 		expect(ret == LZMA_OK);
73 
74 		if (strm.total_out < sizeof(in))
75 			strm.avail_out = 1;
76 	}
77 }
78 
79 
80 static void
decompress_empty(void)81 decompress_empty(void)
82 {
83 	// An empty file with one Block using PowerPC BCJ and LZMA2.
84 	static const uint8_t empty_bcj_lzma2[] = {
85 		0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00, 0x00, 0x01,
86 		0x69, 0x22, 0xDE, 0x36, 0x02, 0x01, 0x05, 0x00,
87 		0x21, 0x01, 0x00, 0x00, 0x7F, 0xE0, 0xF1, 0xC8,
88 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 		0x00, 0x01, 0x11, 0x00, 0x3B, 0x96, 0x5F, 0x73,
90 		0x90, 0x42, 0x99, 0x0D, 0x01, 0x00, 0x00, 0x00,
91 		0x00, 0x01, 0x59, 0x5A
92 	};
93 
94 	// Decompress without giving any output space.
95 	uint64_t memlimit = 1 << 20;
96 	size_t in_pos = 0;
97 	size_t out_pos = 0;
98 	expect(lzma_stream_buffer_decode(&memlimit, 0, NULL,
99 			empty_bcj_lzma2, &in_pos, sizeof(empty_bcj_lzma2),
100 			out, &out_pos, 0) == LZMA_OK);
101 	expect(in_pos == sizeof(empty_bcj_lzma2));
102 	expect(out_pos == 0);
103 }
104 
105 
106 extern int
main(void)107 main(void)
108 {
109 	compress();
110 	decompress();
111 	decompress_empty();
112 	return 0;
113 }
114