Update THANKS
[xz/debian.git] / tests / test_stream_flags.c
blob3bc48be071030062266b81cd53e5a80b0b822025
1 // SPDX-License-Identifier: 0BSD
3 ///////////////////////////////////////////////////////////////////////////////
4 //
5 /// \file test_stream_flags.c
6 /// \brief Tests Stream Header and Stream Footer coders
7 //
8 // Authors: Jia Tan
9 // Lasse Collin
11 ///////////////////////////////////////////////////////////////////////////////
13 #include "tests.h"
16 // Size of the Stream Flags field
17 // (taken from src/liblzma/common/stream_flags_common.h)
18 #define XZ_STREAM_FLAGS_SIZE 2
20 #ifdef HAVE_ENCODERS
21 // Header and footer magic bytes for .xz file format
22 // (taken from src/liblzma/common/stream_flags_common.c)
23 static const uint8_t xz_header_magic[6]
24 = { 0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00 };
25 static const uint8_t xz_footer_magic[2] = { 0x59, 0x5A };
26 #endif
29 #ifdef HAVE_ENCODERS
30 static void
31 stream_header_encode_helper(lzma_check check)
33 lzma_stream_flags flags = {
34 .version = 0,
35 .check = check,
38 uint8_t header[LZMA_STREAM_HEADER_SIZE];
40 // Encode Stream Header
41 assert_lzma_ret(lzma_stream_header_encode(&flags, header), LZMA_OK);
43 // Stream Header must start with Header Magic Bytes
44 const uint32_t magic_size = sizeof(xz_header_magic);
45 assert_array_eq(header, xz_header_magic, magic_size);
47 // Next must come Stream Flags
48 const uint8_t *encoded_stream_flags = header + magic_size;
50 // First byte is always null-byte.
51 // Second byte must have the Check ID in the lowest four bits
52 // and the highest four bits zero.
53 const uint8_t expected_stream_flags[] = { 0, check };
54 assert_array_eq(encoded_stream_flags, expected_stream_flags,
55 XZ_STREAM_FLAGS_SIZE);
57 // Last part is the CRC32 of the Stream Flags
58 const uint8_t *crc_ptr = encoded_stream_flags + XZ_STREAM_FLAGS_SIZE;
59 const uint32_t expected_crc = lzma_crc32(expected_stream_flags,
60 XZ_STREAM_FLAGS_SIZE, 0);
61 assert_uint_eq(read32le(crc_ptr), expected_crc);
63 #endif
66 static void
67 test_lzma_stream_header_encode(void)
69 #ifndef HAVE_ENCODERS
70 assert_skip("Encoder support disabled");
71 #else
72 for (lzma_check i = 0; i < LZMA_CHECK_ID_MAX; i++)
73 stream_header_encode_helper(i);
75 lzma_stream_flags flags = {
76 .version = 0,
77 .check = LZMA_CHECK_CRC32
80 uint8_t header[LZMA_STREAM_HEADER_SIZE];
82 // Should fail if version > 0
83 flags.version = 1;
84 assert_lzma_ret(lzma_stream_header_encode(&flags, header),
85 LZMA_OPTIONS_ERROR);
86 flags.version = 0;
88 // Should fail if Check ID is invalid
89 flags.check = INVALID_LZMA_CHECK_ID;
90 assert_lzma_ret(lzma_stream_header_encode(&flags, header),
91 LZMA_PROG_ERROR);
92 flags.check = LZMA_CHECK_CRC32;
94 // Should pass even if Backward Size is invalid
95 // because Stream Header doesn't have that field.
96 flags.backward_size = LZMA_VLI_MAX + 1;
97 assert_lzma_ret(lzma_stream_header_encode(&flags, header), LZMA_OK);
98 #endif
102 #if defined(HAVE_ENCODERS)
103 static void
104 stream_footer_encode_helper(lzma_check check)
106 lzma_stream_flags flags = {
107 .version = 0,
108 .check = check,
109 .backward_size = LZMA_BACKWARD_SIZE_MIN,
112 uint8_t footer[LZMA_STREAM_HEADER_SIZE];
114 // Encode Stream Footer
115 assert_lzma_ret(lzma_stream_footer_encode(&flags, footer), LZMA_OK);
117 // Stream Footer must start with CRC32
118 const uint32_t crc = read32le(footer);
119 const uint32_t expected_crc = lzma_crc32(footer + sizeof(uint32_t),
120 LZMA_STREAM_HEADER_SIZE - (sizeof(uint32_t) +
121 sizeof(xz_footer_magic)), 0);
122 assert_uint_eq(crc, expected_crc);
124 // Next the Backward Size
125 const uint32_t backwards_size = read32le(footer + sizeof(uint32_t));
126 const uint32_t expected_backwards_size = flags.backward_size / 4 - 1;
127 assert_uint_eq(backwards_size, expected_backwards_size);
129 // Next the Stream Flags
130 const uint8_t *stream_flags = footer + sizeof(uint32_t) * 2;
132 // First byte must be null
133 assert_uint_eq(stream_flags[0], 0);
135 // Second byte must have the Check ID in the lowest four bits
136 // and the highest four bits zero.
137 assert_uint_eq(stream_flags[1], check);
139 // And ends with Footer Magic Bytes
140 const uint8_t *expected_footer_magic = stream_flags +
141 XZ_STREAM_FLAGS_SIZE;
142 assert_array_eq(expected_footer_magic, xz_footer_magic,
143 sizeof(xz_footer_magic));
145 #endif
148 static void
149 test_lzma_stream_footer_encode(void)
151 #ifndef HAVE_ENCODERS
152 assert_skip("Encoder support disabled");
153 #else
154 for (lzma_check i = 0; i < LZMA_CHECK_ID_MAX; i++)
155 stream_footer_encode_helper(i);
157 lzma_stream_flags flags = {
158 .version = 0,
159 .backward_size = LZMA_BACKWARD_SIZE_MIN,
160 .check = LZMA_CHECK_CRC32
163 uint8_t footer[LZMA_STREAM_HEADER_SIZE];
165 // Should fail if version > 0
166 flags.version = 1;
167 assert_lzma_ret(lzma_stream_footer_encode(&flags, footer),
168 LZMA_OPTIONS_ERROR);
169 flags.version = 0;
171 // Should fail if Check ID is invalid
172 flags.check = INVALID_LZMA_CHECK_ID;
173 assert_lzma_ret(lzma_stream_footer_encode(&flags, footer),
174 LZMA_PROG_ERROR);
176 // Should fail if Backward Size is invalid
177 flags.backward_size -= 1;
178 assert_lzma_ret(lzma_stream_footer_encode(&flags, footer),
179 LZMA_PROG_ERROR);
180 flags.backward_size += 2;
181 assert_lzma_ret(lzma_stream_footer_encode(&flags, footer),
182 LZMA_PROG_ERROR);
183 flags.backward_size = LZMA_BACKWARD_SIZE_MAX + 4;
184 assert_lzma_ret(lzma_stream_footer_encode(&flags, footer),
185 LZMA_PROG_ERROR);
186 #endif
190 #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
191 static void
192 stream_header_decode_helper(lzma_check check)
194 lzma_stream_flags flags = {
195 .version = 0,
196 .check = check
199 uint8_t header[LZMA_STREAM_HEADER_SIZE];
201 assert_lzma_ret(lzma_stream_header_encode(&flags, header), LZMA_OK);
203 lzma_stream_flags dest_flags;
204 assert_lzma_ret(lzma_stream_header_decode(&dest_flags, header),
205 LZMA_OK);
207 // Version should be 0
208 assert_uint_eq(dest_flags.version, 0);
210 // Backward Size should be LZMA_VLI_UNKNOWN
211 assert_uint_eq(dest_flags.backward_size, LZMA_VLI_UNKNOWN);
213 // Check ID must equal the argument given to this function.
214 assert_uint_eq(dest_flags.check, check);
216 #endif
219 static void
220 test_lzma_stream_header_decode(void)
222 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
223 assert_skip("Encoder or decoder support disabled");
224 #else
225 for (lzma_check i = 0; i < LZMA_CHECK_ID_MAX; i++)
226 stream_header_decode_helper(i);
228 lzma_stream_flags flags = {
229 .version = 0,
230 .check = LZMA_CHECK_CRC32
233 uint8_t header[LZMA_STREAM_HEADER_SIZE];
234 lzma_stream_flags dest;
236 // First encode known flags to header buffer
237 assert_lzma_ret(lzma_stream_header_encode(&flags, header), LZMA_OK);
239 // Should fail if magic bytes do not match
240 header[0] ^= 1;
241 assert_lzma_ret(lzma_stream_header_decode(&dest, header),
242 LZMA_FORMAT_ERROR);
243 header[0] ^= 1;
245 // Should fail if a reserved bit is set
246 uint8_t *stream_flags = header + sizeof(xz_header_magic);
247 stream_flags[0] = 1;
249 // Need to adjust CRC32 after making a change since the CRC32
250 // is verified before decoding the Stream Flags field.
251 uint8_t *crc32_ptr = header + sizeof(xz_header_magic)
252 + XZ_STREAM_FLAGS_SIZE;
253 const uint32_t crc_orig = read32le(crc32_ptr);
254 uint32_t new_crc32 = lzma_crc32(
255 stream_flags, XZ_STREAM_FLAGS_SIZE, 0);
256 write32le(crc32_ptr, new_crc32);
257 assert_lzma_ret(lzma_stream_header_decode(&dest, header),
258 LZMA_OPTIONS_ERROR);
259 stream_flags[0] = 0;
260 write32le(crc32_ptr, crc_orig);
262 // Should fail if upper bits of check ID are set
263 stream_flags[1] |= 0xF0;
264 new_crc32 = lzma_crc32(stream_flags, XZ_STREAM_FLAGS_SIZE, 0);
265 write32le(crc32_ptr, new_crc32);
266 assert_lzma_ret(lzma_stream_header_decode(&dest, header),
267 LZMA_OPTIONS_ERROR);
268 stream_flags[1] = flags.check;
269 write32le(crc32_ptr, crc_orig);
271 // Should fail if CRC32 does not match.
272 // First, alter a byte in the Stream Flags.
273 stream_flags[0] = 1;
274 assert_lzma_ret(lzma_stream_header_decode(&dest, header),
275 LZMA_DATA_ERROR);
276 stream_flags[0] = 0;
278 // Next, change the CRC32.
279 *crc32_ptr ^= 1;
280 assert_lzma_ret(lzma_stream_header_decode(&dest, header),
281 LZMA_DATA_ERROR);
282 #endif
286 #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
287 static void
288 stream_footer_decode_helper(lzma_check check)
290 lzma_stream_flags flags = {
291 .version = 0,
292 .backward_size = LZMA_BACKWARD_SIZE_MIN,
293 .check = check,
296 uint8_t footer[LZMA_STREAM_HEADER_SIZE];
297 assert_lzma_ret(lzma_stream_footer_encode(&flags, footer), LZMA_OK);
299 lzma_stream_flags dest_flags;
300 assert_lzma_ret(lzma_stream_footer_decode(&dest_flags, footer),
301 LZMA_OK);
303 // Version should be 0.
304 assert_uint_eq(dest_flags.version, 0);
306 // Backward Size should equal the value from the flags.
307 assert_uint_eq(dest_flags.backward_size, flags.backward_size);
309 // Check ID must equal argument given to this function.
310 assert_uint_eq(dest_flags.check, check);
312 #endif
315 static void
316 test_lzma_stream_footer_decode(void)
318 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
319 assert_skip("Encoder or decoder support disabled");
320 #else
321 for (lzma_check i = 0; i < LZMA_CHECK_ID_MAX; i++)
322 stream_footer_decode_helper(i);
324 lzma_stream_flags flags = {
325 .version = 0,
326 .check = LZMA_CHECK_CRC32,
327 .backward_size = LZMA_BACKWARD_SIZE_MIN
330 uint8_t footer[LZMA_STREAM_HEADER_SIZE];
331 lzma_stream_flags dest;
333 // First encode known flags to the footer buffer
334 assert_lzma_ret(lzma_stream_footer_encode(&flags, footer), LZMA_OK);
336 // Should fail if magic bytes do not match
337 footer[LZMA_STREAM_HEADER_SIZE - 1] ^= 1;
338 assert_lzma_ret(lzma_stream_footer_decode(&dest, footer),
339 LZMA_FORMAT_ERROR);
340 footer[LZMA_STREAM_HEADER_SIZE - 1] ^= 1;
342 // Should fail if a reserved bit is set.
343 // In the Stream Footer, the Stream Flags follow the CRC32 (4 bytes)
344 // and the Backward Size (4 bytes)
345 uint8_t *stream_flags = footer + sizeof(uint32_t) * 2;
346 stream_flags[0] = 1;
348 // Need to adjust the CRC32 so it will not fail that check instead
349 uint8_t *crc32_ptr = footer;
350 const uint32_t crc_orig = read32le(crc32_ptr);
351 uint8_t *backward_size = footer + sizeof(uint32_t);
352 uint32_t new_crc32 = lzma_crc32(backward_size, sizeof(uint32_t) +
353 XZ_STREAM_FLAGS_SIZE, 0);
354 write32le(crc32_ptr, new_crc32);
355 assert_lzma_ret(lzma_stream_footer_decode(&dest, footer),
356 LZMA_OPTIONS_ERROR);
357 stream_flags[0] = 0;
358 write32le(crc32_ptr, crc_orig);
360 // Should fail if upper bits of check ID are set
361 stream_flags[1] |= 0xF0;
362 new_crc32 = lzma_crc32(backward_size, sizeof(uint32_t) +
363 XZ_STREAM_FLAGS_SIZE, 0);
364 write32le(crc32_ptr, new_crc32);
365 assert_lzma_ret(lzma_stream_footer_decode(&dest, footer),
366 LZMA_OPTIONS_ERROR);
367 stream_flags[1] = flags.check;
368 write32le(crc32_ptr, crc_orig);
370 // Should fail if CRC32 does not match.
371 // First, alter a byte in the Stream Flags.
372 stream_flags[0] = 1;
373 assert_lzma_ret(lzma_stream_footer_decode(&dest, footer),
374 LZMA_DATA_ERROR);
375 stream_flags[0] = 0;
377 // Next, change the CRC32
378 *crc32_ptr ^= 1;
379 assert_lzma_ret(lzma_stream_footer_decode(&dest, footer),
380 LZMA_DATA_ERROR);
381 #endif
385 static void
386 test_lzma_stream_flags_compare(void)
388 lzma_stream_flags first = {
389 .version = 0,
390 .backward_size = LZMA_BACKWARD_SIZE_MIN,
391 .check = LZMA_CHECK_CRC32,
394 lzma_stream_flags second = first;
396 // First test should pass
397 assert_lzma_ret(lzma_stream_flags_compare(&first, &second), LZMA_OK);
399 // Altering either version should cause an error
400 first.version = 1;
401 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
402 LZMA_OPTIONS_ERROR);
403 second.version = 1;
404 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
405 LZMA_OPTIONS_ERROR);
406 first.version = 0;
407 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
408 LZMA_OPTIONS_ERROR);
409 second.version = 0;
411 // Check types must be under the maximum
412 first.check = INVALID_LZMA_CHECK_ID;
413 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
414 LZMA_PROG_ERROR);
415 second.check = INVALID_LZMA_CHECK_ID;
416 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
417 LZMA_PROG_ERROR);
418 first.check = LZMA_CHECK_CRC32;
419 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
420 LZMA_PROG_ERROR);
421 second.check = LZMA_CHECK_CRC32;
423 // Check types must be equal
424 for (lzma_check i = 0; i < LZMA_CHECK_ID_MAX; i++) {
425 first.check = i;
426 if (i == second.check)
427 assert_lzma_ret(lzma_stream_flags_compare(&first,
428 &second), LZMA_OK);
429 else
430 assert_lzma_ret(lzma_stream_flags_compare(&first,
431 &second), LZMA_DATA_ERROR);
433 first.check = LZMA_CHECK_CRC32;
435 // Backward Size comparison is skipped if either are LZMA_VLI_UNKNOWN
436 first.backward_size = LZMA_VLI_UNKNOWN;
437 assert_lzma_ret(lzma_stream_flags_compare(&first, &second), LZMA_OK);
438 second.backward_size = LZMA_VLI_MAX + 1;
439 assert_lzma_ret(lzma_stream_flags_compare(&first, &second), LZMA_OK);
440 second.backward_size = LZMA_BACKWARD_SIZE_MIN;
442 // Backward Sizes need to be valid
443 first.backward_size = LZMA_VLI_MAX + 4;
444 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
445 LZMA_PROG_ERROR);
446 second.backward_size = LZMA_VLI_MAX + 4;
447 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
448 LZMA_PROG_ERROR);
449 first.backward_size = LZMA_BACKWARD_SIZE_MIN;
450 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
451 LZMA_PROG_ERROR);
452 second.backward_size = LZMA_BACKWARD_SIZE_MIN;
454 // Backward Sizes must be equal
455 second.backward_size = first.backward_size + 4;
456 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
457 LZMA_DATA_ERROR);
459 // Should fail if Backward Sizes are > LZMA_BACKWARD_SIZE_MAX
460 // even though they are equal
461 first.backward_size = LZMA_BACKWARD_SIZE_MAX + 1;
462 second.backward_size = LZMA_BACKWARD_SIZE_MAX + 1;
463 assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
464 LZMA_PROG_ERROR);
468 extern int
469 main(int argc, char **argv)
471 tuktest_start(argc, argv);
472 tuktest_run(test_lzma_stream_header_encode);
473 tuktest_run(test_lzma_stream_footer_encode);
474 tuktest_run(test_lzma_stream_header_decode);
475 tuktest_run(test_lzma_stream_footer_decode);
476 tuktest_run(test_lzma_stream_flags_compare);
477 return tuktest_end();