(root)/
xz-5.4.5/
tests/
test_stream_flags.c
       1  ///////////////////////////////////////////////////////////////////////////////
       2  //
       3  /// \file       test_stream_flags.c
       4  /// \brief      Tests Stream Header and Stream Footer coders
       5  //
       6  //  Authors:    Jia Tan
       7  //              Lasse Collin
       8  //
       9  //  This file has been put into the public domain.
      10  //  You can do whatever you want with this file.
      11  //
      12  ///////////////////////////////////////////////////////////////////////////////
      13  
      14  #include "tests.h"
      15  
      16  
      17  // Size of the Stream Flags field
      18  // (taken from src/liblzma/common/stream_flags_common.h)
      19  #define XZ_STREAM_FLAGS_SIZE 2
      20  
      21  #ifdef HAVE_ENCODERS
      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 };
      27  #endif
      28  
      29  
      30  #ifdef HAVE_ENCODERS
      31  static void
      32  stream_header_encode_helper(lzma_check check)
      33  {
      34  	lzma_stream_flags flags = {
      35  		.version = 0,
      36  		.check = check,
      37  	};
      38  
      39  	uint8_t header[LZMA_STREAM_HEADER_SIZE];
      40  
      41  	// Encode Stream Header
      42  	assert_lzma_ret(lzma_stream_header_encode(&flags, header), LZMA_OK);
      43  
      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);
      47  
      48  	// Next must come Stream Flags
      49  	const uint8_t *encoded_stream_flags = header + magic_size;
      50  
      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);
      57  
      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);
      63  }
      64  #endif
      65  
      66  
      67  static void
      68  test_lzma_stream_header_encode(void)
      69  {
      70  #ifndef HAVE_ENCODERS
      71  	assert_skip("Encoder support disabled");
      72  #else
      73  	for (lzma_check i = 0; i < LZMA_CHECK_ID_MAX; i++)
      74  		stream_header_encode_helper(i);
      75  
      76  	lzma_stream_flags flags = {
      77  		.version = 0,
      78  		.check = LZMA_CHECK_CRC32
      79  	};
      80  
      81  	uint8_t header[LZMA_STREAM_HEADER_SIZE];
      82  
      83  	// Should fail if version > 0
      84  	flags.version = 1;
      85  	assert_lzma_ret(lzma_stream_header_encode(&flags, header),
      86  			LZMA_OPTIONS_ERROR);
      87  	flags.version = 0;
      88  
      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),
      92  			LZMA_PROG_ERROR);
      93  	flags.check = LZMA_CHECK_CRC32;
      94  
      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);
      99  #endif
     100  }
     101  
     102  
     103  #if defined(HAVE_ENCODERS)
     104  static void
     105  stream_footer_encode_helper(lzma_check check)
     106  {
     107  	lzma_stream_flags flags = {
     108  		.version = 0,
     109  		.check = check,
     110  		.backward_size = LZMA_BACKWARD_SIZE_MIN,
     111  	};
     112  
     113  	uint8_t footer[LZMA_STREAM_HEADER_SIZE];
     114  
     115  	// Encode Stream Footer
     116  	assert_lzma_ret(lzma_stream_footer_encode(&flags, footer), LZMA_OK);
     117  
     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);
     124  
     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);
     129  
     130  	// Next the Stream Flags
     131  	const uint8_t *stream_flags = footer + sizeof(uint32_t) * 2;
     132  
     133  	// First byte must be null
     134  	assert_uint_eq(stream_flags[0], 0);
     135  
     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);
     139  
     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));
     145  }
     146  #endif
     147  
     148  
     149  static void
     150  test_lzma_stream_footer_encode(void)
     151  {
     152  #ifndef HAVE_ENCODERS
     153  	assert_skip("Encoder support disabled");
     154  #else
     155  	for (lzma_check i = 0; i < LZMA_CHECK_ID_MAX; i++)
     156  		stream_footer_encode_helper(i);
     157  
     158  	lzma_stream_flags flags = {
     159  		.version = 0,
     160  		.backward_size = LZMA_BACKWARD_SIZE_MIN,
     161  		.check = LZMA_CHECK_CRC32
     162  	};
     163  
     164  	uint8_t footer[LZMA_STREAM_HEADER_SIZE];
     165  
     166  	// Should fail if version > 0
     167  	flags.version = 1;
     168  	assert_lzma_ret(lzma_stream_footer_encode(&flags, footer),
     169  			LZMA_OPTIONS_ERROR);
     170  	flags.version = 0;
     171  
     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),
     175  			LZMA_PROG_ERROR);
     176  
     177  	// Should fail if Backward Size is invalid
     178  	flags.backward_size -= 1;
     179  	assert_lzma_ret(lzma_stream_footer_encode(&flags, footer),
     180  			LZMA_PROG_ERROR);
     181  	flags.backward_size += 2;
     182  	assert_lzma_ret(lzma_stream_footer_encode(&flags, footer),
     183  			LZMA_PROG_ERROR);
     184  	flags.backward_size = LZMA_BACKWARD_SIZE_MAX + 4;
     185  	assert_lzma_ret(lzma_stream_footer_encode(&flags, footer),
     186  			LZMA_PROG_ERROR);
     187  #endif
     188  }
     189  
     190  
     191  #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
     192  static void
     193  stream_header_decode_helper(lzma_check check)
     194  {
     195  	lzma_stream_flags flags = {
     196  		.version = 0,
     197  		.check = check
     198  	};
     199  
     200  	uint8_t header[LZMA_STREAM_HEADER_SIZE];
     201  
     202  	assert_lzma_ret(lzma_stream_header_encode(&flags, header), LZMA_OK);
     203  
     204  	lzma_stream_flags dest_flags;
     205  	assert_lzma_ret(lzma_stream_header_decode(&dest_flags, header),
     206  			LZMA_OK);
     207  
     208  	// Version should be 0
     209  	assert_uint_eq(dest_flags.version, 0);
     210  
     211  	// Backward Size should be LZMA_VLI_UNKNOWN
     212  	assert_uint_eq(dest_flags.backward_size, LZMA_VLI_UNKNOWN);
     213  
     214  	// Check ID must equal the argument given to this function.
     215  	assert_uint_eq(dest_flags.check, check);
     216  }
     217  #endif
     218  
     219  
     220  static void
     221  test_lzma_stream_header_decode(void)
     222  {
     223  #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
     224  	assert_skip("Encoder or decoder support disabled");
     225  #else
     226  	for (lzma_check i = 0; i < LZMA_CHECK_ID_MAX; i++)
     227  		stream_header_decode_helper(i);
     228  
     229  	lzma_stream_flags flags = {
     230  		.version = 0,
     231  		.check = LZMA_CHECK_CRC32
     232  	};
     233  
     234  	uint8_t header[LZMA_STREAM_HEADER_SIZE];
     235  	lzma_stream_flags dest;
     236  
     237  	// First encode known flags to header buffer
     238  	assert_lzma_ret(lzma_stream_header_encode(&flags, header), LZMA_OK);
     239  
     240  	// Should fail if magic bytes do not match
     241  	header[0] ^= 1;
     242  	assert_lzma_ret(lzma_stream_header_decode(&dest, header),
     243  			LZMA_FORMAT_ERROR);
     244  	header[0] ^= 1;
     245  
     246  	// Should fail if a reserved bit is set
     247  	uint8_t *stream_flags = header + sizeof(xz_header_magic);
     248  	stream_flags[0] = 1;
     249  
     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),
     259  			LZMA_OPTIONS_ERROR);
     260  	stream_flags[0] = 0;
     261  	write32le(crc32_ptr, crc_orig);
     262  
     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),
     268  			LZMA_OPTIONS_ERROR);
     269  	stream_flags[1] = flags.check;
     270  	write32le(crc32_ptr, crc_orig);
     271  
     272  	// Should fail if CRC32 does not match.
     273  	// First, alter a byte in the Stream Flags.
     274  	stream_flags[0] = 1;
     275  	assert_lzma_ret(lzma_stream_header_decode(&dest, header),
     276  			LZMA_DATA_ERROR);
     277  	stream_flags[0] = 0;
     278  
     279  	// Next, change the CRC32.
     280  	*crc32_ptr ^= 1;
     281  	assert_lzma_ret(lzma_stream_header_decode(&dest, header),
     282  			LZMA_DATA_ERROR);
     283  #endif
     284  }
     285  
     286  
     287  #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
     288  static void
     289  stream_footer_decode_helper(lzma_check check)
     290  {
     291  	lzma_stream_flags flags = {
     292  		.version = 0,
     293  		.backward_size = LZMA_BACKWARD_SIZE_MIN,
     294  		.check = check,
     295  	};
     296  
     297  	uint8_t footer[LZMA_STREAM_HEADER_SIZE];
     298  	assert_lzma_ret(lzma_stream_footer_encode(&flags, footer), LZMA_OK);
     299  
     300  	lzma_stream_flags dest_flags;
     301  	assert_lzma_ret(lzma_stream_footer_decode(&dest_flags, footer),
     302  			LZMA_OK);
     303  
     304  	// Version should be 0.
     305  	assert_uint_eq(dest_flags.version, 0);
     306  
     307  	// Backward Size should equal the value from the flags.
     308  	assert_uint_eq(dest_flags.backward_size, flags.backward_size);
     309  
     310  	// Check ID must equal argument given to this function.
     311  	assert_uint_eq(dest_flags.check, check);
     312  }
     313  #endif
     314  
     315  
     316  static void
     317  test_lzma_stream_footer_decode(void)
     318  {
     319  #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
     320  	assert_skip("Encoder or decoder support disabled");
     321  #else
     322  	for (lzma_check i = 0; i < LZMA_CHECK_ID_MAX; i++)
     323  		stream_footer_decode_helper(i);
     324  
     325  	lzma_stream_flags flags = {
     326  		.version = 0,
     327  		.check = LZMA_CHECK_CRC32,
     328  		.backward_size = LZMA_BACKWARD_SIZE_MIN
     329  	};
     330  
     331  	uint8_t footer[LZMA_STREAM_HEADER_SIZE];
     332  	lzma_stream_flags dest;
     333  
     334  	// First encode known flags to the footer buffer
     335  	assert_lzma_ret(lzma_stream_footer_encode(&flags, footer), LZMA_OK);
     336  
     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),
     340  			LZMA_FORMAT_ERROR);
     341  	footer[LZMA_STREAM_HEADER_SIZE - 1] ^= 1;
     342  
     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;
     347  	stream_flags[0] = 1;
     348  
     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),
     357  			LZMA_OPTIONS_ERROR);
     358  	stream_flags[0] = 0;
     359  	write32le(crc32_ptr, crc_orig);
     360  
     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),
     367  			LZMA_OPTIONS_ERROR);
     368  	stream_flags[1] = flags.check;
     369  	write32le(crc32_ptr, crc_orig);
     370  
     371  	// Should fail if CRC32 does not match.
     372  	// First, alter a byte in the Stream Flags.
     373  	stream_flags[0] = 1;
     374  	assert_lzma_ret(lzma_stream_footer_decode(&dest, footer),
     375  			LZMA_DATA_ERROR);
     376  	stream_flags[0] = 0;
     377  
     378  	// Next, change the CRC32
     379  	*crc32_ptr ^= 1;
     380  	assert_lzma_ret(lzma_stream_footer_decode(&dest, footer),
     381  			LZMA_DATA_ERROR);
     382  #endif
     383  }
     384  
     385  
     386  static void
     387  test_lzma_stream_flags_compare(void)
     388  {
     389  	lzma_stream_flags first = {
     390  		.version = 0,
     391  		.backward_size = LZMA_BACKWARD_SIZE_MIN,
     392  		.check = LZMA_CHECK_CRC32,
     393  	};
     394  
     395  	lzma_stream_flags second = first;
     396  
     397  	// First test should pass
     398  	assert_lzma_ret(lzma_stream_flags_compare(&first, &second), LZMA_OK);
     399  
     400  	// Altering either version should cause an error
     401  	first.version = 1;
     402  	assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
     403  			LZMA_OPTIONS_ERROR);
     404  	second.version = 1;
     405  	assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
     406  			LZMA_OPTIONS_ERROR);
     407  	first.version = 0;
     408  	assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
     409  			LZMA_OPTIONS_ERROR);
     410  	second.version = 0;
     411  
     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),
     415  			LZMA_PROG_ERROR);
     416  	second.check = INVALID_LZMA_CHECK_ID;
     417  	assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
     418  			LZMA_PROG_ERROR);
     419  	first.check = LZMA_CHECK_CRC32;
     420  	assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
     421  			LZMA_PROG_ERROR);
     422  	second.check = LZMA_CHECK_CRC32;
     423  
     424  	// Check types must be equal
     425  	for (lzma_check i = 0; i < LZMA_CHECK_ID_MAX; i++) {
     426  		first.check = i;
     427  		if (i == second.check)
     428  			assert_lzma_ret(lzma_stream_flags_compare(&first,
     429  					&second), LZMA_OK);
     430  		else
     431  			assert_lzma_ret(lzma_stream_flags_compare(&first,
     432  					&second), LZMA_DATA_ERROR);
     433  	}
     434  	first.check = LZMA_CHECK_CRC32;
     435  
     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;
     442  
     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),
     446  			LZMA_PROG_ERROR);
     447  	second.backward_size = LZMA_VLI_MAX + 4;
     448  	assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
     449  			LZMA_PROG_ERROR);
     450  	first.backward_size = LZMA_BACKWARD_SIZE_MIN;
     451  	assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
     452  			LZMA_PROG_ERROR);
     453  	second.backward_size = LZMA_BACKWARD_SIZE_MIN;
     454  
     455  	// Backward Sizes must be equal
     456  	second.backward_size = first.backward_size + 4;
     457  	assert_lzma_ret(lzma_stream_flags_compare(&first, &second),
     458  			LZMA_DATA_ERROR);
     459  
     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),
     465  			LZMA_PROG_ERROR);
     466  }
     467  
     468  
     469  extern int
     470  main(int argc, char **argv)
     471  {
     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();
     479  }