(root)/
xz-5.4.5/
tests/
test_bcj_exact_size.c
       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  static void
      19  test_exact_size(void)
      20  {
      21  #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
      22  	assert_skip("Encoder or decoder support disabled");
      23  #else
      24  	if (!lzma_filter_encoder_is_supported(LZMA_FILTER_POWERPC)
      25  			|| !lzma_filter_decoder_is_supported(
      26  				LZMA_FILTER_POWERPC))
      27  		assert_skip("PowerPC BCJ encoder and/or decoder "
      28  				"is disabled");
      29  
      30  	// Something to be compressed
      31  	const uint8_t in[16] = "0123456789ABCDEF";
      32  
      33  	// in[] after compression
      34  	uint8_t compressed[1024];
      35  	size_t compressed_size = 0;
      36  
      37  	// Output buffer for decompressing compressed[]
      38  	uint8_t out[sizeof(in)];
      39  
      40  	// Compress with PowerPC BCJ and LZMA2. PowerPC BCJ is used because
      41  	// it has fixed 4-byte alignment which makes triggering the potential
      42  	// bug easy.
      43  	lzma_options_lzma opt_lzma2;
      44  	assert_false(lzma_lzma_preset(&opt_lzma2, 0));
      45  
      46  	lzma_filter filters[3] = {
      47  		{ .id = LZMA_FILTER_POWERPC, .options = NULL },
      48  		{ .id = LZMA_FILTER_LZMA2, .options = &opt_lzma2 },
      49  		{ .id = LZMA_VLI_UNKNOWN, .options = NULL },
      50  	};
      51  
      52  	assert_lzma_ret(lzma_stream_buffer_encode(
      53  			filters, LZMA_CHECK_CRC32, NULL,
      54  			in, sizeof(in),
      55  			compressed, &compressed_size, sizeof(compressed)),
      56  		LZMA_OK);
      57  
      58  	// Decompress so that we won't give more output space than
      59  	// the Stream will need.
      60  	lzma_stream strm = LZMA_STREAM_INIT;
      61  	assert_lzma_ret(lzma_stream_decoder(&strm, 10 << 20, 0), LZMA_OK);
      62  
      63  	strm.next_in = compressed;
      64  	strm.next_out = out;
      65  
      66  	while (true) {
      67  		if (strm.total_in < compressed_size)
      68  			strm.avail_in = 1;
      69  
      70  		const lzma_ret ret = lzma_code(&strm, LZMA_RUN);
      71  		if (ret == LZMA_STREAM_END) {
      72  			assert_uint_eq(strm.total_in, compressed_size);
      73  			assert_uint_eq(strm.total_out, sizeof(in));
      74  			lzma_end(&strm);
      75  			return;
      76  		}
      77  
      78  		assert_lzma_ret(ret, LZMA_OK);
      79  
      80  		if (strm.total_out < sizeof(in))
      81  			strm.avail_out = 1;
      82  	}
      83  #endif
      84  }
      85  
      86  
      87  static void
      88  test_empty_block(void)
      89  {
      90  #ifndef HAVE_DECODERS
      91  	assert_skip("Decoder support disabled");
      92  #else
      93  	if (!lzma_filter_decoder_is_supported(LZMA_FILTER_POWERPC))
      94  		assert_skip("PowerPC BCJ decoder is disabled");
      95  
      96  	// An empty file with one Block using PowerPC BCJ and LZMA2.
      97  	size_t in_size;
      98  	uint8_t *empty_bcj_lzma2 = tuktest_file_from_srcdir(
      99  			"files/good-1-empty-bcj-lzma2.xz", &in_size);
     100  
     101  	// Decompress without giving any output space.
     102  	uint64_t memlimit = 1 << 20;
     103  	uint8_t out[1];
     104  	size_t in_pos = 0;
     105  	size_t out_pos = 0;
     106  	assert_lzma_ret(lzma_stream_buffer_decode(&memlimit, 0, NULL,
     107  			empty_bcj_lzma2, &in_pos, in_size, out, &out_pos, 0),
     108  		LZMA_OK);
     109  	assert_uint_eq(in_pos, in_size);
     110  	assert_uint_eq(out_pos, 0);
     111  #endif
     112  }
     113  
     114  
     115  extern int
     116  main(int argc, char **argv)
     117  {
     118  	tuktest_start(argc, argv);
     119  
     120  	tuktest_run(test_exact_size);
     121  	tuktest_run(test_empty_block);
     122  
     123  	return tuktest_end();
     124  }