]> icculus.org git repositories - icculus/xz.git/blob - tests/test_block_header.c
Fix memory leaks from test_block_header.c.
[icculus/xz.git] / tests / test_block_header.c
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       test_block_header.c
4 /// \brief      Tests Block Header coders
5 //
6 //  Copyright (C) 2007 Lasse Collin
7 //
8 //  This library is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU Lesser General Public
10 //  License as published by the Free Software Foundation; either
11 //  version 2.1 of the License, or (at your option) any later version.
12 //
13 //  This library is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 //  Lesser General Public License for more details.
17 //
18 ///////////////////////////////////////////////////////////////////////////////
19
20 #include "tests.h"
21
22
23 static uint8_t buffer[4096];
24 static lzma_stream strm = LZMA_STREAM_INIT;
25 static lzma_options_block known_options;
26 static lzma_options_block decoded_options;
27
28 // We want to test zero, one, and two filters in the chain.
29
30 static const lzma_options_filter filters_none[1] = {
31         {
32                 .id = LZMA_VLI_VALUE_UNKNOWN,
33                 .options = NULL,
34         },
35 };
36
37 static const lzma_options_filter filters_powerpc[2] = {
38         {
39                 .id = LZMA_FILTER_POWERPC,
40                 .options = NULL,
41         }, {
42                 .id = LZMA_VLI_VALUE_UNKNOWN,
43                 .options = NULL,
44         },
45 };
46
47 static const lzma_options_delta options_delta = {
48         .distance = 4,
49 };
50
51 static const lzma_options_filter filters_delta[3] = {
52         {
53                 .id = LZMA_FILTER_DELTA,
54                 .options = (void *)(&options_delta),
55         }, {
56                 .id = LZMA_FILTER_COPY,
57                 .options = NULL,
58         }, {
59                 .id = LZMA_VLI_VALUE_UNKNOWN,
60                 .options = NULL,
61         },
62 };
63
64
65 static void
66 free_decoded_options(void)
67 {
68         for (size_t i = 0; i < sizeof(decoded_options.filters)
69                         / sizeof(decoded_options.filters[0]); ++i) {
70                 free(decoded_options.filters[i].options);
71                 decoded_options.filters[i].options = NULL;
72         }
73 }
74
75
76 static bool
77 encode(uint32_t header_size)
78 {
79         memcrap(buffer, sizeof(buffer));
80
81         if (lzma_block_header_size(&known_options) != LZMA_OK)
82                 return true;
83
84         if (known_options.header_size != header_size)
85                 return true;
86
87         if (lzma_block_header_encode(buffer, &known_options) != LZMA_OK)
88                 return true;
89
90         return false;
91 }
92
93
94 static bool
95 decode_ret(uint32_t header_size, lzma_ret ret_ok)
96 {
97         memcrap(&decoded_options, sizeof(decoded_options));
98         decoded_options.has_crc32 = known_options.has_crc32;
99
100         expect(lzma_block_header_decoder(&strm, &decoded_options) == LZMA_OK);
101
102         const bool ret = decoder_loop_ret(&strm, buffer, header_size, ret_ok);
103         free_decoded_options();
104         return ret;
105 }
106
107
108 static bool
109 decode(uint32_t header_size)
110 {
111         memcrap(&decoded_options, sizeof(decoded_options));
112         decoded_options.has_crc32 = known_options.has_crc32;
113
114         expect(lzma_block_header_decoder(&strm, &decoded_options) == LZMA_OK);
115
116         const bool ret = decoder_loop(&strm, buffer, header_size);
117         free_decoded_options();
118         if (ret)
119                 return true;
120
121         if (known_options.has_eopm != decoded_options.has_eopm)
122                 return true;
123
124         if (known_options.is_metadata != decoded_options.is_metadata)
125                 return true;
126
127         if (known_options.compressed_size == LZMA_VLI_VALUE_UNKNOWN
128                         && known_options.compressed_reserve != 0) {
129                 if (decoded_options.compressed_size != 0)
130                         return true;
131         } else if (known_options.compressed_size
132                         != decoded_options.compressed_size) {
133                 return true;
134         }
135
136         if (known_options.uncompressed_size == LZMA_VLI_VALUE_UNKNOWN
137                         && known_options.uncompressed_reserve != 0) {
138                 if (decoded_options.uncompressed_size != 0)
139                         return true;
140         } else if (known_options.uncompressed_size
141                         != decoded_options.uncompressed_size) {
142                 return true;
143         }
144
145         if (known_options.compressed_reserve != 0
146                         && known_options.compressed_reserve
147                                 != decoded_options.compressed_reserve)
148                 return true;
149
150         if (known_options.uncompressed_reserve != 0
151                         && known_options.uncompressed_reserve
152                                 != decoded_options.uncompressed_reserve)
153                 return true;
154
155         if (known_options.padding != decoded_options.padding)
156                 return true;
157
158         return false;
159 }
160
161
162 static bool
163 code(uint32_t header_size)
164 {
165         return encode(header_size) || decode(header_size);
166 }
167
168
169 static bool
170 helper_loop(uint32_t unpadded_size, uint32_t multiple)
171 {
172         for (int i = 0; i <= LZMA_BLOCK_HEADER_PADDING_MAX; ++i) {
173                 known_options.padding = i;
174                 if (code(unpadded_size + i))
175                         return true;
176         }
177
178         for (int i = 0 - LZMA_BLOCK_HEADER_PADDING_MAX - 1;
179                         i <= LZMA_BLOCK_HEADER_PADDING_MAX + 1; ++i) {
180                 known_options.alignment = i;
181
182                 uint32_t size = unpadded_size;
183                 while ((size + known_options.alignment) % multiple)
184                         ++size;
185
186                 known_options.padding = LZMA_BLOCK_HEADER_PADDING_AUTO;
187                 if (code(size))
188                         return true;
189
190         } while (++known_options.alignment
191                         <= LZMA_BLOCK_HEADER_PADDING_MAX + 1);
192
193         return false;
194 }
195
196
197 static bool
198 helper(uint32_t unpadded_size, uint32_t multiple)
199 {
200         known_options.has_crc32 = false;
201         known_options.is_metadata = false;
202         if (helper_loop(unpadded_size, multiple))
203                 return true;
204
205         known_options.has_crc32 = false;
206         known_options.is_metadata = true;
207         if (helper_loop(unpadded_size, multiple))
208                 return true;
209
210         known_options.has_crc32 = true;
211         known_options.is_metadata = false;
212         if (helper_loop(unpadded_size + 4, multiple))
213                 return true;
214
215         known_options.has_crc32 = true;
216         known_options.is_metadata = true;
217         if (helper_loop(unpadded_size + 4, multiple))
218                 return true;
219
220         return false;
221 }
222
223
224 static void
225 test1(void)
226 {
227         known_options = (lzma_options_block){
228                 .has_eopm = true,
229                 .compressed_size = LZMA_VLI_VALUE_UNKNOWN,
230                 .uncompressed_size = LZMA_VLI_VALUE_UNKNOWN,
231                 .compressed_reserve = 0,
232                 .uncompressed_reserve = 0,
233         };
234         memcpy(known_options.filters, filters_none, sizeof(filters_none));
235         expect(!helper(2, 1));
236
237         memcpy(known_options.filters, filters_powerpc,
238                         sizeof(filters_powerpc));
239         expect(!helper(3, 4));
240
241         memcpy(known_options.filters, filters_delta, sizeof(filters_delta));
242         expect(!helper(5, 1));
243
244         known_options.padding = LZMA_BLOCK_HEADER_PADDING_MAX + 1;
245         expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR);
246 }
247
248
249 static void
250 test2_helper(uint32_t unpadded_size, uint32_t multiple)
251 {
252         known_options.has_eopm = true;
253         known_options.compressed_size = LZMA_VLI_VALUE_UNKNOWN;
254         known_options.uncompressed_size = LZMA_VLI_VALUE_UNKNOWN;
255         known_options.compressed_reserve = 1;
256         known_options.uncompressed_reserve = 1;
257         expect(!helper(unpadded_size + 2, multiple));
258
259         known_options.compressed_reserve = LZMA_VLI_BYTES_MAX;
260         known_options.uncompressed_reserve = LZMA_VLI_BYTES_MAX;
261         expect(!helper(unpadded_size + 18, multiple));
262
263         known_options.compressed_size = 1234;
264         known_options.uncompressed_size = 2345;
265         expect(!helper(unpadded_size + 18, multiple));
266
267         known_options.compressed_reserve = 1;
268         known_options.uncompressed_reserve = 1;
269         expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR);
270 }
271
272
273 static void
274 test2(void)
275 {
276         memcpy(known_options.filters, filters_none, sizeof(filters_none));
277         test2_helper(2, 1);
278
279         memcpy(known_options.filters, filters_powerpc,
280                         sizeof(filters_powerpc));
281         test2_helper(3, 4);
282
283         memcpy(known_options.filters, filters_delta,
284                         sizeof(filters_delta));
285         test2_helper(5, 1);
286 }
287
288
289 static void
290 test3(void)
291 {
292         known_options = (lzma_options_block){
293                 .has_crc32 = false,
294                 .has_eopm = true,
295                 .is_metadata = false,
296                 .compressed_size = LZMA_VLI_VALUE_UNKNOWN,
297                 .uncompressed_size = LZMA_VLI_VALUE_UNKNOWN,
298                 .compressed_reserve = 1,
299                 .uncompressed_reserve = 1,
300         };
301         memcpy(known_options.filters, filters_none, sizeof(filters_none));
302
303         known_options.header_size = 3;
304         expect(lzma_block_header_encode(buffer, &known_options)
305                         == LZMA_PROG_ERROR);
306
307         known_options.header_size = 4;
308         expect(lzma_block_header_encode(buffer, &known_options) == LZMA_OK);
309
310         known_options.header_size = 5;
311         expect(lzma_block_header_encode(buffer, &known_options)
312                         == LZMA_PROG_ERROR);
313
314         // NOTE: This assumes that Filter ID 0x1F is not supported. Update
315         // this test to use some other ID if 0x1F becomes supported.
316         known_options.filters[0].id = 0x1F;
317         known_options.header_size = 5;
318         expect(lzma_block_header_encode(buffer, &known_options)
319                         == LZMA_HEADER_ERROR);
320 }
321
322
323 static void
324 test4(void)
325 {
326         known_options = (lzma_options_block){
327                 .has_crc32 = false,
328                 .has_eopm = true,
329                 .is_metadata = false,
330                 .compressed_size = 0,
331                 .uncompressed_size = 0,
332                 .compressed_reserve = LZMA_VLI_BYTES_MAX,
333                 .uncompressed_reserve = LZMA_VLI_BYTES_MAX,
334                 .padding = 0,
335         };
336         memcpy(known_options.filters, filters_powerpc,
337                         sizeof(filters_powerpc));
338         expect(!code(21));
339
340         // Reserved bits
341         buffer[0] ^= 0x40;
342         expect(!decode_ret(1, LZMA_HEADER_ERROR));
343         buffer[0] ^= 0x40;
344
345         buffer[1] ^= 0x40;
346         expect(decode_ret(21, LZMA_HEADER_ERROR));
347         buffer[1] ^= 0x40;
348
349
350 }
351
352
353 int
354 main(void)
355 {
356         lzma_init();
357
358         test1();
359         test2();
360         test3();
361         test4();
362
363         lzma_end(&strm);
364
365         return 0;
366 }