1
0
mirror of https://git.tukaani.org/xz.git synced 2025-12-27 07:48:44 +00:00

Compare commits

...

50 Commits

Author SHA1 Message Date
Lasse Collin
18b845e697 Bump version and soname for 5.4.1. 2023-01-11 18:52:54 +02:00
Jia Tan
4080bbb844 Add NEWS for 5.4.1. 2023-01-11 18:52:23 +02:00
Lasse Collin
674c89fdb8 sysdefs.h: Don't include strings.h anymore.
On some platforms src/xz/suffix.c may need <strings.h> for
strcasecmp() but suffix.c includes the header when it needs it.

Unless there is an old system that otherwise supports enough C99
to build XZ Utils but doesn't have C89/C90-compatible <string.h>,
there should be no need to include <strings.h> in sysdefs.h.
2023-01-11 17:49:59 +02:00
Lasse Collin
2a6b938084 xz: Include <strings.h> in suffix.c if needed for strcasecmp().
SUSv2 and POSIX.1‐2017 declare only a few functions in <strings.h>.
Of these, strcasecmp() is used on some platforms in suffix.c.
Nothing else in the project needs <strings.h> (at least if
building on a modern system).

sysdefs.h currently includes <strings.h> if HAVE_STRINGS_H is
defined and suffix.c relied on this.

Note that dos/config.h doesn't #define HAVE_STRINGS_H even though
DJGPP does have strings.h. It isn't needed with DJGPP as strcasecmp()
is also in <string.h> in DJGPP.
2023-01-11 17:49:59 +02:00
Jia Tan
aea639e81b xz: Fix warning -Wformat-nonliteral on clang in message.c.
clang and gcc differ in how they handle -Wformat-nonliteral. gcc will
allow a non-literal format string as long as the function takes its
format arguments as a va_list.
2023-01-11 17:31:54 +02:00
Jia Tan
e3b42bfcb0 Tests: Fix test_filter_flags copy/paste error. 2023-01-11 17:31:54 +02:00
Jia Tan
21625b7e11 Tests: Fix type-limits warning in test_filter_flags.
This only occurs in test_filter_flags when the BCJ filters are not
configured and built. In this case, ARRAY_SIZE() returns 0 and causes a
type-limits warning with the loop variable since an unsigned number will
always be >= 0.
2023-01-11 17:31:54 +02:00
Lasse Collin
c337983e92 liblzma: CLMUL CRC64: Work around a bug in MSVC, second attempt.
This affects only 32-bit x86 builds. x86-64 is OK as is.

I still cannot easily test this myself. The reporter has tested
this and it passes the tests included in the CMake build and
performance is good: raw CRC64 is 2-3 times faster than the
C version of the slice-by-four method. (Note that liblzma doesn't
include a MSVC-compatible version of the 32-bit x86 assembly code
for the slice-by-four method.)

Thanks to Iouri Kharon for figuring out a fix, testing, and
benchmarking.
2023-01-11 17:31:54 +02:00
Jia Tan
b7fb438ea0 Tests: Fix unused function warning in test_block_header.
One of the global arrays of filters was only used in a test that
required both encoders and decoders to be configured in the build.
2023-01-11 17:31:54 +02:00
Jia Tan
68e9ef036d Tests: Fix unused function warning in test_index_hash.
test_index_hash does not use fill_index_hash() unless both encoders
and decoders are configured in the build.
2023-01-11 17:31:54 +02:00
Lasse Collin
a387707cd8 Windows: Update INSTALL-MSVC.txt to recommend CMake over project files. 2023-01-11 17:30:30 +02:00
Lasse Collin
52902ad695 Revert "liblzma: CLMUL CRC64: Workaround a bug in MSVC (VS2015-2022)."
This reverts commit 36edc65ab4cf10a131f239acbd423b4510ba52d5.

It was reported that it wasn't a good enough fix and MSVC
still produced (different kind of) bad code when building
for 32-bit x86 if optimizations are enabled.

Thanks to Iouri Kharon.
2023-01-10 12:51:19 +02:00
Lasse Collin
e81b9fc48c sysdefs.h: Fix a comment. 2023-01-10 10:26:59 +02:00
Lasse Collin
6e89ab58b0 sysdefs.h: Don't include memory.h anymore even if it were available.
It quite probably was never needed, that is, any system where memory.h
was required likely couldn't compile XZ Utils for other reasons anyway.

XZ Utils 5.2.6 and later source packages were generated using
Autoconf 2.71 which no longer defines HAVE_MEMORY_H. So the code
being removed is no longer used anyway.
2023-01-10 10:26:59 +02:00
Lasse Collin
65c59ad429 CMake/Windows: Add a workaround for windres from GNU binutils.
This is combined from the following commits in the master branch:
443dfebced041adc88f10d824188eeef5b5821a9
6b117d3b1fe91eb26d533ab16a2e552f84148d47
5e34774c31d1b7509b5cb77a3be9973adec59ea0

Thanks to Iouri Kharon for the bug report, the original patch,
and testing.
2023-01-10 08:50:26 +02:00
Lasse Collin
43521e77ac Tests: test_filter_flags: Clean up minor issues.
Here are the list of the most significant issues addressed:
- Avoid using internal common.h header. It's not good to copy the
constants like this but common.h cannot be included for use outside
of liblzma. This is the quickest thing to do that could be fixed later.

- Omit the INIT_FILTER macro. Initialization should be done with just
regular designated initializers.

- Use start_offset = 257 for BCJ tests. It demonstrates that Filter
Flags encoder and decoder don't validate the options thoroughly.
257 is valid only for the x86 filter. This is a bit silly but
not a significant problem in practice because the encoder and
decoder initialization functions will catch bad alignment still.
Perhaps this should be fixed but it's not urgent and doesn't need
to be in 5.4.x.

- Various tweaks to comments such as filter id -> Filter ID
2023-01-09 16:58:27 +02:00
Jia Tan
6b44cead95 Tests: Refactors existing filter flags tests.
Converts the existing filter flags tests into tuktests.
2023-01-09 16:58:27 +02:00
Lasse Collin
1bbefa9659 Tests: tuktest.h: Support tuktest_malloc(0).
It's not needed in XZ Utils at least for now. It's good to support
it still because if such use is needed later, it wouldn't be
caught on GNU/Linux since malloc(0) from glibc returns non-NULL.
2023-01-09 16:58:27 +02:00
Lasse Collin
ce3a3fbc7c CMake: Update cmake_minimum_required from 3.13...3.16 to 3.13...3.25.
The changes listed on cmake-policies(7) for versions 3.17 to 3.25
shouldn't affect this project.
2023-01-09 16:58:27 +02:00
Lasse Collin
99fcd57f2e Update THANKS. 2023-01-09 16:58:27 +02:00
Lasse Collin
c0c13d9d82 Update THANKS. 2023-01-09 16:58:27 +02:00
Lasse Collin
3d45987451 CMake: Fix a copypaste error in xzdec Windows resource file handling.
It was my mistake. Thanks to Iouri Kharon for the bug report.
2023-01-09 16:58:27 +02:00
Lasse Collin
706bce5018 CMake/Windows: Add resource files to xz.exe and xzdec.exe.
The command line tools cannot be built with MSVC for now but
they can be built with MinGW-w64.

Thanks to Iouri Kharon for the bug report and the original patch.
2023-01-09 16:58:27 +02:00
Lasse Collin
e96dee55df liblzma: CLMUL CRC64: Workaround a bug in MSVC (VS2015-2022).
I haven't tested with MSVC myself and there doesn't seem to be
information about the problem online, so I'm relying on the bug report.

Thanks to Iouri Kharon for the bug report and the patch.
2023-01-09 16:58:27 +02:00
Lasse Collin
52bc1ee34d Build: Require that _mm_set_epi64x() is usable to enable CLMUL support.
VS2013 doesn't have _mm_set_epi64x() so this way CLMUL gets
disabled with VS2013.

Thanks to Iouri Kharon for the bug report.
2023-01-09 16:58:27 +02:00
Jia Tan
bad44cfe19 Tests: Creates test_index_hash.c
Tests all API functions exported from index_hash.h. Does not have a
dedicated test for lzma_index_hash_end.

[Minor edits were made by Lasse Collin.]
2023-01-09 16:56:07 +02:00
Jia Tan
692ccdf551 liblzma: Remove common.h include from common/index.h.
common/index.h is needed by liblzma internally and tests. common.h will
include and define many things that are not needed by the tests.

Also, this prevents include order problems because both common.h and
lzma.h define LZMA_API. On most platforms it results only in a warning
but on Windows it would break the build as the definition in common.h
must be used only for building liblzma itself.
2023-01-09 16:37:19 +02:00
Jia Tan
2ac7bafc8f liblzma: Add NULL check to lzma_index_hash_append.
This is for consistency with lzma_index_append.
2023-01-09 16:34:32 +02:00
Jia Tan
db714d30e0 liblzma: Replaced hardcoded 0x0 index indicator byte with macro 2023-01-09 16:34:32 +02:00
Jia Tan
39d2585dcd Style: Change #if !defined() to #ifndef in mythread.h. 2023-01-09 16:33:53 +02:00
Jia Tan
3f0130aa28 Build: Add missing stream_decoder_mt.c to .vcxproj files.
The line in the .vcxproj files for building with was missing in 5.4.0.
Thank to Hajin Jang for reporting the issue.
2023-01-09 16:33:53 +02:00
Lasse Collin
f204d1050a Update THANKS. 2023-01-04 23:17:09 +02:00
Lasse Collin
34a9c2d650 Tests: Adjust style in test_compress.sh. 2023-01-04 23:17:09 +02:00
Jia Tan
761c208d58 Tests: Replace non portable shell parameter expansion
The shell parameter expansion using # and ## is not supported in
Solaris 10 Bourne shell (/bin/sh). Even though this is POSIX, it is not fully
portable, so we should avoid it.
2023-01-05 00:30:22 +08:00
Jia Tan
8a7cbc0745 Translations: Add Korean translation of man pages.
Thanks to Seong-ho Cho
2023-01-05 00:30:14 +08:00
Jia Tan
ca2af49bb8 Translations: Update the Esperanto translation. 2023-01-05 00:30:05 +08:00
Lasse Collin
bfba3394ae Build: Fix config.h comments. 2023-01-05 00:29:52 +08:00
Jia Tan
507648ad11 Build: Only define HAVE_PROGRAM_INVOCATION_NAME if it is set to 1.
HAVE_DECL_PROGRAM_INVOCATION_NAME is renamed to
HAVE_PROGRAM_INVOCATION_NAME. Previously,
HAVE_DECL_PROGRAM_INVOCATION_NAME was always set when
building with autotools. CMake would only set this when it was 1, and the
dos/config.h did not define it. The new macro definition is consistent
across build systems.
2023-01-05 00:29:39 +08:00
Lasse Collin
ab5229d32a Tests: test_check: Test corner cases of CLMUL CRC64. 2023-01-05 00:28:09 +08:00
Lasse Collin
8791826f31 Tests: Clarify a comment in test_lzip_decoder.c. 2023-01-05 00:28:01 +08:00
Jia Tan
c410d812ea xz: Includes <time.h> and <sys/time.h> conditionally in mytime.c.
Previously, mytime.c depended on mythread.h for <time.h> to be included.
2023-01-05 00:27:51 +08:00
Jia Tan
501c6013d4 liblzma: Includes sys/time.h conditionally in mythread
Previously, <sys/time.h> was always included, even if mythread only used
clock_gettime. <time.h> is still needed even if clock_gettime is not used
though because struct timespec is needed for mythread_condtime.
2023-01-05 00:26:45 +08:00
Jia Tan
9e3cb514b5 Build: No longer require HAVE_DECL_CLOCK_MONOTONIC to always be set.
Previously, if threading was enabled HAVE_DECL_CLOCK_MONOTONIC would always
be set to 0 or 1. However, this macro was needed in xz so if xz was not
built with threading and HAVE_DECL_CLOCK_MONOTONIC was not defined but
HAVE_CLOCK_GETTIME was, it caused a warning during build. Now,
HAVE_DECL_CLOCK_MONOTONIC has been renamed to HAVE_CLOCK_MONOTONIC and
will only be set if it is 1.
2023-01-05 00:26:35 +08:00
Jia Tan
6fc3e54679 Translations: Add Ukrainian translations of man pages.
Thanks to Yuri Chornoivan
2022-12-28 01:20:44 +08:00
Jia Tan
e84f2ab7f8 liblzma: Update documentation for lzma_filter_encoder. 2022-12-28 01:20:27 +08:00
Jia Tan
b14b8dbba9 Tests: Adds lzip decoder tests 2022-12-28 01:20:16 +08:00
Jia Cheong Tan
09a114805e Doxygen: Update .gitignore for generating docs for in source build.
In source builds are not recommended, but we should still ignore
the generated artifacts.
2022-12-20 22:23:59 +08:00
Jia Tan
d3e6fe4419 liblzma: Fix lzma_microlzma_encoder() return value.
Using return_if_error on lzma_lzma_lclppb_encode was improper because
return_if_error is expecting an lzma_ret value, but
lzma_lzma_lclppb_encode returns a boolean. This could result in
lzma_microlzma_encoder, which would be misleading for applications.
2022-12-20 22:23:59 +08:00
Lasse Collin
b55a27b46f liblzma: Update authors list in arm64.c. 2022-12-20 22:23:59 +08:00
Jia Tan
2fd28d2b7c CMake: Update .gitignore for CMake artifacts from in source build.
In source builds are not recommended, but we can make it easier
by ignoring the generated artifacts from CMake.
2022-12-16 20:58:55 +08:00
51 changed files with 11234 additions and 577 deletions

27
.gitignore vendored
View File

@ -5,6 +5,7 @@
.deps
.libs
*.a
*.gcda
*.gcno
*.la
@ -36,6 +37,8 @@ build-aux/test-driver
coverage
/doc/html
/src/liblzma/liblzma.pc
/src/lzmainfo/lzmainfo
/src/xz/xz
@ -59,6 +62,8 @@ coverage
/tests/test_filter_flags
/tests/test_hardware
/tests/test_index
/tests/test_index_hash
/test/test_lzip_decoder
/tests/test_memlimit
/tests/test_stream_flags
/tests/test_vli
@ -77,3 +82,25 @@ coverage
/src/liblzma/api/Makefile
/src/lzmainfo/Makefile
/src/xzdec/Makefile
/CMakeCache.txt
/CMakeFiles
/CTestTestfile.cmake
/cmake_install.cmake
/DartConfiguration.tcl
/liblzma-config-version.cmake
/liblzma-config.cmake
/lzcat
/lzcat.1
/lzma
/lzma.1
/Testing
/tests_bin/
/unlzma
/unlzma.1
/unxz
/unxz.1
/xz
/xzcat
/xzcat.1
/xzdec

View File

@ -46,7 +46,7 @@
#
#############################################################################
cmake_minimum_required(VERSION 3.13...3.16 FATAL_ERROR)
cmake_minimum_required(VERSION 3.13...3.25 FATAL_ERROR)
include(CMakePushCheckState)
include(CheckIncludeFile)
@ -75,10 +75,40 @@ project(xz VERSION "${XZ_VERSION}" LANGUAGES C)
# On Apple OSes, don't build executables as bundles:
set(CMAKE_MACOSX_BUNDLE OFF)
# windres from GNU binutils can be tricky with command line arguments
# that contain spaces or other funny characters. Unfortunately we need
# a space in PACKAGE_NAME. Using \x20 to encode the US-ASCII space seems
# to work in both cmd.exe and /bin/sh.
#
# However, even \x20 isn't enough in all situations, resulting in
# "syntax error" from windres. Using --use-temp-file prevents windres
# from using popen() and this seems to fix the problem.
#
# llvm-windres claims to be compatible with GNU windres but with that
# the \x20 results in "XZx20Utils" in the compiled binary. (At the
# same time it works correctly with clang (the C compiler).) The option
# --use-temp-file makes no difference.
#
# CMake 3.25 doesn't have CMAKE_RC_COMPILER_ID so we rely on
# CMAKE_C_COMPILER_ID. If Clang is used together with GNU windres
# then it will fail, but this way the risk of a bad string in
# the binary should be fairly low.
if(WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "GNU")
# Use workarounds with GNU windres. The \x20 in PACKAGE_NAME works
# with gcc too so we don't need to worry how to pass different flags
# to windres and gcc.
string(APPEND CMAKE_RC_FLAGS " --use-temp-file")
set(PACKAGE_NAME "XZ\\x20Utils")
else()
# Elsewhere a space is safe. This also keeps things compatible with
# EBCDIC in case CMake-based build is ever done on such a system.
set(PACKAGE_NAME "XZ Utils")
endif()
# Definitions common to all targets:
add_compile_definitions(
# Package info:
PACKAGE_NAME="XZ Utils"
PACKAGE_NAME="${PACKAGE_NAME}"
PACKAGE_BUGREPORT="xz@tukaani.org"
PACKAGE_URL="https://tukaani.org/xz/"
@ -154,13 +184,11 @@ if(NOT WIN32 AND NOT DEFINED HAVE_CLOCK_GETTIME)
endif()
if(HAVE_CLOCK_GETTIME)
# Check if CLOCK_MONOTONIC is available for clock_gettime().
check_symbol_exists(CLOCK_MONOTONIC time.h HAVE_DECL_CLOCK_MONOTONIC)
check_symbol_exists(CLOCK_MONOTONIC time.h HAVE_CLOCK_MONOTONIC)
# HAVE_DECL_CLOCK_MONOTONIC should always be defined to 0 or 1
# when clock_gettime is available.
add_compile_definitions(
HAVE_CLOCK_GETTIME
HAVE_DECL_CLOCK_MONOTONIC=$<BOOL:"${HAVE_DECL_CLOCK_MONOTONIC}">
HAVE_CLOCK_MONOTONIC
)
endif()
endif()
@ -184,7 +212,7 @@ else()
add_compile_definitions(MYTHREAD_POSIX)
# Check if pthread_condattr_setclock() exists to use CLOCK_MONOTONIC.
if(HAVE_DECL_CLOCK_MONOTONIC)
if(HAVE_CLOCK_MONOTONIC)
list(INSERT CMAKE_REQUIRED_LIBRARIES 0 "${CMAKE_THREAD_LIBS_INIT}")
check_symbol_exists(pthread_condattr_setclock pthread.h
HAVE_PTHREAD_CONDATTR_SETCLOCK)
@ -436,8 +464,9 @@ if(HAVE_IMMINTRIN_H)
#if (defined(__GNUC__) || defined(__clang__)) && !defined(__EDG__)
__attribute__((__target__(\"ssse3,sse4.1,pclmul\")))
#endif
__m128i my_clmul(__m128i a, __m128i b)
__m128i my_clmul(__m128i a)
{
const __m128i b = _mm_set_epi64x(1, 2);
return _mm_clmulepi64_si128(a, b, 0);
}
int main(void) { return 0; }
@ -612,6 +641,14 @@ if(HAVE_GETOPT_LONG)
target_link_libraries(xzdec PRIVATE liblzma)
if(WIN32)
# Add the Windows resource file for xzdec.exe.
target_sources(xzdec PRIVATE src/xzdec/xzdec_w32res.rc)
set_target_properties(xzdec PROPERTIES
LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/common/common_w32res.rc"
)
endif()
tuklib_progname(xzdec)
install(TARGETS xzdec
@ -683,6 +720,14 @@ if(NOT MSVC AND HAVE_GETOPT_LONG)
target_compile_definitions(xz PRIVATE ASSUME_RAM=128)
if(WIN32)
# Add the Windows resource file for xz.exe.
target_sources(xz PRIVATE src/xz/xz_w32res.rc)
set_target_properties(xz PROPERTIES
LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/common/common_w32res.rc"
)
endif()
tuklib_progname(xz)
tuklib_mbstr(xz)
@ -803,6 +848,7 @@ if(BUILD_TESTING)
test_filter_flags
test_hardware
test_index
test_index_hash
test_memlimit
test_stream_flags
test_vli
@ -814,6 +860,7 @@ if(BUILD_TESTING)
target_include_directories("${TEST}" PRIVATE
src/common
src/liblzma/api
src/liblzma
lib
)

70
NEWS
View File

@ -2,6 +2,76 @@
XZ Utils Release Notes
======================
5.4.1 (2023-01-11)
* liblzma:
- Fixed the return value of lzma_microlzma_encoder() if the
LZMA options lc/lp/pb are invalid. Invalid lc/lp/pb options
made the function return LZMA_STREAM_END without encoding
anything instead of returning LZMA_OPTIONS_ERROR.
- Windows / Visual Studio: Workaround a possible compiler bug
when targeting 32-bit x86 and compiling the CLMUL version of
the CRC64 code. The CLMUL code isn't enabled by the Windows
project files but it is in the CMake-based builds.
* Build systems:
- Windows-specific CMake changes:
* Don't try to enable CLMUL CRC64 code if _mm_set_epi64x()
isn't available. This fixes CMake-based build with Visual
Studio 2013.
* Created a workaround for a build failure with windres
from GNU binutils. It is used only when the C compiler
is GCC (not Clang). The workaround is incompatible
with llvm-windres, resulting in "XZx20Utils" instead
of "XZ Utils" in the resource file, but without the
workaround llvm-windres works correctly. See the
comment in CMakeLists.txt for details.
* Included the resource files in the xz and xzdec build
rules. Building the command line tools is still
experimental but possible with MinGW-w64.
- Visual Studio: Added stream_decoder_mt.c to the project
files. Now the threaded decompressor lzma_stream_decoder_mt()
gets built. CMake-based build wasn't affected.
- Updated windows/INSTALL-MSVC.txt to mention that CMake-based
build is now the preferred method with Visual Studio. The
project files will probably be removed after 5.4.x releases.
- Changes to #defines in config.h:
* HAVE_DECL_CLOCK_MONOTONIC was replaced by
HAVE_CLOCK_MONOTONIC. The old macro was always defined
in configure-generated config.h to either 0 or 1. The
new macro is defined (to 1) only if the declaration of
CLOCK_MONOTONIC is available. This matches the way most
other config.h macros work and makes things simpler with
other build systems.
* HAVE_DECL_PROGRAM_INVOCATION_NAME was replaced by
HAVE_PROGRAM_INVOCATION_NAME for the same reason.
* Tests:
- Fixed test script compatibility with ancient /bin/sh
versions. Now the five test_compress_* tests should
no longer fail on Solaris 10.
- Added and refactored a few tests.
* Translations:
- Updated the Catalan and Esperanto translations.
- Added Korean and Ukrainian man page translations.
5.4.0 (2022-12-13)
This bumps the minor version of liblzma because new features were

3
THANKS
View File

@ -30,6 +30,7 @@ has been important. :-) In alphabetical order:
- Vitaly Chikunov
- Antoine Cœur
- Gabi Davar
- İhsan Doğan
- Chris Donawa
- Andrew Dudman
- Markus Duft
@ -56,10 +57,12 @@ has been important. :-) In alphabetical order:
- Peter Ivanov
- Nicholas Jackson
- Sam James
- Hajin Jang
- Jouk Jansen
- Jun I Jin
- Kiyoshi Kanazawa
- Per Øyvind Karlsen
- Iouri Kharon
- Thomas Klausner
- Richard Koch
- Ville Koskinen

View File

@ -13,7 +13,6 @@ include(CheckSymbolExists)
function(tuklib_progname TARGET_OR_ALL)
# NOTE: This glibc extension requires _GNU_SOURCE.
check_symbol_exists(program_invocation_name errno.h
HAVE_DECL_PROGRAM_INVOCATION_NAME)
tuklib_add_definition_if("${TARGET_OR_ALL}"
HAVE_DECL_PROGRAM_INVOCATION_NAME)
HAVE_PROGRAM_INVOCATION_NAME)
tuklib_add_definition_if("${TARGET_OR_ALL}" HAVE_PROGRAM_INVOCATION_NAME)
endfunction()

View File

@ -638,7 +638,10 @@ case $enable_threads in
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
AC_SEARCH_LIBS([clock_gettime], [rt])
AC_CHECK_FUNCS([clock_gettime pthread_condattr_setclock])
AC_CHECK_DECLS([CLOCK_MONOTONIC], [], [], [[#include <time.h>]])
AC_CHECK_DECL([CLOCK_MONOTONIC], [AC_DEFINE(
[HAVE_CLOCK_MONOTONIC], [1], [Define to 1 if
`CLOCK_MONOTONIC' is declared in <time.h>.])], [],
[[#include <time.h>]])
CFLAGS=$OLD_CFLAGS
;;
win95)
@ -935,6 +938,8 @@ AC_CHECK_DECL([_mm_movemask_epi8],
# For faster CRC on 32/64-bit x86 and E2K (see also crc64_fast.c):
#
# - Check for the CLMUL intrinsic _mm_clmulepi64_si128 in <immintrin.h>.
# Check also for _mm_set_epi64x for consistency with CMake build
# where it's needed to disable CLMUL with VS2013.
#
# - Check that __attribute__((__target__("ssse3,sse4.1,pclmul"))) works
# together with _mm_clmulepi64_si128 from <immintrin.h>. The attribute
@ -962,13 +967,15 @@ else
#if (defined(__GNUC__) || defined(__clang__)) && !defined(__EDG__)
__attribute__((__target__("ssse3,sse4.1,pclmul")))
#endif
__m128i my_clmul(__m128i a, __m128i b)
__m128i my_clmul(__m128i a)
{
const __m128i b = _mm_set_epi64x(1, 2);
return _mm_clmulepi64_si128(a, b, 0);
}
]])], [
AC_DEFINE([HAVE_USABLE_CLMUL], [1],
[Define to 1 if _mm_clmulepi64_si128 is usable.
[Define to 1 if _mm_set_epi64x and
_mm_clmulepi64_si128 are usable.
See configure.ac for details.])
AC_MSG_RESULT([yes])
], [

View File

@ -21,5 +21,8 @@
AC_DEFUN_ONCE([TUKLIB_PROGNAME], [
AC_REQUIRE([TUKLIB_COMMON])
AC_CHECK_DECLS([program_invocation_name], [], [], [#include <errno.h>])
AC_CHECK_DECL([program_invocation_name], [AC_DEFINE(
[HAVE_PROGRAM_INVOCATION_NAME], [1],
[Define to 1 if `program_invocation_name' is declared in <errno.h>.])],
[], [#include <errno.h>])
])dnl

620
po/eo.po

File diff suppressed because it is too large Load Diff

5552
po4a/ko.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
# to get a new .po file. After translating the .po file, run
# "update-po" again to generate the translated man pages.
[po4a_langs] de fr ro
[po4a_langs] de fr ro uk ko
[po4a_paths] xz-man.pot $lang:$lang.po
[type: man] ../src/xz/xz.1 $lang:man/$lang/xz.1

3676
po4a/uk.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -100,12 +100,18 @@ mythread_sigmask(int how, const sigset_t *restrict set,
// Using pthreads //
////////////////////
#include <sys/time.h>
#include <pthread.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
// If clock_gettime() isn't available, use gettimeofday() from <sys/time.h>
// as a fallback. gettimeofday() is in SUSv2 and thus is supported on all
// relevant POSIX systems.
#ifndef HAVE_CLOCK_GETTIME
# include <sys/time.h>
#endif
#define MYTHREAD_RET_TYPE void *
#define MYTHREAD_RET_VALUE NULL
@ -219,8 +225,8 @@ static inline int
mythread_cond_init(mythread_cond *mycond)
{
#ifdef HAVE_CLOCK_GETTIME
// NOTE: HAVE_DECL_CLOCK_MONOTONIC is always defined to 0 or 1.
# if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && HAVE_DECL_CLOCK_MONOTONIC
# if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && \
defined(HAVE_CLOCK_MONOTONIC)
struct timespec ts;
pthread_condattr_t condattr;

View File

@ -127,7 +127,7 @@
#include <stdlib.h>
#include <assert.h>
// Pre-C99 systems lack stdbool.h. All the code in LZMA Utils must be written
// Pre-C99 systems lack stdbool.h. All the code in XZ Utils must be written
// so that it works with fake bool type, for example:
//
// bool foo = (flags & 0x100) != 0;
@ -149,18 +149,8 @@ typedef unsigned char _Bool;
# define __bool_true_false_are_defined 1
#endif
// string.h should be enough but let's include strings.h and memory.h too if
// they exists, since that shouldn't do any harm, but may improve portability.
#include <string.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_MEMORY_H
# include <memory.h>
#endif
// As of MSVC 2013, inline and restrict are supported with
// non-standard keywords.
#if defined(_WIN32) && defined(_MSC_VER)

View File

@ -14,7 +14,7 @@
#include <string.h>
#if !HAVE_DECL_PROGRAM_INVOCATION_NAME
#ifndef HAVE_PROGRAM_INVOCATION_NAME
char *progname = NULL;
#endif

View File

@ -18,7 +18,7 @@
TUKLIB_DECLS_BEGIN
#if HAVE_DECL_PROGRAM_INVOCATION_NAME
#ifdef HAVE_PROGRAM_INVOCATION_NAME
# define progname program_invocation_name
#else
# define progname TUKLIB_SYMBOL(tuklib_progname)

View File

@ -24,7 +24,7 @@ liblzma_la_CPPFLAGS = \
-I$(top_srcdir)/src/liblzma/simple \
-I$(top_srcdir)/src/common \
-DTUKLIB_SYMBOL_PREFIX=lzma_
liblzma_la_LDFLAGS = -no-undefined -version-info 9:0:4
liblzma_la_LDFLAGS = -no-undefined -version-info 9:1:4
EXTRA_DIST += liblzma_generic.map liblzma_linux.map validate_map.sh
if COND_SYMVERS_GENERIC

View File

@ -22,7 +22,7 @@
*/
#define LZMA_VERSION_MAJOR 5
#define LZMA_VERSION_MINOR 4
#define LZMA_VERSION_PATCH 0
#define LZMA_VERSION_PATCH 1
#define LZMA_VERSION_STABILITY LZMA_VERSION_STABILITY_STABLE
#ifndef LZMA_VERSION_COMMIT

View File

@ -184,6 +184,20 @@ calc_hi(uint64_t poly, uint64_t a)
MASK_H(in, mask, high)
// MSVC (VS2015 - VS2022) produces bad 32-bit x86 code from the CLMUL CRC
// code when optimizations are enabled (release build). According to the bug
// report, the ebx register is corrupted and the calculated result is wrong.
// Trying to workaround the problem with "__asm mov ebx, ebx" didn't help.
// The following pragma works and performance is still good. x86-64 builds
// aren't affected by this problem.
//
// NOTE: Another pragma after the function restores the optimizations.
// If the #if condition here is updated, the other one must be updated too.
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__) \
&& defined(_M_IX86)
# pragma optimize("g", off)
#endif
// EDG-based compilers (Intel's classic compiler and compiler for E2K) can
// define __GNUC__ but the attribute must not be used with them.
// The new Clang-based ICX needs the attribute.
@ -371,6 +385,10 @@ crc64_clmul(const uint8_t *buf, size_t size, uint64_t crc)
# pragma GCC diagnostic pop
#endif
}
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__) \
&& defined(_M_IX86)
# pragma optimize("", on)
#endif
#endif

View File

@ -37,9 +37,12 @@ typedef struct {
uint64_t (*block_size)(const void *options);
/// Tells the size of the Filter Properties field. If options are
/// invalid, UINT32_MAX is returned. If this is NULL, props_size_fixed
/// is used.
/// invalid, LZMA_OPTIONS_ERROR is returned and size is set to
/// UINT32_MAX.
lzma_ret (*props_size_get)(uint32_t *size, const void *options);
/// Some filters will always have the same size Filter Properties
/// field. If props_size_get is NULL, this value is used.
uint32_t props_size_fixed;
/// Encodes Filter Properties.

View File

@ -10,6 +10,7 @@
//
///////////////////////////////////////////////////////////////////////////////
#include "common.h"
#include "index.h"
#include "stream_flags_common.h"

View File

@ -2,6 +2,13 @@
//
/// \file index.h
/// \brief Handling of Index
/// \note This header file does not include common.h or lzma.h because
/// this file is needed by both liblzma internally and by the
/// tests. Including common.h will include and define many things
/// the tests do not need and prevents issues with header file
/// include order. This way, if lzma.h or common.h are not
/// included before this file it will break on every OS instead
/// of causing more subtle errors.
//
// Author: Lasse Collin
//
@ -13,8 +20,6 @@
#ifndef LZMA_INDEX_H
#define LZMA_INDEX_H
#include "common.h"
/// Minimum Unpadded Size
#define UNPADDED_SIZE_MIN LZMA_VLI_C(5)
@ -22,6 +27,9 @@
/// Maximum Unpadded Size
#define UNPADDED_SIZE_MAX (LZMA_VLI_MAX & ~LZMA_VLI_C(3))
/// Index Indicator based on xz specification
#define INDEX_INDICATOR 0
/// Get the size of the Index Padding field. This is needed by Index encoder
/// and decoder, but applications should have no use for this.

View File

@ -80,7 +80,7 @@ index_decode(void *coder_ptr, const lzma_allocator *allocator,
// format". One could argue that the application should
// verify the Index Indicator before trying to decode the
// Index, but well, I suppose it is simpler this way.
if (in[(*in_pos)++] != 0x00)
if (in[(*in_pos)++] != INDEX_INDICATOR)
return LZMA_DATA_ERROR;
coder->sequence = SEQ_COUNT;

View File

@ -13,6 +13,7 @@
#ifndef LZMA_INDEX_DECODER_H
#define LZMA_INDEX_DECODER_H
#include "common.h"
#include "index.h"

View File

@ -65,7 +65,7 @@ index_encode(void *coder_ptr,
while (*out_pos < out_size)
switch (coder->sequence) {
case SEQ_INDICATOR:
out[*out_pos] = 0x00;
out[*out_pos] = INDEX_INDICATOR;
++*out_pos;
coder->sequence = SEQ_COUNT;
break;

View File

@ -145,7 +145,7 @@ lzma_index_hash_append(lzma_index_hash *index_hash, lzma_vli unpadded_size,
lzma_vli uncompressed_size)
{
// Validate the arguments.
if (index_hash->sequence != SEQ_BLOCK
if (index_hash == NULL || index_hash->sequence != SEQ_BLOCK
|| unpadded_size < UNPADDED_SIZE_MIN
|| unpadded_size > UNPADDED_SIZE_MAX
|| uncompressed_size > LZMA_VLI_MAX)
@ -190,7 +190,7 @@ lzma_index_hash_decode(lzma_index_hash *index_hash, const uint8_t *in,
switch (index_hash->sequence) {
case SEQ_BLOCK:
// Check the Index Indicator is present.
if (in[(*in_pos)++] != 0x00)
if (in[(*in_pos)++] != INDEX_INDICATOR)
return LZMA_DATA_ERROR;
index_hash->sequence = SEQ_COUNT;

View File

@ -111,7 +111,8 @@ microlzma_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
// Encode the properties byte. Bitwise-negation of it will be the
// first output byte.
return_if_error(lzma_lzma_lclppb_encode(options, &coder->props));
if (lzma_lzma_lclppb_encode(options, &coder->props))
return LZMA_OPTIONS_ERROR;
// Initialize the LZMA encoder.
const lzma_filter_info filters[2] = {

View File

@ -10,6 +10,7 @@
//
///////////////////////////////////////////////////////////////////////////////
#include "common.h"
#include "index.h"

View File

@ -12,6 +12,7 @@
#include "stream_decoder.h"
#include "block_decoder.h"
#include "index.h"
typedef struct {
@ -164,7 +165,7 @@ stream_decode(void *coder_ptr, const lzma_allocator *allocator,
if (coder->pos == 0) {
// Detect if it's Index.
if (in[*in_pos] == 0x00) {
if (in[*in_pos] == INDEX_INDICATOR) {
coder->sequence = SEQ_INDEX;
break;
}

View File

@ -887,7 +887,7 @@ decode_block_header(struct lzma_stream_coder *coder,
if (coder->pos == 0) {
// Detect if it's Index.
if (in[*in_pos] == 0x00)
if (in[*in_pos] == INDEX_INDICATOR)
return LZMA_INDEX_DETECTED;
// Calculate the size of the Block Header. Note that

View File

@ -14,6 +14,7 @@
//
// Authors: Lasse Collin
// Jia Tan
// Igor Pavlov
//
// This file has been put into the public domain.
// You can do whatever you want with this file.

View File

@ -723,7 +723,16 @@ vmessage(enum message_verbosity v, const char *fmt, va_list ap)
// This is a translatable string because French needs
// a space before a colon.
fprintf(stderr, _("%s: "), progname);
#ifdef __clang__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
vfprintf(stderr, fmt, ap);
#ifdef __clang__
# pragma GCC diagnostic pop
#endif
fputc('\n', stderr);
signals_unblock();

View File

@ -12,7 +12,9 @@
#include "private.h"
#if !(defined(HAVE_CLOCK_GETTIME) && HAVE_DECL_CLOCK_MONOTONIC)
#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_MONOTONIC)
# include <time.h>
#else
# include <sys/time.h>
#endif
@ -28,8 +30,7 @@ static uint64_t next_flush;
static uint64_t
mytime_now(void)
{
// NOTE: HAVE_DECL_CLOCK_MONOTONIC is always defined to 0 or 1.
#if defined(HAVE_CLOCK_GETTIME) && HAVE_DECL_CLOCK_MONOTONIC
#if defined(HAVE_CLOCK_GETTIME) && defined(HAVE_CLOCK_MONOTONIC)
// If CLOCK_MONOTONIC was available at compile time but for some
// reason isn't at runtime, fallback to CLOCK_REALTIME which
// according to POSIX is mandatory for all implementations.

View File

@ -18,6 +18,9 @@
// For case-insensitive filename suffix on case-insensitive systems
#if defined(TUKLIB_DOSLIKE) || defined(__VMS)
# ifdef HAVE_STRINGS_H
# include <strings.h>
# endif
# define strcmp strcasecmp
#endif

View File

@ -26,6 +26,7 @@ EXTRA_DIST = \
AM_CPPFLAGS = \
-I$(top_srcdir)/src/common \
-I$(top_srcdir)/src/liblzma/api \
-I$(top_srcdir)/src/liblzma \
-I$(top_builddir)/lib
LDADD = $(top_builddir)/src/liblzma/liblzma.la
@ -44,8 +45,10 @@ check_PROGRAMS = \
test_filter_flags \
test_block_header \
test_index \
test_index_hash \
test_bcj_exact_size \
test_memlimit \
test_lzip_decoder \
test_vli
TESTS = \
@ -55,8 +58,10 @@ TESTS = \
test_filter_flags \
test_block_header \
test_index \
test_index_hash \
test_bcj_exact_size \
test_memlimit \
test_lzip_decoder \
test_vli \
test_files.sh \
test_compress_prepared_bcj_sparc \

View File

@ -24,7 +24,7 @@
// Avoid re-creating the test files every time the tests are run.
#define maybe_create_test(argc, argv, name) \
do { \
if ((argc < 2 || strcmp(argv[1], #name) == 0) \
if ((argc < 2 || strcmp(argv[1], "compress_generated_" #name) == 0) \
&& !file_exists("compress_generated_" #name)) { \
FILE *file = file_create("compress_generated_" #name); \
write_ ## name(file); \

View File

@ -35,6 +35,9 @@ static lzma_filter filters_one[2] = {
};
// These filters are only used in test_lzma_block_header_decode()
// which only runs if encoders and decoders are configured.
#ifdef HAVE_DECODERS
static lzma_filter filters_four[5] = {
{
.id = LZMA_FILTER_X86,
@ -52,6 +55,7 @@ static lzma_filter filters_four[5] = {
.id = LZMA_VLI_UNKNOWN,
}
};
#endif
static lzma_filter filters_five[6] = {

View File

@ -50,6 +50,22 @@ static uint8_t *sha256_xz_data;
#endif
#ifdef HAVE_CHECK_CRC64
static const uint8_t *
get_random256(uint32_t *seed)
{
static uint8_t buf[256];
for (size_t i = 0; i < sizeof(buf); ++i) {
*seed = *seed * 1103515245 + 12345;
buf[i] = (uint8_t)(*seed >> 22);
}
return buf;
}
#endif
static void
test_lzma_crc32(void)
{
@ -99,6 +115,17 @@ test_lzma_crc64(void)
for (size_t i = 0; i < sizeof(test_string); ++i)
crc = lzma_crc64(test_string + i, 1, crc);
assert_uint_eq(crc, test_vector);
// Test 4: The CLMUL implementation works on 16-byte chunks.
// Test combination of different start and end alignments
// and also short buffer lengths where special handling is needed.
uint32_t seed = 29;
crc = 0x96E30D5184B7FA2C; // Random initial value
for (size_t start = 0; start < 32; ++start)
for (size_t size = 1; size < 256 - 32; ++size)
crc = lzma_crc64(get_random256(&seed), size, crc);
assert_uint_eq(crc, 0x23AB787177231C9F);
#endif
}

View File

@ -84,10 +84,19 @@ XZDEC="../src/xzdec/xzdec" # No memory usage limiter available
test -x ../src/xzdec/xzdec || XZDEC=
# Create the required input file if needed.
#
# Derive temporary filenames for compressed and uncompressed outputs
# from the input filename. This is needed when multiple tests are
# run in parallel.
FILE=$1
TMP_COMP="tmp_comp_$FILE"
TMP_UNCOMP="tmp_uncomp_$FILE"
case $FILE in
# compress_generated files will be created in the build directory
# in the /tests/ sub-directory.
compress_generated_*)
if ./create_compress_files "${FILE#compress_generated_}" ; then
if ./create_compress_files "$FILE" ; then
:
else
rm -f "$FILE"
@ -95,18 +104,17 @@ case $FILE in
exit 1
fi
;;
# compress_prepared files exist in the source directory since they
# do not need to be copied or regenerated.
compress_prepared_*)
FILE="$srcdir/$FILE"
;;
'')
echo "No test file was specified."
exit 1
;;
esac
# Derive temporary filenames for compressed and uncompressed outputs
# from the input filename. This is needed when multiple tests are
# run in parallel.
TMP_COMP="tmp_comp_${FILE##*/}"
TMP_UNCOMP="tmp_uncomp_${FILE##*/}"
# Remove temporary now (in case they are something weird), and on exit.
rm -f "$TMP_COMP" "$TMP_UNCOMP"
trap 'rm -f "$TMP_COMP" "$TMP_UNCOMP"' 0

View File

@ -1,3 +1,3 @@
#!/bin/sh
exec "$srcdir/test_compress.sh" "$srcdir/compress_prepared_bcj_sparc"
exec "$srcdir/test_compress.sh" compress_prepared_bcj_sparc

View File

@ -1,3 +1,3 @@
#!/bin/sh
exec "$srcdir/test_compress.sh" "$srcdir/compress_prepared_bcj_x86"
exec "$srcdir/test_compress.sh" compress_prepared_bcj_x86

View File

@ -3,7 +3,8 @@
/// \file test_filter_flags.c
/// \brief Tests Filter Flags coders
//
// Author: Lasse Collin
// Authors: Jia Tan
// Lasse Collin
//
// This file has been put into the public domain.
// You can do whatever you want with this file.
@ -12,247 +13,515 @@
#include "tests.h"
static uint8_t buffer[4096];
static lzma_filter known_flags;
static lzma_filter decoded_flags;
static lzma_stream strm = LZMA_STREAM_INIT;
// FIXME: This is from src/liblzma/common/common.h but it cannot be
// included here. This constant is needed in only a few files, perhaps
// move it to some other internal header or create a new one?
#define LZMA_FILTER_RESERVED_START (LZMA_VLI_C(1) << 62)
static bool
encode(uint32_t known_size)
{
memcrap(buffer, sizeof(buffer));
#if defined(HAVE_ENCODERS)
// No tests are run without encoders, so init the global filters
// only when the encoders are enabled.
static lzma_filter lzma1_filter = { LZMA_FILTER_LZMA1, NULL };
static lzma_filter lzma2_filter = { LZMA_FILTER_LZMA2, NULL };
static lzma_filter delta_filter = { LZMA_FILTER_DELTA, NULL };
uint32_t tmp;
if (lzma_filter_flags_size(&tmp, &known_flags) != LZMA_OK)
return true;
static lzma_filter bcj_filters_encoders[] = {
#ifdef HAVE_ENCODER_X86
{ LZMA_FILTER_X86, NULL },
#endif
#ifdef HAVE_ENCODER_POWERPC
{ LZMA_FILTER_POWERPC, NULL },
#endif
#ifdef HAVE_ENCODER_IA64
{ LZMA_FILTER_IA64, NULL },
#endif
#ifdef HAVE_ENCODER_ARM
{ LZMA_FILTER_ARM, NULL },
#endif
#ifdef HAVE_ENCODER_ARM64
{ LZMA_FILTER_ARM64, NULL },
#endif
#ifdef HAVE_ENCODER_ARMTHUMB
{ LZMA_FILTER_ARMTHUMB, NULL },
#endif
#ifdef HAVE_ENCODER_SPARC
{ LZMA_FILTER_SPARC, NULL },
#endif
};
if (tmp != known_size)
return true;
// HAVE_ENCODERS ifdef not termianted here because decoders are
// only used if encoders are, but encoders can still be used
// even if decoders are not.
size_t out_pos = 0;
if (lzma_filter_flags_encode(&known_flags,
buffer, &out_pos, known_size) != LZMA_OK)
return true;
if (out_pos != known_size)
return true;
return false;
}
static bool
decode_ret(uint32_t known_size, lzma_ret expected_ret)
{
memcrap(&decoded_flags, sizeof(decoded_flags));
size_t pos = 0;
if (lzma_filter_flags_decode(&decoded_flags, NULL,
buffer, &pos, known_size) != expected_ret
|| pos != known_size)
return true;
return false;
}
static bool
decode(uint32_t known_size)
{
if (decode_ret(known_size, LZMA_OK))
return true;
if (known_flags.id != decoded_flags.id)
return true;
return false;
}
#if defined(HAVE_ENCODER_X86) && defined(HAVE_DECODER_X86)
static void
test_bcj(void)
{
// Test 1
known_flags.id = LZMA_FILTER_X86;
known_flags.options = NULL;
expect(!encode(2));
expect(!decode(2));
expect(decoded_flags.options == NULL);
// Test 2
lzma_options_bcj options;
options.start_offset = 0;
known_flags.options = &options;
expect(!encode(2));
expect(!decode(2));
expect(decoded_flags.options == NULL);
// Test 3
options.start_offset = 123456;
known_flags.options = &options;
expect(!encode(6));
expect(!decode(6));
expect(decoded_flags.options != NULL);
lzma_options_bcj *decoded = decoded_flags.options;
expect(decoded->start_offset == options.start_offset);
free(decoded);
}
#ifdef HAVE_DECODERS
static lzma_filter bcj_filters_decoders[] = {
#ifdef HAVE_DECODER_X86
{ LZMA_FILTER_X86, NULL },
#endif
#ifdef HAVE_DECODER_POWERPC
{ LZMA_FILTER_POWERPC, NULL },
#endif
#ifdef HAVE_DECODER_IA64
{ LZMA_FILTER_IA64, NULL },
#endif
#ifdef HAVE_DECODER_ARM
{ LZMA_FILTER_ARM, NULL },
#endif
#ifdef HAVE_DECODER_ARM64
{ LZMA_FILTER_ARM64, NULL },
#endif
#ifdef HAVE_DECODER_ARMTHUMB
{ LZMA_FILTER_ARMTHUMB, NULL },
#endif
#ifdef HAVE_DECODER_SPARC
{ LZMA_FILTER_SPARC, NULL },
#endif
};
#endif
#endif
#if defined(HAVE_ENCODER_DELTA) && defined(HAVE_DECODER_DELTA)
static void
test_delta(void)
test_lzma_filter_flags_size(void)
{
// Test 1
known_flags.id = LZMA_FILTER_DELTA;
known_flags.options = NULL;
expect(encode(99));
// Test 2
lzma_options_delta options = {
.type = LZMA_DELTA_TYPE_BYTE,
.dist = 0
};
known_flags.options = &options;
expect(encode(99));
// Test 3
options.dist = LZMA_DELTA_DIST_MIN;
expect(!encode(3));
expect(!decode(3));
expect(((lzma_options_delta *)(decoded_flags.options))->dist
== options.dist);
free(decoded_flags.options);
// Test 4
options.dist = LZMA_DELTA_DIST_MAX;
expect(!encode(3));
expect(!decode(3));
expect(((lzma_options_delta *)(decoded_flags.options))->dist
== options.dist);
free(decoded_flags.options);
// Test 5
options.dist = LZMA_DELTA_DIST_MAX + 1;
expect(encode(99));
}
#endif
/*
#ifdef HAVE_FILTER_LZMA
static void
validate_lzma(void)
{
const lzma_options_lzma *known = known_flags.options;
const lzma_options_lzma *decoded = decoded_flags.options;
expect(known->dictionary_size <= decoded->dictionary_size);
if (known->dictionary_size == 1)
expect(decoded->dictionary_size == 1);
else
expect(known->dictionary_size + known->dictionary_size / 2
> decoded->dictionary_size);
expect(known->literal_context_bits == decoded->literal_context_bits);
expect(known->literal_pos_bits == decoded->literal_pos_bits);
expect(known->pos_bits == decoded->pos_bits);
}
static void
test_lzma(void)
{
// Test 1
known_flags.id = LZMA_FILTER_LZMA1;
known_flags.options = NULL;
expect(encode(99));
// Test 2
lzma_options_lzma options = {
.dictionary_size = 0,
.literal_context_bits = 0,
.literal_pos_bits = 0,
.pos_bits = 0,
.preset_dictionary = NULL,
.preset_dictionary_size = 0,
.mode = LZMA_MODE_INVALID,
.fast_bytes = 0,
.match_finder = LZMA_MF_INVALID,
.match_finder_cycles = 0,
};
// Test 3 (empty dictionary not allowed)
known_flags.options = &options;
expect(encode(99));
// Test 4 (brute-force test some valid dictionary sizes)
options.dictionary_size = LZMA_DICTIONARY_SIZE_MIN;
while (options.dictionary_size != LZMA_DICTIONARY_SIZE_MAX) {
if (++options.dictionary_size == 5000)
options.dictionary_size = LZMA_DICTIONARY_SIZE_MAX - 5;
expect(!encode(4));
expect(!decode(4));
validate_lzma();
free(decoded_flags.options);
#ifndef HAVE_ENCODERS
assert_skip("Encoder support disabled");
#else
// For each supported filter, test that the size can be calculated
// and that the size calculated is reasonable. A reasonable size
// must be greater than 0, but less than the maximum size for the
// block header.
uint32_t size = 0;
if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA1)) {
assert_lzma_ret(lzma_filter_flags_size(&size,
&lzma1_filter), LZMA_PROG_ERROR);
}
// Test 5 (too big dictionary size)
options.dictionary_size = LZMA_DICTIONARY_SIZE_MAX + 1;
expect(encode(99));
if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) {
assert_lzma_ret(lzma_filter_flags_size(&size,
&lzma2_filter), LZMA_OK);
assert_true(size != 0 && size < LZMA_BLOCK_HEADER_SIZE_MAX);
}
// Test 6 (brute-force test lc/lp/pb)
options.dictionary_size = LZMA_DICTIONARY_SIZE_MIN;
for (uint32_t lc = LZMA_LITERAL_CONTEXT_BITS_MIN;
lc <= LZMA_LITERAL_CONTEXT_BITS_MAX; ++lc) {
for (uint32_t lp = LZMA_LITERAL_POS_BITS_MIN;
lp <= LZMA_LITERAL_POS_BITS_MAX; ++lp) {
for (uint32_t pb = LZMA_POS_BITS_MIN;
pb <= LZMA_POS_BITS_MAX; ++pb) {
if (lc + lp > LZMA_LITERAL_BITS_MAX)
continue;
// Do not use macro ARRAY_SIZE() in the for loop condition directly.
// If the BCJ filters are not configured and built, then ARRAY_SIZE()
// will return 0 and cause a warning because the for loop will never
// execute since any unsigned number cannot be < 0 (-Werror=type-limits).
const uint32_t bcj_array_size = ARRAY_SIZE(bcj_filters_encoders);
for (uint32_t i = 0; i < bcj_array_size; i++) {
assert_lzma_ret(lzma_filter_flags_size(&size,
&bcj_filters_encoders[i]), LZMA_OK);
assert_true(size != 0 && size < LZMA_BLOCK_HEADER_SIZE_MAX);
}
options.literal_context_bits = lc;
options.literal_pos_bits = lp;
options.pos_bits = pb;
if (lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) {
assert_lzma_ret(lzma_filter_flags_size(&size,
&delta_filter), LZMA_OK);
assert_true(size != 0 && size < LZMA_BLOCK_HEADER_SIZE_MAX);
}
expect(!encode(4));
expect(!decode(4));
validate_lzma();
// Test invalid Filter IDs
lzma_filter bad_filter = { 2, NULL };
free(decoded_flags.options);
}
assert_lzma_ret(lzma_filter_flags_size(&size, &bad_filter),
LZMA_OPTIONS_ERROR);
bad_filter.id = LZMA_VLI_MAX;
assert_lzma_ret(lzma_filter_flags_size(&size, &bad_filter),
LZMA_PROG_ERROR);
bad_filter.id = LZMA_FILTER_RESERVED_START;
assert_lzma_ret(lzma_filter_flags_size(&size, &bad_filter),
LZMA_PROG_ERROR);
#endif
}
// Helper function for test_lzma_filter_flags_encode.
// The should_encode parameter represents if the encoding operation
// is expected to fail.
// Avoid data -> encode -> decode -> compare to data.
// Instead create expected encoding and compare to result from
// lzma_filter_flags_encode.
// Filter Flags in .xz are encoded as:
// |Filter ID (VLI)|Size of Properties (VLI)|Filter Properties|
#if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
static void
verify_filter_flags_encode(lzma_filter *filter, bool should_encode)
{
uint32_t size = 0;
// First calculate the size of Filter Flags to know how much
// memory to allocate to hold the encoded Filter Flags
assert_lzma_ret(lzma_filter_flags_size(&size, filter), LZMA_OK);
uint8_t *encoded_out = tuktest_malloc(size * sizeof(uint8_t));
size_t out_pos = 0;
if (!should_encode) {
assert_false(lzma_filter_flags_encode(filter, encoded_out,
&out_pos, size) == LZMA_OK);
return;
}
// Next encode the Filter Flags for the provided filter
assert_lzma_ret(lzma_filter_flags_encode(filter, encoded_out,
&out_pos, size), LZMA_OK);
assert_uint_eq(size, out_pos);
// Next decode the VLI for the Filter ID and verify it matches
// the expected Filter ID
size_t filter_id_vli_size = 0;
lzma_vli filter_id = 0;
assert_lzma_ret(lzma_vli_decode(&filter_id, NULL, encoded_out,
&filter_id_vli_size, size), LZMA_OK);
assert_uint_eq(filter->id, filter_id);
// Next decode the Size of Properites and ensure it equals
// the expected size.
// Expected size should be:
// total filter flag length - size of filter id VLI + size of
// property size VLI
// Not verifying the contents of Filter Properties since
// that belongs in a different test
size_t size_of_properties_vli_size = 0;
lzma_vli size_of_properties = 0;
assert_lzma_ret(lzma_vli_decode(&size_of_properties, NULL,
encoded_out + filter_id_vli_size,
&size_of_properties_vli_size, size), LZMA_OK);
assert_uint_eq(size - (size_of_properties_vli_size +
filter_id_vli_size), size_of_properties);
}
#endif
static void
test_lzma_filter_flags_encode(void)
{
#if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
assert_skip("Encoder or decoder support disabled");
#else
// No test for LZMA1 since the .xz format does not support LZMA1
// and so the flags cannot be encoded for that filter
if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) {
// Test with NULL options that should fail
lzma_options_lzma *options = lzma2_filter.options;
lzma2_filter.options = NULL;
verify_filter_flags_encode(&lzma2_filter, false);
// Place options back in the filter, and test should pass
lzma2_filter.options = options;
verify_filter_flags_encode(&lzma2_filter, true);
}
// NOTE: Many BCJ filters require that start_offset is a multiple
// of some power of two. The Filter Flags encoder and decoder don't
// completely validate the options and thus 257 passes the tests
// with all BCJ filters. It would be caught when initializing
// a filter chain encoder or decoder.
lzma_options_bcj bcj_options = {
.start_offset = 257
};
const uint32_t bcj_array_size = ARRAY_SIZE(bcj_filters_encoders);
for (uint32_t i = 0; i < bcj_array_size; i++) {
// NULL options should pass for bcj filters
verify_filter_flags_encode(&bcj_filters_encoders[i], true);
lzma_filter bcj_with_options = {
bcj_filters_encoders[i].id, &bcj_options };
verify_filter_flags_encode(&bcj_with_options, true);
}
if (lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) {
lzma_options_delta delta_opts_below_min = {
.type = LZMA_DELTA_TYPE_BYTE,
.dist = LZMA_DELTA_DIST_MIN - 1
};
lzma_options_delta delta_opts_above_max = {
.type = LZMA_DELTA_TYPE_BYTE,
.dist = LZMA_DELTA_DIST_MAX + 1
};
verify_filter_flags_encode(&delta_filter, true);
lzma_filter delta_filter_bad_options = {
LZMA_FILTER_DELTA, &delta_opts_below_min };
// Next test error case using minimum - 1 delta distance
verify_filter_flags_encode(&delta_filter_bad_options, false);
// Next test error case using maximum + 1 delta distance
delta_filter_bad_options.options = &delta_opts_above_max;
verify_filter_flags_encode(&delta_filter_bad_options, false);
// Next test NULL case
delta_filter_bad_options.options = NULL;
verify_filter_flags_encode(&delta_filter_bad_options, false);
}
// Test expected failing cases
lzma_filter bad_filter = { LZMA_FILTER_RESERVED_START, NULL };
size_t out_pos = 0;
size_t out_size = LZMA_BLOCK_HEADER_SIZE_MAX;
uint8_t out[LZMA_BLOCK_HEADER_SIZE_MAX];
// Filter ID outside of valid range
assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out, &out_pos,
out_size), LZMA_PROG_ERROR);
out_pos = 0;
bad_filter.id = LZMA_VLI_MAX + 1;
assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out, &out_pos,
out_size), LZMA_PROG_ERROR);
out_pos = 0;
// Invalid Filter ID
bad_filter.id = 2;
assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out, &out_pos,
out_size), LZMA_OPTIONS_ERROR);
out_pos = 0;
// Out size too small
if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) {
uint32_t bad_size = 0;
// First test with 0 output size
assert_lzma_ret(lzma_filter_flags_encode(
&lzma2_filter, out, &out_pos, 0),
LZMA_PROG_ERROR);
// Next calculate the size needed to encode and
// use less than that
assert_lzma_ret(lzma_filter_flags_size(&bad_size,
&lzma2_filter), LZMA_OK);
assert_lzma_ret(lzma_filter_flags_encode(
&lzma2_filter, out, &out_pos,
bad_size - 1), LZMA_PROG_ERROR);
out_pos = 0;
}
// Invalid options
if (lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) {
bad_filter.id = LZMA_FILTER_DELTA;
// First test with NULL options
assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out,
&out_pos, out_size), LZMA_PROG_ERROR);
out_pos = 0;
// Next test with invalid options
lzma_options_delta bad_options = {
.dist = LZMA_DELTA_DIST_MAX + 1,
.type = LZMA_DELTA_TYPE_BYTE
};
bad_filter.options = &bad_options;
assert_lzma_ret(lzma_filter_flags_encode(&bad_filter, out,
&out_pos, out_size), LZMA_PROG_ERROR);
}
#endif
}
// Helper function for test_lzma_filter_flags_decode.
// Encodes the filter_in without using lzma_filter_flags_encode.
// Leaves the specific assertions of filter_out options to the caller
// because it is agnostic to the type of options used in the call
#if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
static void
verify_filter_flags_decode(lzma_filter *filter_in, lzma_filter *filter_out)
{
uint32_t total_size = 0;
assert_lzma_ret(lzma_filter_flags_size(&total_size, filter_in),
LZMA_OK);
assert_uint(total_size, >, 0);
uint8_t *filter_flag_buffer = tuktest_malloc(total_size);
uint32_t properties_size = 0;
size_t out_pos = 0;
size_t in_pos = 0;
assert_lzma_ret(lzma_properties_size(&properties_size, filter_in),
LZMA_OK);
assert_lzma_ret(lzma_vli_encode(filter_in->id, NULL,
filter_flag_buffer, &out_pos, total_size), LZMA_OK);
assert_lzma_ret(lzma_vli_encode(properties_size, NULL,
filter_flag_buffer, &out_pos, total_size),
LZMA_OK);
assert_lzma_ret(lzma_properties_encode(filter_in,
filter_flag_buffer + out_pos), LZMA_OK);
assert_lzma_ret(lzma_filter_flags_decode(filter_out, NULL,
filter_flag_buffer, &in_pos, total_size),
LZMA_OK);
assert_uint_eq(filter_in->id, filter_out->id);
}
#endif
static void
test_lzma_filter_flags_decode(void)
{
#if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
assert_skip("Encoder or decoder support disabled");
#else
// For each filter, only run the decoder test if both the encoder
// and decoder are enabled. This is because verify_filter_flags_decode
// uses lzma_filter_flags_size which requires the encoder.
if (lzma_filter_decoder_is_supported(LZMA_FILTER_LZMA2) &&
lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) {
lzma_filter lzma2_decoded = { LZMA_FILTER_LZMA2, NULL };
verify_filter_flags_decode(&lzma2_filter, &lzma2_decoded);
lzma_options_lzma *expected = lzma2_filter.options;
lzma_options_lzma *decoded = lzma2_decoded.options;
// Only the dictionary size is encoded and decoded
// so only compare those
assert_uint_eq(decoded->dict_size, expected->dict_size);
// The decoded options must be freed by the caller
free(decoded);
}
const uint32_t bcj_array_size = ARRAY_SIZE(bcj_filters_decoders);
for (uint32_t i = 0; i < bcj_array_size; i++) {
if (lzma_filter_encoder_is_supported(
bcj_filters_decoders[i].id)) {
lzma_filter bcj_decoded = {
bcj_filters_decoders[i].id, NULL };
lzma_filter bcj_encoded = {
bcj_filters_decoders[i].id, NULL };
// First test without options
verify_filter_flags_decode(&bcj_encoded,
&bcj_decoded);
assert_true(bcj_decoded.options == NULL);
// Next test with offset
lzma_options_bcj options = {
.start_offset = 257
};
bcj_encoded.options = &options;
verify_filter_flags_decode(&bcj_encoded,
&bcj_decoded);
lzma_options_bcj *decoded_opts = bcj_decoded.options;
assert_uint_eq(decoded_opts->start_offset,
options.start_offset);
free(decoded_opts);
}
}
}
#endif
*/
int
main(void)
if (lzma_filter_decoder_is_supported(LZMA_FILTER_DELTA) &&
lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) {
lzma_filter delta_decoded = { LZMA_FILTER_DELTA, NULL };
verify_filter_flags_decode(&delta_filter, &delta_decoded);
lzma_options_delta *expected = delta_filter.options;
lzma_options_delta *decoded = delta_decoded.options;
assert_uint_eq(expected->dist, decoded->dist);
assert_uint_eq(expected->type, decoded->type);
free(decoded);
}
// Test expected failing cases
uint8_t bad_encoded_filter[LZMA_BLOCK_HEADER_SIZE_MAX];
lzma_filter bad_filter;
// Filter ID outside of valid range
lzma_vli bad_filter_id = LZMA_FILTER_RESERVED_START;
size_t bad_encoded_out_pos = 0;
size_t in_pos = 0;
assert_lzma_ret(lzma_vli_encode(bad_filter_id, NULL,
bad_encoded_filter, &bad_encoded_out_pos,
LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OK);
assert_lzma_ret(lzma_filter_flags_decode(&bad_filter, NULL,
bad_encoded_filter, &in_pos,
LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_DATA_ERROR);
bad_encoded_out_pos = 0;
in_pos = 0;
// Invalid Filter ID
bad_filter_id = 2;
bad_encoded_out_pos = 0;
in_pos = 0;
assert_lzma_ret(lzma_vli_encode(bad_filter_id, NULL,
bad_encoded_filter, &bad_encoded_out_pos,
LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OK);
// Next encode Size of Properties with the value of 0
assert_lzma_ret(lzma_vli_encode(0, NULL,
bad_encoded_filter, &bad_encoded_out_pos,
LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OK);
// Decode should fail on bad Filter ID
assert_lzma_ret(lzma_filter_flags_decode(&bad_filter, NULL,
bad_encoded_filter, &in_pos,
LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OPTIONS_ERROR);
bad_encoded_out_pos = 0;
in_pos = 0;
// Outsize too small
// Encode the LZMA2 filter normally, but then set
// the out size when decoding as too small
if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2) &&
lzma_filter_decoder_is_supported(LZMA_FILTER_LZMA2)) {
uint32_t filter_flag_size = 0;
assert_lzma_ret(lzma_filter_flags_size(&filter_flag_size,
&lzma2_filter), LZMA_OK);
assert_lzma_ret(lzma_filter_flags_encode(&lzma2_filter,
bad_encoded_filter, &bad_encoded_out_pos,
LZMA_BLOCK_HEADER_SIZE_MAX), LZMA_OK);
assert_lzma_ret(lzma_filter_flags_decode(&bad_filter, NULL,
bad_encoded_filter, &in_pos,
filter_flag_size - 1), LZMA_DATA_ERROR);
}
#endif
}
extern int
main(int argc, char **argv)
{
#if defined(HAVE_ENCODER_X86) && defined(HAVE_DECODER_X86)
test_bcj();
#endif
#if defined(HAVE_ENCODER_DELTA) && defined(HAVE_DECODER_DELTA)
test_delta();
#endif
// #ifdef HAVE_FILTER_LZMA
// test_lzma();
// #endif
tuktest_start(argc, argv);
lzma_end(&strm);
#ifdef HAVE_ENCODERS
// Only init filter options if encoder is supported because decoder
// tests requires encoder support, so the decoder tests will only
// run if for a given filter both the encoder and decoder are enabled.
if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA1)) {
lzma_options_lzma *options = tuktest_malloc(
sizeof(lzma_options_lzma));
lzma_lzma_preset(options, LZMA_PRESET_DEFAULT);
lzma1_filter.options = options;
}
return 0;
if (lzma_filter_encoder_is_supported(LZMA_FILTER_LZMA2)) {
lzma_options_lzma *options = tuktest_malloc(
sizeof(lzma_options_lzma));
lzma_lzma_preset(options, LZMA_PRESET_DEFAULT);
lzma2_filter.options = options;
}
if (lzma_filter_encoder_is_supported(LZMA_FILTER_DELTA)) {
lzma_options_delta *options = tuktest_malloc(
sizeof(lzma_options_delta));
options->dist = LZMA_DELTA_DIST_MIN;
options->type = LZMA_DELTA_TYPE_BYTE;
delta_filter.options = options;
}
#endif
tuktest_run(test_lzma_filter_flags_size);
tuktest_run(test_lzma_filter_flags_encode);
tuktest_run(test_lzma_filter_flags_decode);
return tuktest_end();
}

386
tests/test_index_hash.c Normal file
View File

@ -0,0 +1,386 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file test_index_hash.c
/// \brief Tests src/liblzma/common/index_hash.c API functions
///
/// \note No test included for lzma_index_hash_end since it
/// would be trivial unless tested for memory leaks
/// with something like valgrind
//
// Author: Jia Tan
//
// This file has been put into the public domain.
// You can do whatever you want with this file.
//
///////////////////////////////////////////////////////////////////////////////
#include "tests.h"
// Needed for UNPADDED_SIZE_MIN and UNPADDED_SIZE_MAX macro definitions
// and index_size and vli_ceil4 helper functions
#include "common/index.h"
static void
test_lzma_index_hash_init(void)
{
#ifndef HAVE_DECODERS
assert_skip("Decoder support disabled");
#else
// First test with NULL index_hash.
// This should create a fresh index_hash.
lzma_index_hash *index_hash = lzma_index_hash_init(NULL, NULL);
assert_true(index_hash != NULL);
// Next test with non-NULL index_hash.
lzma_index_hash *second_hash = lzma_index_hash_init(index_hash, NULL);
// It should not create a new index_hash pointer.
// Instead it must just re-init the first index_hash.
assert_true(index_hash == second_hash);
lzma_index_hash_end(index_hash, NULL);
#endif
}
static void
test_lzma_index_hash_append(void)
{
#ifndef HAVE_DECODERS
assert_skip("Decoder support disabled");
#else
// Test all invalid parameters
assert_lzma_ret(lzma_index_hash_append(NULL, 0, 0),
LZMA_PROG_ERROR);
// Test NULL index_hash
assert_lzma_ret(lzma_index_hash_append(NULL, UNPADDED_SIZE_MIN,
LZMA_VLI_MAX), LZMA_PROG_ERROR);
// Test with invalid Unpadded Size
lzma_index_hash *index_hash = lzma_index_hash_init(NULL, NULL);
assert_true(index_hash != NULL);
assert_lzma_ret(lzma_index_hash_append(index_hash,
UNPADDED_SIZE_MIN - 1, LZMA_VLI_MAX),
LZMA_PROG_ERROR);
// Test with invalid Uncompressed Size
assert_lzma_ret(lzma_index_hash_append(index_hash,
UNPADDED_SIZE_MIN, LZMA_VLI_MAX + 1),
LZMA_PROG_ERROR);
// First append a Record describing a small Block.
// This should succeed.
assert_lzma_ret(lzma_index_hash_append(index_hash,
UNPADDED_SIZE_MIN, 1), LZMA_OK);
// Append another small Record.
assert_lzma_ret(lzma_index_hash_append(index_hash,
UNPADDED_SIZE_MIN, 1), LZMA_OK);
// Append a Record that would cause the compressed size to grow
// too big
assert_lzma_ret(lzma_index_hash_append(index_hash,
UNPADDED_SIZE_MAX, 1), LZMA_DATA_ERROR);
lzma_index_hash_end(index_hash, NULL);
#endif
}
#if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
// Fill an index_hash with unpadded and uncompressed VLIs
// by calling lzma_index_hash_append
static void
fill_index_hash(lzma_index_hash *index_hash, const lzma_vli *unpadded_sizes,
const lzma_vli *uncomp_sizes, uint32_t block_count)
{
for (uint32_t i = 0; i < block_count; ++i)
assert_lzma_ret(lzma_index_hash_append(index_hash,
unpadded_sizes[i], uncomp_sizes[i]), LZMA_OK);
}
// Set the contents of buf to the expected Index based on the
// .xz specification. This needs the unpadded and uncompressed VLIs
// to correctly create the Index.
static void
generate_index(uint8_t *buf, const lzma_vli *unpadded_sizes,
const lzma_vli *uncomp_sizes, uint32_t block_count,
size_t index_max_size)
{
size_t in_pos = 0;
size_t out_pos = 0;
// First set Index Indicator
buf[out_pos++] = INDEX_INDICATOR;
// Next write out Number of Records
assert_lzma_ret(lzma_vli_encode(block_count, &in_pos, buf,
&out_pos, index_max_size), LZMA_STREAM_END);
// Next write out each Record.
// A Record consists of Unpadded Size and Uncompressed Size
// written next to each other as VLIs.
for (uint32_t i = 0; i < block_count; ++i) {
in_pos = 0;
assert_lzma_ret(lzma_vli_encode(unpadded_sizes[i], &in_pos,
buf, &out_pos, index_max_size), LZMA_STREAM_END);
in_pos = 0;
assert_lzma_ret(lzma_vli_encode(uncomp_sizes[i], &in_pos,
buf, &out_pos, index_max_size), LZMA_STREAM_END);
}
// Add Index Padding
lzma_vli rounded_out_pos = vli_ceil4(out_pos);
memzero(buf + out_pos, rounded_out_pos - out_pos);
out_pos = rounded_out_pos;
// Add the CRC32
write32le(buf + out_pos, lzma_crc32(buf, out_pos, 0));
out_pos += 4;
assert_uint_eq(out_pos, index_max_size);
}
#endif
static void
test_lzma_index_hash_decode(void)
{
#if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
assert_skip("Encoder or decoder support disabled");
#else
lzma_index_hash *index_hash = lzma_index_hash_init(NULL, NULL);
assert_true(index_hash != NULL);
size_t in_pos = 0;
// Six valid values for the Unpadded Size fields in an Index
const lzma_vli unpadded_sizes[6] = {
UNPADDED_SIZE_MIN,
1000,
4000,
8000,
16000,
32000
};
// Six valid values for the Uncompressed Size fields in an Index
const lzma_vli uncomp_sizes[6] = {
1,
500,
8000,
20,
1,
500
};
// Add two Records to an index_hash
fill_index_hash(index_hash, unpadded_sizes, uncomp_sizes, 2);
const lzma_vli size_two_records = lzma_index_hash_size(index_hash);
assert_uint(size_two_records, >, 0);
uint8_t *index_two_records = tuktest_malloc(size_two_records);
generate_index(index_two_records, unpadded_sizes, uncomp_sizes, 2,
size_two_records);
// First test for basic buffer size error
in_pos = size_two_records + 1;
assert_lzma_ret(lzma_index_hash_decode(index_hash,
index_two_records, &in_pos,
size_two_records), LZMA_BUF_ERROR);
// Next test for invalid Index Indicator
in_pos = 0;
index_two_records[0] ^= 1;
assert_lzma_ret(lzma_index_hash_decode(index_hash,
index_two_records, &in_pos,
size_two_records), LZMA_DATA_ERROR);
index_two_records[0] ^= 1;
// Next verify the index_hash as expected
in_pos = 0;
assert_lzma_ret(lzma_index_hash_decode(index_hash,
index_two_records, &in_pos,
size_two_records), LZMA_STREAM_END);
// Next test an index_hash with three Records
index_hash = lzma_index_hash_init(index_hash, NULL);
fill_index_hash(index_hash, unpadded_sizes, uncomp_sizes, 3);
const lzma_vli size_three_records = lzma_index_hash_size(
index_hash);
assert_uint(size_three_records, >, 0);
uint8_t *index_three_records = tuktest_malloc(size_three_records);
generate_index(index_three_records, unpadded_sizes, uncomp_sizes,
3, size_three_records);
in_pos = 0;
assert_lzma_ret(lzma_index_hash_decode(index_hash,
index_three_records, &in_pos,
size_three_records), LZMA_STREAM_END);
// Next test an index_hash with five Records
index_hash = lzma_index_hash_init(index_hash, NULL);
fill_index_hash(index_hash, unpadded_sizes, uncomp_sizes, 5);
const lzma_vli size_five_records = lzma_index_hash_size(
index_hash);
assert_uint(size_five_records, >, 0);
uint8_t *index_five_records = tuktest_malloc(size_five_records);
generate_index(index_five_records, unpadded_sizes, uncomp_sizes, 5,
size_five_records);
// Instead of testing all input at once, give input
// one byte at a time
in_pos = 0;
for (lzma_vli i = 0; i < size_five_records - 1; ++i) {
assert_lzma_ret(lzma_index_hash_decode(index_hash,
index_five_records, &in_pos, in_pos + 1),
LZMA_OK);
}
// Last byte should return LZMA_STREAM_END
assert_lzma_ret(lzma_index_hash_decode(index_hash,
index_five_records, &in_pos,
in_pos + 1), LZMA_STREAM_END);
// Next test if the index_hash is given an incorrect Unpadded
// Size. Should detect and report LZMA_DATA_ERROR
index_hash = lzma_index_hash_init(index_hash, NULL);
fill_index_hash(index_hash, unpadded_sizes, uncomp_sizes, 5);
// The sixth Record will have an invalid Unpadded Size
assert_lzma_ret(lzma_index_hash_append(index_hash,
unpadded_sizes[5] + 1,
uncomp_sizes[5]), LZMA_OK);
const lzma_vli size_six_records = lzma_index_hash_size(
index_hash);
assert_uint(size_six_records, >, 0);
uint8_t *index_six_records = tuktest_malloc(size_six_records);
generate_index(index_six_records, unpadded_sizes, uncomp_sizes, 6,
size_six_records);
in_pos = 0;
assert_lzma_ret(lzma_index_hash_decode(index_hash,
index_six_records, &in_pos,
size_six_records), LZMA_DATA_ERROR);
// Next test if the Index is corrupt (invalid CRC32).
// Should detect and report LZMA_DATA_ERROR
index_hash = lzma_index_hash_init(index_hash, NULL);
fill_index_hash(index_hash, unpadded_sizes, uncomp_sizes, 2);
index_two_records[size_two_records - 1] ^= 1;
in_pos = 0;
assert_lzma_ret(lzma_index_hash_decode(index_hash,
index_two_records, &in_pos,
size_two_records), LZMA_DATA_ERROR);
// Next test with Index and index_hash struct not matching
// a Record
index_hash = lzma_index_hash_init(index_hash, NULL);
fill_index_hash(index_hash, unpadded_sizes, uncomp_sizes, 2);
// Recalculate Index with invalid Unpadded Size
const lzma_vli unpadded_sizes_invalid[2] = {
unpadded_sizes[0],
unpadded_sizes[1] + 1
};
generate_index(index_two_records, unpadded_sizes_invalid,
uncomp_sizes, 2, size_two_records);
in_pos = 0;
assert_lzma_ret(lzma_index_hash_decode(index_hash,
index_two_records, &in_pos,
size_two_records), LZMA_DATA_ERROR);
lzma_index_hash_end(index_hash, NULL);
#endif
}
static void
test_lzma_index_hash_size(void)
{
#ifndef HAVE_DECODERS
assert_skip("Decoder support disabled");
#else
lzma_index_hash *index_hash = lzma_index_hash_init(NULL, NULL);
assert_true(index_hash != NULL);
// First test empty index_hash
// Expected size should be:
// Index Indicator - 1 byte
// Number of Records - 1 byte
// List of Records - 0 bytes
// Index Padding - 2 bytes
// CRC32 - 4 bytes
// Total - 8 bytes
assert_uint_eq(lzma_index_hash_size(index_hash), 8);
// Append a Record describing a small Block to the index_hash
assert_lzma_ret(lzma_index_hash_append(index_hash,
UNPADDED_SIZE_MIN, 1), LZMA_OK);
// Expected size should be:
// Index Indicator - 1 byte
// Number of Records - 1 byte
// List of Records - 2 bytes
// Index Padding - 0 bytes
// CRC32 - 4 bytes
// Total - 8 bytes
lzma_vli expected_size = 8;
assert_uint_eq(lzma_index_hash_size(index_hash), expected_size);
// Append additional small Record
assert_lzma_ret(lzma_index_hash_append(index_hash,
UNPADDED_SIZE_MIN, 1), LZMA_OK);
// Expected size should be:
// Index Indicator - 1 byte
// Number of Records - 1 byte
// List of Records - 4 bytes
// Index Padding - 2 bytes
// CRC32 - 4 bytes
// Total - 12 bytes
expected_size = 12;
assert_uint_eq(lzma_index_hash_size(index_hash), expected_size);
// Append a larger Record to the index_hash (3 bytes for each VLI)
const lzma_vli three_byte_vli = 0x10000;
assert_lzma_ret(lzma_index_hash_append(index_hash,
three_byte_vli, three_byte_vli), LZMA_OK);
// Expected size should be:
// Index Indicator - 1 byte
// Number of Records - 1 byte
// List of Records - 10 bytes
// Index Padding - 0 bytes
// CRC32 - 4 bytes
// Total - 16 bytes
expected_size = 16;
assert_uint_eq(lzma_index_hash_size(index_hash), expected_size);
lzma_index_hash_end(index_hash, NULL);
#endif
}
extern int
main(int argc, char **argv)
{
tuktest_start(argc, argv);
tuktest_run(test_lzma_index_hash_init);
tuktest_run(test_lzma_index_hash_append);
tuktest_run(test_lzma_index_hash_decode);
tuktest_run(test_lzma_index_hash_size);
return tuktest_end();
}

475
tests/test_lzip_decoder.c Normal file
View File

@ -0,0 +1,475 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file test_lzip_decoder.c
/// \brief Tests decoding lzip data
//
// Author: Jia Tan
//
// This file has been put into the public domain.
// You can do whatever you want with this file.
//
///////////////////////////////////////////////////////////////////////////////
#include "tests.h"
#ifdef HAVE_LZIP_DECODER
// Memlimit large enough to pass all of the test files
#define MEMLIMIT (1U << 20)
#define DECODE_CHUNK_SIZE 1024
// The uncompressed data in the test files are short US-ASCII strings.
// The tests check if the decompressed output is what it is expected to be.
// Storing the strings here as text would break the tests on EBCDIC systems
// and storing the strings as an array of hex values is inconvenient, so
// store the CRC32 values of the expected data instead.
//
// CRC32 value of "Hello\nWorld\n"
static const uint32_t hello_world_crc = 0x15A2A343;
// CRC32 value of "Trailing garbage\n"
static const uint32_t trailing_garbage_crc = 0x87081A60;
// Helper function to decode a good file with no flags and plenty high memlimit
static void
basic_lzip_decode(const char *src, const uint32_t expected_crc) {
size_t file_size;
uint8_t *data = tuktest_file_from_srcdir(src, &file_size);
uint32_t checksum = 0;
lzma_stream strm = LZMA_STREAM_INIT;
assert_lzma_ret(lzma_lzip_decoder(&strm, MEMLIMIT, 0), LZMA_OK);
uint8_t *output_buffer = tuktest_malloc(DECODE_CHUNK_SIZE);
strm.next_in = data;
strm.next_out = output_buffer;
strm.avail_out = DECODE_CHUNK_SIZE;
// Feed 1 byte at a time to the decoder to look for any bugs
// when switching between decoding sequences
lzma_ret ret = LZMA_OK;
while (ret == LZMA_OK) {
strm.avail_in = 1;
ret = lzma_code(&strm, LZMA_RUN);
if (strm.avail_out == 0) {
checksum = lzma_crc32(output_buffer,
strm.next_out - output_buffer,
checksum);
// No need to free output_buffer because it will
// automatically be freed at the end of the test by
// tuktest.
output_buffer = tuktest_malloc(DECODE_CHUNK_SIZE);
strm.next_out = output_buffer;
strm.avail_out = DECODE_CHUNK_SIZE;
}
}
assert_lzma_ret(ret, LZMA_STREAM_END);
assert_uint_eq(strm.total_in, file_size);
checksum = lzma_crc32(output_buffer, strm.next_out - output_buffer,
checksum);
assert_uint_eq(checksum, expected_crc);
lzma_end(&strm);
}
static void
test_options(void)
{
// Test NULL stream
assert_lzma_ret(lzma_lzip_decoder(NULL, MEMLIMIT, 0),
LZMA_PROG_ERROR);
// Test invalid flags
lzma_stream strm = LZMA_STREAM_INIT;
assert_lzma_ret(lzma_lzip_decoder(&strm, MEMLIMIT, UINT32_MAX),
LZMA_OPTIONS_ERROR);
// Memlimit tests are done elsewhere
}
static void
test_v0_decode(void) {
// This tests if liblzma can decode lzip version 0 files.
// lzip 1.17 and older can decompress this, but lzip 1.18
// and newer can no longer decode these files.
basic_lzip_decode("files/good-1-v0.lz", hello_world_crc);
}
static void
test_v1_decode(void) {
// This tests decoding a basic lzip v1 file
basic_lzip_decode("files/good-1-v1.lz", hello_world_crc);
}
// Helper function to decode a good file with trailing bytes after
// the lzip stream
static void
trailing_helper(const char *src, const uint32_t expected_data_checksum,
const uint32_t expected_trailing_checksum) {
size_t file_size;
uint32_t checksum = 0;
uint8_t *data = tuktest_file_from_srcdir(src, &file_size);
lzma_stream strm = LZMA_STREAM_INIT;
assert_lzma_ret(lzma_lzip_decoder(&strm, MEMLIMIT,
LZMA_CONCATENATED), LZMA_OK);
uint8_t *output_buffer = tuktest_malloc(DECODE_CHUNK_SIZE);
strm.next_in = data;
strm.next_out = output_buffer;
strm.avail_in = file_size;
strm.avail_out = DECODE_CHUNK_SIZE;
lzma_ret ret = LZMA_OK;
while (ret == LZMA_OK) {
ret = lzma_code(&strm, LZMA_RUN);
if (strm.avail_out == 0) {
checksum = lzma_crc32(output_buffer,
strm.next_out - output_buffer,
checksum);
// No need to free output_buffer because it will
// automatically be freed at the end of the test by
// tuktest.
output_buffer = tuktest_malloc(DECODE_CHUNK_SIZE);
strm.next_out = output_buffer;
strm.avail_out = DECODE_CHUNK_SIZE;
}
}
assert_lzma_ret(ret, LZMA_STREAM_END);
assert_uint(strm.total_in, <, file_size);
checksum = lzma_crc32(output_buffer,
strm.next_out - output_buffer,
checksum);
assert_uint_eq(checksum, expected_data_checksum);
// Trailing data should be readable from strm.next_in
checksum = lzma_crc32(strm.next_in, strm.avail_in, 0);
assert_uint_eq(checksum, expected_trailing_checksum);
lzma_end(&strm);
}
// Helper function to decode a bad file and compare to returned error to
// what the caller expects
static void
decode_expect_error(const char *src, lzma_ret expected_error)
{
lzma_stream strm = LZMA_STREAM_INIT;
size_t file_size;
uint8_t *data = tuktest_file_from_srcdir(src, &file_size);
assert_lzma_ret(lzma_lzip_decoder(&strm, MEMLIMIT,
LZMA_CONCATENATED), LZMA_OK);
uint8_t output_buffer[DECODE_CHUNK_SIZE];
strm.avail_in = file_size;
strm.next_in = data;
strm.avail_out = DECODE_CHUNK_SIZE;
strm.next_out = output_buffer;
lzma_ret ret = LZMA_OK;
while (ret == LZMA_OK) {
// Discard output since we are only looking for errors
strm.next_out = output_buffer;
strm.avail_out = DECODE_CHUNK_SIZE;
if (strm.avail_in == 0)
ret = lzma_code(&strm, LZMA_FINISH);
else
ret = lzma_code(&strm, LZMA_RUN);
}
assert_lzma_ret(ret, expected_error);
lzma_end(&strm);
}
static void
test_v0_trailing(void) {
trailing_helper("files/good-1-v0-trailing-1.lz", hello_world_crc,
trailing_garbage_crc);
}
static void
test_v1_trailing(void) {
trailing_helper("files/good-1-v1-trailing-1.lz", hello_world_crc,
trailing_garbage_crc);
// The second files/good-1-v1-trailing-2.lz will have the same
// expected output and trailing output as
// files/good-1-v1-trailing-1.lz, but this tests if the prefix
// to the trailing data contains lzip magic bytes.
// When this happens, the expected behavior is to silently ignore
// the magic byte prefix and consume it from the input file.
trailing_helper("files/good-1-v1-trailing-2.lz", hello_world_crc,
trailing_garbage_crc);
// Expect LZMA_BUF error if a file ends with the lzip magic bytes
// but does not contain any data after
decode_expect_error("files/bad-1-v1-trailing-magic.lz",
LZMA_BUF_ERROR);
}
static void
test_concatentated(void)
{
// First test a file with one v0 member and one v1 member
// The first member should contain "Hello\n" and
// the second member should contain "World!\n"
lzma_stream strm = LZMA_STREAM_INIT;
size_t file_size;
uint8_t *v0_v1 = tuktest_file_from_srcdir("files/good-2-v0-v1.lz",
&file_size);
assert_lzma_ret(lzma_lzip_decoder(&strm, MEMLIMIT,
LZMA_CONCATENATED), LZMA_OK);
uint8_t output_buffer[DECODE_CHUNK_SIZE];
strm.avail_in = file_size;
strm.next_in = v0_v1;
strm.avail_out = DECODE_CHUNK_SIZE;
strm.next_out = output_buffer;
assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_STREAM_END);
assert_uint_eq(strm.total_in, file_size);
uint32_t checksum = lzma_crc32(output_buffer, strm.total_out, 0);
assert_uint_eq(checksum, hello_world_crc);
// The second file contains one v1 member and one v2 member
uint8_t *v1_v0 = tuktest_file_from_srcdir("files/good-2-v1-v0.lz",
&file_size);
assert_lzma_ret(lzma_lzip_decoder(&strm, MEMLIMIT,
LZMA_CONCATENATED), LZMA_OK);
strm.avail_in = file_size;
strm.next_in = v1_v0;
strm.avail_out = DECODE_CHUNK_SIZE;
strm.next_out = output_buffer;
assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_STREAM_END);
assert_uint_eq(strm.total_in, file_size);
checksum = lzma_crc32(output_buffer, strm.total_out, 0);
assert_uint_eq(checksum, hello_world_crc);
// The third file contains 2 v1 members
uint8_t *v1_v1 = tuktest_file_from_srcdir("files/good-2-v1-v1.lz",
&file_size);
assert_lzma_ret(lzma_lzip_decoder(&strm, MEMLIMIT,
LZMA_CONCATENATED), LZMA_OK);
strm.avail_in = file_size;
strm.next_in = v1_v1;
strm.avail_out = DECODE_CHUNK_SIZE;
strm.next_out = output_buffer;
assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_STREAM_END);
assert_uint_eq(strm.total_in, file_size);
checksum = lzma_crc32(output_buffer, strm.total_out, 0);
assert_uint_eq(checksum, hello_world_crc);
lzma_end(&strm);
}
static void
test_crc(void) {
// Test invalid checksum
lzma_stream strm = LZMA_STREAM_INIT;
size_t file_size;
uint8_t *data = tuktest_file_from_srcdir("files/bad-1-v1-crc32.lz",
&file_size);
assert_lzma_ret(lzma_lzip_decoder(&strm, MEMLIMIT,
LZMA_CONCATENATED), LZMA_OK);
uint8_t output_buffer[DECODE_CHUNK_SIZE];
strm.avail_in = file_size;
strm.next_in = data;
strm.avail_out = DECODE_CHUNK_SIZE;
strm.next_out = output_buffer;
assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_DATA_ERROR);
// Test ignoring the checksum value - should decode successfully
assert_lzma_ret(lzma_lzip_decoder(&strm, MEMLIMIT,
LZMA_CONCATENATED | LZMA_IGNORE_CHECK), LZMA_OK);
strm.avail_in = file_size;
strm.next_in = data;
strm.avail_out = DECODE_CHUNK_SIZE;
strm.next_out = output_buffer;
assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_STREAM_END);
assert_uint_eq(strm.total_in, file_size);
// Test tell check
assert_lzma_ret(lzma_lzip_decoder(&strm, MEMLIMIT,
LZMA_CONCATENATED | LZMA_TELL_ANY_CHECK), LZMA_OK);
strm.avail_in = file_size;
strm.next_in = data;
strm.avail_out = DECODE_CHUNK_SIZE;
strm.next_out = output_buffer;
assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_GET_CHECK);
assert_uint_eq(lzma_get_check(&strm), LZMA_CHECK_CRC32);
assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_DATA_ERROR);
lzma_end(&strm);
}
static void
test_invalid_magic_bytes(void) {
uint8_t lzip_id_string[] = { 0x4C, 0x5A, 0x49, 0x50 };
lzma_stream strm = LZMA_STREAM_INIT;
for (uint32_t i = 0; i < ARRAY_SIZE(lzip_id_string); i++) {
// Corrupt magic bytes
lzip_id_string[i] ^= 1;
uint8_t output_buffer[DECODE_CHUNK_SIZE];
assert_lzma_ret(lzma_lzip_decoder(&strm, MEMLIMIT, 0),
LZMA_OK);
strm.next_in = lzip_id_string;
strm.avail_in = sizeof(lzip_id_string);
strm.next_out = output_buffer;
strm.avail_out = DECODE_CHUNK_SIZE;
assert_lzma_ret(lzma_code(&strm, LZMA_RUN),
LZMA_FORMAT_ERROR);
// Reset magic bytes
lzip_id_string[i] ^= 1;
}
lzma_end(&strm);
}
static void
test_invalid_version(void)
{
// The file contains a version number that is not 0 or 1,
// so it should cause an error
decode_expect_error("files/unsupported-1-v234.lz",
LZMA_OPTIONS_ERROR);
}
static void
test_invalid_dictionary_size(void) {
// First file has too small dictionary size field
decode_expect_error("files/bad-1-v1-dict-1.lz", LZMA_DATA_ERROR);
// Second file has too large dictionary size field
decode_expect_error("files/bad-1-v1-dict-2.lz", LZMA_DATA_ERROR);
}
static void
test_invalid_uncomp_size(void) {
// Test invalid v0 lzip file uncomp size
decode_expect_error("files/bad-1-v0-uncomp-size.lz",
LZMA_DATA_ERROR);
// Test invalid v1 lzip file uncomp size
decode_expect_error("files/bad-1-v1-uncomp-size.lz",
LZMA_DATA_ERROR);
}
static void
test_invalid_member_size(void) {
decode_expect_error("files/bad-1-v1-member-size.lz",
LZMA_DATA_ERROR);
}
static void
test_invalid_memlimit(void) {
// A very low memlimit should prevent decoding.
// Should be able to update the memlimit after failing
size_t file_size;
uint8_t *data = tuktest_file_from_srcdir("files/good-1-v1.lz",
&file_size);
uint8_t output_buffer[DECODE_CHUNK_SIZE];
lzma_stream strm = LZMA_STREAM_INIT;
assert_lzma_ret(lzma_lzip_decoder(&strm, 1, 0), LZMA_OK);
strm.next_in = data;
strm.avail_in = file_size;
strm.next_out = output_buffer;
strm.avail_out = DECODE_CHUNK_SIZE;
assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_MEMLIMIT_ERROR);
// Up the memlimit so decoding can continue.
// First only increase by a small amount and expect an error
assert_lzma_ret(lzma_memlimit_set(&strm, 100), LZMA_MEMLIMIT_ERROR);
assert_lzma_ret(lzma_memlimit_set(&strm, MEMLIMIT), LZMA_OK);
// Finish decoding
assert_lzma_ret(lzma_code(&strm, LZMA_FINISH), LZMA_STREAM_END);
assert_uint_eq(strm.total_in, file_size);
uint32_t checksum = lzma_crc32(output_buffer, strm.total_out, 0);
assert_uint_eq(checksum, hello_world_crc);
lzma_end(&strm);
}
#endif
extern int
main(int argc, char **argv)
{
tuktest_start(argc, argv);
#ifndef HAVE_LZIP_DECODER
tuktest_early_skip("lzip decoder disabled");
#else
tuktest_run(test_options);
tuktest_run(test_v0_decode);
tuktest_run(test_v1_decode);
tuktest_run(test_v0_trailing);
tuktest_run(test_v1_trailing);
tuktest_run(test_concatentated);
tuktest_run(test_crc);
tuktest_run(test_invalid_magic_bytes);
tuktest_run(test_invalid_version);
tuktest_run(test_invalid_dictionary_size);
tuktest_run(test_invalid_uncomp_size);
tuktest_run(test_invalid_member_size);
tuktest_run(test_invalid_memlimit);
return tuktest_end();
#endif
}

View File

@ -2,7 +2,7 @@
//
/// \file tuktest.h
/// \brief Helper macros for writing simple test programs
/// \version 2022-06-16
/// \version 2023-01-08
///
/// Some inspiration was taken from STest by Keith Nicholas.
///
@ -349,7 +349,7 @@ static struct tuktest_malloc_record *tuktest_malloc_global = NULL;
static void *
tuktest_malloc_impl(size_t size, const char *filename, unsigned line)
{
void *p = malloc(size);
void *p = malloc(size == 0 ? 1 : size);
struct tuktest_malloc_record *r = malloc(sizeof(*r));
if (p == NULL || r == NULL) {

View File

@ -18,7 +18,11 @@ Introduction
Building
--------
The following files in this directory are for MSVC:
It is recommended to use CMake to generate build files for MSVC.
The project files in vs201x directories will be removed in the
future (5.4.x releases will include them still).
Descriptions of the files in the vs201x directories:
config.h liblzma configuration #defines for MSVC.
liblzma.vcxproj This builds static liblzma.
@ -34,12 +38,8 @@ Building
This means that you may need to either install Windows SDK 8.1 or
you may need to set the target platform version before building.
Currently no test programs are built or run under MSVC.
MSVC gives a bunch of compiler warnings. Some warnings are specific
to 32-bit or 64-bit build and some appear for both builds. These
are known and shouldn't be a problem. Some of them will probably
be fixed in the future.
Currently no test programs are built or run under MSVC from the
project files. CMake-based builds include tests too.
Notes
@ -49,3 +49,8 @@ Notes
by default. To avoid this when using static liblzma from your code,
#define LZMA_API_STATIC before #including <lzma.h>.
MSVC gives a bunch of compiler warnings. Some warnings are specific
to 32-bit or 64-bit build and some appear for both builds. These
are known and shouldn't be a problem. Some of them will probably
be fixed in the future.

View File

@ -248,6 +248,7 @@
<ClCompile Include="..\..\src\liblzma\common\stream_buffer_decoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_buffer_encoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_decoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_decoder_mt.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_encoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_encoder_mt.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_flags_common.c" />

View File

@ -280,6 +280,7 @@
<ClCompile Include="..\..\src\liblzma\common\stream_buffer_decoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_buffer_encoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_decoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_decoder_mt.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_encoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_encoder_mt.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_flags_common.c" />

View File

@ -248,6 +248,7 @@
<ClCompile Include="..\..\src\liblzma\common\stream_buffer_decoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_buffer_encoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_decoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_decoder_mt.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_encoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_encoder_mt.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_flags_common.c" />

View File

@ -280,6 +280,7 @@
<ClCompile Include="..\..\src\liblzma\common\stream_buffer_decoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_buffer_encoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_decoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_decoder_mt.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_encoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_encoder_mt.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_flags_common.c" />

View File

@ -249,6 +249,7 @@
<ClCompile Include="..\..\src\liblzma\common\stream_buffer_decoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_buffer_encoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_decoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_decoder_mt.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_encoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_encoder_mt.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_flags_common.c" />

View File

@ -281,6 +281,7 @@
<ClCompile Include="..\..\src\liblzma\common\stream_buffer_decoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_buffer_encoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_decoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_decoder_mt.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_encoder.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_encoder_mt.c" />
<ClCompile Include="..\..\src\liblzma\common\stream_flags_common.c" />