1 ///////////////////////////////////////////////////////////////////////////////
3 /// \file test_stream_flags.c
4 /// \brief Tests Stream Header and Stream Footer coders
9 // This file has been put into the public domain.
10 // You can do whatever you want with this file.
12 ///////////////////////////////////////////////////////////////////////////////
17 // Size of the Stream Flags field
18 // (taken from src/liblzma/common/stream_flags_common.h)
19 #define XZ_STREAM_FLAGS_SIZE 2
22 // Header and footer magic bytes for .xz file format
23 // (taken from src/liblzma/common/stream_flags_common.c)
24 static const uint8_t xz_header_magic
[6]
25 = { 0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00 };
26 static const uint8_t xz_footer_magic
[2] = { 0x59, 0x5A };
32 stream_header_encode_helper(lzma_check check
)
34 lzma_stream_flags flags
= {
39 uint8_t header
[LZMA_STREAM_HEADER_SIZE
];
41 // Encode Stream Header
42 assert_lzma_ret(lzma_stream_header_encode(&flags
, header
), LZMA_OK
);
44 // Stream Header must start with Header Magic Bytes
45 const uint32_t magic_size
= sizeof(xz_header_magic
);
46 assert_array_eq(header
, xz_header_magic
, magic_size
);
48 // Next must come Stream Flags
49 const uint8_t *encoded_stream_flags
= header
+ magic_size
;
51 // First byte is always null-byte.
52 // Second byte must have the Check ID in the lowest four bits
53 // and the highest four bits zero.
54 const uint8_t expected_stream_flags
[] = { 0, check
};
55 assert_array_eq(encoded_stream_flags
, expected_stream_flags
,
56 XZ_STREAM_FLAGS_SIZE
);
58 // Last part is the CRC32 of the Stream Flags
59 const uint8_t *crc_ptr
= encoded_stream_flags
+ XZ_STREAM_FLAGS_SIZE
;
60 const uint32_t expected_crc
= lzma_crc32(expected_stream_flags
,
61 XZ_STREAM_FLAGS_SIZE
, 0);
62 assert_uint_eq(read32le(crc_ptr
), expected_crc
);
68 test_lzma_stream_header_encode(void)
71 assert_skip("Encoder support disabled");
73 for (lzma_check i
= 0; i
< LZMA_CHECK_ID_MAX
; i
++)
74 stream_header_encode_helper(i
);
76 lzma_stream_flags flags
= {
78 .check
= LZMA_CHECK_CRC32
81 uint8_t header
[LZMA_STREAM_HEADER_SIZE
];
83 // Should fail if version > 0
85 assert_lzma_ret(lzma_stream_header_encode(&flags
, header
),
89 // Should fail if Check ID is invalid
90 flags
.check
= INVALID_LZMA_CHECK_ID
;
91 assert_lzma_ret(lzma_stream_header_encode(&flags
, header
),
93 flags
.check
= LZMA_CHECK_CRC32
;
95 // Should pass even if Backward Size is invalid
96 // because Stream Header doesn't have that field.
97 flags
.backward_size
= LZMA_VLI_MAX
+ 1;
98 assert_lzma_ret(lzma_stream_header_encode(&flags
, header
), LZMA_OK
);
103 #if defined(HAVE_ENCODERS)
105 stream_footer_encode_helper(lzma_check check
)
107 lzma_stream_flags flags
= {
110 .backward_size
= LZMA_BACKWARD_SIZE_MIN
,
113 uint8_t footer
[LZMA_STREAM_HEADER_SIZE
];
115 // Encode Stream Footer
116 assert_lzma_ret(lzma_stream_footer_encode(&flags
, footer
), LZMA_OK
);
118 // Stream Footer must start with CRC32
119 const uint32_t crc
= read32le(footer
);
120 const uint32_t expected_crc
= lzma_crc32(footer
+ sizeof(uint32_t),
121 LZMA_STREAM_HEADER_SIZE
- (sizeof(uint32_t) +
122 sizeof(xz_footer_magic
)), 0);
123 assert_uint_eq(crc
, expected_crc
);
125 // Next the Backward Size
126 const uint32_t backwards_size
= read32le(footer
+ sizeof(uint32_t));
127 const uint32_t expected_backwards_size
= flags
.backward_size
/ 4 - 1;
128 assert_uint_eq(backwards_size
, expected_backwards_size
);
130 // Next the Stream Flags
131 const uint8_t *stream_flags
= footer
+ sizeof(uint32_t) * 2;
133 // First byte must be null
134 assert_uint_eq(stream_flags
[0], 0);
136 // Second byte must have the Check ID in the lowest four bits
137 // and the highest four bits zero.
138 assert_uint_eq(stream_flags
[1], check
);
140 // And ends with Footer Magic Bytes
141 const uint8_t *expected_footer_magic
= stream_flags
+
142 XZ_STREAM_FLAGS_SIZE
;
143 assert_array_eq(expected_footer_magic
, xz_footer_magic
,
144 sizeof(xz_footer_magic
));
150 test_lzma_stream_footer_encode(void)
152 #ifndef HAVE_ENCODERS
153 assert_skip("Encoder support disabled");
155 for (lzma_check i
= 0; i
< LZMA_CHECK_ID_MAX
; i
++)
156 stream_footer_encode_helper(i
);
158 lzma_stream_flags flags
= {
160 .backward_size
= LZMA_BACKWARD_SIZE_MIN
,
161 .check
= LZMA_CHECK_CRC32
164 uint8_t footer
[LZMA_STREAM_HEADER_SIZE
];
166 // Should fail if version > 0
168 assert_lzma_ret(lzma_stream_footer_encode(&flags
, footer
),
172 // Should fail if Check ID is invalid
173 flags
.check
= INVALID_LZMA_CHECK_ID
;
174 assert_lzma_ret(lzma_stream_footer_encode(&flags
, footer
),
177 // Should fail if Backward Size is invalid
178 flags
.backward_size
-= 1;
179 assert_lzma_ret(lzma_stream_footer_encode(&flags
, footer
),
181 flags
.backward_size
+= 2;
182 assert_lzma_ret(lzma_stream_footer_encode(&flags
, footer
),
184 flags
.backward_size
= LZMA_BACKWARD_SIZE_MAX
+ 4;
185 assert_lzma_ret(lzma_stream_footer_encode(&flags
, footer
),
191 #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
193 stream_header_decode_helper(lzma_check check
)
195 lzma_stream_flags flags
= {
200 uint8_t header
[LZMA_STREAM_HEADER_SIZE
];
202 assert_lzma_ret(lzma_stream_header_encode(&flags
, header
), LZMA_OK
);
204 lzma_stream_flags dest_flags
;
205 assert_lzma_ret(lzma_stream_header_decode(&dest_flags
, header
),
208 // Version should be 0
209 assert_uint_eq(dest_flags
.version
, 0);
211 // Backward Size should be LZMA_VLI_UNKNOWN
212 assert_uint_eq(dest_flags
.backward_size
, LZMA_VLI_UNKNOWN
);
214 // Check ID must equal the argument given to this function.
215 assert_uint_eq(dest_flags
.check
, check
);
221 test_lzma_stream_header_decode(void)
223 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
224 assert_skip("Encoder or decoder support disabled");
226 for (lzma_check i
= 0; i
< LZMA_CHECK_ID_MAX
; i
++)
227 stream_header_decode_helper(i
);
229 lzma_stream_flags flags
= {
231 .check
= LZMA_CHECK_CRC32
234 uint8_t header
[LZMA_STREAM_HEADER_SIZE
];
235 lzma_stream_flags dest
;
237 // First encode known flags to header buffer
238 assert_lzma_ret(lzma_stream_header_encode(&flags
, header
), LZMA_OK
);
240 // Should fail if magic bytes do not match
242 assert_lzma_ret(lzma_stream_header_decode(&dest
, header
),
246 // Should fail if a reserved bit is set
247 uint8_t *stream_flags
= header
+ sizeof(xz_header_magic
);
250 // Need to adjust CRC32 after making a change since the CRC32
251 // is verified before decoding the Stream Flags field.
252 uint8_t *crc32_ptr
= header
+ sizeof(xz_header_magic
)
253 + XZ_STREAM_FLAGS_SIZE
;
254 const uint32_t crc_orig
= read32le(crc32_ptr
);
255 uint32_t new_crc32
= lzma_crc32(
256 stream_flags
, XZ_STREAM_FLAGS_SIZE
, 0);
257 write32le(crc32_ptr
, new_crc32
);
258 assert_lzma_ret(lzma_stream_header_decode(&dest
, header
),
261 write32le(crc32_ptr
, crc_orig
);
263 // Should fail if upper bits of check ID are set
264 stream_flags
[1] |= 0xF0;
265 new_crc32
= lzma_crc32(stream_flags
, XZ_STREAM_FLAGS_SIZE
, 0);
266 write32le(crc32_ptr
, new_crc32
);
267 assert_lzma_ret(lzma_stream_header_decode(&dest
, header
),
269 stream_flags
[1] = flags
.check
;
270 write32le(crc32_ptr
, crc_orig
);
272 // Should fail if CRC32 does not match.
273 // First, alter a byte in the Stream Flags.
275 assert_lzma_ret(lzma_stream_header_decode(&dest
, header
),
279 // Next, change the CRC32.
281 assert_lzma_ret(lzma_stream_header_decode(&dest
, header
),
287 #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
289 stream_footer_decode_helper(lzma_check check
)
291 lzma_stream_flags flags
= {
293 .backward_size
= LZMA_BACKWARD_SIZE_MIN
,
297 uint8_t footer
[LZMA_STREAM_HEADER_SIZE
];
298 assert_lzma_ret(lzma_stream_footer_encode(&flags
, footer
), LZMA_OK
);
300 lzma_stream_flags dest_flags
;
301 assert_lzma_ret(lzma_stream_footer_decode(&dest_flags
, footer
),
304 // Version should be 0.
305 assert_uint_eq(dest_flags
.version
, 0);
307 // Backward Size should equal the value from the flags.
308 assert_uint_eq(dest_flags
.backward_size
, flags
.backward_size
);
310 // Check ID must equal argument given to this function.
311 assert_uint_eq(dest_flags
.check
, check
);
317 test_lzma_stream_footer_decode(void)
319 #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
320 assert_skip("Encoder or decoder support disabled");
322 for (lzma_check i
= 0; i
< LZMA_CHECK_ID_MAX
; i
++)
323 stream_footer_decode_helper(i
);
325 lzma_stream_flags flags
= {
327 .check
= LZMA_CHECK_CRC32
,
328 .backward_size
= LZMA_BACKWARD_SIZE_MIN
331 uint8_t footer
[LZMA_STREAM_HEADER_SIZE
];
332 lzma_stream_flags dest
;
334 // First encode known flags to the footer buffer
335 assert_lzma_ret(lzma_stream_footer_encode(&flags
, footer
), LZMA_OK
);
337 // Should fail if magic bytes do not match
338 footer
[LZMA_STREAM_HEADER_SIZE
- 1] ^= 1;
339 assert_lzma_ret(lzma_stream_footer_decode(&dest
, footer
),
341 footer
[LZMA_STREAM_HEADER_SIZE
- 1] ^= 1;
343 // Should fail if a reserved bit is set.
344 // In the Stream Footer, the Stream Flags follow the CRC32 (4 bytes)
345 // and the Backward Size (4 bytes)
346 uint8_t *stream_flags
= footer
+ sizeof(uint32_t) * 2;
349 // Need to adjust the CRC32 so it will not fail that check instead
350 uint8_t *crc32_ptr
= footer
;
351 const uint32_t crc_orig
= read32le(crc32_ptr
);
352 uint8_t *backward_size
= footer
+ sizeof(uint32_t);
353 uint32_t new_crc32
= lzma_crc32(backward_size
, sizeof(uint32_t) +
354 XZ_STREAM_FLAGS_SIZE
, 0);
355 write32le(crc32_ptr
, new_crc32
);
356 assert_lzma_ret(lzma_stream_footer_decode(&dest
, footer
),
359 write32le(crc32_ptr
, crc_orig
);
361 // Should fail if upper bits of check ID are set
362 stream_flags
[1] |= 0xF0;
363 new_crc32
= lzma_crc32(backward_size
, sizeof(uint32_t) +
364 XZ_STREAM_FLAGS_SIZE
, 0);
365 write32le(crc32_ptr
, new_crc32
);
366 assert_lzma_ret(lzma_stream_footer_decode(&dest
, footer
),
368 stream_flags
[1] = flags
.check
;
369 write32le(crc32_ptr
, crc_orig
);
371 // Should fail if CRC32 does not match.
372 // First, alter a byte in the Stream Flags.
374 assert_lzma_ret(lzma_stream_footer_decode(&dest
, footer
),
378 // Next, change the CRC32
380 assert_lzma_ret(lzma_stream_footer_decode(&dest
, footer
),
387 test_lzma_stream_flags_compare(void)
389 lzma_stream_flags first
= {
391 .backward_size
= LZMA_BACKWARD_SIZE_MIN
,
392 .check
= LZMA_CHECK_CRC32
,
395 lzma_stream_flags second
= first
;
397 // First test should pass
398 assert_lzma_ret(lzma_stream_flags_compare(&first
, &second
), LZMA_OK
);
400 // Altering either version should cause an error
402 assert_lzma_ret(lzma_stream_flags_compare(&first
, &second
),
405 assert_lzma_ret(lzma_stream_flags_compare(&first
, &second
),
408 assert_lzma_ret(lzma_stream_flags_compare(&first
, &second
),
412 // Check types must be under the maximum
413 first
.check
= INVALID_LZMA_CHECK_ID
;
414 assert_lzma_ret(lzma_stream_flags_compare(&first
, &second
),
416 second
.check
= INVALID_LZMA_CHECK_ID
;
417 assert_lzma_ret(lzma_stream_flags_compare(&first
, &second
),
419 first
.check
= LZMA_CHECK_CRC32
;
420 assert_lzma_ret(lzma_stream_flags_compare(&first
, &second
),
422 second
.check
= LZMA_CHECK_CRC32
;
424 // Check types must be equal
425 for (lzma_check i
= 0; i
< LZMA_CHECK_ID_MAX
; i
++) {
427 if (i
== second
.check
)
428 assert_lzma_ret(lzma_stream_flags_compare(&first
,
431 assert_lzma_ret(lzma_stream_flags_compare(&first
,
432 &second
), LZMA_DATA_ERROR
);
434 first
.check
= LZMA_CHECK_CRC32
;
436 // Backward Size comparison is skipped if either are LZMA_VLI_UNKNOWN
437 first
.backward_size
= LZMA_VLI_UNKNOWN
;
438 assert_lzma_ret(lzma_stream_flags_compare(&first
, &second
), LZMA_OK
);
439 second
.backward_size
= LZMA_VLI_MAX
+ 1;
440 assert_lzma_ret(lzma_stream_flags_compare(&first
, &second
), LZMA_OK
);
441 second
.backward_size
= LZMA_BACKWARD_SIZE_MIN
;
443 // Backward Sizes need to be valid
444 first
.backward_size
= LZMA_VLI_MAX
+ 4;
445 assert_lzma_ret(lzma_stream_flags_compare(&first
, &second
),
447 second
.backward_size
= LZMA_VLI_MAX
+ 4;
448 assert_lzma_ret(lzma_stream_flags_compare(&first
, &second
),
450 first
.backward_size
= LZMA_BACKWARD_SIZE_MIN
;
451 assert_lzma_ret(lzma_stream_flags_compare(&first
, &second
),
453 second
.backward_size
= LZMA_BACKWARD_SIZE_MIN
;
455 // Backward Sizes must be equal
456 second
.backward_size
= first
.backward_size
+ 4;
457 assert_lzma_ret(lzma_stream_flags_compare(&first
, &second
),
460 // Should fail if Backward Sizes are > LZMA_BACKWARD_SIZE_MAX
461 // even though they are equal
462 first
.backward_size
= LZMA_BACKWARD_SIZE_MAX
+ 1;
463 second
.backward_size
= LZMA_BACKWARD_SIZE_MAX
+ 1;
464 assert_lzma_ret(lzma_stream_flags_compare(&first
, &second
),
470 main(int argc
, char **argv
)
472 tuktest_start(argc
, argv
);
473 tuktest_run(test_lzma_stream_header_encode
);
474 tuktest_run(test_lzma_stream_footer_encode
);
475 tuktest_run(test_lzma_stream_header_decode
);
476 tuktest_run(test_lzma_stream_footer_decode
);
477 tuktest_run(test_lzma_stream_flags_compare
);
478 return tuktest_end();