From 039b23c9238cdf8995ad978ae6342957c2f819fa Mon Sep 17 00:00:00 2001 From: Xin LI Date: Sat, 25 Nov 2023 16:53:12 -0800 Subject: [PATCH] Vendor import of xz 5.4.5 (trimmed) --- ChangeLog | 870 ++++++++++++++++++++++- THANKS | 4 + doxygen/Doxyfile | 7 +- src/common/mythread.h | 2 +- src/common/sysdefs.h | 10 +- src/common/tuklib_integer.h | 294 ++++++-- src/liblzma/api/lzma.h | 4 +- src/liblzma/api/lzma/version.h | 4 +- src/liblzma/check/check.h | 7 + src/liblzma/check/crc64_fast.c | 8 + src/liblzma/check/crc64_table.c | 6 +- src/liblzma/common/common.c | 6 +- src/liblzma/common/common.h | 36 +- src/liblzma/common/index.c | 6 + src/liblzma/common/index.h | 2 +- src/liblzma/common/memcmplen.h | 2 +- src/liblzma/common/stream_flags_common.h | 3 + src/liblzma/liblzma.pc.in | 1 + src/liblzma/lz/lz_encoder_hash.h | 1 + src/liblzma/lzma/fastpos.h | 1 + src/liblzma/lzma/fastpos_tablegen.c | 2 + src/liblzma/rangecoder/price.h | 1 + src/lzmainfo/lzmainfo.c | 6 +- src/xz/coder.c | 3 +- src/xz/file_io.c | 40 +- src/xz/file_io.h | 4 +- src/xz/hardware.h | 3 +- src/xz/message.h | 30 +- src/xz/options.c | 3 +- src/xz/util.c | 89 +-- src/xz/util.h | 10 +- src/xz/xz.1 | 1 - src/xzdec/xzdec.c | 9 +- 33 files changed, 1301 insertions(+), 174 deletions(-) diff --git a/ChangeLog b/ChangeLog index 64c79dbce0bc..4dd0978ef313 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,870 @@ -commit c1e396a9ac1c1c28ce4ede5cbadb955c516477bc +commit 49053c0a649f4c8bd2b8d97ce915f401fbc0f3d9 +Author: Jia Tan +Date: 2023-10-31 22:30:29 +0800 + + Bump version and soname for 5.4.5. + + src/liblzma/Makefile.am | 2 +- + src/liblzma/api/lzma/version.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +commit 84c0cfc556287628df871703672879e530d0391f +Author: Jia Tan +Date: 2023-11-01 20:18:30 +0800 + + Add NEWS for 5.4.5. + + NEWS | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 74 insertions(+) + +commit d90ed84db9770712e2421e170076b43bda9b64a7 +Author: Lasse Collin +Date: 2023-10-31 21:41:09 +0200 + + liblzma: Fix compilation of fastpos_tablegen.c. + + The macro lzma_attr_visibility_hidden has to be defined to make + fastpos.h usable. The visibility attribute is irrelevant to + fastpos_tablegen.c so simply #define the macro to an empty value. + + fastpos_tablegen.c is never built by the included build systems + and so the problem wasn't noticed earlier. It's just a standalone + program for generating fastpos_table.c. + + Fixes: https://github.com/tukaani-project/xz/pull/69 + Thanks to GitHub user Jamaika1. + + src/liblzma/lzma/fastpos_tablegen.c | 2 ++ + 1 file changed, 2 insertions(+) + +commit 9b1268538b0b2c6c0a121f95165de65fc71ad23c +Author: Jia Tan +Date: 2023-10-31 21:51:40 +0800 + + Build: Fix text wrapping in an output message. + + configure.ac | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +commit 068ee436f4a8a706125ef43e8228b30001b1554e +Author: Lasse Collin +Date: 2023-10-22 17:59:11 +0300 + + liblzma: Use lzma_always_inline in memcmplen.h. + + src/liblzma/common/memcmplen.h | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +commit 6cdf0a7b7974baf58c1fd20ec3278f3b84ae56e5 +Author: Lasse Collin +Date: 2023-10-30 17:43:03 +0200 + + liblzma: #define lzma_always_inline in common.h. + + src/liblzma/common/common.h | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +commit 33daad3961a4f07f3902b40f13e823e6e43e85da +Author: Lasse Collin +Date: 2023-10-22 17:15:32 +0300 + + liblzma: Use lzma_attr_visibility_hidden on private extern declarations. + + These variables are internal to liblzma and not exposed in the API. + + src/liblzma/check/check.h | 7 +++++++ + src/liblzma/common/stream_flags_common.h | 3 +++ + src/liblzma/lz/lz_encoder_hash.h | 1 + + src/liblzma/lzma/fastpos.h | 1 + + src/liblzma/rangecoder/price.h | 1 + + 5 files changed, 13 insertions(+) + +commit 6961a5ac7df178bfc2b7a181c40575847bc3035f +Author: Lasse Collin +Date: 2023-10-22 17:08:39 +0300 + + liblzma: #define lzma_attr_visibility_hidden in common.h. + + In ELF shared libs: + + -fvisibility=hidden affects definitions of symbols but not + declarations.[*] This doesn't affect direct calls to functions + inside liblzma as a linker can replace a call to lzma_foo@plt + with a call directly to lzma_foo when -fvisibility=hidden is used. + + [*] It has to be like this because otherwise every installed + header file would need to explictly set the symbol visibility + to default. + + When accessing extern variables that aren't defined in the + same translation unit, compiler assumes that the variable has + the default visibility and thus indirection is needed. Unlike + function calls, linker cannot optimize this. + + Using __attribute__((__visibility__("hidden"))) with the extern + variable declarations tells the compiler that indirection isn't + needed because the definition is in the same shared library. + + About 15+ years ago, someone told me that it would be good if + the CRC tables would be defined in the same translation unit + as the C code of the CRC functions. While I understood that it + could help a tiny amount, I didn't want to change the code because + a separate translation unit for the CRC tables was needed for the + x86 assembly code anyway. But when visibility attributes are + supported, simply marking the extern declaration with the + hidden attribute will get identical result. When there are only + a few affected variables, this is trivial to do. I wish I had + understood this back then already. + + src/liblzma/common/common.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +commit 5b9e16764905d06fa8e8339ba185ddfee304e5fb +Author: Lasse Collin +Date: 2023-09-30 22:54:28 +0300 + + liblzma: Refer to MinGW-w64 instead of MinGW in the API headers. + + MinGW (formely a MinGW.org Project, later the MinGW.OSDN Project + at ) has GCC 9.2.0 as the + most recent GCC package (released 2021-02-02). The project might + still be alive but majority of people have switched to MinGW-w64. + Thus it seems clearer to refer to MinGW-w64 in our API headers too. + Building with MinGW is likely to still work but I haven't tested it + in the recent years. + + src/liblzma/api/lzma.h | 4 ++-- + src/liblzma/api/lzma/version.h | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +commit 36fabdbe67c8a8fbdc3ac695a91fc443a1328cc4 +Author: Lasse Collin +Date: 2023-09-27 00:58:17 +0300 + + CMake: Use -D_FILE_OFFSET_BITS=64 if (and only if) needed. + + A CMake option LARGE_FILE_SUPPORT is created if and only if + -D_FILE_OFFSET_BITS=64 affects sizeof(off_t). + + This is needed on many 32-bit platforms and even with 64-bit builds + with MinGW-w64 to get support for files larger than 2 GiB. + + CMakeLists.txt | 7 ++++- + cmake/tuklib_large_file_support.cmake | 52 +++++++++++++++++++++++++++++++++++ + 2 files changed, 58 insertions(+), 1 deletion(-) + +commit 989c8c354cbd2d20fbae4a432a3e31f5bc1cb9bf +Author: Lasse Collin +Date: 2023-09-30 02:14:25 +0300 + + CMake: Generate and install liblzma.pc if not using MSVC. + + Autotools based build uses -pthread and thus adds it to Libs.private + in liblzma.pc. CMake doesn't use -pthread at all if pthread functions + are available in libc so Libs.private doesn't get -pthread either. + + CMakeLists.txt | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +commit 983f3b458dc79c5976a4237fdfe4f8079f8d8830 +Author: Lasse Collin +Date: 2023-09-30 01:13:13 +0300 + + CMake: Rearrange the PACKAGE_ variables. + + The windres workaround now replaces spaces with \x20 so + the package name isn't repeated. + + These changes will help with creation of liblzma.pc. + + CMakeLists.txt | 26 +++++++++++++++----------- + 1 file changed, 15 insertions(+), 11 deletions(-) + +commit 4083c8e9501a48934a5fb563d2c3ce2ae143cd27 +Author: Lasse Collin +Date: 2023-09-29 20:46:11 +0300 + + liblzma: Add Cflags.private to liblzma.pc.in for MSYS2. + + It properly adds -DLZMA_API_STATIC when compiling code that + will be linked against static liblzma. Having it there on + systems other than Windows does no harm. + + See: https://www.msys2.org/docs/pkgconfig/ + + src/liblzma/liblzma.pc.in | 1 + + 1 file changed, 1 insertion(+) + +commit 661549ecb7a9b136d72a01c137d9776c75d52d51 +Author: Lasse Collin +Date: 2023-09-27 22:46:20 +0300 + + CMake: Create liblzma.def when building liblzma.dll with MinGW-w64. + + CMakeLists.txt | 20 ++++++++++++++++++++ + cmake/remove-ordinals.cmake | 26 ++++++++++++++++++++++++++ + 2 files changed, 46 insertions(+) + +commit 0e546eb4da05c52b7d257e5bd85e15c51c4d86a3 +Author: Lasse Collin +Date: 2023-10-26 21:44:42 +0300 + + CMake: Change one CMAKE_CURRENT_SOURCE_DIR to CMAKE_CURRENT_LIST_DIR. + + In this case they have identical values. + + CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit da4d04e4d6e199d28b58bd2e0df4e120c52dd5d7 +Author: Lasse Collin +Date: 2023-10-01 19:10:57 +0300 + + CMake/Windows: Fix the import library filename. + + Both PREFIX and IMPORT_PERFIX have to be set to "" to get + liblzma.dll and liblzma.dll.a. + + CMakeLists.txt | 1 + + 1 file changed, 1 insertion(+) + +commit 007558a358c48a0175cc8d47d11798d7967282ab +Author: Lasse Collin +Date: 2023-10-11 19:47:44 +0300 + + CMake: Don't shadow the cache entry ENABLE_THREADS with a normal variable. + + Using set(ENABLE_THREADS "posix") is confusing because it sets + a new normal variable and leaves the cache entry with the same + name unchanged. The intent wasn't to change the cache entry so + this switches to a different variable name. + + CMakeLists.txt | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +commit 7d01de67ee3dd76cfc12c23220e2e4cdc59708f1 +Author: Lasse Collin +Date: 2023-10-09 21:12:31 +0300 + + CMake: Edit threading related messages. + + It's mostly to change from "thread method" to "threading method". + + CMakeLists.txt | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +commit f8edcf3da689aad4b21e139197725450f2c456a0 +Author: Lasse Collin +Date: 2023-10-09 20:59:24 +0300 + + CMake: Use FATAL_ERROR if user-supplied options aren't understood. + + This way typos are caught quickly and compounding error messages + are avoided (a single typo could cause more than one error). + + This keeps using SEND_ERROR when the system is lacking a feature + (like threading library or sandboxing method). This way the whole + configuration log will be generated in case someone wishes to + report a problem upstream. + + CMakeLists.txt | 28 ++++++++++++++-------------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +commit 1695021e4a233a9388ddd428654c1447f0ea3bfb +Author: Jia Tan +Date: 2023-10-19 16:09:01 +0800 + + CMake: Add ALLOW_CLMUL_CRC option to enable/disable CLMUL. + + The option is enabled by default, but will only be visible to a user + listing cache variables or using a CMake GUI application if the + immintrin.h header file is found. + + This mirrors our Autotools build --disable-clmul-crc functionality. + + CMakeLists.txt | 40 +++++++++++++++++++++++----------------- + 1 file changed, 23 insertions(+), 17 deletions(-) + +commit 5056bc51071d1a07097c5667a0d5bd85242e31b9 +Author: Lasse Collin +Date: 2023-10-14 17:56:59 +0300 + + tuklib_integer: Revise unaligned reads and writes on strict-align archs. + + In XZ Utils context this doesn't matter much because + unaligned reads and writes aren't used in hot code + when TUKLIB_FAST_UNALIGNED_ACCESS isn't #defined. + + src/common/tuklib_integer.h | 256 ++++++++++++++++++++++++++++++++------------ + 1 file changed, 189 insertions(+), 67 deletions(-) + +commit 9e14743ee5ba79181076bc33952245d5b18fbc58 +Author: Lasse Collin +Date: 2023-09-23 02:21:49 +0300 + + tuklib_integer: Add missing write64be and write64le fallback functions. + + src/common/tuklib_integer.h | 34 ++++++++++++++++++++++++++++++++++ + 1 file changed, 34 insertions(+) + +commit 4cc91ceb3992ef4f51302b56178c3b2c2aeaaaad +Author: Jia Tan +Date: 2023-10-12 20:12:18 +0800 + + Build: Update visibility.m4 from Gnulib. + + Updating from version 6 -> 8 from upstream. Declarations for variables + and function bodies were added to avoid unnecessary failures with + -Werror. + + m4/visibility.m4 | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +commit 1824a6007cb1c8d5d7abcc7bf649148bc06fa72c +Author: Lasse Collin +Date: 2023-10-06 19:36:35 +0300 + + Update THANKS. + + THANKS | 1 + + 1 file changed, 1 insertion(+) + +commit 8fdc71a27d07b10a3da52432432e080b6d577642 +Author: Jia Tan +Date: 2023-09-29 20:14:39 +0800 + + CMake: Rename xz and man page symlink custom targets. + + The Ninja Generator for CMake cannot have a custom target and its + BYPRODUCTS have the same name. This has prevented Ninja builds on + Unix-like systems since the xz symlinks were introduced in + 80a1a8bb838842a2be343bd88ad1462c21c5e2c9. + + CMakeLists.txt | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit 38171492ded6426ddf53d0c200fa8c93fcd02a60 +Author: Lasse Collin +Date: 2023-09-27 19:54:35 +0300 + + CMake: Fix Windows build with Clang/LLVM 17. + + llvm-windres 17.0.0 has more accurate emulation of GNU windres, so + the hack for GNU windres must now be used with llvm-windres too. + + LLVM 16.0.6 has the old behavior and there likely won't be more + 16.x releases. So we can simply check for >= 17.0.0. + + The workaround must not be used with Clang that is acting in + MSVC mode. This checks for the known environments that need + the workaround instead of using "NOT MSVC". + + See also: + https://github.com/llvm/llvm-project/commit/2bcc0fdc58a220cb9921b47ec8a32c85f2511a47 + + CMakeLists.txt | 26 ++++++++++++++------------ + 1 file changed, 14 insertions(+), 12 deletions(-) + +commit 1bce6fe48334b5df33d0487a9cbe41950122230e +Author: Jia Tan +Date: 2023-09-27 00:02:11 +0800 + + liblzma: Avoid compiler warning without creating extra symbol. + + When the generic fast crc64 method is used, then we omit + lzma_crc64_table[][]. + + The C standards don't allow an empty translation unit which can be + avoided by declaring something, without exporting any symbols. + + src/liblzma/check/crc64_table.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +commit dce95a593e6cd9779110aa1e314abd8b35c75f6b +Author: Lasse Collin +Date: 2023-09-26 17:24:15 +0300 + + Build: Update the comment about -Werror usage in checks. + + configure.ac | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +commit f3c32762ae309afa2fe330e7fb397acfdedc4d37 +Author: Lasse Collin +Date: 2023-09-26 13:51:31 +0300 + + Build: Fix underquoted AC_LANG_SOURCE. + + It made no practical difference in this case. + + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 7dd57f2f2c8fde93fa42b4dbf6d9860717723b41 +Author: Lasse Collin +Date: 2023-09-26 13:14:37 +0300 + + Build: Silence Autoconf warning. + + There was a use of AC_COMPILE_IFELSE that didn't use + AC_LANG_SOURCE and Autoconf warned about this. The omission + had been intentional but it turned out that this didn't do + what I thought it would. + + Autoconf 2.71 manual gives an impression that AC_LANG_SOURCE + inserts all #defines that have been made with AC_DEFINE so + far (confdefs.h). The idea was that omitting AC_LANG_SOURCE + would mean that only the exact code included in the + AC_COMPILE_IFELSE call would be compiled. + + With C programs this is not true: the #defines get added without + AC_LANG_SOURCE too. There seems to be no neat way to avoid this. + Thus, with the C language at least, adding AC_LANG_SOURCE makes + no other difference than silencing a warning from Autoconf. The + generated "configure" remains identical. (Docs of AC_LANG_CONFTEST + say that the #defines have been inserted since Autoconf 2.63b and + that AC_COMPILE_IFELSE uses AC_LANG_CONFTEST. So the behavior is + documented if one also reads the docs of macros that one isn't + calling directly.) + + Any extra code, including #defines, can cause problems for + these two tests because these tests must use -Werror. + CC=clang CFLAGS=-Weverything is the most extreme example. + It enables -Wreserved-macro-identifier which warns about + It's possible to write a test file that passes -Weverything but + it becomes impossible when Autoconf inserts confdefs.h. + + So this commit adds AC_LANG_SOURCE to silence Autoconf warnings. + A different solution is needed for -Werror tests. + + configure.ac | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +commit edec253e418562f3164a01ecc8805295fa022efa +Author: Jia Tan +Date: 2023-09-26 00:47:26 +0800 + + Build: Remove Gnulib dependency from tests. + + The tests do not use any Gnulib replacements so they do not need to link + libgnu.a or have /lib in the include path. + + tests/Makefile.am | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +commit 46cb133ce7360496eecca1255b364c05f0205855 +Author: Jia Tan +Date: 2023-09-26 00:43:43 +0800 + + CMake: Remove /lib from tests include path. + + The tests never included anything from /lib, so this was not needed. + + CMakeLists.txt | 1 - + 1 file changed, 1 deletion(-) + +commit 4ae13cfe0dedb8ddc3cf9ded8cd1ac09361b3bd1 +Author: Lasse Collin +Date: 2023-09-24 16:32:32 +0300 + + sysdefs.h: Update the comment about __USE_MINGW_ANSI_STDIO. + + src/common/sysdefs.h | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +commit 660c8c29e57d30dbd5009ef1f0ec1bbe195ccef6 +Author: Lasse Collin +Date: 2023-09-22 02:33:29 +0300 + + xz: Windows: Don't (de)compress to special files like "con" or "nul". + + Before this commit, the following writes "foo" to the + console and deletes the input file: + + echo foo | xz > con_xz + xz --suffix=_xz --decompress con_xz + + It cannot happen without --suffix because names like con.xz + are also special and so attempting to decompress con.xz + (or compress con to con.xz) will already fail when opening + the input file. + + Similar thing is possible when compressing. The following + writes to "nul" and the input file "n" is deleted. + + echo foo | xz > n + xz --suffix=ul n + + Now xz checks if the destination is a special file before + continuing. DOS/DJGPP version had a check for this but + Windows (and OS/2) didn't. + + src/xz/file_io.c | 35 ++++++++++++++++++++++++++++------- + 1 file changed, 28 insertions(+), 7 deletions(-) + +commit b7ce6e80786fc0c08ed129e8ee262ea96a5473a1 +Author: Lasse Collin +Date: 2023-09-21 20:42:52 +0300 + + CMake: Wrap two overlong lines that are possible to wrap. + + CMakeLists.txt | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +commit 1595f454d5c8257c668cccd6a86dd68175d5c430 +Author: Lasse Collin +Date: 2023-09-21 20:36:31 +0300 + + CMake: Add a comment about threads on Cygwin. + + CMakeLists.txt | 1 + + 1 file changed, 1 insertion(+) + +commit 5be6275f19784cdd5a954f0188045c8ff4934d54 +Author: Lasse Collin +Date: 2023-09-12 21:12:34 +0300 + + CMake: Bump maximum policy version to 3.27. + + There are several new policies. CMP0149 may affect the Windows SDK + version that CMake will choose by default. The new behavior is more + predictable, always choosing the latest SDK version by default. + + The other new policies shouldn't affect this package. + + CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit e515643d7524851d1eb7dab73453e26d8521324c +Author: Lasse Collin +Date: 2023-09-08 19:08:57 +0300 + + Doxygen: Add more C macro names to PREDEFINED. + + doxygen/Doxyfile | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +commit e3478ae4f36cd06522a2fef023860893f068434d +Author: Lasse Collin +Date: 2023-09-11 18:47:26 +0300 + + liblzma: Move a few __attribute__ uses in function declarations. + + The API headers have many attributes but these were left + as is for now. + + src/liblzma/common/common.c | 6 ++++-- + src/liblzma/common/common.h | 8 ++++---- + src/liblzma/common/memcmplen.h | 3 ++- + 3 files changed, 10 insertions(+), 7 deletions(-) + +commit b71b8922ef3971e5ccffd1e213888d44abe21d11 +Author: Lasse Collin +Date: 2023-09-11 19:03:35 +0300 + + xz, xzdec, lzmainfo: Use tuklib_attr_noreturn. + + For compatibility with C23's [[noreturn]], tuklib_attr_noreturn + must be at the beginning of declaration (before "extern" or + "static", and even before any GNU C's __attribute__). + + This commit also moves all other function attributes to + the beginning of function declarations. "extern" is kept + at the beginning of a line so the attributes are listed on + separate lines before "extern" or "static". + + src/lzmainfo/lzmainfo.c | 6 ++++-- + src/xz/coder.c | 3 ++- + src/xz/hardware.h | 3 ++- + src/xz/message.h | 30 +++++++++++++++++------------- + src/xz/options.c | 3 ++- + src/xz/util.h | 8 ++++---- + src/xzdec/xzdec.c | 9 ++++++--- + 7 files changed, 37 insertions(+), 25 deletions(-) + +commit 359e5c6cb128dab64ea6070d21d1c240f96cea6b +Author: Lasse Collin +Date: 2023-09-11 18:53:31 +0300 + + Remove incorrect uses of __attribute__((__malloc__)). + + xrealloc() is obviously incorrect, modern GCC docs even + mention realloc() as an example where this attribute + cannot be used. + + liblzma's lzma_alloc() and lzma_alloc_zero() would be + correct uses most of the time but custom allocators + may use a memory pool or otherwise hold the pointer + so aliasing issues could happen in theory. + + The xstrdup() case likely was correct but I removed it anyway. + Now there are no __malloc__ attributes left in the code. + The allocations aren't in hot paths so this should make + no practical difference. + + src/liblzma/common/common.c | 4 ++-- + src/liblzma/common/common.h | 4 ++-- + src/xz/util.h | 4 ++-- + 3 files changed, 6 insertions(+), 6 deletions(-) + +commit 589b4cba22fccb1dbc919df5d134aefb2b5a6b01 +Author: Lasse Collin +Date: 2023-09-19 14:03:45 +0300 + + Update THANKS. + + THANKS | 1 + + 1 file changed, 1 insertion(+) + +commit 43728ed2267e921fbdfa699ee1e91b105ab0e98b +Author: Lasse Collin +Date: 2023-09-14 16:35:46 +0300 + + Update THANKS. + + THANKS | 1 + + 1 file changed, 1 insertion(+) + +commit caf00e0988ba47842cfd93dfbb17f7d30120d6e7 +Author: Lasse Collin +Date: 2023-09-14 16:34:07 +0300 + + liblzma: Mark crc64_clmul() with __attribute__((__no_sanitize_address__)). + + Thanks to Agostino Sarubbo. + Fixes: https://github.com/tukaani-project/xz/issues/62 + + src/liblzma/check/crc64_fast.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +commit a70e96d2da761b8b3a77bf14e08002d871e5950b +Author: Jia Tan +Date: 2023-09-12 22:36:12 +0800 + + CMake: Fix time.h checks not running on second CMake run. + + If CMake was configured more than once, HAVE_CLOCK_GETTIME and + HAVE_CLOCK_MONOTONIC would not be set as compile definitions. The check + for librt being needed to provide HAVE_CLOCK_GETTIME was also + simplified. + + CMakeLists.txt | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +commit d5275d83bd2a9701c5feb8666785007c074b1359 +Author: Jia Tan +Date: 2023-09-12 22:34:06 +0800 + + CMake: Fix unconditionally defining HAVE_CLOCK_MONOTONIC. + + If HAVE_CLOCK_GETTIME was defined, then HAVE_CLOCK_MONOTONIC was always + added as a compile definition even if the check for it failed. + + CMakeLists.txt | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +commit 1f6e7c68fbdeeaa9482fc77de090be63d90912fd +Author: Lasse Collin +Date: 2023-08-31 19:50:05 +0300 + + xz: Refactor thousand separator detection and disable it on MSVC. + + Now the two variations of the format strings are created with + a macro, and the whole detection code can be easily disabled + on platforms where thousand separator formatting is known to + not work (MSVC has no support, and on DJGPP 2.05 it can have + problems in some cases). + + src/xz/util.c | 89 ++++++++++++++++++++++++++++++----------------------------- + 1 file changed, 45 insertions(+), 44 deletions(-) + +commit ef71f83973a20cc28a3221f85681922026ea33f5 +Author: Lasse Collin +Date: 2023-08-31 18:14:43 +0300 + + xz: Fix a too relaxed assertion and remove uses of SSIZE_MAX. + + SSIZE_MAX isn't readily available on MSVC. Removing it means + that there is one thing less to worry when porting to MSVC. + + src/xz/file_io.c | 5 ++--- + src/xz/file_io.h | 4 ++-- + 2 files changed, 4 insertions(+), 5 deletions(-) + +commit cf8ba7c3a89e37736b926dfbe85dffeff725db47 +Author: Jia Tan +Date: 2023-08-28 23:14:45 +0800 + + Tests: Improve invalid unpadded size check in test_lzma_index_append(). + + This check was extended to test the code added to fix a failing assert + in 68bda971bb8b666a009331455fcedb4e18d837a4. + + tests/test_index.c | 26 +++++++++++++++++++++++--- + 1 file changed, 23 insertions(+), 3 deletions(-) + +commit 4a4180ce74788e97e90b9aab579bfd7c6dce3f59 +Author: Jia Tan +Date: 2023-08-28 21:54:41 +0800 + + Tests: Improve comments in test_index.c. + + tests/test_index.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +commit 4b23b84b89e39a5117e16f66c3b01db4f08ed3e7 +Author: Jia Tan +Date: 2023-08-28 21:52:54 +0800 + + Update THANKS. + + THANKS | 1 + + 1 file changed, 1 insertion(+) + +commit 773f1e8622cb1465df528cb16a749517650acd93 +Author: Jia Tan +Date: 2023-08-28 21:50:16 +0800 + + liblzma: Update assert in vli_ceil4(). + + The argument to vli_ceil4() should always guarantee the return value + is also a valid lzma_vli. Thus the highest three valid lzma_vli values + are invalid arguments. All uses of the function ensure this so the + assert is updated to match this. + + src/liblzma/common/index.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 68bda971bb8b666a009331455fcedb4e18d837a4 +Author: Jia Tan +Date: 2023-08-28 21:31:25 +0800 + + liblzma: Add overflow check for Unpadded size in lzma_index_append(). + + This was not a security bug since there was no path to overflow + UINT64_MAX in lzma_index_append() or when it calls index_file_size(). + The bug was discovered by a failing assert() in vli_ceil4() when called + from index_file_size() when unpadded_sum (the sum of the compressed size + of current Stream and the unpadded_size parameter) exceeds LZMA_VLI_MAX. + + Previously, the unpadded_size parameter was checked to be not greater + than UNPADDED_SIZE_MAX, but no check was done once compressed_base was + added. + + This could not have caused an integer overflow in index_file_size() when + called by lzma_index_append(). The calculation for file_size breaks down + into the sum of: + + - Compressed base from all previous Streams + - 2 * LZMA_STREAM_HEADER_SIZE (size of the current Streams header and + footer) + - stream_padding (can be set by lzma_index_stream_padding()) + - Compressed base from the current Stream + - Unpadded size (parameter to lzma_index_append()) + + The sum of everything except for Unpadded size must be less than + LZMA_VLI_MAX. This is guarenteed by overflow checks in the functions + that can set these values including lzma_index_stream_padding(), + lzma_index_append(), and lzma_index_cat(). The maximum value for + Unpadded size is enforced by lzma_index_append() to be less than or + equal UNPADDED_SIZE_MAX. Thus, the sum cannot exceed UINT64_MAX since + LZMA_VLI_MAX is half of UINT64_MAX. + + Thanks to Joona Kannisto for reporting this. + + src/liblzma/common/index.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +commit b41bb79c602481d7ea93d65f5b3e3f08dc54233b +Author: Jia Tan +Date: 2023-08-28 22:18:29 +0800 + + Translations: Update the Esperanto translation. + + po/eo.po | 47 +++++++++++++++++++++++++++++------------------ + 1 file changed, 29 insertions(+), 18 deletions(-) + +commit 6614e6d4bf8e2b5af6eb73930148e0ffc8d2265a +Author: Jia Tan +Date: 2023-08-09 20:55:36 +0800 + + Docs: Update INSTALL for --enable-threads method win95. + + The Autotools build allows win95 threads and --enable-small together now + if the compiler supports __attribute__((__constructor__)). + + INSTALL | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +commit bfb623ad96fa6f1dbc0c560403c4296e3c8e26c9 +Author: Jia Tan +Date: 2023-08-09 20:54:15 +0800 + + CMake: Conditionally allow win95 threads and --enable-small. + + CMakeLists.txt | 27 +++++++++++++++++++-------- + 1 file changed, 19 insertions(+), 8 deletions(-) + +commit e919ebb29ac9f5270cd7176a39d0d3b4cea875a9 +Author: Jia Tan +Date: 2023-08-09 20:35:16 +0800 + + Build: Conditionally allow win95 threads and --enable-small. + + When the compiler supports __attribute__((__constructor__)) + mythread_once() is never used, even with --enable-small. A configuration + with win95 threads and --enable-small will compile and be thread safe so + it can be allowed. + + This isn't a very common configuration since MSVC does not support + __attribute__((__constructor__)), but MINGW32 and CLANG32 environments + for MSYS2 can use win95 threads and have + __attribute__((__constructor__)) support. + + configure.ac | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +commit c0c0cd4a483a672b66a13761583bc4f84d86d501 +Author: Jamaika1 +Date: 2023-08-08 14:07:59 +0200 + + mythread.h: Fix typo error in Vista threads mythread_once(). + + The "once_" variable was accidentally referred to as just "once". This + prevented building with Vista threads when + HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR was not defined. + + src/common/mythread.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit d93fbefcc48a8737fdf5678ce66d1c1d605752a0 +Author: Jia Tan +Date: 2023-08-03 20:10:21 +0800 + + Tests: Style fixes to test_lzip_decoder.c. + + tests/test_lzip_decoder.c | 36 ++++++++++++++++++++++++------------ + 1 file changed, 24 insertions(+), 12 deletions(-) + +commit 65981d8e45741fd1502e007609469e1d60312e69 +Author: Jia Tan +Date: 2023-08-03 15:56:20 +0800 + + Translations: Update the Chinese (simplified) translation. + + po/zh_CN.po | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit a108ed589171d683c34238a87e358b87f69e39a0 +Author: Lasse Collin +Date: 2023-08-02 17:15:12 +0300 + + xz: Omit an empty paragraph on the man page. + + src/xz/xz.1 | 1 - + 1 file changed, 1 deletion(-) + +commit 03c51c5c08fe3579d8bbc8eea8251a1128001330 Author: Jia Tan Date: 2023-08-02 20:32:20 +0800 @@ -8,7 +874,7 @@ Date: 2023-08-02 20:32:20 +0800 src/liblzma/api/lzma/version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) -commit 7d266d25ae323a2dc5f2e254c991ef84b997adad +commit d7fa3f1b58a77f79b1a4e12452418b5555632e18 Author: Jia Tan Date: 2023-08-02 20:30:07 +0800 diff --git a/THANKS b/THANKS index cf7c59c844c5..0206af938f1a 100644 --- a/THANKS +++ b/THANKS @@ -19,6 +19,7 @@ has been important. :-) In alphabetical order: - Jakub Bogusz - Adam Borowski - Maarten Bosmans + - Lukas Braune - Benjamin Buch - Trent W. Buck - Kevin R. Bulgrien @@ -64,6 +65,7 @@ has been important. :-) In alphabetical order: - Jouk Jansen - Jun I Jin - Kiyoshi Kanazawa + - Joona Kannisto - Per Øyvind Karlsen - Iouri Kharon - Thomas Klausner @@ -127,6 +129,7 @@ has been important. :-) In alphabetical order: - Torsten Rupp - Stephen Sachs - Jukka Salmi + - Agostino Sarubbo - Alexandre Sauvé - Benno Schulenberg - Andreas Schwab @@ -138,6 +141,7 @@ has been important. :-) In alphabetical order: - Brad Smith - Bruce Stark - Pippijn van Steenhoven + - Martin Storsjö - Jonathan Stott - Dan Stromberg - Jia Tan diff --git a/doxygen/Doxyfile b/doxygen/Doxyfile index 20afb528e4f4..14350cf44f64 100644 --- a/doxygen/Doxyfile +++ b/doxygen/Doxyfile @@ -2277,8 +2277,11 @@ INCLUDE_FILE_PATTERNS = # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. PREDEFINED = LZMA_API(type)=type \ - LZMA_API_IMPORT \ - LZMA_API_CALL= + LZMA_API_IMPORT= \ + LZMA_API_CALL= \ + tuklib_attr_noreturn= \ + lzma_attribute(attr)= \ + lzma_attr_alloc_size(size)= # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The diff --git a/src/common/mythread.h b/src/common/mythread.h index 1cce50e9fd85..4495e017b290 100644 --- a/src/common/mythread.h +++ b/src/common/mythread.h @@ -378,7 +378,7 @@ typedef struct { abort(); \ if (pending_) { \ func(); \ - if (!InitOnceComplete(&once, 0, NULL)) \ + if (!InitOnceComplete(&once_, 0, NULL)) \ abort(); \ } \ } while (0) diff --git a/src/common/sysdefs.h b/src/common/sysdefs.h index 97be4ee380d0..f04e45dd2147 100644 --- a/src/common/sysdefs.h +++ b/src/common/sysdefs.h @@ -24,7 +24,15 @@ # include #endif -// Get standard-compliant stdio functions under MinGW and MinGW-w64. +// This #define ensures that C99 and POSIX compliant stdio functions are +// available with MinGW-w64 (both 32-bit and 64-bit). Modern MinGW-w64 adds +// this automatically, for example, when the compiler is in C99 (or later) +// mode when building against msvcrt.dll. It still doesn't hurt to be explicit +// that we always want this and #define this unconditionally. +// +// With Universal CRT (UCRT) this is less important because UCRT contains +// C99-compatible stdio functions. It's still nice to #define this as UCRT +// doesn't support the POSIX thousand separator flag in printf (like "%'u"). #ifdef __MINGW32__ # define __USE_MINGW_ANSI_STDIO 1 #endif diff --git a/src/common/tuklib_integer.h b/src/common/tuklib_integer.h index 24d9efb1165a..e22aa8ad83b2 100644 --- a/src/common/tuklib_integer.h +++ b/src/common/tuklib_integer.h @@ -195,6 +195,9 @@ // Unaligned reads and writes // //////////////////////////////// +// No-strict-align archs like x86-64 +// --------------------------------- +// // The traditional way of casting e.g. *(const uint16_t *)uint8_pointer // is bad even if the uint8_pointer is properly aligned because this kind // of casts break strict aliasing rules and result in undefined behavior. @@ -209,12 +212,115 @@ // build time. A third method, casting to a packed struct, would also be // an option but isn't provided to keep things simpler (it's already a mess). // Hopefully this is flexible enough in practice. +// +// Some compilers on x86-64 like Clang >= 10 and GCC >= 5.1 detect that +// +// buf[0] | (buf[1] << 8) +// +// reads a 16-bit value and can emit a single 16-bit load and produce +// identical code than with the memcpy() method. In other cases Clang and GCC +// produce either the same or better code with memcpy(). For example, Clang 9 +// on x86-64 can detect 32-bit load but not 16-bit load. +// +// MSVC uses unaligned access with the memcpy() method but emits byte-by-byte +// code for "buf[0] | (buf[1] << 8)". +// +// Conclusion: The memcpy() method is the best choice when unaligned access +// is supported. +// +// Strict-align archs like SPARC +// ----------------------------- +// +// GCC versions from around 4.x to to at least 13.2.0 produce worse code +// from the memcpy() method than from simple byte-by-byte shift-or code +// when reading a 32-bit integer: +// +// (1) It may be constructed on stack using using four 8-bit loads, +// four 8-bit stores to stack, and finally one 32-bit load from stack. +// +// (2) Especially with -Os, an actual memcpy() call may be emitted. +// +// This is true on at least on ARM, ARM64, SPARC, SPARC64, MIPS64EL, and +// RISC-V. Of these, ARM, ARM64, and RISC-V support unaligned access in +// some processors but not all so this is relevant only in the case when +// GCC assumes that unaligned is not supported or -mstrict-align or +// -mno-unaligned-access is used. +// +// For Clang it makes little difference. ARM64 with -O2 -mstrict-align +// was one the very few with a minor difference: the memcpy() version +// was one instruction longer. +// +// Conclusion: At least in case of GCC and Clang, byte-by-byte code is +// the best choise for strict-align archs to do unaligned access. +// +// See also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111502 +// +// Thanks to it was easy to test different compilers. +// The following is for little endian targets: +/* +#include +#include + +uint32_t bytes16(const uint8_t *b) +{ + return (uint32_t)b[0] + | ((uint32_t)b[1] << 8); +} + +uint32_t copy16(const uint8_t *b) +{ + uint16_t v; + memcpy(&v, b, sizeof(v)); + return v; +} + +uint32_t bytes32(const uint8_t *b) +{ + return (uint32_t)b[0] + | ((uint32_t)b[1] << 8) + | ((uint32_t)b[2] << 16) + | ((uint32_t)b[3] << 24); +} + +uint32_t copy32(const uint8_t *b) +{ + uint32_t v; + memcpy(&v, b, sizeof(v)); + return v; +} + +void wbytes16(uint8_t *b, uint16_t v) +{ + b[0] = (uint8_t)v; + b[1] = (uint8_t)(v >> 8); +} + +void wcopy16(uint8_t *b, uint16_t v) +{ + memcpy(b, &v, sizeof(v)); +} + +void wbytes32(uint8_t *b, uint32_t v) +{ + b[0] = (uint8_t)v; + b[1] = (uint8_t)(v >> 8); + b[2] = (uint8_t)(v >> 16); + b[3] = (uint8_t)(v >> 24); +} + +void wcopy32(uint8_t *b, uint32_t v) +{ + memcpy(b, &v, sizeof(v)); +} +*/ + + +#ifdef TUKLIB_FAST_UNALIGNED_ACCESS static inline uint16_t read16ne(const uint8_t *buf) { -#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \ - && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) +#ifdef TUKLIB_USE_UNSAFE_TYPE_PUNNING return *(const uint16_t *)buf; #else uint16_t num; @@ -227,8 +333,7 @@ read16ne(const uint8_t *buf) static inline uint32_t read32ne(const uint8_t *buf) { -#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \ - && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) +#ifdef TUKLIB_USE_UNSAFE_TYPE_PUNNING return *(const uint32_t *)buf; #else uint32_t num; @@ -241,8 +346,7 @@ read32ne(const uint8_t *buf) static inline uint64_t read64ne(const uint8_t *buf) { -#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \ - && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) +#ifdef TUKLIB_USE_UNSAFE_TYPE_PUNNING return *(const uint64_t *)buf; #else uint64_t num; @@ -255,8 +359,7 @@ read64ne(const uint8_t *buf) static inline void write16ne(uint8_t *buf, uint16_t num) { -#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \ - && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) +#ifdef TUKLIB_USE_UNSAFE_TYPE_PUNNING *(uint16_t *)buf = num; #else memcpy(buf, &num, sizeof(num)); @@ -268,8 +371,7 @@ write16ne(uint8_t *buf, uint16_t num) static inline void write32ne(uint8_t *buf, uint32_t num) { -#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \ - && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) +#ifdef TUKLIB_USE_UNSAFE_TYPE_PUNNING *(uint32_t *)buf = num; #else memcpy(buf, &num, sizeof(num)); @@ -281,8 +383,7 @@ write32ne(uint8_t *buf, uint32_t num) static inline void write64ne(uint8_t *buf, uint64_t num) { -#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \ - && defined(TUKLIB_USE_UNSAFE_TYPE_PUNNING) +#ifdef TUKLIB_USE_UNSAFE_TYPE_PUNNING *(uint64_t *)buf = num; #else memcpy(buf, &num, sizeof(num)); @@ -294,68 +395,122 @@ write64ne(uint8_t *buf, uint64_t num) static inline uint16_t read16be(const uint8_t *buf) { -#if defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS) uint16_t num = read16ne(buf); return conv16be(num); -#else - uint16_t num = ((uint16_t)buf[0] << 8) | (uint16_t)buf[1]; - return num; -#endif } static inline uint16_t read16le(const uint8_t *buf) { -#if !defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS) uint16_t num = read16ne(buf); return conv16le(num); -#else - uint16_t num = ((uint16_t)buf[0]) | ((uint16_t)buf[1] << 8); - return num; -#endif } static inline uint32_t read32be(const uint8_t *buf) { -#if defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS) uint32_t num = read32ne(buf); return conv32be(num); -#else - uint32_t num = (uint32_t)buf[0] << 24; - num |= (uint32_t)buf[1] << 16; - num |= (uint32_t)buf[2] << 8; - num |= (uint32_t)buf[3]; - return num; -#endif } static inline uint32_t read32le(const uint8_t *buf) { -#if !defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS) uint32_t num = read32ne(buf); return conv32le(num); -#else - uint32_t num = (uint32_t)buf[0]; - num |= (uint32_t)buf[1] << 8; - num |= (uint32_t)buf[2] << 16; - num |= (uint32_t)buf[3] << 24; - return num; -#endif } static inline uint64_t read64be(const uint8_t *buf) { -#if defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS) uint64_t num = read64ne(buf); return conv64be(num); +} + + +static inline uint64_t +read64le(const uint8_t *buf) +{ + uint64_t num = read64ne(buf); + return conv64le(num); +} + + +// NOTE: Possible byte swapping must be done in a macro to allow the compiler +// to optimize byte swapping of constants when using glibc's or *BSD's +// byte swapping macros. The actual write is done in an inline function +// to make type checking of the buf pointer possible. +#define write16be(buf, num) write16ne(buf, conv16be(num)) +#define write32be(buf, num) write32ne(buf, conv32be(num)) +#define write64be(buf, num) write64ne(buf, conv64be(num)) +#define write16le(buf, num) write16ne(buf, conv16le(num)) +#define write32le(buf, num) write32ne(buf, conv32le(num)) +#define write64le(buf, num) write64ne(buf, conv64le(num)) + #else + +#ifdef WORDS_BIGENDIAN +# define read16ne read16be +# define read32ne read32be +# define read64ne read64be +# define write16ne write16be +# define write32ne write32be +# define write64ne write64be +#else +# define read16ne read16le +# define read32ne read32le +# define read64ne read64le +# define write16ne write16le +# define write32ne write32le +# define write64ne write64le +#endif + + +static inline uint16_t +read16be(const uint8_t *buf) +{ + uint16_t num = ((uint16_t)buf[0] << 8) | (uint16_t)buf[1]; + return num; +} + + +static inline uint16_t +read16le(const uint8_t *buf) +{ + uint16_t num = ((uint16_t)buf[0]) | ((uint16_t)buf[1] << 8); + return num; +} + + +static inline uint32_t +read32be(const uint8_t *buf) +{ + uint32_t num = (uint32_t)buf[0] << 24; + num |= (uint32_t)buf[1] << 16; + num |= (uint32_t)buf[2] << 8; + num |= (uint32_t)buf[3]; + return num; +} + + +static inline uint32_t +read32le(const uint8_t *buf) +{ + uint32_t num = (uint32_t)buf[0]; + num |= (uint32_t)buf[1] << 8; + num |= (uint32_t)buf[2] << 16; + num |= (uint32_t)buf[3] << 24; + return num; +} + + +static inline uint64_t +read64be(const uint8_t *buf) +{ uint64_t num = (uint64_t)buf[0] << 56; num |= (uint64_t)buf[1] << 48; num |= (uint64_t)buf[2] << 40; @@ -365,17 +520,12 @@ read64be(const uint8_t *buf) num |= (uint64_t)buf[6] << 8; num |= (uint64_t)buf[7]; return num; -#endif } static inline uint64_t read64le(const uint8_t *buf) { -#if !defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS) - uint64_t num = read64ne(buf); - return conv64le(num); -#else uint64_t num = (uint64_t)buf[0]; num |= (uint64_t)buf[1] << 8; num |= (uint64_t)buf[2] << 16; @@ -385,28 +535,9 @@ read64le(const uint8_t *buf) num |= (uint64_t)buf[6] << 48; num |= (uint64_t)buf[7] << 56; return num; -#endif } -// NOTE: Possible byte swapping must be done in a macro to allow the compiler -// to optimize byte swapping of constants when using glibc's or *BSD's -// byte swapping macros. The actual write is done in an inline function -// to make type checking of the buf pointer possible. -#if defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS) -# define write16be(buf, num) write16ne(buf, conv16be(num)) -# define write32be(buf, num) write32ne(buf, conv32be(num)) -# define write64be(buf, num) write64ne(buf, conv64be(num)) -#endif - -#if !defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS) -# define write16le(buf, num) write16ne(buf, conv16le(num)) -# define write32le(buf, num) write32ne(buf, conv32le(num)) -# define write64le(buf, num) write64ne(buf, conv64le(num)) -#endif - - -#ifndef write16be static inline void write16be(uint8_t *buf, uint16_t num) { @@ -414,10 +545,8 @@ write16be(uint8_t *buf, uint16_t num) buf[1] = (uint8_t)num; return; } -#endif -#ifndef write16le static inline void write16le(uint8_t *buf, uint16_t num) { @@ -425,10 +554,8 @@ write16le(uint8_t *buf, uint16_t num) buf[1] = (uint8_t)(num >> 8); return; } -#endif -#ifndef write32be static inline void write32be(uint8_t *buf, uint32_t num) { @@ -438,10 +565,8 @@ write32be(uint8_t *buf, uint32_t num) buf[3] = (uint8_t)num; return; } -#endif -#ifndef write32le static inline void write32le(uint8_t *buf, uint32_t num) { @@ -451,6 +576,37 @@ write32le(uint8_t *buf, uint32_t num) buf[3] = (uint8_t)(num >> 24); return; } + + +static inline void +write64be(uint8_t *buf, uint64_t num) +{ + buf[0] = (uint8_t)(num >> 56); + buf[1] = (uint8_t)(num >> 48); + buf[2] = (uint8_t)(num >> 40); + buf[3] = (uint8_t)(num >> 32); + buf[4] = (uint8_t)(num >> 24); + buf[5] = (uint8_t)(num >> 16); + buf[6] = (uint8_t)(num >> 8); + buf[7] = (uint8_t)num; + return; +} + + +static inline void +write64le(uint8_t *buf, uint64_t num) +{ + buf[0] = (uint8_t)num; + buf[1] = (uint8_t)(num >> 8); + buf[2] = (uint8_t)(num >> 16); + buf[3] = (uint8_t)(num >> 24); + buf[4] = (uint8_t)(num >> 32); + buf[5] = (uint8_t)(num >> 40); + buf[6] = (uint8_t)(num >> 48); + buf[7] = (uint8_t)(num >> 56); + return; +} + #endif diff --git a/src/liblzma/api/lzma.h b/src/liblzma/api/lzma.h index f38513d35a45..de12f225859f 100644 --- a/src/liblzma/api/lzma.h +++ b/src/liblzma/api/lzma.h @@ -182,11 +182,11 @@ * against static liblzma on them, don't worry about LZMA_API_STATIC. That * is, most developers will never need to use LZMA_API_STATIC. * - * The GCC variants are a special case on Windows (Cygwin and MinGW). + * The GCC variants are a special case on Windows (Cygwin and MinGW-w64). * We rely on GCC doing the right thing with its auto-import feature, * and thus don't use __declspec(dllimport). This way developers don't * need to worry about LZMA_API_STATIC. Also the calling convention is - * omitted on Cygwin but not on MinGW. + * omitted on Cygwin but not on MinGW-w64. */ #ifndef LZMA_API_IMPORT # if !defined(LZMA_API_STATIC) && defined(_WIN32) && !defined(__GNUC__) diff --git a/src/liblzma/api/lzma/version.h b/src/liblzma/api/lzma/version.h index 8739d751c704..8dac38297273 100644 --- a/src/liblzma/api/lzma/version.h +++ b/src/liblzma/api/lzma/version.h @@ -23,7 +23,7 @@ #define LZMA_VERSION_MINOR 4 /** \brief Patch version number of the liblzma release. */ -#define LZMA_VERSION_PATCH 4 +#define LZMA_VERSION_PATCH 5 /** * \brief Version stability marker @@ -106,7 +106,7 @@ LZMA_VERSION_COMMIT) -/* #ifndef is needed for use with windres (MinGW or Cygwin). */ +/* #ifndef is needed for use with windres (MinGW-w64 or Cygwin). */ #ifndef LZMA_H_INTERNAL_RC /** diff --git a/src/liblzma/check/check.h b/src/liblzma/check/check.h index 783627bd21b9..8ae95d59019f 100644 --- a/src/liblzma/check/check.h +++ b/src/liblzma/check/check.h @@ -99,10 +99,17 @@ typedef struct { /// lzma_crc32_table[0] is needed by LZ encoder so we need to keep /// the array two-dimensional. #ifdef HAVE_SMALL +lzma_attr_visibility_hidden extern uint32_t lzma_crc32_table[1][256]; + extern void lzma_crc32_init(void); + #else + +lzma_attr_visibility_hidden extern const uint32_t lzma_crc32_table[8][256]; + +lzma_attr_visibility_hidden extern const uint64_t lzma_crc64_table[4][256]; #endif diff --git a/src/liblzma/check/crc64_fast.c b/src/liblzma/check/crc64_fast.c index e686dbd742f4..0c8622a1f367 100644 --- a/src/liblzma/check/crc64_fast.c +++ b/src/liblzma/check/crc64_fast.c @@ -206,6 +206,14 @@ calc_hi(uint64_t poly, uint64_t a) #if (defined(__GNUC__) || defined(__clang__)) && !defined(__EDG__) __attribute__((__target__("ssse3,sse4.1,pclmul"))) #endif +// The intrinsics use 16-byte-aligned reads from buf, thus they may read +// up to 15 bytes before or after the buffer (depending on the alignment +// of the buf argument). The values of the extra bytes are ignored. +// This unavoidably trips -fsanitize=address so address sanitizier has +// to be disabled for this function. +#if lzma_has_attribute(__no_sanitize_address__) +__attribute__((__no_sanitize_address__)) +#endif static uint64_t crc64_clmul(const uint8_t *buf, size_t size, uint64_t crc) { diff --git a/src/liblzma/check/crc64_table.c b/src/liblzma/check/crc64_table.c index 241adcd4a5cb..688e527b0fd1 100644 --- a/src/liblzma/check/crc64_table.c +++ b/src/liblzma/check/crc64_table.c @@ -18,10 +18,8 @@ #if (defined(__x86_64__) && defined(__SSSE3__) \ && defined(__SSE4_1__) && defined(__PCLMUL__)) \ || (defined(__e2k__) && __iset__ >= 6) -// No table needed but something has to be exported to keep some toolchains -// happy. Also use a declaration to silence compiler warnings. -extern const char lzma_crc64_dummy; -const char lzma_crc64_dummy; +// No table needed. Use a typedef to avoid an empty translation unit. +typedef void lzma_crc64_dummy; #else // Having the declaration here silences clang -Wmissing-variable-declarations. diff --git a/src/liblzma/common/common.c b/src/liblzma/common/common.c index baad3dd84c7b..adb50d785d52 100644 --- a/src/liblzma/common/common.c +++ b/src/liblzma/common/common.c @@ -35,7 +35,8 @@ lzma_version_string(void) // Memory allocation // /////////////////////// -extern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1) +lzma_attr_alloc_size(1) +extern void * lzma_alloc(size_t size, const lzma_allocator *allocator) { // Some malloc() variants return NULL if called with size == 0. @@ -53,7 +54,8 @@ lzma_alloc(size_t size, const lzma_allocator *allocator) } -extern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1) +lzma_attr_alloc_size(1) +extern void * lzma_alloc_zero(size_t size, const lzma_allocator *allocator) { // Some calloc() variants return NULL if called with size == 0. diff --git a/src/liblzma/common/common.h b/src/liblzma/common/common.h index 4d9cab53cdbb..378923e4012b 100644 --- a/src/liblzma/common/common.h +++ b/src/liblzma/common/common.h @@ -17,17 +17,28 @@ #include "mythread.h" #include "tuklib_integer.h" +// LZMA_API_EXPORT is used to mark the exported API functions. +// It's used to define the LZMA_API macro. +// +// lzma_attr_visibility_hidden is used for marking *declarations* of extern +// variables that are internal to liblzma (-fvisibility=hidden alone is +// enough to hide the *definitions*). Such markings allow slightly more +// efficient code to accesses those variables in ELF shared libraries. #if defined(_WIN32) || defined(__CYGWIN__) # ifdef DLL_EXPORT # define LZMA_API_EXPORT __declspec(dllexport) # else # define LZMA_API_EXPORT # endif +# define lzma_attr_visibility_hidden // Don't use ifdef or defined() below. #elif HAVE_VISIBILITY # define LZMA_API_EXPORT __attribute__((__visibility__("default"))) +# define lzma_attr_visibility_hidden \ + __attribute__((__visibility__("hidden"))) #else # define LZMA_API_EXPORT +# define lzma_attr_visibility_hidden #endif #define LZMA_API(type) LZMA_API_EXPORT type LZMA_API_CALL @@ -87,6 +98,23 @@ # endif #endif +// MSVC has __forceinline which shouldn't be combined with the inline keyword +// (results in a warning). +// +// GCC 3.1 added always_inline attribute so we don't need to check +// for __GNUC__ version. Similarly, all relevant Clang versions +// support it (at least Clang 3.0.0 does already). +// Other compilers might support too which also support __has_attribute +// (Solaris Studio) so do that check too. +#if defined(_MSC_VER) +# define lzma_always_inline __forceinline +#elif defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) \ + || lzma_has_attribute(__always_inline__) +# define lzma_always_inline inline __attribute__((__always_inline__)) +#else +# define lzma_always_inline inline +#endif + // These allow helping the compiler in some often-executed branches, whose // result is almost always the same. #ifdef __GNUC__ @@ -297,14 +325,14 @@ struct lzma_internal_s { /// Allocates memory -extern void *lzma_alloc(size_t size, const lzma_allocator *allocator) - lzma_attribute((__malloc__)) lzma_attr_alloc_size(1); +lzma_attr_alloc_size(1) +extern void *lzma_alloc(size_t size, const lzma_allocator *allocator); /// Allocates memory and zeroes it (like calloc()). This can be faster /// than lzma_alloc() + memzero() while being backward compatible with /// custom allocators. -extern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1) - lzma_alloc_zero(size_t size, const lzma_allocator *allocator); +lzma_attr_alloc_size(1) +extern void *lzma_alloc_zero(size_t size, const lzma_allocator *allocator); /// Frees memory extern void lzma_free(void *ptr, const lzma_allocator *allocator); diff --git a/src/liblzma/common/index.c b/src/liblzma/common/index.c index 97cc9f953fae..8a35f4398dbe 100644 --- a/src/liblzma/common/index.c +++ b/src/liblzma/common/index.c @@ -661,6 +661,12 @@ lzma_index_append(lzma_index *i, const lzma_allocator *allocator, if (uncompressed_base + uncompressed_size > LZMA_VLI_MAX) return LZMA_DATA_ERROR; + // Check that the new unpadded sum will not overflow. This is + // checked again in index_file_size(), but the unpadded sum is + // passed to vli_ceil4() which expects a valid lzma_vli value. + if (compressed_base + unpadded_size > UNPADDED_SIZE_MAX) + return LZMA_DATA_ERROR; + // Check that the file size will stay within limits. if (index_file_size(s->node.compressed_base, compressed_base + unpadded_size, s->record_count + 1, diff --git a/src/liblzma/common/index.h b/src/liblzma/common/index.h index 031efcc718f2..7b27d7004cfa 100644 --- a/src/liblzma/common/index.h +++ b/src/liblzma/common/index.h @@ -46,7 +46,7 @@ extern void lzma_index_prealloc(lzma_index *i, lzma_vli records); static inline lzma_vli vli_ceil4(lzma_vli vli) { - assert(vli <= LZMA_VLI_MAX); + assert(vli <= UNPADDED_SIZE_MAX); return (vli + 3) & ~LZMA_VLI_C(3); } diff --git a/src/liblzma/common/memcmplen.h b/src/liblzma/common/memcmplen.h index 3c12422beaaf..99d9c519cc0d 100644 --- a/src/liblzma/common/memcmplen.h +++ b/src/liblzma/common/memcmplen.h @@ -49,7 +49,7 @@ /// It's rounded up to 2^n. This extra amount needs to be /// allocated in the buffers being used. It needs to be /// initialized too to keep Valgrind quiet. -static inline uint32_t lzma_attribute((__always_inline__)) +static lzma_always_inline uint32_t lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2, uint32_t len, uint32_t limit) { diff --git a/src/liblzma/common/stream_flags_common.h b/src/liblzma/common/stream_flags_common.h index 9f3122a3b1e5..84e96ba1ff66 100644 --- a/src/liblzma/common/stream_flags_common.h +++ b/src/liblzma/common/stream_flags_common.h @@ -18,7 +18,10 @@ /// Size of the Stream Flags field #define LZMA_STREAM_FLAGS_SIZE 2 +lzma_attr_visibility_hidden extern const uint8_t lzma_header_magic[6]; + +lzma_attr_visibility_hidden extern const uint8_t lzma_footer_magic[2]; diff --git a/src/liblzma/liblzma.pc.in b/src/liblzma/liblzma.pc.in index 9fa489115a0a..d077cb77135a 100644 --- a/src/liblzma/liblzma.pc.in +++ b/src/liblzma/liblzma.pc.in @@ -15,5 +15,6 @@ Description: General purpose data compression library URL: @PACKAGE_URL@ Version: @PACKAGE_VERSION@ Cflags: -I${includedir} +Cflags.private: -DLZMA_API_STATIC Libs: -L${libdir} -llzma Libs.private: @PTHREAD_CFLAGS@ @LIBS@ diff --git a/src/liblzma/lz/lz_encoder_hash.h b/src/liblzma/lz/lz_encoder_hash.h index fb15c58146db..4d9971ae6a5d 100644 --- a/src/liblzma/lz/lz_encoder_hash.h +++ b/src/liblzma/lz/lz_encoder_hash.h @@ -17,6 +17,7 @@ // This is to make liblzma produce the same output on big endian // systems that it does on little endian systems. lz_encoder.c // takes care of including the actual table. + lzma_attr_visibility_hidden extern const uint32_t lzma_lz_hash_table[256]; # define hash_table lzma_lz_hash_table #else diff --git a/src/liblzma/lzma/fastpos.h b/src/liblzma/lzma/fastpos.h index cba442c27e5c..dbeb16f7e31a 100644 --- a/src/liblzma/lzma/fastpos.h +++ b/src/liblzma/lzma/fastpos.h @@ -91,6 +91,7 @@ get_dist_slot_2(uint32_t dist) #define FASTPOS_BITS 13 +lzma_attr_visibility_hidden extern const uint8_t lzma_fastpos[1 << FASTPOS_BITS]; diff --git a/src/liblzma/lzma/fastpos_tablegen.c b/src/liblzma/lzma/fastpos_tablegen.c index d4484c82d0b5..57ed15039b27 100644 --- a/src/liblzma/lzma/fastpos_tablegen.c +++ b/src/liblzma/lzma/fastpos_tablegen.c @@ -13,6 +13,8 @@ #include #include + +#define lzma_attr_visibility_hidden #include "fastpos.h" diff --git a/src/liblzma/rangecoder/price.h b/src/liblzma/rangecoder/price.h index 8ae02ca7474e..45dbbbb20cef 100644 --- a/src/liblzma/rangecoder/price.h +++ b/src/liblzma/rangecoder/price.h @@ -22,6 +22,7 @@ /// Lookup table for the inline functions defined in this file. +lzma_attr_visibility_hidden extern const uint8_t lzma_rc_prices[RC_PRICE_TABLE_SIZE]; diff --git a/src/lzmainfo/lzmainfo.c b/src/lzmainfo/lzmainfo.c index b0ccdfb430ec..71e62958ad67 100644 --- a/src/lzmainfo/lzmainfo.c +++ b/src/lzmainfo/lzmainfo.c @@ -26,7 +26,8 @@ #endif -static void lzma_attribute((__noreturn__)) +tuklib_attr_noreturn +static void help(void) { printf( @@ -45,7 +46,8 @@ _("Usage: %s [--help] [--version] [FILE]...\n" } -static void lzma_attribute((__noreturn__)) +tuklib_attr_noreturn +static void version(void) { puts("lzmainfo (" PACKAGE_NAME ") " LZMA_VERSION_STRING); diff --git a/src/xz/coder.c b/src/xz/coder.c index 589ec072e63c..91d40ed2bb7b 100644 --- a/src/xz/coder.c +++ b/src/xz/coder.c @@ -128,7 +128,8 @@ coder_add_filter(lzma_vli id, void *options) } -static void lzma_attribute((__noreturn__)) +tuklib_attr_noreturn +static void memlimit_too_small(uint64_t memory_usage) { message(V_ERROR, _("Memory usage limit is too low for the given " diff --git a/src/xz/file_io.c b/src/xz/file_io.c index a181b531258f..28280293ef39 100644 --- a/src/xz/file_io.c +++ b/src/xz/file_io.c @@ -944,20 +944,41 @@ io_open_dest_real(file_pair *pair) } } -#ifndef TUKLIB_DOSLIKE - // dest_st isn't used on DOS-like systems except as a dummy - // argument to io_unlink(), so don't fstat() on such systems. if (fstat(pair->dest_fd, &pair->dest_st)) { // If fstat() really fails, we have a safe fallback here. -# if defined(__VMS) +#if defined(__VMS) pair->dest_st.st_ino[0] = 0; pair->dest_st.st_ino[1] = 0; pair->dest_st.st_ino[2] = 0; -# else +#else pair->dest_st.st_dev = 0; pair->dest_st.st_ino = 0; -# endif - } else if (try_sparse && opt_mode == MODE_DECOMPRESS) { +#endif + } +#if defined(TUKLIB_DOSLIKE) && !defined(__DJGPP__) + // Check that the output file is a regular file. We open with O_EXCL + // but that doesn't prevent open()/_open() on Windows from opening + // files like "con" or "nul". + // + // With DJGPP this check is done with stat() even before opening + // the output file. That method or a variant of it doesn't work on + // Windows because on Windows stat()/_stat64() sets st.st_mode so + // that S_ISREG(st.st_mode) will be true even for special files. + // With fstat()/_fstat64() it works. + else if (pair->dest_fd != STDOUT_FILENO + && !S_ISREG(pair->dest_st.st_mode)) { + message_error("%s: Destination is not a regular file", + pair->dest_name); + + // dest_fd needs to be reset to -1 to keep io_close() working. + (void)close(pair->dest_fd); + pair->dest_fd = -1; + + free(pair->dest_name); + return true; + } +#elif !defined(TUKLIB_DOSLIKE) + else if (try_sparse && opt_mode == MODE_DECOMPRESS) { // When writing to standard output, we need to be extra // careful: // - It may be connected to something else than @@ -1157,8 +1178,7 @@ io_fix_src_pos(file_pair *pair, size_t rewind_size) extern size_t io_read(file_pair *pair, io_buf *buf, size_t size) { - // We use small buffers here. - assert(size < SSIZE_MAX); + assert(size <= IO_BUFFER_SIZE); size_t pos = 0; @@ -1285,7 +1305,7 @@ is_sparse(const io_buf *buf) static bool io_write_buf(file_pair *pair, const uint8_t *buf, size_t size) { - assert(size < SSIZE_MAX); + assert(size <= IO_BUFFER_SIZE); while (size > 0) { const ssize_t amount = write(pair->dest_fd, buf, size); diff --git a/src/xz/file_io.h b/src/xz/file_io.h index 8a9e33630db3..6992efa4f86c 100644 --- a/src/xz/file_io.h +++ b/src/xz/file_io.h @@ -118,7 +118,7 @@ extern void io_close(file_pair *pair, bool success); /// /// \param pair File pair having the source file open for reading /// \param buf Destination buffer to hold the read data -/// \param size Size of the buffer; assumed be smaller than SSIZE_MAX +/// \param size Size of the buffer; must be at most IO_BUFFER_SIZE /// /// \return On success, number of bytes read is returned. On end of /// file zero is returned and pair->src_eof set to true. @@ -172,7 +172,7 @@ extern bool io_pread(file_pair *pair, io_buf *buf, size_t size, uint64_t pos); /// /// \param pair File pair having the destination file open for writing /// \param buf Buffer containing the data to be written -/// \param size Size of the buffer; assumed be smaller than SSIZE_MAX +/// \param size Size of the buffer; must be at most IO_BUFFER_SIZE /// /// \return On success, zero is returned. On error, -1 is returned /// and error message printed. diff --git a/src/xz/hardware.h b/src/xz/hardware.h index 2bb3d7ba9493..a67b26efecb8 100644 --- a/src/xz/hardware.h +++ b/src/xz/hardware.h @@ -71,4 +71,5 @@ extern bool hardware_memlimit_mtenc_is_default(void); extern uint64_t hardware_memlimit_mtdec_get(void); /// Display the amount of RAM and memory usage limits and exit. -extern void hardware_memlimit_show(void) lzma_attribute((__noreturn__)); +tuklib_attr_noreturn +extern void hardware_memlimit_show(void); diff --git a/src/xz/message.h b/src/xz/message.h index b264f82153a3..f608ec75dffa 100644 --- a/src/xz/message.h +++ b/src/xz/message.h @@ -44,42 +44,44 @@ extern enum message_verbosity message_verbosity_get(void); /// \brief Print a message if verbosity level is at least "verbosity" /// /// This doesn't touch the exit status. -extern void message(enum message_verbosity verbosity, const char *fmt, ...) - lzma_attribute((__format__(__printf__, 2, 3))); +lzma_attribute((__format__(__printf__, 2, 3))) +extern void message(enum message_verbosity verbosity, const char *fmt, ...); /// \brief Prints a warning and possibly sets exit status /// /// The message is printed only if verbosity level is at least V_WARNING. /// The exit status is set to WARNING unless it was already at ERROR. -extern void message_warning(const char *fmt, ...) - lzma_attribute((__format__(__printf__, 1, 2))); +lzma_attribute((__format__(__printf__, 1, 2))) +extern void message_warning(const char *fmt, ...); /// \brief Prints an error message and sets exit status /// /// The message is printed only if verbosity level is at least V_ERROR. /// The exit status is set to ERROR. -extern void message_error(const char *fmt, ...) - lzma_attribute((__format__(__printf__, 1, 2))); +lzma_attribute((__format__(__printf__, 1, 2))) +extern void message_error(const char *fmt, ...); /// \brief Prints an error message and exits with EXIT_ERROR /// /// The message is printed only if verbosity level is at least V_ERROR. -extern void message_fatal(const char *fmt, ...) - lzma_attribute((__format__(__printf__, 1, 2))) - lzma_attribute((__noreturn__)); +tuklib_attr_noreturn +lzma_attribute((__format__(__printf__, 1, 2))) +extern void message_fatal(const char *fmt, ...); /// Print an error message that an internal error occurred and exit with /// EXIT_ERROR. -extern void message_bug(void) lzma_attribute((__noreturn__)); +tuklib_attr_noreturn +extern void message_bug(void); /// Print a message that establishing signal handlers failed, and exit with /// exit status ERROR. -extern void message_signal_handler(void) lzma_attribute((__noreturn__)); +tuklib_attr_noreturn +extern void message_signal_handler(void); /// Convert lzma_ret to a string. @@ -100,11 +102,13 @@ extern void message_try_help(void); /// Prints the version number to stdout and exits with exit status SUCCESS. -extern void message_version(void) lzma_attribute((__noreturn__)); +tuklib_attr_noreturn +extern void message_version(void); /// Print the help message. -extern void message_help(bool long_help) lzma_attribute((__noreturn__)); +tuklib_attr_noreturn +extern void message_help(bool long_help); /// \brief Set the total number of files to be processed diff --git a/src/xz/options.c b/src/xz/options.c index f46621311d92..4d5e899ccdc1 100644 --- a/src/xz/options.c +++ b/src/xz/options.c @@ -241,7 +241,8 @@ enum { }; -static void lzma_attribute((__noreturn__)) +tuklib_attr_noreturn +static void error_lzma_preset(const char *valuestr) { message_fatal(_("Unsupported LZMA1/LZMA2 preset: %s"), valuestr); diff --git a/src/xz/util.c b/src/xz/util.c index 9f9a8fb024e4..6ab4c2d776ce 100644 --- a/src/xz/util.c +++ b/src/xz/util.c @@ -17,9 +17,45 @@ /// Buffers for uint64_to_str() and uint64_to_nicestr() static char bufs[4][128]; -/// Thousand separator support in uint64_to_str() and uint64_to_nicestr() + +// Thousand separator support in uint64_to_str() and uint64_to_nicestr(): +// +// DJGPP 2.05 added support for thousands separators but it's broken +// at least under WinXP with Finnish locale that uses a non-breaking space +// as the thousands separator. Workaround by disabling thousands separators +// for DJGPP builds. +// +// MSVC doesn't support thousand separators. +#if defined(__DJGPP__) || defined(_MSC_VER) +# define FORMAT_THOUSAND_SEP(prefix, suffix) prefix suffix +# define check_thousand_sep(slot) do { } while (0) +#else +# define FORMAT_THOUSAND_SEP(prefix, suffix) ((thousand == WORKS) \ + ? prefix "'" suffix \ + : prefix suffix) + static enum { UNKNOWN, WORKS, BROKEN } thousand = UNKNOWN; +/// Check if thousands separator is supported. Run-time checking is easiest +/// because it seems to be sometimes lacking even on a POSIXish system. +/// Note that trying to use thousands separators when snprintf() doesn't +/// support them results in undefined behavior. This just has happened to +/// work well enough in practice. +/// +/// This must be called before using the FORMAT_THOUSAND_SEP macro. +static void +check_thousand_sep(uint32_t slot) +{ + if (thousand == UNKNOWN) { + bufs[slot][0] = '\0'; + snprintf(bufs[slot], sizeof(bufs[slot]), "%'u", 1U); + thousand = bufs[slot][0] == '1' ? WORKS : BROKEN; + } + + return; +} +#endif + extern void * xrealloc(void *ptr, size_t size) @@ -142,31 +178,6 @@ round_up_to_mib(uint64_t n) } -/// Check if thousands separator is supported. Run-time checking is easiest -/// because it seems to be sometimes lacking even on a POSIXish system. -/// Note that trying to use thousands separators when snprintf() doesn't -/// support them results in undefined behavior. This just has happened to -/// work well enough in practice. -/// -/// DJGPP 2.05 added support for thousands separators but it's broken -/// at least under WinXP with Finnish locale that uses a non-breaking space -/// as the thousands separator. Workaround by disabling thousands separators -/// for DJGPP builds. -static void -check_thousand_sep(uint32_t slot) -{ - if (thousand == UNKNOWN) { - bufs[slot][0] = '\0'; -#ifndef __DJGPP__ - snprintf(bufs[slot], sizeof(bufs[slot]), "%'u", 1U); -#endif - thousand = bufs[slot][0] == '1' ? WORKS : BROKEN; - } - - return; -} - - extern const char * uint64_to_str(uint64_t value, uint32_t slot) { @@ -174,10 +185,8 @@ uint64_to_str(uint64_t value, uint32_t slot) check_thousand_sep(slot); - if (thousand == WORKS) - snprintf(bufs[slot], sizeof(bufs[slot]), "%'" PRIu64, value); - else - snprintf(bufs[slot], sizeof(bufs[slot]), "%" PRIu64, value); + snprintf(bufs[slot], sizeof(bufs[slot]), + FORMAT_THOUSAND_SEP("%", PRIu64), value); return bufs[slot]; } @@ -201,10 +210,8 @@ uint64_to_nicestr(uint64_t value, enum nicestr_unit unit_min, if ((unit_min == NICESTR_B && value < 10000) || unit_max == NICESTR_B) { // The value is shown as bytes. - if (thousand == WORKS) - my_snprintf(&pos, &left, "%'u", (unsigned int)value); - else - my_snprintf(&pos, &left, "%u", (unsigned int)value); + my_snprintf(&pos, &left, FORMAT_THOUSAND_SEP("%", "u"), + (unsigned int)value); } else { // Scale the value to a nicer unit. Unless unit_min and // unit_max limit us, we will show at most five significant @@ -215,21 +222,15 @@ uint64_to_nicestr(uint64_t value, enum nicestr_unit unit_min, ++unit; } while (unit < unit_min || (d > 9999.9 && unit < unit_max)); - if (thousand == WORKS) - my_snprintf(&pos, &left, "%'.1f", d); - else - my_snprintf(&pos, &left, "%.1f", d); + my_snprintf(&pos, &left, FORMAT_THOUSAND_SEP("%", ".1f"), d); } static const char suffix[5][4] = { "B", "KiB", "MiB", "GiB", "TiB" }; my_snprintf(&pos, &left, " %s", suffix[unit]); - if (always_also_bytes && value >= 10000) { - if (thousand == WORKS) - snprintf(pos, left, " (%'" PRIu64 " B)", value); - else - snprintf(pos, left, " (%" PRIu64 " B)", value); - } + if (always_also_bytes && value >= 10000) + snprintf(pos, left, FORMAT_THOUSAND_SEP(" (%", PRIu64 " B)"), + value); return bufs[slot]; } diff --git a/src/xz/util.h b/src/xz/util.h index 4a536f52ea4e..6d7e1481863b 100644 --- a/src/xz/util.h +++ b/src/xz/util.h @@ -19,12 +19,12 @@ /// \brief Safe realloc() that never returns NULL -extern void *xrealloc(void *ptr, size_t size) - lzma_attribute((__malloc__)) lzma_attr_alloc_size(2); +lzma_attr_alloc_size(2) +extern void *xrealloc(void *ptr, size_t size); /// \brief Safe strdup() that never returns NULL -extern char *xstrdup(const char *src) lzma_attribute((__malloc__)); +extern char *xstrdup(const char *src); /// \brief Fancy version of strtoull() @@ -101,8 +101,8 @@ extern const char *uint64_to_nicestr(uint64_t value, /// /// A maximum of *left bytes is written starting from *pos. *pos and *left /// are updated accordingly. -extern void my_snprintf(char **pos, size_t *left, const char *fmt, ...) - lzma_attribute((__format__(__printf__, 3, 4))); +lzma_attribute((__format__(__printf__, 3, 4))) +extern void my_snprintf(char **pos, size_t *left, const char *fmt, ...); /// \brief Test if stdin is a terminal diff --git a/src/xz/xz.1 b/src/xz/xz.1 index 8e85a17e920e..73ca6efd6aff 100644 --- a/src/xz/xz.1 +++ b/src/xz/xz.1 @@ -1160,7 +1160,6 @@ to resets the .I limit to the default system-specific value. -.IP "" .TP \fB\-M\fR \fIlimit\fR, \fB\-\-memlimit=\fIlimit\fR, \fB\-\-memory=\fIlimit This is equivalent to specifying diff --git a/src/xzdec/xzdec.c b/src/xzdec/xzdec.c index c1bd19986424..556c548d05ad 100644 --- a/src/xzdec/xzdec.c +++ b/src/xzdec/xzdec.c @@ -40,7 +40,8 @@ static int display_errors = 2; -static void lzma_attribute((__format__(__printf__, 1, 2))) +lzma_attribute((__format__(__printf__, 1, 2))) +static void my_errorf(const char *fmt, ...) { va_list ap; @@ -57,7 +58,8 @@ my_errorf(const char *fmt, ...) } -static void lzma_attribute((__noreturn__)) +tuklib_attr_noreturn +static void help(void) { printf( @@ -81,7 +83,8 @@ PACKAGE_NAME " home page: <" PACKAGE_URL ">\n", progname); } -static void lzma_attribute((__noreturn__)) +tuklib_attr_noreturn +static void version(void) { printf(TOOL_FORMAT "dec (" PACKAGE_NAME ") " LZMA_VERSION_STRING "\n"