1
0
mirror of https://git.tukaani.org/xz.git synced 2025-04-16 04:30:52 +00:00

1449 Commits

Author SHA1 Message Date
Lasse Collin
a522a22654
Bump version and soname for 5.8.1 2025-04-03 14:34:43 +03:00
Lasse Collin
0c80045ab8
liblzma: mt dec: Fix lack of parallelization in single-shot decoding
Single-shot decoding means calling lzma_code() by giving it the whole
input at once and enough output buffer space to store the uncompressed
data, and combining this with LZMA_FINISH and no timeout
(lzma_mt.timeout = 0). This way the file is decoded with a single
lzma_code() call if possible.

The bug prevented the decoder from starting more than one worker thread
in single-shot mode. The issue was noticed when reviewing the code;
there are no bug reports. Thus maybe few have tried this mode.

Fixes: 64b6d496dc81 ("liblzma: Threaded decoder: Always wait for output if LZMA_FINISH is used.")
2025-04-03 14:34:42 +03:00
Lasse Collin
8188048854
liblzma: mt dec: Don't modify thr->in_size in the worker thread
Don't set thr->in_size = 0 when returning the thread to the stack of
available threads. Not only is it useless, but the main thread may
read the value in SEQ_BLOCK_THR_RUN. With valid inputs, it made
no difference if the main thread saw the original value or 0. With
invalid inputs (when worker thread stops early), thr->in_size was
no longer modified after the previous commit with the security fix
("Don't free the input buffer too early").

So while the bug appears harmless now, it's important to fix it because
the variable was being modified without proper locking. It's trivial
to fix because there is no need to change the value. Only main thread
needs to set the value in (in SEQ_BLOCK_THR_INIT) when starting a new
Block before the worker thread is activated.

Fixes: 4cce3e27f529 ("liblzma: Add threaded .xz decompressor.")
Reviewed-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Thanks-to: Sam James <sam@gentoo.org>
2025-04-03 14:34:42 +03:00
Lasse Collin
d5a2ffe41b
liblzma: mt dec: Don't free the input buffer too early (CVE-2025-31115)
The input buffer must be valid as long as the main thread is writing
to the worker-specific input buffer. Fix it by making the worker
thread not free the buffer on errors and not return the worker thread to
the pool. The input buffer will be freed when threads_end() is called.

With invalid input, the bug could at least result in a crash. The
effects include heap use after free and writing to an address based
on the null pointer plus an offset.

The bug has been there since the first committed version of the threaded
decoder and thus affects versions from 5.3.3alpha to 5.8.0.

As the commit message in 4cce3e27f529 says, I had made significant
changes on top of Sebastian's patch. This bug was indeed introduced
by my changes; it wasn't in Sebastian's version.

Thanks to Harri K. Koskinen for discovering and reporting this issue.

Fixes: 4cce3e27f529 ("liblzma: Add threaded .xz decompressor.")
Reported-by: Harri K. Koskinen <x64nop@nannu.org>
Reviewed-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Thanks-to: Sam James <sam@gentoo.org>
2025-04-03 14:34:42 +03:00
Lasse Collin
c0c835964d
liblzma: mt dec: Simplify by removing the THR_STOP state
The main thread can directly set THR_IDLE in threads_stop() which is
called when errors are detected. threads_stop() won't return the stopped
threads to the pool or free the memory pointed by thr->in anymore, but
it doesn't matter because the existing workers won't be reused after
an error. The resources will be cleaned up when threads_end() is
called (reinitializing the decoder always calls threads_end()).

Reviewed-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Thanks-to: Sam James <sam@gentoo.org>
2025-04-03 14:34:42 +03:00
Lasse Collin
831b55b971
liblzma: mt dec: Fix a comment
Reviewed-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Thanks-to: Sam James <sam@gentoo.org>
2025-04-03 14:34:42 +03:00
Lasse Collin
b9d168eee4
liblzma: Add assertions to lzma_bufcpy() 2025-04-03 14:34:30 +03:00
Lasse Collin
307c02ed69
sysdefs.h: Avoid <stdalign.h> even with C11 compilers
Oracle Developer Studio 12.6 on Solaris 10 claims C11 support in
__STDC_VERSION__ and supports _Alignas. However, <stdalign.h> is missing.
We only need alignas, so define it to _Alignas with C11/C17 compilers.
If something included <stdalign.h> later, it shouldn't cause problems.

Thanks to Ihsan Dogan for reporting the issue and testing the fix.

Fixes: c0e7eaae8d6eef1e313c9d0da20ccf126ec61f38
2025-03-29 12:41:32 +02:00
Lasse Collin
db9258e828
Bump version and soname for 5.8.0
Also remove the LZMA_UNSTABLE macro.
2025-03-25 15:18:32 +02:00
Lasse Collin
ff5d944749
liblzma: Count the extra bytes in LZMA/LZMA2 decoder memory usage 2025-03-25 15:18:31 +02:00
Lasse Collin
943b012d09
liblzma: Use SSE2 intrinsics instead of memcpy() in dict_repeat()
SSE2 is supported on every x86-64 processor. The SSE2 code is used on
32-bit x86 if compiler options permit unconditional use of SSE2.

dict_repeat() copies short random-sized unaligned buffers. At least
on glibc, FreeBSD, and Windows (MSYS2, UCRT, MSVCRT), memcpy() is
clearly faster than byte-by-byte copying in this use case. Compared
to the memcpy() version, the new SSE2 version reduces decompression
time by 0-5 % depending on the machine and libc. It should never be
slower than the memcpy() version.

However, on musl 1.2.5 on x86-64, the memcpy() version is the slowest.
Compared to the memcpy() version:

  - The byte-by-version takes 6-7 % less time to decompress.
  - The SSE2 version takes 16-18 % less time to decompress.

The numbers are from decompressing a Linux kernel source tarball in
single-threaded mode on older AMD and Intel systems. The tarball
compresses well, and thus dict_repeat() performance matters more
than with some other files.
2025-03-25 15:18:31 +02:00
Lasse Collin
bc14e4c94e
liblzma: Add "restrict" to a few functions in lz_decoder.h
This doesn't make any difference in practice because compilers can
already see that writing through the dict->buf pointer cannot modify
the contents of *dict itself: The LZMA decoder makes a local copy of
the lzma_dict structure, and even if it didn't, the pointer to
lzma_dict in the LZMA decoder is already "restrict".

It's nice to add "restrict" anyway. uint8_t is typically unsigned char
which can alias anything. Without the above conditions or "restrict",
compilers could need to assume that writing through dict->buf might
modify *dict. This would matter in dict_repeat() because the loops
refer to dict->buf and dict->pos instead of making local copies of
those members for the duration of the loops. If compilers had to
assume that writing through dict->buf can affect *dict, then compilers
would need to emit code that reloads dict->buf and dict->pos after
every write through dict->buf.
2025-03-25 15:18:31 +02:00
Lasse Collin
e82ee090c5
liblzma: Define LZ_DICT_INIT_POS for initial dictionary position
It's more readable.
2025-03-25 15:18:30 +02:00
Collin Funk
4434671a04
tuklib_physmem: Silence -Wsign-conversion on AIX
Closes: https://github.com/tukaani-project/xz/pull/168
2025-03-10 11:36:44 +02:00
Lasse Collin
cc7f2fc1cf
Bump version and soname for 5.7.2beta 2025-03-08 14:38:56 +02:00
Lasse Collin
db9827dc38
xz: Update the man page about the environment variables again 2025-03-08 14:25:16 +02:00
Lasse Collin
99c584891b
liblzma: Edit spelling in a comment
It was found with codespell.
2025-03-06 19:37:03 +02:00
Lasse Collin
7a234c8c05
xz: Update the man page about the environment variables 2025-03-06 19:37:03 +02:00
Lasse Collin
808f05af3e
Docs: Add a few TRANSLATORS comments to man pages
All translators know that --command-line-options must not be translated.
With some other strings it's not obvious when the untranslated string
must be preserved. These comments hopefully help.
2025-03-06 19:37:03 +02:00
Lasse Collin
051de255f0
Scripts: Mark the LZMA Utils script aliases as deprecated
The deprecated aliases are lzcmp, lzdiff, lzless, lzmore,
lzgrep, lzegrep, and lzfgrep. The commands that start with
the xz prefix have identical behavior, for example, both
lzgrep and xzgrep handle all supported file formats.

This doesn't affect lzma, unlzma, lzcat, lzmadec, or lzmainfo.
The last release of LZMA Utils was made in 2008, but the lzma
compatibility alias for the gzip-like tool is still in common use.
Deprecating it would cause unnecessary breakage.
2025-03-06 19:36:56 +02:00
Lasse Collin
2eaf242c56
Build: Fix out-of-tree builds when using the replacement getopt_long
Nowaways $(top_builddir)/lib/getopt.h depends on headers in
$(top_srcdir)/lib, so both have to be in the include path.
CMake-based build already did this.

Fixes: 7e884c00d0093c38339f17fb1d280eec493f42ca
2025-02-17 21:48:24 +02:00
Lasse Collin
7d73ff7a9d
lzmainfo: Use tuklib_mbstr_wrap for --help text
Some languages have so long strings that they need to be wrapped.
2025-01-29 20:59:53 +02:00
Lasse Collin
999ce26371
tuklib_physmem: Clean up disabled code 2025-01-29 20:59:51 +02:00
Lasse Collin
4d7e7c9d94
Windows: Avoid an error message on broken pipe
Also make xz not process more input files after a broken pipe has
been detected. This matches the behavior on POSIX. If all files
are being written to standard output, trying with the next file is
pointless when it's known that standard output won't accept more data.

xzdec already stopped after the first error. It does so with all
errors, so it differs from xz:

    $ xz -dc not_found_1 not_found_2
    xz: not_found_1: No such file or directory
    xz: not_found_2: No such file or directory

    $ xzdec not_found_1 not_found_2
    xzdec: not_found_1: No such file or directory

Reported-by: Vincent Torri
2025-01-29 20:59:44 +02:00
Lasse Collin
cdae0df31e
Bump version and soname for 5.7.1alpha 2025-01-23 11:50:47 +02:00
Lasse Collin
4eae859ae8
Windows: Disable MinGW-w64's stdio functions in size-optimized builds
This only affects builds with UCRT. With legacy MSVCRT, the replacement
functions are always enabled.

Omitting the MinGW-w64 replacements saves over 20 KiB per executable.
The downside is that --enable-small or XZ_SMALL=ON disables thousand
separator support in xz messages. If someone is OK with the slower
speed of slightly smaller builds, lack of thousand separators won't
matter.

Don't override __USE_MINGW_ANSI_STDIO if it is already defined (via
CPPFLAGS or such method).
2025-01-22 15:39:05 +02:00
Lasse Collin
a831bc185b
liblzma: Add raw ARM64, RISC-V, and x86 BCJ filter APIs
Put them behind the LZMA_UNSTABLE macro for now.

These low-level special APIs might become useful in erofs-utils.
2025-01-20 16:44:27 +02:00
Lasse Collin
6f5cdd4534
xz: Unify a few strings with liblzma
Avoid having both "%s: foo" and "foo" as translatable strings
so that translators don't need to handle it twice.
2025-01-20 16:31:49 +02:00
Lasse Collin
713fdaa8b0
xz: Translate error messages from lzma_str_to_filters()
liblzma doesn't use gettext but the messages are included in xz.pot,
so xz can translate the messages.
2025-01-20 16:31:49 +02:00
Lasse Collin
f2e2b267ca
liblzma: Mark string conversion messages as translatable 2025-01-20 16:31:49 +02:00
Lasse Collin
f49d7413d9
liblzma: Tweak a few error messages in lzma_str_to_filters() 2025-01-20 16:31:35 +02:00
Lasse Collin
51f038f8cb
liblzma: memcmplen.h: Use 8-byte method on 64-bit unaligned archs
Previously it was enabled only on x86-64 and ARM64 when also support
for unaligned access was detected or manually enabled at built time.

In the default build configuration, the 8-byte method is now enabled
also on 64-bit RISC-V and 64-bit PowerPC (both endiannesses). It was
reported that on big endian POWER9, encoding time may reduce 12-13 %.

This change only affects builds with GCC and Clang because the code
uses __builtin_ctzll or __builtin_clzll.

Thanks to Marcus Comstedt for testing on POWER9.
2025-01-13 08:44:58 +02:00
Lasse Collin
150356207c
liblzma: Fix the encoder breakage on big endian ARM64
When the 8-byte method was enabled for ARM64, a check for endianness
wasn't added. This broke the LZMA/LZMA2 encoder. Test suite caught it.

Fixes: cd64dd70d5665b6048829c45772d08606f44672e
Co-authored-by: Marcus Comstedt <marcus@mc.pp.se>
2025-01-12 13:08:55 +02:00
Lasse Collin
b01b095802
Windows: Update manifest comments about long UTF-8 filenames 2025-01-12 13:08:55 +02:00
Lasse Collin
75d91d6b39
xz: Workaround broken O_SEARCH in musl
Testing with musl 1.2.5 and Linux 6.12, O_SEARCH doesn't result
in a file descriptor that works with fsync() although it should work.
See the added comment.

The same issue affected gzip --synchronous:

    https://bugs.gnu.org/75405

Thanks to Paul Eggert.
2025-01-08 19:20:28 +02:00
Lasse Collin
ea92eae122
Revert "xz: O_SEARCH cannot be used for fsync()"
This reverts commit 4014e2479c7b0273f15bd0c9c017c5fe859b0d8f.

POSIX-conforming O_SEARCH should allow fsync().
2025-01-08 19:20:21 +02:00
Lasse Collin
4014e2479c
xz: O_SEARCH cannot be used for fsync()
Opening a directory with O_SEARCH results in a file descriptor that can
be used with functions like openat(). Such a file descriptor cannot be
used with fsync(). Use O_RDONLY instead.

In musl, O_SEARCH becomes Linux-specific O_PATH. A file descriptor
from O_PATH doesn't allow fsync().

Seems that it's not possible to fsync() a directory that has write
and search permissions but not read permission.

Fixes: 2a9e91d796d091740489d951fa7780525e4275f1
2025-01-05 21:43:11 +02:00
Lasse Collin
c405264c03
tuklib_mbstr_nonprint: Preserve the value of errno
A typical use case is like this:

    printf("%s: %s\n", tuklib_mask_nonprint(filename), strerror(errno));

tuklib_mask_nonprint() may call mbrtowc() and malloc() which may modify
errno. If errno isn't preserved, the error message might be wrong if
a compiler decides to call tuklib_mask_nonprint() before strerror().

Fixes: 40e573305535960574404d2eae848b248c95ea7e
2025-01-05 20:16:09 +02:00
Lasse Collin
2a9e91d796
xz: Use fsync() before deleting the input file, and add --no-sync
xz's default behavior is to delete the input file after successful
compression or decompression (unless writing to standard output).
If the system crashes soon after the deletion, it is possible that
the newly written file has not yet hit the disk while the previous
delete operation might have. In that case neither the original file
nor the written file is available.

Call fsync() on the file. On POSIX systems, sync also the directory
where the file was created.

Add a new option --no-sync which disables fsync() usage. It can avoid
a (possibly significant) performance penalty when processing many
small files. It's fine to use --no-sync when one knows that the files
are easy to recreate or restore after a system crash.

Using fsync() after every flush initiated by --flush-timeout was
considered. It wasn't implemented at least for now.

  - --flush-timeout is typically used when writing to stdout. If stdout
    is a file, xz cannot (portably) sync the directory of the file.
    One would need to create the output file first, sync the directory,
    and then run xz with fsync() enabled.

  - If xz --flush-timeout output goes to a file, it's possible to use
    a separate script to sync the file, for example, once per minute
    while telling xz to flush more frequently.

  - Not supporting syncing with --flush-timeout was simpler.

Portability notes:

  - On systems that lack O_SEARCH (like Linux), "xz dir/file" will now
    fail if "dir" cannot be opened for reading. If "dir" still has
    write and search permissions (like d-wx------ in "ls -l"),
    previously xz would have been able to compress "dir/file" still.
    Now it only works if using --no-sync (or --keep or --stdout).

  - <libgen.h> and dirname() should be available on all POSIX systems,
    and aren't needed on non-POSIX systems.

  - fsync() is available on all POSIX systems. The directory syncing
    could be changed to fdatasync() although at least on ext4 it
    doesn't seem to make a performance difference in xz's usage.
    fdatasync() would need a build system check to support (old)
    special cases, for example, MINIX 3.3.0 doesn't have fdatasync()
    and Solaris 10 needs -lrt.

  - On native Windows, _commit() is used to replace fsync(). Directory
    syncing isn't done and shouldn't be needed. (In Cygwin, fsync() on
    directories is a no-op.)

  - DJGPP has fsync() for files. ;-)

Using fsync() was considered somewhere around 2009 and again in 2016 but
those times the idea was rejected. For comparison, GNU gzip 1.7 (2016)
added the option --synchronous which enables fsync().

Co-authored-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
Fixes: https://bugs.debian.org/814089
Link: https://www.mail-archive.com/xz-devel@tukaani.org/msg00282.html
Closes: https://github.com/tukaani-project/xz/pull/151
2025-01-05 20:16:08 +02:00
Lasse Collin
2e28c71457
xz: Use "goto" for error handling in io_open_dest_real() 2025-01-05 20:16:01 +02:00
Lasse Collin
7510721767
liblzma: Always validate the first digit of a preset string
lzma_str_to_filters() may call parse_lzma12_preset() in two ways. The
call from str_to_filters() detects the string type from the first
character(s) and as a side-effect it validates the first digit of
the preset string. So this change makes no difference there.

However, the call from parse_options() doesn't pre-validate the string.
parse_lzma12_preset() will return an invalid value which is passed to
lzma_lzma_preset() which safely rejects it. The bug still affects the
the error message:

    $ xz --filters=lzma2:preset=X
    xz: Error in --filters=FILTERS option:
    xz: lzma2:preset=X
    xz:               ^
    xz: Unsupported preset

After the fix:

    $ xz --filters=lzma2:preset=X
    xz: Error in --filters=FILTERS option:
    xz: lzma2:preset=X
    xz:              ^
    xz: Unsupported preset

The ^ now correctly points to the X and not past it because the X itself
is the problematic character.

Fixes: cedeeca2ea6ada5b0411b2ae10d7a859e837f203
2025-01-05 12:58:22 +02:00
Lasse Collin
52ff324337
xz: Fix getopt_long argument type in --filters*
Forgetting the argument (or not using = to separate the option from
the argument) resulted in lzma_str_to_filters() being called with NULL
as input string argument. The function handles it fine but xz passes
the NULL to printf() too:

    $ xz --filters
    xz: Error in --filters=FILTERS option:
    xz: (null)
    xz: ^
    xz: Unexpected NULL pointer argument(s) to lzma_str_to_filters()

Now it's correct:

    $ xz --filters
    xz: option '--filters' requires an argument

The --filters-help option doesn't take any arguments.

Fixes: 9ded880a0221f4d1256845fc4ab957ffd377c760
Fixes: d6af7f347077b22403133239592e478931307759
Fixes: a165d7df1964121eb9df715e6f836a31c865beef
2025-01-05 11:41:40 +02:00
Lasse Collin
2655c81b5e
xzdec: Don't leave Landlock file descriptor open for no reason
This fix is similar to 48ff3f06521ca326996ab9a04d1b342098960427.

Fixes: d74fb5f060b76db709b50f5fd37490394e52f975
2025-01-04 20:05:03 +02:00
Lasse Collin
35df4c2bc0
xz: Make --single-stream imply --keep
Suggested by xx on #tukaani on 2024-04-12.
2025-01-04 20:02:18 +02:00
Lasse Collin
6f412814a8
Update AUTHORS
The contributions have been rewritten.
2025-01-04 19:57:17 +02:00
Lasse Collin
5651d15303
xz: Avoid printf formats like %2$s
It's a POSIX feature that isn't in standard C. It's not available on
Windows. Even MinGW-w64 with __USE_MINGW_ANSI_STDIO doesn't support
it even though it supports POSIX %'d for thousand separators.

Gettext's <libintl.h> provides overrides for printf and other functions
which do support the %2$s formats. Translations use them. But xz should
work on Windows without <libintl.h> too.

Fixes: 3e9177fd206d20d6d8acc7d203c25a9ae0549229
2025-01-04 17:37:46 +02:00
Lasse Collin
63b246c90e
tuklib_mbstr_wrap: Add printf format attribute
It's supported by GCC 3.x already.
2025-01-04 17:37:46 +02:00
Lasse Collin
a7313c01d9
xz: Translate a Windows-specific string
Originally I thought that native Windows builds wouldn't be translated
but nowadays at least MSYS2 ships such binaries.
2025-01-04 17:37:39 +02:00
Lasse Collin
00eb6073c0
xz: Use my_landlock.h
A slightly silly thing is that xz may now query the ABI version up to
three times. We could call my_landlock_ruleset_attr_forbid_all() only
once and cache the result but it didn't seem worth doing.
2025-01-02 15:43:38 +02:00
Lasse Collin
0fc5a625d7
xzdec: Use my_landlock.h 2025-01-02 15:43:38 +02:00