diff --git a/tests/Makefile.am b/tests/Makefile.am index ebf2df92..e612aa68 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -45,6 +45,7 @@ check_PROGRAMS = \ test_block_header \ test_index \ test_bcj_exact_size \ + test_memlimit \ test_vli TESTS = \ @@ -55,6 +56,7 @@ TESTS = \ test_block_header \ test_index \ test_bcj_exact_size \ + test_memlimit \ test_vli \ test_files.sh \ test_compress_prepared_bcj_sparc \ diff --git a/tests/test_memlimit.c b/tests/test_memlimit.c new file mode 100644 index 00000000..24b7f6e1 --- /dev/null +++ b/tests/test_memlimit.c @@ -0,0 +1,151 @@ +/////////////////////////////////////////////////////////////////////////////// +// +/// \file test_memlimit.c +/// \brief Tests memory usage limit in decoders +// +// Author: Lasse Collin +// +// This file has been put into the public domain. +// You can do whatever you want with this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tests.h" + + +#define MEMLIMIT_TOO_LOW 1234U +#define MEMLIMIT_HIGH_ENOUGH (2U << 20) + + +static uint8_t *in; +static size_t in_size; +static uint8_t out[8192]; + + +static void +test_memlimit_stream_decoder(void) +{ + lzma_stream strm = LZMA_STREAM_INIT; + assert_lzma_ret(lzma_stream_decoder(&strm, MEMLIMIT_TOO_LOW, 0), + LZMA_OK); + + strm.next_in = in; + strm.avail_in = in_size; + strm.next_out = out; + strm.avail_out = sizeof(out); + + assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_MEMLIMIT_ERROR); + + assert_uint_eq(lzma_memlimit_get(&strm), MEMLIMIT_TOO_LOW); + assert_lzma_ret(lzma_memlimit_set(&strm, MEMLIMIT_TOO_LOW + 1), + LZMA_MEMLIMIT_ERROR); + assert_lzma_ret(lzma_memlimit_set(&strm, MEMLIMIT_HIGH_ENOUGH), + LZMA_OK); + + // This fails before commit 660739f99ab211edec4071de98889fb32ed04e98 + // (liblzma <= 5.2.6, liblzma <= 5.3.3alpha). It was fixed in 5.2.7. + assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_STREAM_END); + + lzma_end(&strm); +} + + +static void +test_memlimit_stream_decoder_mt(void) +{ + lzma_stream strm = LZMA_STREAM_INIT; + lzma_mt mt = { + .flags = 0, + .threads = 1, + .timeout = 0, + .memlimit_threading = 0, + .memlimit_stop = MEMLIMIT_TOO_LOW, + }; + + assert_lzma_ret(lzma_stream_decoder_mt(&strm, &mt), LZMA_OK); + + strm.next_in = in; + strm.avail_in = in_size; + strm.next_out = out; + strm.avail_out = sizeof(out); + + assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_MEMLIMIT_ERROR); + + assert_uint_eq(lzma_memlimit_get(&strm), MEMLIMIT_TOO_LOW); + assert_lzma_ret(lzma_memlimit_set(&strm, MEMLIMIT_TOO_LOW + 1), + LZMA_MEMLIMIT_ERROR); + assert_lzma_ret(lzma_memlimit_set(&strm, MEMLIMIT_HIGH_ENOUGH), + LZMA_OK); + + assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_STREAM_END); + lzma_end(&strm); +} + + +static void +test_memlimit_alone_decoder(void) +{ + size_t alone_size; + uint8_t *alone_buf = tuktest_file_from_srcdir( + "files/good-unknown_size-with_eopm.lzma", &alone_size); + + lzma_stream strm = LZMA_STREAM_INIT; + assert_lzma_ret(lzma_alone_decoder(&strm, MEMLIMIT_TOO_LOW), LZMA_OK); + + strm.next_in = alone_buf; + strm.avail_in = alone_size; + strm.next_out = out; + strm.avail_out = sizeof(out); + + assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_MEMLIMIT_ERROR); + + assert_uint_eq(lzma_memlimit_get(&strm), MEMLIMIT_TOO_LOW); + assert_lzma_ret(lzma_memlimit_set(&strm, MEMLIMIT_TOO_LOW + 1), + LZMA_MEMLIMIT_ERROR); + assert_lzma_ret(lzma_memlimit_set(&strm, MEMLIMIT_HIGH_ENOUGH), + LZMA_OK); + + assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_STREAM_END); + lzma_end(&strm); +} + + +static void +test_memlimit_auto_decoder(void) +{ + lzma_stream strm = LZMA_STREAM_INIT; + assert_lzma_ret(lzma_auto_decoder(&strm, MEMLIMIT_TOO_LOW, 0), + LZMA_OK); + + strm.next_in = in; + strm.avail_in = in_size; + strm.next_out = out; + strm.avail_out = sizeof(out); + + assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_MEMLIMIT_ERROR); + + assert_uint_eq(lzma_memlimit_get(&strm), MEMLIMIT_TOO_LOW); + assert_lzma_ret(lzma_memlimit_set(&strm, MEMLIMIT_TOO_LOW + 1), + LZMA_MEMLIMIT_ERROR); + assert_lzma_ret(lzma_memlimit_set(&strm, MEMLIMIT_HIGH_ENOUGH), + LZMA_OK); + + assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_STREAM_END); + lzma_end(&strm); +} + + +extern int +main(int argc, char **argv) +{ + tuktest_start(argc, argv); + + in = tuktest_file_from_srcdir("files/good-1-check-crc32.xz", &in_size); + + tuktest_run(test_memlimit_stream_decoder); + tuktest_run(test_memlimit_stream_decoder_mt); + tuktest_run(test_memlimit_alone_decoder); + tuktest_run(test_memlimit_auto_decoder); + + return tuktest_end(); +}