瀏覽代碼

Merge branch 'upstream-liblzma' into update-liblzma

# By liblzma upstream
* upstream-liblzma:
  liblzma 2024-10-01 (9331ce40)
Brad King 9 月之前
父節點
當前提交
63a2a79c4f
共有 100 個文件被更改,包括 8136 次插入1251 次删除
  1. 55 37
      Utilities/cmliblzma/COPYING
  2. 18 11
      Utilities/cmliblzma/common/common_w32res.rc
  3. 41 14
      Utilities/cmliblzma/common/mythread.h
  4. 20 20
      Utilities/cmliblzma/common/sysdefs.h
  5. 24 5
      Utilities/cmliblzma/common/tuklib_common.h
  6. 5 0
      Utilities/cmliblzma/common/tuklib_config.h
  7. 11 3
      Utilities/cmliblzma/common/tuklib_cpucores.c
  8. 2 3
      Utilities/cmliblzma/common/tuklib_cpucores.h
  9. 291 79
      Utilities/cmliblzma/common/tuklib_integer.h
  10. 20 19
      Utilities/cmliblzma/liblzma/api/lzma.h
  11. 109 21
      Utilities/cmliblzma/liblzma/api/lzma/base.h
  12. 31 23
      Utilities/cmliblzma/liblzma/api/lzma/bcj.h
  13. 149 36
      Utilities/cmliblzma/liblzma/api/lzma/block.h
  14. 31 18
      Utilities/cmliblzma/liblzma/api/lzma/check.h
  15. 442 79
      Utilities/cmliblzma/liblzma/api/lzma/container.h
  16. 23 5
      Utilities/cmliblzma/liblzma/api/lzma/delta.h
  17. 432 89
      Utilities/cmliblzma/liblzma/api/lzma/filter.h
  18. 4 6
      Utilities/cmliblzma/liblzma/api/lzma/hardware.h
  19. 247 51
      Utilities/cmliblzma/liblzma/api/lzma/index.h
  20. 31 15
      Utilities/cmliblzma/liblzma/api/lzma/index_hash.h
  21. 172 24
      Utilities/cmliblzma/liblzma/api/lzma/lzma12.h
  22. 78 36
      Utilities/cmliblzma/liblzma/api/lzma/stream_flags.h
  23. 28 15
      Utilities/cmliblzma/liblzma/api/lzma/version.h
  24. 13 13
      Utilities/cmliblzma/liblzma/api/lzma/vli.h
  25. 2 3
      Utilities/cmliblzma/liblzma/check/check.c
  26. 9 7
      Utilities/cmliblzma/liblzma/check/check.h
  27. 122 0
      Utilities/cmliblzma/liblzma/check/crc32_arm64.h
  28. 140 18
      Utilities/cmliblzma/liblzma/check/crc32_fast.c
  29. 9 3
      Utilities/cmliblzma/liblzma/check/crc32_small.c
  30. 27 7
      Utilities/cmliblzma/liblzma/check/crc32_table.c
  31. 3 1
      Utilities/cmliblzma/liblzma/check/crc32_table_be.h
  32. 3 1
      Utilities/cmliblzma/liblzma/check/crc32_table_le.h
  33. 13 10
      Utilities/cmliblzma/liblzma/check/crc32_tablegen.c
  34. 14 6
      Utilities/cmliblzma/liblzma/check/crc32_x86.S
  35. 99 15
      Utilities/cmliblzma/liblzma/check/crc64_fast.c
  36. 7 3
      Utilities/cmliblzma/liblzma/check/crc64_small.c
  37. 22 7
      Utilities/cmliblzma/liblzma/check/crc64_table.c
  38. 3 1
      Utilities/cmliblzma/liblzma/check/crc64_table_be.h
  39. 3 1
      Utilities/cmliblzma/liblzma/check/crc64_table_le.h
  40. 8 7
      Utilities/cmliblzma/liblzma/check/crc64_tablegen.c
  41. 13 5
      Utilities/cmliblzma/liblzma/check/crc64_x86.S
  42. 137 0
      Utilities/cmliblzma/liblzma/check/crc_common.h
  43. 0 30
      Utilities/cmliblzma/liblzma/check/crc_macros.h
  44. 432 0
      Utilities/cmliblzma/liblzma/check/crc_x86_clmul.h
  45. 7 14
      Utilities/cmliblzma/liblzma/check/sha256.c
  46. 17 11
      Utilities/cmliblzma/liblzma/common/alone_decoder.c
  47. 2 3
      Utilities/cmliblzma/liblzma/common/alone_decoder.h
  48. 3 14
      Utilities/cmliblzma/liblzma/common/alone_encoder.c
  49. 21 11
      Utilities/cmliblzma/liblzma/common/auto_decoder.c
  50. 2 3
      Utilities/cmliblzma/liblzma/common/block_buffer_decoder.c
  51. 21 4
      Utilities/cmliblzma/liblzma/common/block_buffer_encoder.c
  52. 2 3
      Utilities/cmliblzma/liblzma/common/block_buffer_encoder.h
  53. 60 29
      Utilities/cmliblzma/liblzma/common/block_decoder.c
  54. 2 3
      Utilities/cmliblzma/liblzma/common/block_decoder.h
  55. 8 5
      Utilities/cmliblzma/liblzma/common/block_encoder.c
  56. 2 3
      Utilities/cmliblzma/liblzma/common/block_encoder.h
  57. 12 22
      Utilities/cmliblzma/liblzma/common/block_header_decoder.c
  58. 2 3
      Utilities/cmliblzma/liblzma/common/block_header_encoder.c
  59. 2 3
      Utilities/cmliblzma/liblzma/common/block_util.c
  60. 46 15
      Utilities/cmliblzma/liblzma/common/common.c
  61. 113 15
      Utilities/cmliblzma/liblzma/common/common.h
  62. 2 3
      Utilities/cmliblzma/liblzma/common/easy_buffer_encoder.c
  63. 2 3
      Utilities/cmliblzma/liblzma/common/easy_decoder_memusage.c
  64. 2 3
      Utilities/cmliblzma/liblzma/common/easy_encoder.c
  65. 2 3
      Utilities/cmliblzma/liblzma/common/easy_encoder_memusage.c
  66. 2 3
      Utilities/cmliblzma/liblzma/common/easy_preset.c
  67. 7 3
      Utilities/cmliblzma/liblzma/common/easy_preset.h
  68. 854 0
      Utilities/cmliblzma/liblzma/common/file_info.c
  69. 3 4
      Utilities/cmliblzma/liblzma/common/filter_buffer_decoder.c
  70. 2 3
      Utilities/cmliblzma/liblzma/common/filter_buffer_encoder.c
  71. 69 13
      Utilities/cmliblzma/liblzma/common/filter_common.c
  72. 5 3
      Utilities/cmliblzma/liblzma/common/filter_common.h
  73. 36 6
      Utilities/cmliblzma/liblzma/common/filter_decoder.c
  74. 2 3
      Utilities/cmliblzma/liblzma/common/filter_decoder.h
  75. 64 20
      Utilities/cmliblzma/liblzma/common/filter_encoder.c
  76. 3 8
      Utilities/cmliblzma/liblzma/common/filter_encoder.h
  77. 2 3
      Utilities/cmliblzma/liblzma/common/filter_flags_decoder.c
  78. 2 3
      Utilities/cmliblzma/liblzma/common/filter_flags_encoder.c
  79. 14 3
      Utilities/cmliblzma/liblzma/common/hardware_cputhreads.c
  80. 2 3
      Utilities/cmliblzma/liblzma/common/hardware_physmem.c
  81. 23 5
      Utilities/cmliblzma/liblzma/common/index.c
  82. 13 6
      Utilities/cmliblzma/liblzma/common/index.h
  83. 33 13
      Utilities/cmliblzma/liblzma/common/index_decoder.c
  84. 24 0
      Utilities/cmliblzma/liblzma/common/index_decoder.h
  85. 12 6
      Utilities/cmliblzma/liblzma/common/index_encoder.c
  86. 2 3
      Utilities/cmliblzma/liblzma/common/index_encoder.h
  87. 23 15
      Utilities/cmliblzma/liblzma/common/index_hash.c
  88. 417 0
      Utilities/cmliblzma/liblzma/common/lzip_decoder.c
  89. 21 0
      Utilities/cmliblzma/liblzma/common/lzip_decoder.h
  90. 44 20
      Utilities/cmliblzma/liblzma/common/memcmplen.h
  91. 220 0
      Utilities/cmliblzma/liblzma/common/microlzma_decoder.c
  92. 140 0
      Utilities/cmliblzma/liblzma/common/microlzma_encoder.c
  93. 203 101
      Utilities/cmliblzma/liblzma/common/outqueue.c
  94. 144 42
      Utilities/cmliblzma/liblzma/common/outqueue.h
  95. 2 3
      Utilities/cmliblzma/liblzma/common/stream_buffer_decoder.c
  96. 3 3
      Utilities/cmliblzma/liblzma/common/stream_buffer_encoder.c
  97. 23 17
      Utilities/cmliblzma/liblzma/common/stream_decoder.c
  98. 2 3
      Utilities/cmliblzma/liblzma/common/stream_decoder.h
  99. 2017 0
      Utilities/cmliblzma/liblzma/common/stream_decoder_mt.c
  100. 30 16
      Utilities/cmliblzma/liblzma/common/stream_encoder.c

+ 55 - 37
Utilities/cmliblzma/COPYING

@@ -3,63 +3,81 @@ XZ Utils Licensing
 ==================
 ==================
 
 
     Different licenses apply to different files in this package. Here
     Different licenses apply to different files in this package. Here
-    is a rough summary of which licenses apply to which parts of this
-    package (but check the individual files to be sure!):
+    is a summary of which licenses apply to which parts of this package:
 
 
-      - liblzma is in the public domain.
+      - liblzma is under the BSD Zero Clause License (0BSD).
 
 
-      - xz, xzdec, and lzmadec command line tools are in the public
-        domain unless GNU getopt_long had to be compiled and linked
-        in from the lib directory. The getopt_long code is under
-        GNU LGPLv2.1+.
+      - The command line tools xz, xzdec, lzmadec, and lzmainfo are
+        under 0BSD except that, on systems that don't have a usable
+        getopt_long, GNU getopt_long is compiled and linked in from the
+        'lib' directory. The getopt_long code is under GNU LGPLv2.1+.
 
 
       - The scripts to grep, diff, and view compressed files have been
       - The scripts to grep, diff, and view compressed files have been
-        adapted from gzip. These scripts and their documentation are
-        under GNU GPLv2+.
+        adapted from GNU gzip. These scripts (xzgrep, xzdiff, xzless,
+        and xzmore) are under GNU GPLv2+. The man pages of the scripts
+        are under 0BSD; they aren't based on the man pages of GNU gzip.
 
 
-      - All the documentation in the doc directory and most of the
-        XZ Utils specific documentation files in other directories
-        are in the public domain.
+      - Most of the XZ Utils specific documentation that is in
+        plain text files (like README, INSTALL, PACKAGERS, NEWS,
+        and ChangeLog) are under 0BSD unless stated otherwise in
+        the file itself. The files xz-file-format.txt and
+        lzma-file-format.xt are in the public domain but may
+        be distributed under the terms of 0BSD too.
 
 
-      - Translated messages are in the public domain.
+      - Translated messages and man pages are under 0BSD except that
+        some old translations are in the public domain.
 
 
-      - The build system contains public domain files, and files that
-        are under GNU GPLv2+ or GNU GPLv3+. None of these files end up
-        in the binaries being built.
+      - Test files and test code in the 'tests' directory, and
+        debugging utilities in the 'debug' directory are under
+        the BSD Zero Clause License (0BSD).
 
 
-      - Test files and test code in the tests directory, and debugging
-        utilities in the debug directory are in the public domain.
+      - The GNU Autotools based build system contains files that are
+        under GNU GPLv2+, GNU GPLv3+, and a few permissive licenses.
+        These files don't affect the licensing of the binaries being
+        built.
 
 
-      - The extra directory may contain public domain files, and files
-        that are under various free software licenses.
+      - The 'extra' directory contains files that are under various
+        free software licenses. These aren't built or installed as
+        part of XZ Utils.
 
 
-    You can do whatever you want with the files that have been put into
-    the public domain. If you find public domain legally problematic,
-    take the previous sentence as a license grant. If you still find
-    the lack of copyright legally problematic, you have too many
-    lawyers.
+    For the files under the BSD Zero Clause License (0BSD), if
+    a copyright notice is needed, the following is sufficient:
 
 
-    As usual, this software is provided "as is", without any warranty.
+        Copyright (C) The XZ Utils authors and contributors
 
 
-    If you copy significant amounts of public domain code from XZ Utils
+    If you copy significant amounts of 0BSD-licensed code from XZ Utils
     into your project, acknowledging this somewhere in your software is
     into your project, acknowledging this somewhere in your software is
     polite (especially if it is proprietary, non-free software), but
     polite (especially if it is proprietary, non-free software), but
-    naturally it is not legally required. Here is an example of a good
-    notice to put into "about box" or into documentation:
+    it is not legally required by the license terms. Here is an example
+    of a good notice to put into "about box" or into documentation:
 
 
         This software includes code from XZ Utils <https://tukaani.org/xz/>.
         This software includes code from XZ Utils <https://tukaani.org/xz/>.
 
 
     The following license texts are included in the following files:
     The following license texts are included in the following files:
+      - COPYING.0BSD: BSD Zero Clause License
       - COPYING.LGPLv2.1: GNU Lesser General Public License version 2.1
       - COPYING.LGPLv2.1: GNU Lesser General Public License version 2.1
       - COPYING.GPLv2: GNU General Public License version 2
       - COPYING.GPLv2: GNU General Public License version 2
       - COPYING.GPLv3: GNU General Public License version 3
       - COPYING.GPLv3: GNU General Public License version 3
 
 
-    Note that the toolchain (compiler, linker etc.) may add some code
-    pieces that are copyrighted. Thus, it is possible that e.g. liblzma
-    binary wouldn't actually be in the public domain in its entirety
-    even though it contains no copyrighted code from the XZ Utils source
-    package.
-
-    If you have questions, don't hesitate to ask the author(s) for more
-    information.
+    A note about old XZ Utils releases:
+
+        XZ Utils releases 5.4.6 and older and 5.5.1alpha have a
+        significant amount of code put into the public domain and
+        that obviously remains so. The switch from public domain to
+        0BSD for newer releases was made in Febrary 2024 because
+        public domain has (real or perceived) legal ambiguities in
+        some jurisdictions.
+
+        There is very little *practical* difference between public
+        domain and 0BSD. The main difference likely is that one
+        shouldn't claim that 0BSD-licensed code is in the public
+        domain; 0BSD-licensed code is copyrighted but available under
+        an extremely permissive license. Neither 0BSD nor public domain
+        require retaining or reproducing author, copyright holder, or
+        license notices when distributing the software. (Compare to,
+        for example, BSD 2-Clause "Simplified" License which does have
+        such requirements.)
+
+    If you have questions, don't hesitate to ask for more information.
+    The contact information is in the README file.
 
 

+ 18 - 11
Utilities/cmliblzma/common/common_w32res.rc

@@ -1,12 +1,13 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /*
 /*
  * Author: Lasse Collin
  * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
  */
  */
 
 
 #include <winresrc.h>
 #include <winresrc.h>
-#include "config.h"
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
 #define LZMA_H_INTERNAL
 #define LZMA_H_INTERNAL
 #define LZMA_H_INTERNAL_RC
 #define LZMA_H_INTERNAL_RC
 #include "lzma/version.h"
 #include "lzma/version.h"
@@ -21,14 +22,15 @@
 #define MY_PRODUCT     PACKAGE_NAME " <" PACKAGE_URL ">"
 #define MY_PRODUCT     PACKAGE_NAME " <" PACKAGE_URL ">"
 
 
 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
 VS_VERSION_INFO VERSIONINFO
 VS_VERSION_INFO VERSIONINFO
-  FILEVERSION MY_VERSION
-  PRODUCTVERSION MY_VERSION
-  FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
-  FILEFLAGS 0
-  FILEOS VOS_NT_WINDOWS32
-  FILETYPE MY_TYPE
-  FILESUBTYPE 0x0L
+FILEVERSION MY_VERSION
+PRODUCTVERSION MY_VERSION
+FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+FILEFLAGS 0
+FILEOS VOS_NT_WINDOWS32
+FILETYPE MY_TYPE
+FILESUBTYPE 0x0L
 BEGIN
 BEGIN
     BLOCK "StringFileInfo"
     BLOCK "StringFileInfo"
     BEGIN
     BEGIN
@@ -48,3 +50,8 @@ BEGIN
         VALUE "Translation", 0x409, 1200
         VALUE "Translation", 0x409, 1200
     END
     END
 END
 END
+
+/* Omit the manifest on Cygwin and MSYS2 (both define __CYGWIN__). */
+#if MY_TYPE == VFT_APP && !defined(__CYGWIN__)
+CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "w32_application.manifest"
+#endif

+ 41 - 14
Utilities/cmliblzma/common/mythread.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       mythread.h
 /// \file       mythread.h
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef MYTHREAD_H
 #ifndef MYTHREAD_H
@@ -79,7 +78,7 @@ do { \
 } while (0)
 } while (0)
 
 
 
 
-#if !(defined(_WIN32) && !defined(__CYGWIN__))
+#if !(defined(_WIN32) && !defined(__CYGWIN__)) && !defined(__wasm__)
 // Use sigprocmask() to set the signal mask in single-threaded programs.
 // Use sigprocmask() to set the signal mask in single-threaded programs.
 #include <signal.h>
 #include <signal.h>
 
 
@@ -100,12 +99,37 @@ mythread_sigmask(int how, const sigset_t *restrict set,
 // Using pthreads //
 // Using pthreads //
 ////////////////////
 ////////////////////
 
 
-#include <sys/time.h>
 #include <pthread.h>
 #include <pthread.h>
 #include <signal.h>
 #include <signal.h>
 #include <time.h>
 #include <time.h>
 #include <errno.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
+
+// MinGW-w64 with winpthreads:
+//
+// NOTE: Typical builds with MinGW-w64 don't use this code (MYTHREAD_POSIX).
+// Instead, native Windows threading APIs are used (MYTHREAD_VISTA or
+// MYTHREAD_WIN95).
+//
+// MinGW-w64 has _sigset_t (an integer type) in <sys/types.h>.
+// If _POSIX was #defined, the header would add the alias sigset_t too.
+// Let's keep this working even without _POSIX.
+//
+// There are no functions that actually do something with sigset_t
+// because signals barely exist on Windows. The sigfillset macro below
+// is just to silence warnings. There is no sigfillset() in MinGW-w64.
+#ifdef __MINGW32__
+#	include <sys/types.h>
+#	define sigset_t _sigset_t
+#	define sigfillset(set_ptr) do { *(set_ptr) = 0; } while (0)
+#endif
+
 #define MYTHREAD_RET_TYPE void *
 #define MYTHREAD_RET_TYPE void *
 #define MYTHREAD_RET_VALUE NULL
 #define MYTHREAD_RET_VALUE NULL
 
 
@@ -134,11 +158,13 @@ typedef struct timespec mythread_condtime;
 
 
 // Use pthread_sigmask() to set the signal mask in multi-threaded programs.
 // Use pthread_sigmask() to set the signal mask in multi-threaded programs.
 // Do nothing on OpenVMS since it lacks pthread_sigmask().
 // Do nothing on OpenVMS since it lacks pthread_sigmask().
+// Do nothing on MinGW-w64 too to silence warnings (its pthread_sigmask()
+// is #defined to 0 so it's a no-op).
 static inline void
 static inline void
 mythread_sigmask(int how, const sigset_t *restrict set,
 mythread_sigmask(int how, const sigset_t *restrict set,
 		sigset_t *restrict oset)
 		sigset_t *restrict oset)
 {
 {
-#ifdef __VMS
+#if defined(__VMS) || defined(__MINGW32__)
 	(void)how;
 	(void)how;
 	(void)set;
 	(void)set;
 	(void)oset;
 	(void)oset;
@@ -174,7 +200,7 @@ mythread_join(mythread thread)
 }
 }
 
 
 
 
-// Initiatlizes a mutex. Returns zero on success and non-zero on error.
+// Initializes a mutex. Returns zero on success and non-zero on error.
 static inline int
 static inline int
 mythread_mutex_init(mythread_mutex *mutex)
 mythread_mutex_init(mythread_mutex *mutex)
 {
 {
@@ -219,8 +245,8 @@ static inline int
 mythread_cond_init(mythread_cond *mycond)
 mythread_cond_init(mythread_cond *mycond)
 {
 {
 #ifdef HAVE_CLOCK_GETTIME
 #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;
 	struct timespec ts;
 	pthread_condattr_t condattr;
 	pthread_condattr_t condattr;
 
 
@@ -294,8 +320,8 @@ static inline void
 mythread_condtime_set(mythread_condtime *condtime, const mythread_cond *cond,
 mythread_condtime_set(mythread_condtime *condtime, const mythread_cond *cond,
 		uint32_t timeout_ms)
 		uint32_t timeout_ms)
 {
 {
-	condtime->tv_sec = timeout_ms / 1000;
-	condtime->tv_nsec = (timeout_ms % 1000) * 1000000;
+	condtime->tv_sec = (time_t)(timeout_ms / 1000);
+	condtime->tv_nsec = (long)((timeout_ms % 1000) * 1000000);
 
 
 #ifdef HAVE_CLOCK_GETTIME
 #ifdef HAVE_CLOCK_GETTIME
 	struct timespec now;
 	struct timespec now;
@@ -370,10 +396,11 @@ typedef struct {
 		BOOL pending_; \
 		BOOL pending_; \
 		if (!InitOnceBeginInitialize(&once_, 0, &pending_, NULL)) \
 		if (!InitOnceBeginInitialize(&once_, 0, &pending_, NULL)) \
 			abort(); \
 			abort(); \
-		if (pending_) \
+		if (pending_) { \
 			func(); \
 			func(); \
-		if (!InitOnceComplete(&once, 0, NULL)) \
-			abort(); \
+			if (!InitOnceComplete(&once_, 0, NULL)) \
+				abort(); \
+		} \
 	} while (0)
 	} while (0)
 #endif
 #endif
 
 

+ 20 - 20
Utilities/cmliblzma/common/sysdefs.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       sysdefs.h
 /// \file       sysdefs.h
@@ -8,9 +10,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef LZMA_SYSDEFS_H
 #ifndef LZMA_SYSDEFS_H
@@ -29,7 +28,15 @@
 
 
 #include "config.h"
 #include "config.h"
 
 
-// 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__
 #ifdef __MINGW32__
 #	define __USE_MINGW_ANSI_STDIO 1
 #	define __USE_MINGW_ANSI_STDIO 1
 #endif
 #endif
@@ -138,7 +145,7 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #include <assert.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:
 // so that it works with fake bool type, for example:
 //
 //
 //    bool foo = (flags & 0x100) != 0;
 //    bool foo = (flags & 0x100) != 0;
@@ -160,25 +167,18 @@ typedef unsigned char _Bool;
 #	define __bool_true_false_are_defined 1
 #	define __bool_true_false_are_defined 1
 #endif
 #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>
 #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)
-#	ifndef inline
+// Visual Studio 2013 update 2 supports only __inline, not inline.
+// MSVC v19.0 / VS 2015 and newer support both.
+//
+// MSVC v19.27 (VS 2019 version 16.7) added support for restrict.
+// Older ones support only __restrict.
+#ifdef _MSC_VER
+#	if _MSC_VER < 1900 && !defined(inline)
 #		define inline __inline
 #		define inline __inline
 #	endif
 #	endif
-#	ifndef restrict
+#	if _MSC_VER < 1927 && !defined(restrict)
 #		define restrict __restrict
 #		define restrict __restrict
 #	endif
 #	endif
 #elif defined(__EDG__) && defined(__LCC__)
 #elif defined(__EDG__) && defined(__LCC__)

+ 24 - 5
Utilities/cmliblzma/common/tuklib_common.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       tuklib_common.h
 /// \file       tuklib_common.h
@@ -5,16 +7,13 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef TUKLIB_COMMON_H
 #ifndef TUKLIB_COMMON_H
 #define TUKLIB_COMMON_H
 #define TUKLIB_COMMON_H
 
 
 // The config file may be replaced by a package-specific file.
 // The config file may be replaced by a package-specific file.
-// It should include at least stddef.h, inttypes.h, and limits.h.
+// It should include at least stddef.h, stdbool.h, inttypes.h, and limits.h.
 #include "tuklib_config.h"
 #include "tuklib_config.h"
 
 
 // TUKLIB_SYMBOL_PREFIX is prefixed to all symbols exported by
 // TUKLIB_SYMBOL_PREFIX is prefixed to all symbols exported by
@@ -57,8 +56,28 @@
 #	define TUKLIB_GNUC_REQ(major, minor) 0
 #	define TUKLIB_GNUC_REQ(major, minor) 0
 #endif
 #endif
 
 
-#if TUKLIB_GNUC_REQ(2, 5)
+// tuklib_attr_noreturn attribute is used to mark functions as non-returning.
+// We cannot use "noreturn" as the macro name because then C23 code that
+// uses [[noreturn]] would break as it would expand to [[ [[noreturn]] ]].
+//
+// tuklib_attr_noreturn must be used at the beginning of function declaration
+// to work in all cases. The [[noreturn]] syntax is the most limiting, it
+// must be even before any GNU C's __attribute__ keywords:
+//
+//     tuklib_attr_noreturn
+//     __attribute__((nonnull(1)))
+//     extern void foo(const char *s);
+//
+// FIXME: Update __STDC_VERSION__ for the final C23 version. 202000 is used
+// by GCC 13 and Clang 15 with -std=c2x.
+#if   defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000
+#	define tuklib_attr_noreturn [[noreturn]]
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112
+#	define tuklib_attr_noreturn _Noreturn
+#elif TUKLIB_GNUC_REQ(2, 5)
 #	define tuklib_attr_noreturn __attribute__((__noreturn__))
 #	define tuklib_attr_noreturn __attribute__((__noreturn__))
+#elif defined(_MSC_VER)
+#	define tuklib_attr_noreturn __declspec(noreturn)
 #else
 #else
 #	define tuklib_attr_noreturn
 #	define tuklib_attr_noreturn
 #endif
 #endif

+ 5 - 0
Utilities/cmliblzma/common/tuklib_config.h

@@ -1,7 +1,12 @@
+// SPDX-License-Identifier: 0BSD
+
+// If config.h isn't available, assume that the headers required by
+// tuklib_common.h are available. This is required by crc32_tablegen.c.
 #ifdef HAVE_CONFIG_H
 #ifdef HAVE_CONFIG_H
 #	include "sysdefs.h"
 #	include "sysdefs.h"
 #else
 #else
 #	include <stddef.h>
 #	include <stddef.h>
+#	include <stdbool.h>
 #	include <inttypes.h>
 #	include <inttypes.h>
 #	include <limits.h>
 #	include <limits.h>
 #endif
 #endif

+ 11 - 3
Utilities/cmliblzma/common/tuklib_cpucores.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       tuklib_cpucores.c
 /// \file       tuklib_cpucores.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "tuklib_cpucores.h"
 #include "tuklib_cpucores.h"
@@ -72,7 +71,16 @@ tuklib_cpucores(void)
 	}
 	}
 
 
 #elif defined(TUKLIB_CPUCORES_SYSCTL)
 #elif defined(TUKLIB_CPUCORES_SYSCTL)
+	// On OpenBSD HW_NCPUONLINE tells the number of processor cores that
+	// are online so it is preferred over HW_NCPU which also counts cores
+	// that aren't currently available. The number of cores online is
+	// often less than HW_NCPU because OpenBSD disables simultaneous
+	// multi-threading (SMT) by default.
+#	ifdef HW_NCPUONLINE
+	int name[2] = { CTL_HW, HW_NCPUONLINE };
+#	else
 	int name[2] = { CTL_HW, HW_NCPU };
 	int name[2] = { CTL_HW, HW_NCPU };
+#	endif
 	int cpus;
 	int cpus;
 	size_t cpus_size = sizeof(cpus);
 	size_t cpus_size = sizeof(cpus);
 	if (sysctl(name, 2, &cpus, &cpus_size, NULL, 0) != -1
 	if (sysctl(name, 2, &cpus, &cpus_size, NULL, 0) != -1

+ 2 - 3
Utilities/cmliblzma/common/tuklib_cpucores.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       tuklib_cpucores.h
 /// \file       tuklib_cpucores.h
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef TUKLIB_CPUCORES_H
 #ifndef TUKLIB_CPUCORES_H

+ 291 - 79
Utilities/cmliblzma/common/tuklib_integer.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       tuklib_integer.h
 /// \file       tuklib_integer.h
@@ -14,11 +16,11 @@
 ///
 ///
 /// Endianness-converting integer operations (these can be macros!)
 /// Endianness-converting integer operations (these can be macros!)
 /// (XX = 16, 32, or 64; Y = b or l):
 /// (XX = 16, 32, or 64; Y = b or l):
-///   - Byte swapping: bswapXX(num)
+///   - Byte swapping: byteswapXX(num)
 ///   - Byte order conversions to/from native (byteswaps if Y isn't
 ///   - Byte order conversions to/from native (byteswaps if Y isn't
 ///     the native endianness): convXXYe(num)
 ///     the native endianness): convXXYe(num)
-///   - Unaligned reads (16/32-bit only): readXXYe(ptr)
-///   - Unaligned writes (16/32-bit only): writeXXYe(ptr, num)
+///   - Unaligned reads: readXXYe(ptr)
+///   - Unaligned writes: writeXXYe(ptr, num)
 ///   - Aligned reads: aligned_readXXYe(ptr)
 ///   - Aligned reads: aligned_readXXYe(ptr)
 ///   - Aligned writes: aligned_writeXXYe(ptr, num)
 ///   - Aligned writes: aligned_writeXXYe(ptr, num)
 ///
 ///
@@ -37,9 +39,6 @@
 //  Authors:    Lasse Collin
 //  Authors:    Lasse Collin
 //              Joachim Henke
 //              Joachim Henke
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef TUKLIB_INTEGER_H
 #ifndef TUKLIB_INTEGER_H
@@ -52,6 +51,12 @@
 // and such functions.
 // and such functions.
 #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500)
 #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500)
 #	include <immintrin.h>
 #	include <immintrin.h>
+// Only include <intrin.h> when it is needed. GCC and Clang can both
+// use __builtin's, so we only need Windows instrincs when using MSVC.
+// GCC and Clang can set _MSC_VER on Windows, so we need to exclude these
+// cases explicitly.
+#elif defined(_MSC_VER) && !TUKLIB_GNUC_REQ(3, 4) && !defined(__clang__)
+#	include <intrin.h>
 #endif
 #endif
 
 
 
 
@@ -61,38 +66,47 @@
 
 
 #if defined(HAVE___BUILTIN_BSWAPXX)
 #if defined(HAVE___BUILTIN_BSWAPXX)
 	// GCC >= 4.8 and Clang
 	// GCC >= 4.8 and Clang
-#	define bswap16(n) __builtin_bswap16(n)
-#	define bswap32(n) __builtin_bswap32(n)
-#	define bswap64(n) __builtin_bswap64(n)
+#	define byteswap16(num) __builtin_bswap16(num)
+#	define byteswap32(num) __builtin_bswap32(num)
+#	define byteswap64(num) __builtin_bswap64(num)
 
 
 #elif defined(HAVE_BYTESWAP_H)
 #elif defined(HAVE_BYTESWAP_H)
 	// glibc, uClibc, dietlibc
 	// glibc, uClibc, dietlibc
 #	include <byteswap.h>
 #	include <byteswap.h>
 #	ifdef HAVE_BSWAP_16
 #	ifdef HAVE_BSWAP_16
-#		define bswap16(num) bswap_16(num)
+#		define byteswap16(num) bswap_16(num)
 #	endif
 #	endif
 #	ifdef HAVE_BSWAP_32
 #	ifdef HAVE_BSWAP_32
-#		define bswap32(num) bswap_32(num)
+#		define byteswap32(num) bswap_32(num)
 #	endif
 #	endif
 #	ifdef HAVE_BSWAP_64
 #	ifdef HAVE_BSWAP_64
-#		define bswap64(num) bswap_64(num)
+#		define byteswap64(num) bswap_64(num)
 #	endif
 #	endif
 
 
 #elif defined(HAVE_SYS_ENDIAN_H)
 #elif defined(HAVE_SYS_ENDIAN_H)
 	// *BSDs and Darwin
 	// *BSDs and Darwin
 #	include <sys/endian.h>
 #	include <sys/endian.h>
+#	ifdef __OpenBSD__
+#		define byteswap16(num) swap16(num)
+#		define byteswap32(num) swap32(num)
+#		define byteswap64(num) swap64(num)
+#	else
+#		define byteswap16(num) bswap16(num)
+#		define byteswap32(num) bswap32(num)
+#		define byteswap64(num) bswap64(num)
+#	endif
 
 
 #elif defined(HAVE_SYS_BYTEORDER_H)
 #elif defined(HAVE_SYS_BYTEORDER_H)
 	// Solaris
 	// Solaris
 #	include <sys/byteorder.h>
 #	include <sys/byteorder.h>
 #	ifdef BSWAP_16
 #	ifdef BSWAP_16
-#		define bswap16(num) BSWAP_16(num)
+#		define byteswap16(num) BSWAP_16(num)
 #	endif
 #	endif
 #	ifdef BSWAP_32
 #	ifdef BSWAP_32
-#		define bswap32(num) BSWAP_32(num)
+#		define byteswap32(num) BSWAP_32(num)
 #	endif
 #	endif
 #	ifdef BSWAP_64
 #	ifdef BSWAP_64
-#		define bswap64(num) BSWAP_64(num)
+#		define byteswap64(num) BSWAP_64(num)
 #	endif
 #	endif
 #	ifdef BE_16
 #	ifdef BE_16
 #		define conv16be(num) BE_16(num)
 #		define conv16be(num) BE_16(num)
@@ -114,15 +128,15 @@
 #	endif
 #	endif
 #endif
 #endif
 
 
-#ifndef bswap16
-#	define bswap16(n) (uint16_t)( \
+#ifndef byteswap16
+#	define byteswap16(n) (uint16_t)( \
 		  (((n) & 0x00FFU) << 8) \
 		  (((n) & 0x00FFU) << 8) \
 		| (((n) & 0xFF00U) >> 8) \
 		| (((n) & 0xFF00U) >> 8) \
 	)
 	)
 #endif
 #endif
 
 
-#ifndef bswap32
-#	define bswap32(n) (uint32_t)( \
+#ifndef byteswap32
+#	define byteswap32(n) (uint32_t)( \
 		  (((n) & UINT32_C(0x000000FF)) << 24) \
 		  (((n) & UINT32_C(0x000000FF)) << 24) \
 		| (((n) & UINT32_C(0x0000FF00)) << 8) \
 		| (((n) & UINT32_C(0x0000FF00)) << 8) \
 		| (((n) & UINT32_C(0x00FF0000)) >> 8) \
 		| (((n) & UINT32_C(0x00FF0000)) >> 8) \
@@ -130,8 +144,8 @@
 	)
 	)
 #endif
 #endif
 
 
-#ifndef bswap64
-#	define bswap64(n) (uint64_t)( \
+#ifndef byteswap64
+#	define byteswap64(n) (uint64_t)( \
 		  (((n) & UINT64_C(0x00000000000000FF)) << 56) \
 		  (((n) & UINT64_C(0x00000000000000FF)) << 56) \
 		| (((n) & UINT64_C(0x000000000000FF00)) << 40) \
 		| (((n) & UINT64_C(0x000000000000FF00)) << 40) \
 		| (((n) & UINT64_C(0x0000000000FF0000)) << 24) \
 		| (((n) & UINT64_C(0x0000000000FF0000)) << 24) \
@@ -155,23 +169,23 @@
 #		define conv64be(num) ((uint64_t)(num))
 #		define conv64be(num) ((uint64_t)(num))
 #	endif
 #	endif
 #	ifndef conv16le
 #	ifndef conv16le
-#		define conv16le(num) bswap16(num)
+#		define conv16le(num) byteswap16(num)
 #	endif
 #	endif
 #	ifndef conv32le
 #	ifndef conv32le
-#		define conv32le(num) bswap32(num)
+#		define conv32le(num) byteswap32(num)
 #	endif
 #	endif
 #	ifndef conv64le
 #	ifndef conv64le
-#		define conv64le(num) bswap64(num)
+#		define conv64le(num) byteswap64(num)
 #	endif
 #	endif
 #else
 #else
 #	ifndef conv16be
 #	ifndef conv16be
-#		define conv16be(num) bswap16(num)
+#		define conv16be(num) byteswap16(num)
 #	endif
 #	endif
 #	ifndef conv32be
 #	ifndef conv32be
-#		define conv32be(num) bswap32(num)
+#		define conv32be(num) byteswap32(num)
 #	endif
 #	endif
 #	ifndef conv64be
 #	ifndef conv64be
-#		define conv64be(num) bswap64(num)
+#		define conv64be(num) byteswap64(num)
 #	endif
 #	endif
 #	ifndef conv16le
 #	ifndef conv16le
 #		define conv16le(num) ((uint16_t)(num))
 #		define conv16le(num) ((uint16_t)(num))
@@ -189,6 +203,9 @@
 // Unaligned reads and writes //
 // Unaligned reads and writes //
 ////////////////////////////////
 ////////////////////////////////
 
 
+// No-strict-align archs like x86-64
+// ---------------------------------
+//
 // The traditional way of casting e.g. *(const uint16_t *)uint8_pointer
 // 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
 // is bad even if the uint8_pointer is properly aligned because this kind
 // of casts break strict aliasing rules and result in undefined behavior.
 // of casts break strict aliasing rules and result in undefined behavior.
@@ -203,12 +220,115 @@
 // build time. A third method, casting to a packed struct, would also be
 // 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).
 // an option but isn't provided to keep things simpler (it's already a mess).
 // Hopefully this is flexible enough in practice.
 // 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 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 choice for strict-align archs to do unaligned access.
+//
+// See also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111502
+//
+// Thanks to <https://godbolt.org/> it was easy to test different compilers.
+// The following is for little endian targets:
+/*
+#include <stdint.h>
+#include <string.h>
+
+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
 static inline uint16_t
 read16ne(const uint8_t *buf)
 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;
 	return *(const uint16_t *)buf;
 #else
 #else
 	uint16_t num;
 	uint16_t num;
@@ -221,8 +341,7 @@ read16ne(const uint8_t *buf)
 static inline uint32_t
 static inline uint32_t
 read32ne(const uint8_t *buf)
 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;
 	return *(const uint32_t *)buf;
 #else
 #else
 	uint32_t num;
 	uint32_t num;
@@ -235,8 +354,7 @@ read32ne(const uint8_t *buf)
 static inline uint64_t
 static inline uint64_t
 read64ne(const uint8_t *buf)
 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;
 	return *(const uint64_t *)buf;
 #else
 #else
 	uint64_t num;
 	uint64_t num;
@@ -249,8 +367,7 @@ read64ne(const uint8_t *buf)
 static inline void
 static inline void
 write16ne(uint8_t *buf, uint16_t num)
 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;
 	*(uint16_t *)buf = num;
 #else
 #else
 	memcpy(buf, &num, sizeof(num));
 	memcpy(buf, &num, sizeof(num));
@@ -262,8 +379,7 @@ write16ne(uint8_t *buf, uint16_t num)
 static inline void
 static inline void
 write32ne(uint8_t *buf, uint32_t num)
 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;
 	*(uint32_t *)buf = num;
 #else
 #else
 	memcpy(buf, &num, sizeof(num));
 	memcpy(buf, &num, sizeof(num));
@@ -275,8 +391,7 @@ write32ne(uint8_t *buf, uint32_t num)
 static inline void
 static inline void
 write64ne(uint8_t *buf, uint64_t num)
 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;
 	*(uint64_t *)buf = num;
 #else
 #else
 	memcpy(buf, &num, sizeof(num));
 	memcpy(buf, &num, sizeof(num));
@@ -288,77 +403,149 @@ write64ne(uint8_t *buf, uint64_t num)
 static inline uint16_t
 static inline uint16_t
 read16be(const uint8_t *buf)
 read16be(const uint8_t *buf)
 {
 {
-#if defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS)
 	uint16_t num = read16ne(buf);
 	uint16_t num = read16ne(buf);
 	return conv16be(num);
 	return conv16be(num);
-#else
-	uint16_t num = ((uint16_t)buf[0] << 8) | (uint16_t)buf[1];
-	return num;
-#endif
 }
 }
 
 
 
 
 static inline uint16_t
 static inline uint16_t
 read16le(const uint8_t *buf)
 read16le(const uint8_t *buf)
 {
 {
-#if !defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS)
 	uint16_t num = read16ne(buf);
 	uint16_t num = read16ne(buf);
 	return conv16le(num);
 	return conv16le(num);
-#else
-	uint16_t num = ((uint16_t)buf[0]) | ((uint16_t)buf[1] << 8);
-	return num;
-#endif
 }
 }
 
 
 
 
 static inline uint32_t
 static inline uint32_t
 read32be(const uint8_t *buf)
 read32be(const uint8_t *buf)
 {
 {
-#if defined(WORDS_BIGENDIAN) || defined(TUKLIB_FAST_UNALIGNED_ACCESS)
 	uint32_t num = read32ne(buf);
 	uint32_t num = read32ne(buf);
 	return conv32be(num);
 	return conv32be(num);
+}
+
+
+static inline uint32_t
+read32le(const uint8_t *buf)
+{
+	uint32_t num = read32ne(buf);
+	return conv32le(num);
+}
+
+
+static inline uint64_t
+read64be(const uint8_t *buf)
+{
+	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
 #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;
 	uint32_t num = (uint32_t)buf[0] << 24;
 	num |= (uint32_t)buf[1] << 16;
 	num |= (uint32_t)buf[1] << 16;
 	num |= (uint32_t)buf[2] << 8;
 	num |= (uint32_t)buf[2] << 8;
 	num |= (uint32_t)buf[3];
 	num |= (uint32_t)buf[3];
 	return num;
 	return num;
-#endif
 }
 }
 
 
 
 
 static inline uint32_t
 static inline uint32_t
 read32le(const uint8_t *buf)
 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];
 	uint32_t num = (uint32_t)buf[0];
 	num |= (uint32_t)buf[1] << 8;
 	num |= (uint32_t)buf[1] << 8;
 	num |= (uint32_t)buf[2] << 16;
 	num |= (uint32_t)buf[2] << 16;
 	num |= (uint32_t)buf[3] << 24;
 	num |= (uint32_t)buf[3] << 24;
 	return num;
 	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))
-#endif
+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;
+	num |= (uint64_t)buf[3] << 32;
+	num |= (uint64_t)buf[4] << 24;
+	num |= (uint64_t)buf[5] << 16;
+	num |= (uint64_t)buf[6] << 8;
+	num |= (uint64_t)buf[7];
+	return num;
+}
 
 
-#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))
-#endif
+
+static inline uint64_t
+read64le(const uint8_t *buf)
+{
+	uint64_t num = (uint64_t)buf[0];
+	num |= (uint64_t)buf[1] << 8;
+	num |= (uint64_t)buf[2] << 16;
+	num |= (uint64_t)buf[3] << 24;
+	num |= (uint64_t)buf[4] << 32;
+	num |= (uint64_t)buf[5] << 40;
+	num |= (uint64_t)buf[6] << 48;
+	num |= (uint64_t)buf[7] << 56;
+	return num;
+}
 
 
 
 
-#ifndef write16be
 static inline void
 static inline void
 write16be(uint8_t *buf, uint16_t num)
 write16be(uint8_t *buf, uint16_t num)
 {
 {
@@ -366,10 +553,8 @@ write16be(uint8_t *buf, uint16_t num)
 	buf[1] = (uint8_t)num;
 	buf[1] = (uint8_t)num;
 	return;
 	return;
 }
 }
-#endif
 
 
 
 
-#ifndef write16le
 static inline void
 static inline void
 write16le(uint8_t *buf, uint16_t num)
 write16le(uint8_t *buf, uint16_t num)
 {
 {
@@ -377,10 +562,8 @@ write16le(uint8_t *buf, uint16_t num)
 	buf[1] = (uint8_t)(num >> 8);
 	buf[1] = (uint8_t)(num >> 8);
 	return;
 	return;
 }
 }
-#endif
 
 
 
 
-#ifndef write32be
 static inline void
 static inline void
 write32be(uint8_t *buf, uint32_t num)
 write32be(uint8_t *buf, uint32_t num)
 {
 {
@@ -390,10 +573,8 @@ write32be(uint8_t *buf, uint32_t num)
 	buf[3] = (uint8_t)num;
 	buf[3] = (uint8_t)num;
 	return;
 	return;
 }
 }
-#endif
 
 
 
 
-#ifndef write32le
 static inline void
 static inline void
 write32le(uint8_t *buf, uint32_t num)
 write32le(uint8_t *buf, uint32_t num)
 {
 {
@@ -403,6 +584,37 @@ write32le(uint8_t *buf, uint32_t num)
 	buf[3] = (uint8_t)(num >> 24);
 	buf[3] = (uint8_t)(num >> 24);
 	return;
 	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
 #endif
 
 
 
 
@@ -421,7 +633,7 @@ write32le(uint8_t *buf, uint32_t num)
 // aligned but some compilers have language extensions to do that. With
 // aligned but some compilers have language extensions to do that. With
 // such language extensions the memcpy() method gives excellent results.
 // such language extensions the memcpy() method gives excellent results.
 //
 //
-// What to do on a strict-align system when no known language extentensions
+// What to do on a strict-align system when no known language extensions
 // are available? Falling back to byte-by-byte access would be safe but ruin
 // are available? Falling back to byte-by-byte access would be safe but ruin
 // optimizations that have been made specifically with aligned access in mind.
 // optimizations that have been made specifically with aligned access in mind.
 // As a compromise, aligned reads will fall back to non-compliant type punning
 // As a compromise, aligned reads will fall back to non-compliant type punning
@@ -588,7 +800,7 @@ bsr32(uint32_t n)
 #if defined(__INTEL_COMPILER)
 #if defined(__INTEL_COMPILER)
 	return _bit_scan_reverse(n);
 	return _bit_scan_reverse(n);
 
 
-#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX == UINT32_MAX
+#elif (TUKLIB_GNUC_REQ(3, 4) || defined(__clang__)) && UINT_MAX == UINT32_MAX
 	// GCC >= 3.4 has __builtin_clz(), which gives good results on
 	// GCC >= 3.4 has __builtin_clz(), which gives good results on
 	// multiple architectures. On x86, __builtin_clz() ^ 31U becomes
 	// multiple architectures. On x86, __builtin_clz() ^ 31U becomes
 	// either plain BSR (so the XOR gets optimized away) or LZCNT and
 	// either plain BSR (so the XOR gets optimized away) or LZCNT and
@@ -637,7 +849,7 @@ clz32(uint32_t n)
 #if defined(__INTEL_COMPILER)
 #if defined(__INTEL_COMPILER)
 	return _bit_scan_reverse(n) ^ 31U;
 	return _bit_scan_reverse(n) ^ 31U;
 
 
-#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX == UINT32_MAX
+#elif (TUKLIB_GNUC_REQ(3, 4) || defined(__clang__)) && UINT_MAX == UINT32_MAX
 	return (uint32_t)__builtin_clz(n);
 	return (uint32_t)__builtin_clz(n);
 
 
 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
@@ -684,7 +896,7 @@ ctz32(uint32_t n)
 #if defined(__INTEL_COMPILER)
 #if defined(__INTEL_COMPILER)
 	return _bit_scan_forward(n);
 	return _bit_scan_forward(n);
 
 
-#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX >= UINT32_MAX
+#elif (TUKLIB_GNUC_REQ(3, 4) || defined(__clang__)) && UINT_MAX >= UINT32_MAX
 	return (uint32_t)__builtin_ctz(n);
 	return (uint32_t)__builtin_ctz(n);
 
 
 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))

+ 20 - 19
Utilities/cmliblzma/liblzma/api/lzma.h

@@ -1,30 +1,30 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /**
 /**
  * \file        api/lzma.h
  * \file        api/lzma.h
  * \brief       The public API of liblzma data compression library
  * \brief       The public API of liblzma data compression library
+ * \mainpage
+ *
+ * liblzma is a general-purpose data compression library with a zlib-like API.
+ * The native file format is .xz, but also the old .lzma format and raw (no
+ * headers) streams are supported. Multiple compression algorithms (filters)
+ * are supported. Currently LZMA2 is the primary filter.
  *
  *
- * liblzma is a public domain general-purpose data compression library with
- * a zlib-like API. The native file format is .xz, but also the old .lzma
- * format and raw (no headers) streams are supported. Multiple compression
- * algorithms (filters) are supported. Currently LZMA2 is the primary filter.
+ * liblzma is part of XZ Utils <https://tukaani.org/xz/>. XZ Utils
+ * includes a gzip-like command line tool named xz and some other tools.
+ * XZ Utils is developed and maintained by Lasse Collin.
  *
  *
- * liblzma is part of XZ Utils <http://tukaani.org/xz/>. XZ Utils includes
- * a gzip-like command line tool named xz and some other tools. XZ Utils
- * is developed and maintained by Lasse Collin.
+ * Major parts of liblzma are based on code written by Igor Pavlov,
+ * specifically the LZMA SDK <https://7-zip.org/sdk.html>.
  *
  *
- * Major parts of liblzma are based on Igor Pavlov's public domain LZMA SDK
- * <http://7-zip.org/sdk.html>.
+ * The SHA-256 implementation in liblzma is based on code written by
+ * Wei Dai in Crypto++ Library <https://www.cryptopp.com/>.
  *
  *
- * The SHA-256 implementation is based on the public domain code found from
- * 7-Zip <http://7-zip.org/>, which has a modified version of the public
- * domain SHA-256 code found from Crypto++ <http://www.cryptopp.com/>.
- * The SHA-256 code in Crypto++ was written by Kevin Springle and Wei Dai.
+ * liblzma is distributed under the BSD Zero Clause License (0BSD).
  */
  */
 
 
 /*
 /*
  * Author: Lasse Collin
  * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
  */
  */
 
 
 #ifndef LZMA_H
 #ifndef LZMA_H
@@ -181,11 +181,11 @@
  * against static liblzma on them, don't worry about LZMA_API_STATIC. That
  * against static liblzma on them, don't worry about LZMA_API_STATIC. That
  * is, most developers will never need to use LZMA_API_STATIC.
  * 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,
  * 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
  * and thus don't use __declspec(dllimport). This way developers don't
  * need to worry about LZMA_API_STATIC. Also the calling convention is
  * 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
 #ifndef LZMA_API_IMPORT
 #	if !defined(LZMA_API_STATIC) && defined(_WIN32) && !defined(__GNUC__)
 #	if !defined(LZMA_API_STATIC) && defined(_WIN32) && !defined(__GNUC__)
@@ -219,7 +219,8 @@
  */
  */
 #ifndef lzma_nothrow
 #ifndef lzma_nothrow
 #	if defined(__cplusplus)
 #	if defined(__cplusplus)
-#		if __cplusplus >= 201103L
+#		if __cplusplus >= 201103L || (defined(_MSVC_LANG) \
+				&& _MSVC_LANG >= 201103L)
 #			define lzma_nothrow noexcept
 #			define lzma_nothrow noexcept
 #		else
 #		else
 #			define lzma_nothrow throw()
 #			define lzma_nothrow throw()

+ 109 - 21
Utilities/cmliblzma/liblzma/api/lzma/base.h

@@ -1,15 +1,13 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /**
 /**
  * \file        lzma/base.h
  * \file        lzma/base.h
  * \brief       Data types and functions used in many places in liblzma API
  * \brief       Data types and functions used in many places in liblzma API
+ * \note        Never include this file directly. Use <lzma.h> instead.
  */
  */
 
 
 /*
 /*
  * Author: Lasse Collin
  * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
- * See ../lzma.h for information about liblzma as a whole.
  */
  */
 
 
 #ifndef LZMA_H_INTERNAL
 #ifndef LZMA_H_INTERNAL
@@ -22,8 +20,8 @@
  *
  *
  * This is here because C89 doesn't have stdbool.h. To set a value for
  * This is here because C89 doesn't have stdbool.h. To set a value for
  * variables having type lzma_bool, you can use
  * variables having type lzma_bool, you can use
- *   - C99's `true' and `false' from stdbool.h;
- *   - C++'s internal `true' and `false'; or
+ *   - C99's 'true' and 'false' from stdbool.h;
+ *   - C++'s internal 'true' and 'false'; or
  *   - integers one (true) and zero (false).
  *   - integers one (true) and zero (false).
  */
  */
 typedef unsigned char lzma_bool;
 typedef unsigned char lzma_bool;
@@ -138,13 +136,19 @@ typedef enum {
 		 */
 		 */
 
 
 	LZMA_MEMLIMIT_ERROR     = 6,
 	LZMA_MEMLIMIT_ERROR     = 6,
-		/**
+		/**<
 		 * \brief       Memory usage limit was reached
 		 * \brief       Memory usage limit was reached
 		 *
 		 *
 		 * Decoder would need more memory than allowed by the
 		 * Decoder would need more memory than allowed by the
 		 * specified memory usage limit. To continue decoding,
 		 * specified memory usage limit. To continue decoding,
 		 * the memory usage limit has to be increased with
 		 * the memory usage limit has to be increased with
 		 * lzma_memlimit_set().
 		 * lzma_memlimit_set().
+		 *
+		 * liblzma 5.2.6 and earlier had a bug in single-threaded .xz
+		 * decoder (lzma_stream_decoder()) which made it impossible
+		 * to continue decoding after LZMA_MEMLIMIT_ERROR even if
+		 * the limit was increased using lzma_memlimit_set().
+		 * Other decoders worked correctly.
 		 */
 		 */
 
 
 	LZMA_FORMAT_ERROR       = 7,
 	LZMA_FORMAT_ERROR       = 7,
@@ -234,17 +238,47 @@ typedef enum {
 		 * can be a sign of a bug in liblzma. See the documentation
 		 * can be a sign of a bug in liblzma. See the documentation
 		 * how to report bugs.
 		 * how to report bugs.
 		 */
 		 */
+
+	LZMA_SEEK_NEEDED        = 12,
+		/**<
+		 * \brief       Request to change the input file position
+		 *
+		 * Some coders can do random access in the input file. The
+		 * initialization functions of these coders take the file size
+		 * as an argument. No other coders can return LZMA_SEEK_NEEDED.
+		 *
+		 * When this value is returned, the application must seek to
+		 * the file position given in lzma_stream.seek_pos. This value
+		 * is guaranteed to never exceed the file size that was
+		 * specified at the coder initialization.
+		 *
+		 * After seeking the application should read new input and
+		 * pass it normally via lzma_stream.next_in and .avail_in.
+		 */
+
+	/*
+	 * These enumerations may be used internally by liblzma
+	 * but they will never be returned to applications.
+	 */
+	LZMA_RET_INTERNAL1      = 101,
+	LZMA_RET_INTERNAL2      = 102,
+	LZMA_RET_INTERNAL3      = 103,
+	LZMA_RET_INTERNAL4      = 104,
+	LZMA_RET_INTERNAL5      = 105,
+	LZMA_RET_INTERNAL6      = 106,
+	LZMA_RET_INTERNAL7      = 107,
+	LZMA_RET_INTERNAL8      = 108
 } lzma_ret;
 } lzma_ret;
 
 
 
 
 /**
 /**
- * \brief       The `action' argument for lzma_code()
+ * \brief       The 'action' argument for lzma_code()
  *
  *
  * After the first use of LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, LZMA_FULL_BARRIER,
  * After the first use of LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, LZMA_FULL_BARRIER,
- * or LZMA_FINISH, the same `action' must is used until lzma_code() returns
+ * or LZMA_FINISH, the same 'action' must be used until lzma_code() returns
  * LZMA_STREAM_END. Also, the amount of input (that is, strm->avail_in) must
  * LZMA_STREAM_END. Also, the amount of input (that is, strm->avail_in) must
  * not be modified by the application until lzma_code() returns
  * not be modified by the application until lzma_code() returns
- * LZMA_STREAM_END. Changing the `action' or modifying the amount of input
+ * LZMA_STREAM_END. Changing the 'action' or modifying the amount of input
  * will make lzma_code() return LZMA_PROG_ERROR.
  * will make lzma_code() return LZMA_PROG_ERROR.
  */
  */
 typedef enum {
 typedef enum {
@@ -358,8 +392,8 @@ typedef enum {
  * Single-threaded mode only: liblzma doesn't make an internal copy of
  * Single-threaded mode only: liblzma doesn't make an internal copy of
  * lzma_allocator. Thus, it is OK to change these function pointers in
  * lzma_allocator. Thus, it is OK to change these function pointers in
  * the middle of the coding process, but obviously it must be done
  * the middle of the coding process, but obviously it must be done
- * carefully to make sure that the replacement `free' can deallocate
- * memory allocated by the earlier `alloc' function(s).
+ * carefully to make sure that the replacement 'free' can deallocate
+ * memory allocated by the earlier 'alloc' function(s).
  *
  *
  * Multithreaded mode: liblzma might internally store pointers to the
  * Multithreaded mode: liblzma might internally store pointers to the
  * lzma_allocator given via the lzma_stream structure. The application
  * lzma_allocator given via the lzma_stream structure. The application
@@ -387,7 +421,7 @@ typedef struct {
 	 *                      liblzma never sets this to zero.
 	 *                      liblzma never sets this to zero.
 	 *
 	 *
 	 * \return      Pointer to the beginning of a memory block of
 	 * \return      Pointer to the beginning of a memory block of
-	 *              `size' bytes, or NULL if allocation fails
+	 *              'size' bytes, or NULL if allocation fails
 	 *              for some reason. When allocation fails, functions
 	 *              for some reason. When allocation fails, functions
 	 *              of liblzma return LZMA_MEM_ERROR.
 	 *              of liblzma return LZMA_MEM_ERROR.
 	 *
 	 *
@@ -447,7 +481,7 @@ typedef struct lzma_internal_s lzma_internal;
  *
  *
  * The lzma_stream structure is used for
  * The lzma_stream structure is used for
  *  - passing pointers to input and output buffers to liblzma;
  *  - passing pointers to input and output buffers to liblzma;
- *  - defining custom memory hander functions; and
+ *  - defining custom memory handler functions; and
  *  - holding a pointer to coder-specific internal data structures.
  *  - holding a pointer to coder-specific internal data structures.
  *
  *
  * Typical usage:
  * Typical usage:
@@ -510,15 +544,44 @@ typedef struct {
 	 * you should not touch these, because the names of these variables
 	 * you should not touch these, because the names of these variables
 	 * may change.
 	 * may change.
 	 */
 	 */
+
+	/** \private     Reserved member. */
 	void *reserved_ptr1;
 	void *reserved_ptr1;
+
+	/** \private     Reserved member. */
 	void *reserved_ptr2;
 	void *reserved_ptr2;
+
+	/** \private     Reserved member. */
 	void *reserved_ptr3;
 	void *reserved_ptr3;
+
+	/** \private     Reserved member. */
 	void *reserved_ptr4;
 	void *reserved_ptr4;
-	uint64_t reserved_int1;
+
+	/**
+	 * \brief       New seek input position for LZMA_SEEK_NEEDED
+	 *
+	 * When lzma_code() returns LZMA_SEEK_NEEDED, the new input position
+	 * needed by liblzma will be available seek_pos. The value is
+	 * guaranteed to not exceed the file size that was specified when
+	 * this lzma_stream was initialized.
+	 *
+	 * In all other situations the value of this variable is undefined.
+	 */
+	uint64_t seek_pos;
+
+	/** \private     Reserved member. */
 	uint64_t reserved_int2;
 	uint64_t reserved_int2;
+
+	/** \private     Reserved member. */
 	size_t reserved_int3;
 	size_t reserved_int3;
+
+	/** \private     Reserved member. */
 	size_t reserved_int4;
 	size_t reserved_int4;
+
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum1;
 	lzma_reserved_enum reserved_enum1;
+
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum2;
 	lzma_reserved_enum reserved_enum2;
 
 
 } lzma_stream;
 } lzma_stream;
@@ -558,7 +621,15 @@ typedef struct {
  * to and get output from liblzma.
  * to and get output from liblzma.
  *
  *
  * See the description of the coder-specific initialization function to find
  * See the description of the coder-specific initialization function to find
- * out what `action' values are supported by the coder.
+ * out what 'action' values are supported by the coder.
+ *
+ * \param       strm    Pointer to lzma_stream that is at least initialized
+ *                      with LZMA_STREAM_INIT.
+ * \param       action  Action for this function to take. Must be a valid
+ *                      lzma_action enum value.
+ *
+ * \return      Any valid lzma_ret. See the lzma_ret enum description for more
+ *              information.
  */
  */
 extern LZMA_API(lzma_ret) lzma_code(lzma_stream *strm, lzma_action action)
 extern LZMA_API(lzma_ret) lzma_code(lzma_stream *strm, lzma_action action)
 		lzma_nothrow lzma_attr_warn_unused_result;
 		lzma_nothrow lzma_attr_warn_unused_result;
@@ -567,15 +638,15 @@ extern LZMA_API(lzma_ret) lzma_code(lzma_stream *strm, lzma_action action)
 /**
 /**
  * \brief       Free memory allocated for the coder data structures
  * \brief       Free memory allocated for the coder data structures
  *
  *
- * \param       strm    Pointer to lzma_stream that is at least initialized
- *                      with LZMA_STREAM_INIT.
- *
  * After lzma_end(strm), strm->internal is guaranteed to be NULL. No other
  * After lzma_end(strm), strm->internal is guaranteed to be NULL. No other
  * members of the lzma_stream structure are touched.
  * members of the lzma_stream structure are touched.
  *
  *
  * \note        zlib indicates an error if application end()s unfinished
  * \note        zlib indicates an error if application end()s unfinished
  *              stream structure. liblzma doesn't do this, and assumes that
  *              stream structure. liblzma doesn't do this, and assumes that
  *              application knows what it is doing.
  *              application knows what it is doing.
+ *
+ * \param       strm    Pointer to lzma_stream that is at least initialized
+ *                      with LZMA_STREAM_INIT.
  */
  */
 extern LZMA_API(void) lzma_end(lzma_stream *strm) lzma_nothrow;
 extern LZMA_API(void) lzma_end(lzma_stream *strm) lzma_nothrow;
 
 
@@ -594,6 +665,11 @@ extern LZMA_API(void) lzma_end(lzma_stream *strm) lzma_nothrow;
  * mode by taking into account the progress made by each thread. In
  * mode by taking into account the progress made by each thread. In
  * single-threaded mode *progress_in and *progress_out are set to
  * single-threaded mode *progress_in and *progress_out are set to
  * strm->total_in and strm->total_out, respectively.
  * strm->total_in and strm->total_out, respectively.
+ *
+ * \param       strm          Pointer to lzma_stream that is at least
+ *                            initialized with LZMA_STREAM_INIT.
+ * \param[out]  progress_in   Pointer to the number of input bytes processed.
+ * \param[out]  progress_out  Pointer to the number of output bytes processed.
  */
  */
 extern LZMA_API(void) lzma_get_progress(lzma_stream *strm,
 extern LZMA_API(void) lzma_get_progress(lzma_stream *strm,
 		uint64_t *progress_in, uint64_t *progress_out) lzma_nothrow;
 		uint64_t *progress_in, uint64_t *progress_out) lzma_nothrow;
@@ -612,6 +688,9 @@ extern LZMA_API(void) lzma_get_progress(lzma_stream *strm,
  * this may give misleading information if decoding .xz Streams that have
  * this may give misleading information if decoding .xz Streams that have
  * multiple Blocks, because each Block can have different memory requirements.
  * multiple Blocks, because each Block can have different memory requirements.
  *
  *
+ * \param       strm    Pointer to lzma_stream that is at least initialized
+ *                      with LZMA_STREAM_INIT.
+ *
  * \return      How much memory is currently allocated for the filter
  * \return      How much memory is currently allocated for the filter
  *              decoders. If no filter chain is currently allocated,
  *              decoders. If no filter chain is currently allocated,
  *              some non-zero value is still returned, which is less than
  *              some non-zero value is still returned, which is less than
@@ -631,6 +710,9 @@ extern LZMA_API(uint64_t) lzma_memusage(const lzma_stream *strm)
  * This function is supported only when *strm has been initialized with
  * This function is supported only when *strm has been initialized with
  * a function that takes a memlimit argument.
  * a function that takes a memlimit argument.
  *
  *
+ * \param       strm    Pointer to lzma_stream that is at least initialized
+ *                      with LZMA_STREAM_INIT.
+ *
  * \return      On success, the current memory usage limit is returned
  * \return      On success, the current memory usage limit is returned
  *              (always non-zero). On error, zero is returned.
  *              (always non-zero). On error, zero is returned.
  */
  */
@@ -649,7 +731,13 @@ extern LZMA_API(uint64_t) lzma_memlimit_get(const lzma_stream *strm)
  * return LZMA_OK. Later versions treat 0 as if 1 had been specified (so
  * return LZMA_OK. Later versions treat 0 as if 1 had been specified (so
  * lzma_memlimit_get() will return 1 even if you specify 0 here).
  * lzma_memlimit_get() will return 1 even if you specify 0 here).
  *
  *
- * \return      - LZMA_OK: New memory usage limit successfully set.
+ * liblzma 5.2.6 and earlier had a bug in single-threaded .xz decoder
+ * (lzma_stream_decoder()) which made it impossible to continue decoding
+ * after LZMA_MEMLIMIT_ERROR even if the limit was increased using
+ * lzma_memlimit_set(). Other decoders worked correctly.
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: New memory usage limit successfully set.
  *              - LZMA_MEMLIMIT_ERROR: The new limit is too small.
  *              - LZMA_MEMLIMIT_ERROR: The new limit is too small.
  *                The limit was not changed.
  *                The limit was not changed.
  *              - LZMA_PROG_ERROR: Invalid arguments, e.g. *strm doesn't
  *              - LZMA_PROG_ERROR: Invalid arguments, e.g. *strm doesn't

+ 31 - 23
Utilities/cmliblzma/liblzma/api/lzma/bcj.h

@@ -1,15 +1,13 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /**
 /**
  * \file        lzma/bcj.h
  * \file        lzma/bcj.h
  * \brief       Branch/Call/Jump conversion filters
  * \brief       Branch/Call/Jump conversion filters
+ * \note        Never include this file directly. Use <lzma.h> instead.
  */
  */
 
 
 /*
 /*
  * Author: Lasse Collin
  * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
- * See ../lzma.h for information about liblzma as a whole.
  */
  */
 
 
 #ifndef LZMA_H_INTERNAL
 #ifndef LZMA_H_INTERNAL
@@ -19,35 +17,45 @@
 
 
 /* Filter IDs for lzma_filter.id */
 /* Filter IDs for lzma_filter.id */
 
 
+/**
+ * \brief       Filter for x86 binaries
+ */
 #define LZMA_FILTER_X86         LZMA_VLI_C(0x04)
 #define LZMA_FILTER_X86         LZMA_VLI_C(0x04)
-	/**<
-	 * Filter for x86 binaries
-	 */
 
 
+/**
+ * \brief       Filter for Big endian PowerPC binaries
+ */
 #define LZMA_FILTER_POWERPC     LZMA_VLI_C(0x05)
 #define LZMA_FILTER_POWERPC     LZMA_VLI_C(0x05)
-	/**<
-	 * Filter for Big endian PowerPC binaries
-	 */
 
 
+/**
+ * \brief       Filter for IA-64 (Itanium) binaries
+ */
 #define LZMA_FILTER_IA64        LZMA_VLI_C(0x06)
 #define LZMA_FILTER_IA64        LZMA_VLI_C(0x06)
-	/**<
-	 * Filter for IA-64 (Itanium) binaries.
-	 */
 
 
+/**
+ * \brief       Filter for ARM binaries
+ */
 #define LZMA_FILTER_ARM         LZMA_VLI_C(0x07)
 #define LZMA_FILTER_ARM         LZMA_VLI_C(0x07)
-	/**<
-	 * Filter for ARM binaries.
-	 */
 
 
+/**
+ * \brief       Filter for ARM-Thumb binaries
+ */
 #define LZMA_FILTER_ARMTHUMB    LZMA_VLI_C(0x08)
 #define LZMA_FILTER_ARMTHUMB    LZMA_VLI_C(0x08)
-	/**<
-	 * Filter for ARM-Thumb binaries.
-	 */
 
 
+/**
+ * \brief       Filter for SPARC binaries
+ */
 #define LZMA_FILTER_SPARC       LZMA_VLI_C(0x09)
 #define LZMA_FILTER_SPARC       LZMA_VLI_C(0x09)
-	/**<
-	 * Filter for SPARC binaries.
-	 */
+
+/**
+ * \brief       Filter for ARM64 binaries
+ */
+#define LZMA_FILTER_ARM64       LZMA_VLI_C(0x0A)
+
+/**
+ * \brief       Filter for RISC-V binaries
+ */
+#define LZMA_FILTER_RISCV       LZMA_VLI_C(0x0B)
 
 
 
 
 /**
 /**

+ 149 - 36
Utilities/cmliblzma/liblzma/api/lzma/block.h

@@ -1,15 +1,13 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /**
 /**
  * \file        lzma/block.h
  * \file        lzma/block.h
  * \brief       .xz Block handling
  * \brief       .xz Block handling
+ * \note        Never include this file directly. Use <lzma.h> instead.
  */
  */
 
 
 /*
 /*
  * Author: Lasse Collin
  * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
- * See ../lzma.h for information about liblzma as a whole.
  */
  */
 
 
 #ifndef LZMA_H_INTERNAL
 #ifndef LZMA_H_INTERNAL
@@ -32,19 +30,28 @@ typedef struct {
 	 * \brief       Block format version
 	 * \brief       Block format version
 	 *
 	 *
 	 * To prevent API and ABI breakages when new features are needed,
 	 * To prevent API and ABI breakages when new features are needed,
-	 * a version number is used to indicate which fields in this
+	 * a version number is used to indicate which members in this
 	 * structure are in use:
 	 * structure are in use:
 	 *   - liblzma >= 5.0.0: version = 0 is supported.
 	 *   - liblzma >= 5.0.0: version = 0 is supported.
 	 *   - liblzma >= 5.1.4beta: Support for version = 1 was added,
 	 *   - liblzma >= 5.1.4beta: Support for version = 1 was added,
-	 *     which adds the ignore_check field.
+	 *     which adds the ignore_check member.
 	 *
 	 *
 	 * If version is greater than one, most Block related functions
 	 * If version is greater than one, most Block related functions
 	 * will return LZMA_OPTIONS_ERROR (lzma_block_header_decode() works
 	 * will return LZMA_OPTIONS_ERROR (lzma_block_header_decode() works
 	 * with any version value).
 	 * with any version value).
 	 *
 	 *
 	 * Read by:
 	 * Read by:
-	 *  - All functions that take pointer to lzma_block as argument,
-	 *    including lzma_block_header_decode().
+	 *  - lzma_block_header_size()
+	 *  - lzma_block_header_encode()
+	 *  - lzma_block_header_decode()
+	 *  - lzma_block_compressed_size()
+	 *  - lzma_block_unpadded_size()
+	 *  - lzma_block_total_size()
+	 *  - lzma_block_encoder()
+	 *  - lzma_block_decoder()
+	 *  - lzma_block_buffer_encode()
+	 *  - lzma_block_uncomp_encode()
+	 *  - lzma_block_buffer_decode()
 	 *
 	 *
 	 * Written by:
 	 * Written by:
 	 *  - lzma_block_header_decode()
 	 *  - lzma_block_header_decode()
@@ -52,7 +59,7 @@ typedef struct {
 	uint32_t version;
 	uint32_t version;
 
 
 	/**
 	/**
-	 * \brief       Size of the Block Header field
+	 * \brief       Size of the Block Header field in bytes
 	 *
 	 *
 	 * This is always a multiple of four.
 	 * This is always a multiple of four.
 	 *
 	 *
@@ -68,6 +75,7 @@ typedef struct {
 	 * Written by:
 	 * Written by:
 	 *  - lzma_block_header_size()
 	 *  - lzma_block_header_size()
 	 *  - lzma_block_buffer_encode()
 	 *  - lzma_block_buffer_encode()
+	 *  - lzma_block_uncomp_encode()
 	 */
 	 */
 	uint32_t header_size;
 	uint32_t header_size;
 #	define LZMA_BLOCK_HEADER_SIZE_MIN 8
 #	define LZMA_BLOCK_HEADER_SIZE_MIN 8
@@ -143,6 +151,7 @@ typedef struct {
 	 *  - lzma_block_encoder()
 	 *  - lzma_block_encoder()
 	 *  - lzma_block_decoder()
 	 *  - lzma_block_decoder()
 	 *  - lzma_block_buffer_encode()
 	 *  - lzma_block_buffer_encode()
+	 *  - lzma_block_uncomp_encode()
 	 *  - lzma_block_buffer_decode()
 	 *  - lzma_block_buffer_decode()
 	 */
 	 */
 	lzma_vli compressed_size;
 	lzma_vli compressed_size;
@@ -167,6 +176,7 @@ typedef struct {
 	 *  - lzma_block_encoder()
 	 *  - lzma_block_encoder()
 	 *  - lzma_block_decoder()
 	 *  - lzma_block_decoder()
 	 *  - lzma_block_buffer_encode()
 	 *  - lzma_block_buffer_encode()
+	 *  - lzma_block_uncomp_encode()
 	 *  - lzma_block_buffer_decode()
 	 *  - lzma_block_buffer_decode()
 	 */
 	 */
 	lzma_vli uncompressed_size;
 	lzma_vli uncompressed_size;
@@ -212,6 +222,7 @@ typedef struct {
 	 *  - lzma_block_encoder()
 	 *  - lzma_block_encoder()
 	 *  - lzma_block_decoder()
 	 *  - lzma_block_decoder()
 	 *  - lzma_block_buffer_encode()
 	 *  - lzma_block_buffer_encode()
+	 *  - lzma_block_uncomp_encode()
 	 *  - lzma_block_buffer_decode()
 	 *  - lzma_block_buffer_decode()
 	 */
 	 */
 	uint8_t raw_check[LZMA_CHECK_SIZE_MAX];
 	uint8_t raw_check[LZMA_CHECK_SIZE_MAX];
@@ -223,26 +234,56 @@ typedef struct {
 	 * with the currently supported options, so it is safe to leave these
 	 * with the currently supported options, so it is safe to leave these
 	 * uninitialized.
 	 * uninitialized.
 	 */
 	 */
+
+	/** \private     Reserved member. */
 	void *reserved_ptr1;
 	void *reserved_ptr1;
+
+	/** \private     Reserved member. */
 	void *reserved_ptr2;
 	void *reserved_ptr2;
+
+	/** \private     Reserved member. */
 	void *reserved_ptr3;
 	void *reserved_ptr3;
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int1;
 	uint32_t reserved_int1;
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int2;
 	uint32_t reserved_int2;
+
+	/** \private     Reserved member. */
 	lzma_vli reserved_int3;
 	lzma_vli reserved_int3;
+
+	/** \private     Reserved member. */
 	lzma_vli reserved_int4;
 	lzma_vli reserved_int4;
+
+	/** \private     Reserved member. */
 	lzma_vli reserved_int5;
 	lzma_vli reserved_int5;
+
+	/** \private     Reserved member. */
 	lzma_vli reserved_int6;
 	lzma_vli reserved_int6;
+
+	/** \private     Reserved member. */
 	lzma_vli reserved_int7;
 	lzma_vli reserved_int7;
+
+	/** \private     Reserved member. */
 	lzma_vli reserved_int8;
 	lzma_vli reserved_int8;
+
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum1;
 	lzma_reserved_enum reserved_enum1;
+
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum2;
 	lzma_reserved_enum reserved_enum2;
+
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum3;
 	lzma_reserved_enum reserved_enum3;
+
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum4;
 	lzma_reserved_enum reserved_enum4;
 
 
 	/**
 	/**
 	 * \brief       A flag to Block decoder to not verify the Check field
 	 * \brief       A flag to Block decoder to not verify the Check field
 	 *
 	 *
-	 * This field is supported by liblzma >= 5.1.4beta if .version >= 1.
+	 * This member is supported by liblzma >= 5.1.4beta if .version >= 1.
 	 *
 	 *
 	 * If this is set to true, the integrity check won't be calculated
 	 * If this is set to true, the integrity check won't be calculated
 	 * and verified. Unless you know what you are doing, you should
 	 * and verified. Unless you know what you are doing, you should
@@ -260,12 +301,25 @@ typedef struct {
 	 */
 	 */
 	lzma_bool ignore_check;
 	lzma_bool ignore_check;
 
 
+	/** \private     Reserved member. */
 	lzma_bool reserved_bool2;
 	lzma_bool reserved_bool2;
+
+	/** \private     Reserved member. */
 	lzma_bool reserved_bool3;
 	lzma_bool reserved_bool3;
+
+	/** \private     Reserved member. */
 	lzma_bool reserved_bool4;
 	lzma_bool reserved_bool4;
+
+	/** \private     Reserved member. */
 	lzma_bool reserved_bool5;
 	lzma_bool reserved_bool5;
+
+	/** \private     Reserved member. */
 	lzma_bool reserved_bool6;
 	lzma_bool reserved_bool6;
+
+	/** \private     Reserved member. */
 	lzma_bool reserved_bool7;
 	lzma_bool reserved_bool7;
+
+	/** \private     Reserved member. */
 	lzma_bool reserved_bool8;
 	lzma_bool reserved_bool8;
 
 
 } lzma_block;
 } lzma_block;
@@ -280,7 +334,8 @@ typedef struct {
  * Note that if the first byte is 0x00, it indicates beginning of Index; use
  * Note that if the first byte is 0x00, it indicates beginning of Index; use
  * this macro only when the byte is not 0x00.
  * this macro only when the byte is not 0x00.
  *
  *
- * There is no encoding macro, because Block Header encoder is enough for that.
+ * There is no encoding macro because lzma_block_header_size() and
+ * lzma_block_header_encode() should be used.
  */
  */
 #define lzma_block_header_size_decode(b) (((uint32_t)(b) + 1) * 4)
 #define lzma_block_header_size_decode(b) (((uint32_t)(b) + 1) * 4)
 
 
@@ -294,17 +349,20 @@ typedef struct {
  * four and doesn't exceed LZMA_BLOCK_HEADER_SIZE_MAX. Increasing header_size
  * four and doesn't exceed LZMA_BLOCK_HEADER_SIZE_MAX. Increasing header_size
  * just means that lzma_block_header_encode() will add Header Padding.
  * just means that lzma_block_header_encode() will add Header Padding.
  *
  *
- * \return      - LZMA_OK: Size calculated successfully and stored to
- *                block->header_size.
- *              - LZMA_OPTIONS_ERROR: Unsupported version, filters or
- *                filter options.
- *              - LZMA_PROG_ERROR: Invalid values like compressed_size == 0.
- *
  * \note        This doesn't check that all the options are valid i.e. this
  * \note        This doesn't check that all the options are valid i.e. this
  *              may return LZMA_OK even if lzma_block_header_encode() or
  *              may return LZMA_OK even if lzma_block_header_encode() or
  *              lzma_block_encoder() would fail. If you want to validate the
  *              lzma_block_encoder() would fail. If you want to validate the
  *              filter chain, consider using lzma_memlimit_encoder() which as
  *              filter chain, consider using lzma_memlimit_encoder() which as
  *              a side-effect validates the filter chain.
  *              a side-effect validates the filter chain.
+ *
+ * \param       block   Block options
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Size calculated successfully and stored to
+ *                block->header_size.
+ *              - LZMA_OPTIONS_ERROR: Unsupported version, filters or
+ *                filter options.
+ *              - LZMA_PROG_ERROR: Invalid values like compressed_size == 0.
  */
  */
 extern LZMA_API(lzma_ret) lzma_block_header_size(lzma_block *block)
 extern LZMA_API(lzma_ret) lzma_block_header_size(lzma_block *block)
 		lzma_nothrow lzma_attr_warn_unused_result;
 		lzma_nothrow lzma_attr_warn_unused_result;
@@ -318,11 +376,12 @@ extern LZMA_API(lzma_ret) lzma_block_header_size(lzma_block *block)
  * lzma_block_header_size() is used, the Block Header will be padded to the
  * lzma_block_header_size() is used, the Block Header will be padded to the
  * specified size.
  * specified size.
  *
  *
- * \param       out         Beginning of the output buffer. This must be
- *                          at least block->header_size bytes.
  * \param       block       Block options to be encoded.
  * \param       block       Block options to be encoded.
+ * \param[out]  out         Beginning of the output buffer. This must be
+ *                          at least block->header_size bytes.
  *
  *
- * \return      - LZMA_OK: Encoding was successful. block->header_size
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Encoding was successful. block->header_size
  *                bytes were written to output buffer.
  *                bytes were written to output buffer.
  *              - LZMA_OPTIONS_ERROR: Invalid or unsupported options.
  *              - LZMA_OPTIONS_ERROR: Invalid or unsupported options.
  *              - LZMA_PROG_ERROR: Invalid arguments, for example
  *              - LZMA_PROG_ERROR: Invalid arguments, for example
@@ -354,14 +413,15 @@ extern LZMA_API(lzma_ret) lzma_block_header_encode(
  * block->filters must have been allocated, but they don't need to be
  * block->filters must have been allocated, but they don't need to be
  * initialized (possible existing filter options are not freed).
  * initialized (possible existing filter options are not freed).
  *
  *
- * \param       block       Destination for Block options.
+ * \param[out]  block       Destination for Block options
  * \param       allocator   lzma_allocator for custom allocator functions.
  * \param       allocator   lzma_allocator for custom allocator functions.
  *                          Set to NULL to use malloc() (and also free()
  *                          Set to NULL to use malloc() (and also free()
  *                          if an error occurs).
  *                          if an error occurs).
  * \param       in          Beginning of the input buffer. This must be
  * \param       in          Beginning of the input buffer. This must be
  *                          at least block->header_size bytes.
  *                          at least block->header_size bytes.
  *
  *
- * \return      - LZMA_OK: Decoding was successful. block->header_size
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Decoding was successful. block->header_size
  *                bytes were read from the input buffer.
  *                bytes were read from the input buffer.
  *              - LZMA_OPTIONS_ERROR: The Block Header specifies some
  *              - LZMA_OPTIONS_ERROR: The Block Header specifies some
  *                unsupported options such as unsupported filters. This can
  *                unsupported options such as unsupported filters. This can
@@ -398,7 +458,12 @@ extern LZMA_API(lzma_ret) lzma_block_header_decode(lzma_block *block,
  *              field so that it can properly validate Compressed Size if it
  *              field so that it can properly validate Compressed Size if it
  *              was present in Block Header.
  *              was present in Block Header.
  *
  *
- * \return      - LZMA_OK: block->compressed_size was set successfully.
+ * \param       block           Block options: block->header_size must
+ *                              already be set with lzma_block_header_size().
+ * \param       unpadded_size   Unpadded Size from the Index field in bytes
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: block->compressed_size was set successfully.
  *              - LZMA_DATA_ERROR: unpadded_size is too small compared to
  *              - LZMA_DATA_ERROR: unpadded_size is too small compared to
  *                block->header_size and lzma_check_size(block->check).
  *                block->header_size and lzma_check_size(block->check).
  *              - LZMA_PROG_ERROR: Some values are invalid. For example,
  *              - LZMA_PROG_ERROR: Some values are invalid. For example,
@@ -419,6 +484,9 @@ extern LZMA_API(lzma_ret) lzma_block_compressed_size(
  * Compressed Size, and size of the Check field. This is where this function
  * Compressed Size, and size of the Check field. This is where this function
  * is needed.
  * is needed.
  *
  *
+ * \param       block   Block options: block->header_size must already be
+ *                      set with lzma_block_header_size().
+ *
  * \return      Unpadded Size on success, or zero on error.
  * \return      Unpadded Size on success, or zero on error.
  */
  */
 extern LZMA_API(lzma_vli) lzma_block_unpadded_size(const lzma_block *block)
 extern LZMA_API(lzma_vli) lzma_block_unpadded_size(const lzma_block *block)
@@ -431,6 +499,9 @@ extern LZMA_API(lzma_vli) lzma_block_unpadded_size(const lzma_block *block)
  * This is equivalent to lzma_block_unpadded_size() except that the returned
  * This is equivalent to lzma_block_unpadded_size() except that the returned
  * value includes the size of the Block Padding field.
  * value includes the size of the Block Padding field.
  *
  *
+ * \param       block   Block options: block->header_size must already be
+ *                      set with lzma_block_header_size().
+ *
  * \return      On success, total encoded size of the Block. On error,
  * \return      On success, total encoded size of the Block. On error,
  *              zero is returned.
  *              zero is returned.
  */
  */
@@ -444,7 +515,17 @@ extern LZMA_API(lzma_vli) lzma_block_total_size(const lzma_block *block)
  * Valid actions for lzma_code() are LZMA_RUN, LZMA_SYNC_FLUSH (only if the
  * Valid actions for lzma_code() are LZMA_RUN, LZMA_SYNC_FLUSH (only if the
  * filter chain supports it), and LZMA_FINISH.
  * filter chain supports it), and LZMA_FINISH.
  *
  *
- * \return      - LZMA_OK: All good, continue with lzma_code().
+ * The Block encoder encodes the Block Data, Block Padding, and Check value.
+ * It does NOT encode the Block Header which can be encoded with
+ * lzma_block_header_encode().
+ *
+ * \param       strm    Pointer to lzma_stream that is at least initialized
+ *                      with LZMA_STREAM_INIT.
+ * \param       block   Block options: block->version, block->check,
+ *                      and block->filters must have been initialized.
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: All good, continue with lzma_code().
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_UNSUPPORTED_CHECK: block->check specifies a Check ID
  *              - LZMA_UNSUPPORTED_CHECK: block->check specifies a Check ID
@@ -463,10 +544,16 @@ extern LZMA_API(lzma_ret) lzma_block_encoder(
  * Valid actions for lzma_code() are LZMA_RUN and LZMA_FINISH. Using
  * Valid actions for lzma_code() are LZMA_RUN and LZMA_FINISH. Using
  * LZMA_FINISH is not required. It is supported only for convenience.
  * LZMA_FINISH is not required. It is supported only for convenience.
  *
  *
- * \return      - LZMA_OK: All good, continue with lzma_code().
- *              - LZMA_UNSUPPORTED_CHECK: Initialization was successful, but
- *                the given Check ID is not supported, thus Check will be
- *                ignored.
+ * The Block decoder decodes the Block Data, Block Padding, and Check value.
+ * It does NOT decode the Block Header which can be decoded with
+ * lzma_block_header_decode().
+ *
+ * \param       strm    Pointer to lzma_stream that is at least initialized
+ *                      with LZMA_STREAM_INIT.
+ * \param       block   Block options
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: All good, continue with lzma_code().
  *              - LZMA_PROG_ERROR
  *              - LZMA_PROG_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
  */
  */
@@ -480,6 +567,11 @@ extern LZMA_API(lzma_ret) lzma_block_decoder(
  *
  *
  * This is equivalent to lzma_stream_buffer_bound() but for .xz Blocks.
  * This is equivalent to lzma_stream_buffer_bound() but for .xz Blocks.
  * See the documentation of lzma_stream_buffer_bound().
  * See the documentation of lzma_stream_buffer_bound().
+ *
+ * \param       uncompressed_size   Size of the data to be encoded with the
+ *                                  single-call Block encoder.
+ *
+ * \return      Maximum output size in bytes for single-call Block encoding.
  */
  */
 extern LZMA_API(size_t) lzma_block_buffer_bound(size_t uncompressed_size)
 extern LZMA_API(size_t) lzma_block_buffer_bound(size_t uncompressed_size)
 		lzma_nothrow;
 		lzma_nothrow;
@@ -508,13 +600,14 @@ extern LZMA_API(size_t) lzma_block_buffer_bound(size_t uncompressed_size)
  *                          Set to NULL to use malloc() and free().
  *                          Set to NULL to use malloc() and free().
  * \param       in          Beginning of the input buffer
  * \param       in          Beginning of the input buffer
  * \param       in_size     Size of the input buffer
  * \param       in_size     Size of the input buffer
- * \param       out         Beginning of the output buffer
- * \param       out_pos     The next byte will be written to out[*out_pos].
+ * \param[out]  out         Beginning of the output buffer
+ * \param[out]  out_pos     The next byte will be written to out[*out_pos].
  *                          *out_pos is updated only if encoding succeeds.
  *                          *out_pos is updated only if encoding succeeds.
  * \param       out_size    Size of the out buffer; the first byte into
  * \param       out_size    Size of the out buffer; the first byte into
  *                          which no data is written to is out[out_size].
  *                          which no data is written to is out[out_size].
  *
  *
- * \return      - LZMA_OK: Encoding was successful.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Encoding was successful.
  *              - LZMA_BUF_ERROR: Not enough output buffer space.
  *              - LZMA_BUF_ERROR: Not enough output buffer space.
  *              - LZMA_UNSUPPORTED_CHECK
  *              - LZMA_UNSUPPORTED_CHECK
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_OPTIONS_ERROR
@@ -540,6 +633,25 @@ extern LZMA_API(lzma_ret) lzma_block_buffer_encode(
  * Since the data won't be compressed, this function ignores block->filters.
  * Since the data won't be compressed, this function ignores block->filters.
  * This function doesn't take lzma_allocator because this function doesn't
  * This function doesn't take lzma_allocator because this function doesn't
  * allocate any memory from the heap.
  * allocate any memory from the heap.
+ *
+ * \param       block       Block options: block->version, block->check,
+ *                          and block->filters must have been initialized.
+ * \param       in          Beginning of the input buffer
+ * \param       in_size     Size of the input buffer
+ * \param[out]  out         Beginning of the output buffer
+ * \param[out]  out_pos     The next byte will be written to out[*out_pos].
+ *                          *out_pos is updated only if encoding succeeds.
+ * \param       out_size    Size of the out buffer; the first byte into
+ *                          which no data is written to is out[out_size].
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Encoding was successful.
+ *              - LZMA_BUF_ERROR: Not enough output buffer space.
+ *              - LZMA_UNSUPPORTED_CHECK
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_DATA_ERROR
+ *              - LZMA_PROG_ERROR
  */
  */
 extern LZMA_API(lzma_ret) lzma_block_uncomp_encode(lzma_block *block,
 extern LZMA_API(lzma_ret) lzma_block_uncomp_encode(lzma_block *block,
 		const uint8_t *in, size_t in_size,
 		const uint8_t *in, size_t in_size,
@@ -553,7 +665,7 @@ extern LZMA_API(lzma_ret) lzma_block_uncomp_encode(lzma_block *block,
  * This is single-call equivalent of lzma_block_decoder(), and requires that
  * This is single-call equivalent of lzma_block_decoder(), and requires that
  * the caller has already decoded Block Header and checked its memory usage.
  * the caller has already decoded Block Header and checked its memory usage.
  *
  *
- * \param       block       Block options just like with lzma_block_decoder().
+ * \param       block       Block options
  * \param       allocator   lzma_allocator for custom allocator functions.
  * \param       allocator   lzma_allocator for custom allocator functions.
  *                          Set to NULL to use malloc() and free().
  *                          Set to NULL to use malloc() and free().
  * \param       in          Beginning of the input buffer
  * \param       in          Beginning of the input buffer
@@ -561,13 +673,14 @@ extern LZMA_API(lzma_ret) lzma_block_uncomp_encode(lzma_block *block,
  *                          *in_pos is updated only if decoding succeeds.
  *                          *in_pos is updated only if decoding succeeds.
  * \param       in_size     Size of the input buffer; the first byte that
  * \param       in_size     Size of the input buffer; the first byte that
  *                          won't be read is in[in_size].
  *                          won't be read is in[in_size].
- * \param       out         Beginning of the output buffer
- * \param       out_pos     The next byte will be written to out[*out_pos].
+ * \param[out]  out         Beginning of the output buffer
+ * \param[out]  out_pos     The next byte will be written to out[*out_pos].
  *                          *out_pos is updated only if encoding succeeds.
  *                          *out_pos is updated only if encoding succeeds.
  * \param       out_size    Size of the out buffer; the first byte into
  * \param       out_size    Size of the out buffer; the first byte into
  *                          which no data is written to is out[out_size].
  *                          which no data is written to is out[out_size].
  *
  *
- * \return      - LZMA_OK: Decoding was successful.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Decoding was successful.
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_DATA_ERROR
  *              - LZMA_DATA_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR

+ 31 - 18
Utilities/cmliblzma/liblzma/api/lzma/check.h

@@ -1,15 +1,13 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /**
 /**
  * \file        lzma/check.h
  * \file        lzma/check.h
  * \brief       Integrity checks
  * \brief       Integrity checks
+ * \note        Never include this file directly. Use <lzma.h> instead.
  */
  */
 
 
 /*
 /*
  * Author: Lasse Collin
  * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
- * See ../lzma.h for information about liblzma as a whole.
  */
  */
 
 
 #ifndef LZMA_H_INTERNAL
 #ifndef LZMA_H_INTERNAL
@@ -71,12 +69,17 @@ typedef enum {
 /**
 /**
  * \brief       Test if the given Check ID is supported
  * \brief       Test if the given Check ID is supported
  *
  *
- * Return true if the given Check ID is supported by this liblzma build.
- * Otherwise false is returned. It is safe to call this with a value that
- * is not in the range [0, 15]; in that case the return value is always false.
+ * LZMA_CHECK_NONE and LZMA_CHECK_CRC32 are always supported (even if
+ * liblzma is built with limited features).
  *
  *
- * You can assume that LZMA_CHECK_NONE and LZMA_CHECK_CRC32 are always
- * supported (even if liblzma is built with limited features).
+ * \note        It is safe to call this with a value that is not in the
+ *              range [0, 15]; in that case the return value is always false.
+ *
+ * \param       check   Check ID
+ *
+ * \return      lzma_bool:
+ *              - true if Check ID is supported by this liblzma build.
+ *              - false otherwise.
  */
  */
 extern LZMA_API(lzma_bool) lzma_check_is_supported(lzma_check check)
 extern LZMA_API(lzma_bool) lzma_check_is_supported(lzma_check check)
 		lzma_nothrow lzma_attr_const;
 		lzma_nothrow lzma_attr_const;
@@ -90,7 +93,10 @@ extern LZMA_API(lzma_bool) lzma_check_is_supported(lzma_check check)
  * the Check field with the specified Check ID. The values are:
  * the Check field with the specified Check ID. The values are:
  * { 0, 4, 4, 4, 8, 8, 8, 16, 16, 16, 32, 32, 32, 64, 64, 64 }
  * { 0, 4, 4, 4, 8, 8, 8, 16, 16, 16, 32, 32, 32, 64, 64, 64 }
  *
  *
- * If the argument is not in the range [0, 15], UINT32_MAX is returned.
+ * \param       check   Check ID
+ *
+ * \return      Size of the Check field in bytes. If the argument is not in
+ *              the range [0, 15], UINT32_MAX is returned.
  */
  */
 extern LZMA_API(uint32_t) lzma_check_size(lzma_check check)
 extern LZMA_API(uint32_t) lzma_check_size(lzma_check check)
 		lzma_nothrow lzma_attr_const;
 		lzma_nothrow lzma_attr_const;
@@ -126,25 +132,32 @@ extern LZMA_API(uint32_t) lzma_crc32(
  *
  *
  * Calculate CRC64 using the polynomial from the ECMA-182 standard.
  * Calculate CRC64 using the polynomial from the ECMA-182 standard.
  *
  *
- * This function is used similarly to lzma_crc32(). See its documentation.
+ * This function is used similarly to lzma_crc32().
+ *
+ * \param       buf     Pointer to the input buffer
+ * \param       size    Size of the input buffer
+ * \param       crc     Previously returned CRC value. This is used to
+ *                      calculate the CRC of a big buffer in smaller chunks.
+ *                      Set to zero when starting a new calculation.
+ *
+ * \return      Updated CRC value, which can be passed to this function
+ *              again to continue CRC calculation.
  */
  */
 extern LZMA_API(uint64_t) lzma_crc64(
 extern LZMA_API(uint64_t) lzma_crc64(
 		const uint8_t *buf, size_t size, uint64_t crc)
 		const uint8_t *buf, size_t size, uint64_t crc)
 		lzma_nothrow lzma_attr_pure;
 		lzma_nothrow lzma_attr_pure;
 
 
 
 
-/*
- * SHA-256 functions are currently not exported to public API.
- * Contact Lasse Collin if you think it should be.
- */
-
-
 /**
 /**
  * \brief       Get the type of the integrity check
  * \brief       Get the type of the integrity check
  *
  *
  * This function can be called only immediately after lzma_code() has
  * This function can be called only immediately after lzma_code() has
  * returned LZMA_NO_CHECK, LZMA_UNSUPPORTED_CHECK, or LZMA_GET_CHECK.
  * returned LZMA_NO_CHECK, LZMA_UNSUPPORTED_CHECK, or LZMA_GET_CHECK.
  * Calling this function in any other situation has undefined behavior.
  * Calling this function in any other situation has undefined behavior.
+ *
+ * \param       strm    Pointer to lzma_stream meeting the above conditions.
+ *
+ * \return      Check ID in the lzma_stream, or undefined if called improperly.
  */
  */
 extern LZMA_API(lzma_check) lzma_get_check(const lzma_stream *strm)
 extern LZMA_API(lzma_check) lzma_get_check(const lzma_stream *strm)
 		lzma_nothrow;
 		lzma_nothrow;

+ 442 - 79
Utilities/cmliblzma/liblzma/api/lzma/container.h

@@ -1,15 +1,13 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /**
 /**
  * \file        lzma/container.h
  * \file        lzma/container.h
  * \brief       File formats
  * \brief       File formats
+ * \note        Never include this file directly. Use <lzma.h> instead.
  */
  */
 
 
 /*
 /*
  * Author: Lasse Collin
  * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
- * See ../lzma.h for information about liblzma as a whole.
  */
  */
 
 
 #ifndef LZMA_H_INTERNAL
 #ifndef LZMA_H_INTERNAL
@@ -51,7 +49,7 @@
  *
  *
  * This flag modifies the preset to make the encoding significantly slower
  * This flag modifies the preset to make the encoding significantly slower
  * while improving the compression ratio only marginally. This is useful
  * while improving the compression ratio only marginally. This is useful
- * when you don't mind wasting time to get as small result as possible.
+ * when you don't mind spending time to get as small result as possible.
  *
  *
  * This flag doesn't affect the memory usage requirements of the decoder (at
  * This flag doesn't affect the memory usage requirements of the decoder (at
  * least not significantly). The memory usage of the encoder may be increased
  * least not significantly). The memory usage of the encoder may be increased
@@ -69,7 +67,15 @@ typedef struct {
 	 *
 	 *
 	 * Set this to zero if no flags are wanted.
 	 * Set this to zero if no flags are wanted.
 	 *
 	 *
-	 * No flags are currently supported.
+	 * Encoder: No flags are currently supported.
+	 *
+	 * Decoder: Bitwise-or of zero or more of the decoder flags:
+	 * - LZMA_TELL_NO_CHECK
+	 * - LZMA_TELL_UNSUPPORTED_CHECK
+	 * - LZMA_TELL_ANY_CHECK
+	 * - LZMA_IGNORE_CHECK
+	 * - LZMA_CONCATENATED
+	 * - LZMA_FAIL_FAST
 	 */
 	 */
 	uint32_t flags;
 	uint32_t flags;
 
 
@@ -79,7 +85,7 @@ typedef struct {
 	uint32_t threads;
 	uint32_t threads;
 
 
 	/**
 	/**
-	 * \brief       Maximum uncompressed size of a Block
+	 * \brief       Encoder only: Maximum uncompressed size of a Block
 	 *
 	 *
 	 * The encoder will start a new .xz Block every block_size bytes.
 	 * The encoder will start a new .xz Block every block_size bytes.
 	 * Using LZMA_FULL_FLUSH or LZMA_FULL_BARRIER with lzma_code()
 	 * Using LZMA_FULL_FLUSH or LZMA_FULL_BARRIER with lzma_code()
@@ -106,7 +112,7 @@ typedef struct {
 	/**
 	/**
 	 * \brief       Timeout to allow lzma_code() to return early
 	 * \brief       Timeout to allow lzma_code() to return early
 	 *
 	 *
-	 * Multithreading can make liblzma to consume input and produce
+	 * Multithreading can make liblzma consume input and produce
 	 * output in a very bursty way: it may first read a lot of input
 	 * output in a very bursty way: it may first read a lot of input
 	 * to fill internal buffers, then no input or output occurs for
 	 * to fill internal buffers, then no input or output occurs for
 	 * a while.
 	 * a while.
@@ -123,19 +129,18 @@ typedef struct {
 	 * LZMA_OK. Reasonable values are 100 ms or more. The xz command
 	 * LZMA_OK. Reasonable values are 100 ms or more. The xz command
 	 * line tool uses 300 ms.
 	 * line tool uses 300 ms.
 	 *
 	 *
-	 * If long blocking times are fine for you, set timeout to a special
-	 * value of 0, which will disable the timeout mechanism and will make
+	 * If long blocking times are acceptable, set timeout to a special
+	 * value of 0. This will disable the timeout mechanism and will make
 	 * lzma_code() block until all the input is consumed or the output
 	 * lzma_code() block until all the input is consumed or the output
 	 * buffer has been filled.
 	 * buffer has been filled.
 	 *
 	 *
 	 * \note        Even with a timeout, lzma_code() might sometimes take
 	 * \note        Even with a timeout, lzma_code() might sometimes take
-	 *              somewhat long time to return. No timing guarantees
-	 *              are made.
+	 *              a long time to return. No timing guarantees are made.
 	 */
 	 */
 	uint32_t timeout;
 	uint32_t timeout;
 
 
 	/**
 	/**
-	 * \brief       Compression preset (level and possible flags)
+	 * \brief       Encoder only: Compression preset
 	 *
 	 *
 	 * The preset is set just like with lzma_easy_encoder().
 	 * The preset is set just like with lzma_easy_encoder().
 	 * The preset is ignored if filters below is non-NULL.
 	 * The preset is ignored if filters below is non-NULL.
@@ -143,7 +148,7 @@ typedef struct {
 	uint32_t preset;
 	uint32_t preset;
 
 
 	/**
 	/**
-	 * \brief       Filter chain (alternative to a preset)
+	 * \brief       Encoder only: Filter chain (alternative to a preset)
 	 *
 	 *
 	 * If this is NULL, the preset above is used. Otherwise the preset
 	 * If this is NULL, the preset above is used. Otherwise the preset
 	 * is ignored and the filter chain specified here is used.
 	 * is ignored and the filter chain specified here is used.
@@ -151,7 +156,7 @@ typedef struct {
 	const lzma_filter *filters;
 	const lzma_filter *filters;
 
 
 	/**
 	/**
-	 * \brief       Integrity check type
+	 * \brief       Encoder only: Integrity check type
 	 *
 	 *
 	 * See check.h for available checks. The xz command line tool
 	 * See check.h for available checks. The xz command line tool
 	 * defaults to LZMA_CHECK_CRC64, which is a good choice if you
 	 * defaults to LZMA_CHECK_CRC64, which is a good choice if you
@@ -166,20 +171,86 @@ typedef struct {
 	 * with the currently supported options, so it is safe to leave these
 	 * with the currently supported options, so it is safe to leave these
 	 * uninitialized.
 	 * uninitialized.
 	 */
 	 */
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum1;
 	lzma_reserved_enum reserved_enum1;
+
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum2;
 	lzma_reserved_enum reserved_enum2;
+
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum3;
 	lzma_reserved_enum reserved_enum3;
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int1;
 	uint32_t reserved_int1;
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int2;
 	uint32_t reserved_int2;
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int3;
 	uint32_t reserved_int3;
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int4;
 	uint32_t reserved_int4;
-	uint64_t reserved_int5;
-	uint64_t reserved_int6;
+
+	/**
+	 * \brief       Memory usage limit to reduce the number of threads
+	 *
+	 * Encoder: Ignored.
+	 *
+	 * Decoder:
+	 *
+	 * If the number of threads has been set so high that more than
+	 * memlimit_threading bytes of memory would be needed, the number
+	 * of threads will be reduced so that the memory usage will not exceed
+	 * memlimit_threading bytes. However, if memlimit_threading cannot
+	 * be met even in single-threaded mode, then decoding will continue
+	 * in single-threaded mode and memlimit_threading may be exceeded
+	 * even by a large amount. That is, memlimit_threading will never make
+	 * lzma_code() return LZMA_MEMLIMIT_ERROR. To truly cap the memory
+	 * usage, see memlimit_stop below.
+	 *
+	 * Setting memlimit_threading to UINT64_MAX or a similar huge value
+	 * means that liblzma is allowed to keep the whole compressed file
+	 * and the whole uncompressed file in memory in addition to the memory
+	 * needed by the decompressor data structures used by each thread!
+	 * In other words, a reasonable value limit must be set here or it
+	 * will cause problems sooner or later. If you have no idea what
+	 * a reasonable value could be, try lzma_physmem() / 4 as a starting
+	 * point. Setting this limit will never prevent decompression of
+	 * a file; this will only reduce the number of threads.
+	 *
+	 * If memlimit_threading is greater than memlimit_stop, then the value
+	 * of memlimit_stop will be used for both.
+	 */
+	uint64_t memlimit_threading;
+
+	/**
+	 * \brief       Memory usage limit that should never be exceeded
+	 *
+	 * Encoder: Ignored.
+	 *
+	 * Decoder: If decompressing will need more than this amount of
+	 * memory even in the single-threaded mode, then lzma_code() will
+	 * return LZMA_MEMLIMIT_ERROR.
+	 */
+	uint64_t memlimit_stop;
+
+	/** \private     Reserved member. */
 	uint64_t reserved_int7;
 	uint64_t reserved_int7;
+
+	/** \private     Reserved member. */
 	uint64_t reserved_int8;
 	uint64_t reserved_int8;
+
+	/** \private     Reserved member. */
 	void *reserved_ptr1;
 	void *reserved_ptr1;
+
+	/** \private     Reserved member. */
 	void *reserved_ptr2;
 	void *reserved_ptr2;
+
+	/** \private     Reserved member. */
 	void *reserved_ptr3;
 	void *reserved_ptr3;
+
+	/** \private     Reserved member. */
 	void *reserved_ptr4;
 	void *reserved_ptr4;
 
 
 } lzma_mt;
 } lzma_mt;
@@ -193,8 +264,7 @@ typedef struct {
  * \param       preset  Compression preset (level and possible flags)
  * \param       preset  Compression preset (level and possible flags)
  *
  *
  * \return      Number of bytes of memory required for the given
  * \return      Number of bytes of memory required for the given
- *              preset when encoding. If an error occurs, for example
- *              due to unsupported preset, UINT64_MAX is returned.
+ *              preset when encoding or UINT64_MAX on error.
  */
  */
 extern LZMA_API(uint64_t) lzma_easy_encoder_memusage(uint32_t preset)
 extern LZMA_API(uint64_t) lzma_easy_encoder_memusage(uint32_t preset)
 		lzma_nothrow lzma_attr_pure;
 		lzma_nothrow lzma_attr_pure;
@@ -208,9 +278,8 @@ extern LZMA_API(uint64_t) lzma_easy_encoder_memusage(uint32_t preset)
  * \param       preset  Compression preset (level and possible flags)
  * \param       preset  Compression preset (level and possible flags)
  *
  *
  * \return      Number of bytes of memory required to decompress a file
  * \return      Number of bytes of memory required to decompress a file
- *              that was compressed using the given preset. If an error
- *              occurs, for example due to unsupported preset, UINT64_MAX
- *              is returned.
+ *              that was compressed using the given preset or UINT64_MAX
+ *              on error.
  */
  */
 extern LZMA_API(uint64_t) lzma_easy_decoder_memusage(uint32_t preset)
 extern LZMA_API(uint64_t) lzma_easy_decoder_memusage(uint32_t preset)
 		lzma_nothrow lzma_attr_pure;
 		lzma_nothrow lzma_attr_pure;
@@ -220,7 +289,16 @@ extern LZMA_API(uint64_t) lzma_easy_decoder_memusage(uint32_t preset)
  * \brief       Initialize .xz Stream encoder using a preset number
  * \brief       Initialize .xz Stream encoder using a preset number
  *
  *
  * This function is intended for those who just want to use the basic features
  * This function is intended for those who just want to use the basic features
- * if liblzma (that is, most developers out there).
+ * of liblzma (that is, most developers out there).
+ *
+ * If initialization fails (return value is not LZMA_OK), all the memory
+ * allocated for *strm by liblzma is always freed. Thus, there is no need
+ * to call lzma_end() after failed initialization.
+ *
+ * If initialization succeeds, use lzma_code() to do the actual encoding.
+ * Valid values for 'action' (the second argument of lzma_code()) are
+ * LZMA_RUN, LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, and LZMA_FINISH. In future,
+ * there may be compression levels or flags that don't support LZMA_SYNC_FLUSH.
  *
  *
  * \param       strm    Pointer to lzma_stream that is at least initialized
  * \param       strm    Pointer to lzma_stream that is at least initialized
  *                      with LZMA_STREAM_INIT.
  *                      with LZMA_STREAM_INIT.
@@ -228,7 +306,7 @@ extern LZMA_API(uint64_t) lzma_easy_decoder_memusage(uint32_t preset)
  *                      number and zero or more flags. Usually flags aren't
  *                      number and zero or more flags. Usually flags aren't
  *                      used, so preset is simply a number [0, 9] which match
  *                      used, so preset is simply a number [0, 9] which match
  *                      the options -0 ... -9 of the xz command line tool.
  *                      the options -0 ... -9 of the xz command line tool.
- *                      Additional flags can be be set using bitwise-or with
+ *                      Additional flags can be set using bitwise-or with
  *                      the preset level number, e.g. 6 | LZMA_PRESET_EXTREME.
  *                      the preset level number, e.g. 6 | LZMA_PRESET_EXTREME.
  * \param       check   Integrity check type to use. See check.h for available
  * \param       check   Integrity check type to use. See check.h for available
  *                      checks. The xz command line tool defaults to
  *                      checks. The xz command line tool defaults to
@@ -236,7 +314,8 @@ extern LZMA_API(uint64_t) lzma_easy_decoder_memusage(uint32_t preset)
  *                      unsure. LZMA_CHECK_CRC32 is good too as long as the
  *                      unsure. LZMA_CHECK_CRC32 is good too as long as the
  *                      uncompressed file is not many gigabytes.
  *                      uncompressed file is not many gigabytes.
  *
  *
- * \return      - LZMA_OK: Initialization succeeded. Use lzma_code() to
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Initialization succeeded. Use lzma_code() to
  *                encode your data.
  *                encode your data.
  *              - LZMA_MEM_ERROR: Memory allocation failed.
  *              - LZMA_MEM_ERROR: Memory allocation failed.
  *              - LZMA_OPTIONS_ERROR: The given compression preset is not
  *              - LZMA_OPTIONS_ERROR: The given compression preset is not
@@ -245,15 +324,6 @@ extern LZMA_API(uint64_t) lzma_easy_decoder_memusage(uint32_t preset)
  *                supported by this liblzma build.
  *                supported by this liblzma build.
  *              - LZMA_PROG_ERROR: One or more of the parameters have values
  *              - LZMA_PROG_ERROR: One or more of the parameters have values
  *                that will never be valid. For example, strm == NULL.
  *                that will never be valid. For example, strm == NULL.
- *
- * If initialization fails (return value is not LZMA_OK), all the memory
- * allocated for *strm by liblzma is always freed. Thus, there is no need
- * to call lzma_end() after failed initialization.
- *
- * If initialization succeeds, use lzma_code() to do the actual encoding.
- * Valid values for `action' (the second argument of lzma_code()) are
- * LZMA_RUN, LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, and LZMA_FINISH. In future,
- * there may be compression levels or flags that don't support LZMA_SYNC_FLUSH.
  */
  */
 extern LZMA_API(lzma_ret) lzma_easy_encoder(
 extern LZMA_API(lzma_ret) lzma_easy_encoder(
 		lzma_stream *strm, uint32_t preset, lzma_check check)
 		lzma_stream *strm, uint32_t preset, lzma_check check)
@@ -274,13 +344,14 @@ extern LZMA_API(lzma_ret) lzma_easy_encoder(
  *                          Set to NULL to use malloc() and free().
  *                          Set to NULL to use malloc() and free().
  * \param       in          Beginning of the input buffer
  * \param       in          Beginning of the input buffer
  * \param       in_size     Size of the input buffer
  * \param       in_size     Size of the input buffer
- * \param       out         Beginning of the output buffer
- * \param       out_pos     The next byte will be written to out[*out_pos].
+ * \param[out]  out         Beginning of the output buffer
+ * \param[out]  out_pos     The next byte will be written to out[*out_pos].
  *                          *out_pos is updated only if encoding succeeds.
  *                          *out_pos is updated only if encoding succeeds.
  * \param       out_size    Size of the out buffer; the first byte into
  * \param       out_size    Size of the out buffer; the first byte into
  *                          which no data is written to is out[out_size].
  *                          which no data is written to is out[out_size].
  *
  *
- * \return      - LZMA_OK: Encoding was successful.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Encoding was successful.
  *              - LZMA_BUF_ERROR: Not enough output buffer space.
  *              - LZMA_BUF_ERROR: Not enough output buffer space.
  *              - LZMA_UNSUPPORTED_CHECK
  *              - LZMA_UNSUPPORTED_CHECK
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_OPTIONS_ERROR
@@ -298,14 +369,16 @@ extern LZMA_API(lzma_ret) lzma_easy_buffer_encode(
 /**
 /**
  * \brief       Initialize .xz Stream encoder using a custom filter chain
  * \brief       Initialize .xz Stream encoder using a custom filter chain
  *
  *
- * \param       strm    Pointer to properly prepared lzma_stream
- * \param       filters Array of filters. This must be terminated with
- *                      filters[n].id = LZMA_VLI_UNKNOWN. See filter.h for
- *                      more information.
+ * \param       strm    Pointer to lzma_stream that is at least initialized
+ *                      with LZMA_STREAM_INIT.
+ * \param       filters Array of filters terminated with
+ *                      .id == LZMA_VLI_UNKNOWN. See filters.h for more
+ *                      information.
  * \param       check   Type of the integrity check to calculate from
  * \param       check   Type of the integrity check to calculate from
  *                      uncompressed data.
  *                      uncompressed data.
  *
  *
- * \return      - LZMA_OK: Initialization was successful.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Initialization was successful.
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_UNSUPPORTED_CHECK
  *              - LZMA_UNSUPPORTED_CHECK
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_OPTIONS_ERROR
@@ -345,10 +418,12 @@ extern LZMA_API(uint64_t) lzma_stream_encoder_mt_memusage(
  * LZMA_FULL_BARRIER, and LZMA_FINISH. Support for LZMA_SYNC_FLUSH might be
  * LZMA_FULL_BARRIER, and LZMA_FINISH. Support for LZMA_SYNC_FLUSH might be
  * added in the future.
  * added in the future.
  *
  *
- * \param       strm    Pointer to properly prepared lzma_stream
+ * \param       strm    Pointer to lzma_stream that is at least initialized
+ *                      with LZMA_STREAM_INIT.
  * \param       options Pointer to multithreaded compression options
  * \param       options Pointer to multithreaded compression options
  *
  *
- * \return      - LZMA_OK
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_UNSUPPORTED_CHECK
  *              - LZMA_UNSUPPORTED_CHECK
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_OPTIONS_ERROR
@@ -359,6 +434,34 @@ extern LZMA_API(lzma_ret) lzma_stream_encoder_mt(
 		lzma_nothrow lzma_attr_warn_unused_result;
 		lzma_nothrow lzma_attr_warn_unused_result;
 
 
 
 
+/**
+ * \brief       Calculate recommended Block size for multithreaded .xz encoder
+ *
+ * This calculates a recommended Block size for multithreaded encoding given
+ * a filter chain. This is used internally by lzma_stream_encoder_mt() to
+ * determine the Block size if the block_size member is not set to the
+ * special value of 0 in the lzma_mt options struct.
+ *
+ * If one wishes to change the filters between Blocks, this function is
+ * helpful to set the block_size member of the lzma_mt struct before calling
+ * lzma_stream_encoder_mt(). Since the block_size member represents the
+ * maximum possible Block size for the multithreaded .xz encoder, one can
+ * use this function to find the maximum recommended Block size based on
+ * all planned filter chains. Otherwise, the multithreaded encoder will
+ * base its maximum Block size on the first filter chain used (if the
+ * block_size member is not set), which may unnecessarily limit the Block
+ * size for a later filter chain.
+ *
+ * \param       filters   Array of filters terminated with
+ *                        .id == LZMA_VLI_UNKNOWN.
+ *
+ * \return      Recommended Block size in bytes, or UINT64_MAX if
+ *              an error occurred.
+ */
+extern LZMA_API(uint64_t) lzma_mt_block_size(const lzma_filter *filters)
+		lzma_nothrow;
+
+
 /**
 /**
  * \brief       Initialize .lzma encoder (legacy file format)
  * \brief       Initialize .lzma encoder (legacy file format)
  *
  *
@@ -374,7 +477,12 @@ extern LZMA_API(lzma_ret) lzma_stream_encoder_mt(
  * No kind of flushing is supported, because the file format doesn't make
  * No kind of flushing is supported, because the file format doesn't make
  * it possible.
  * it possible.
  *
  *
- * \return      - LZMA_OK
+ * \param       strm    Pointer to lzma_stream that is at least initialized
+ *                      with LZMA_STREAM_INIT.
+ * \param       options Pointer to encoder options
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_PROG_ERROR
  *              - LZMA_PROG_ERROR
@@ -387,7 +495,7 @@ extern LZMA_API(lzma_ret) lzma_alone_encoder(
 /**
 /**
  * \brief       Calculate output buffer size for single-call Stream encoder
  * \brief       Calculate output buffer size for single-call Stream encoder
  *
  *
- * When trying to compress uncompressible data, the encoded size will be
+ * When trying to compress incompressible data, the encoded size will be
  * slightly bigger than the input data. This function calculates how much
  * slightly bigger than the input data. This function calculates how much
  * output buffer space is required to be sure that lzma_stream_buffer_encode()
  * output buffer space is required to be sure that lzma_stream_buffer_encode()
  * doesn't return LZMA_BUF_ERROR.
  * doesn't return LZMA_BUF_ERROR.
@@ -403,8 +511,13 @@ extern LZMA_API(lzma_ret) lzma_alone_encoder(
  * \note        The limit calculated by this function applies only to
  * \note        The limit calculated by this function applies only to
  *              single-call encoding. Multi-call encoding may (and probably
  *              single-call encoding. Multi-call encoding may (and probably
  *              will) have larger maximum expansion when encoding
  *              will) have larger maximum expansion when encoding
- *              uncompressible data. Currently there is no function to
+ *              incompressible data. Currently there is no function to
  *              calculate the maximum expansion of multi-call encoding.
  *              calculate the maximum expansion of multi-call encoding.
+ *
+ * \param       uncompressed_size   Size in bytes of the uncompressed
+ *                                  input data
+ *
+ * \return      Maximum number of bytes needed to store the compressed data.
  */
  */
 extern LZMA_API(size_t) lzma_stream_buffer_bound(size_t uncompressed_size)
 extern LZMA_API(size_t) lzma_stream_buffer_bound(size_t uncompressed_size)
 		lzma_nothrow;
 		lzma_nothrow;
@@ -413,22 +526,23 @@ extern LZMA_API(size_t) lzma_stream_buffer_bound(size_t uncompressed_size)
 /**
 /**
  * \brief       Single-call .xz Stream encoder
  * \brief       Single-call .xz Stream encoder
  *
  *
- * \param       filters     Array of filters. This must be terminated with
- *                          filters[n].id = LZMA_VLI_UNKNOWN. See filter.h
- *                          for more information.
+ * \param       filters     Array of filters terminated with
+ *                          .id == LZMA_VLI_UNKNOWN. See filters.h for more
+ *                          information.
  * \param       check       Type of the integrity check to calculate from
  * \param       check       Type of the integrity check to calculate from
  *                          uncompressed data.
  *                          uncompressed data.
  * \param       allocator   lzma_allocator for custom allocator functions.
  * \param       allocator   lzma_allocator for custom allocator functions.
  *                          Set to NULL to use malloc() and free().
  *                          Set to NULL to use malloc() and free().
  * \param       in          Beginning of the input buffer
  * \param       in          Beginning of the input buffer
  * \param       in_size     Size of the input buffer
  * \param       in_size     Size of the input buffer
- * \param       out         Beginning of the output buffer
- * \param       out_pos     The next byte will be written to out[*out_pos].
+ * \param[out]  out         Beginning of the output buffer
+ * \param[out]  out_pos     The next byte will be written to out[*out_pos].
  *                          *out_pos is updated only if encoding succeeds.
  *                          *out_pos is updated only if encoding succeeds.
  * \param       out_size    Size of the out buffer; the first byte into
  * \param       out_size    Size of the out buffer; the first byte into
  *                          which no data is written to is out[out_size].
  *                          which no data is written to is out[out_size].
  *
  *
- * \return      - LZMA_OK: Encoding was successful.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Encoding was successful.
  *              - LZMA_BUF_ERROR: Not enough output buffer space.
  *              - LZMA_BUF_ERROR: Not enough output buffer space.
  *              - LZMA_UNSUPPORTED_CHECK
  *              - LZMA_UNSUPPORTED_CHECK
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_OPTIONS_ERROR
@@ -444,6 +558,66 @@ extern LZMA_API(lzma_ret) lzma_stream_buffer_encode(
 		lzma_nothrow lzma_attr_warn_unused_result;
 		lzma_nothrow lzma_attr_warn_unused_result;
 
 
 
 
+/**
+ * \brief       MicroLZMA encoder
+ *
+ * The MicroLZMA format is a raw LZMA stream whose first byte (always 0x00)
+ * has been replaced with bitwise-negation of the LZMA properties (lc/lp/pb).
+ * This encoding ensures that the first byte of MicroLZMA stream is never
+ * 0x00. There is no end of payload marker and thus the uncompressed size
+ * must be stored separately. For the best error detection the dictionary
+ * size should be stored separately as well but alternatively one may use
+ * the uncompressed size as the dictionary size when decoding.
+ *
+ * With the MicroLZMA encoder, lzma_code() behaves slightly unusually.
+ * The action argument must be LZMA_FINISH and the return value will never be
+ * LZMA_OK. Thus the encoding is always done with a single lzma_code() after
+ * the initialization. The benefit of the combination of initialization
+ * function and lzma_code() is that memory allocations can be re-used for
+ * better performance.
+ *
+ * lzma_code() will try to encode as much input as is possible to fit into
+ * the given output buffer. If not all input can be encoded, the stream will
+ * be finished without encoding all the input. The caller must check both
+ * input and output buffer usage after lzma_code() (total_in and total_out
+ * in lzma_stream can be convenient). Often lzma_code() can fill the output
+ * buffer completely if there is a lot of input, but sometimes a few bytes
+ * may remain unused because the next LZMA symbol would require more space.
+ *
+ * lzma_stream.avail_out must be at least 6. Otherwise LZMA_PROG_ERROR
+ * will be returned.
+ *
+ * The LZMA dictionary should be reasonably low to speed up the encoder
+ * re-initialization. A good value is bigger than the resulting
+ * uncompressed size of most of the output chunks. For example, if output
+ * size is 4 KiB, dictionary size of 32 KiB or 64 KiB is good. If the
+ * data compresses extremely well, even 128 KiB may be useful.
+ *
+ * The MicroLZMA format and this encoder variant were made with the EROFS
+ * file system in mind. This format may be convenient in other embedded
+ * uses too where many small streams are needed. XZ Embedded includes a
+ * decoder for this format.
+ *
+ * \param       strm    Pointer to lzma_stream that is at least initialized
+ *                      with LZMA_STREAM_INIT.
+ * \param       options Pointer to encoder options
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_STREAM_END: All good. Check the amounts of input used
+ *                and output produced. Store the amount of input used
+ *                (uncompressed size) as it needs to be known to decompress
+ *                the data.
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_PROG_ERROR: In addition to the generic reasons for this
+ *                error code, this may also be returned if there isn't enough
+ *                output space (6 bytes) to create a valid MicroLZMA stream.
+ */
+extern LZMA_API(lzma_ret) lzma_microlzma_encoder(
+		lzma_stream *strm, const lzma_options_lzma *options)
+		lzma_nothrow;
+
+
 /************
 /************
  * Decoding *
  * Decoding *
  ************/
  ************/
@@ -501,24 +675,54 @@ extern LZMA_API(lzma_ret) lzma_stream_buffer_encode(
 /**
 /**
  * This flag enables decoding of concatenated files with file formats that
  * This flag enables decoding of concatenated files with file formats that
  * allow concatenating compressed files as is. From the formats currently
  * allow concatenating compressed files as is. From the formats currently
- * supported by liblzma, only the .xz format allows concatenated files.
- * Concatenated files are not allowed with the legacy .lzma format.
+ * supported by liblzma, only the .xz and .lz formats allow concatenated
+ * files. Concatenated files are not allowed with the legacy .lzma format.
  *
  *
- * This flag also affects the usage of the `action' argument for lzma_code().
+ * This flag also affects the usage of the 'action' argument for lzma_code().
  * When LZMA_CONCATENATED is used, lzma_code() won't return LZMA_STREAM_END
  * When LZMA_CONCATENATED is used, lzma_code() won't return LZMA_STREAM_END
- * unless LZMA_FINISH is used as `action'. Thus, the application has to set
+ * unless LZMA_FINISH is used as 'action'. Thus, the application has to set
  * LZMA_FINISH in the same way as it does when encoding.
  * LZMA_FINISH in the same way as it does when encoding.
  *
  *
  * If LZMA_CONCATENATED is not used, the decoders still accept LZMA_FINISH
  * If LZMA_CONCATENATED is not used, the decoders still accept LZMA_FINISH
- * as `action' for lzma_code(), but the usage of LZMA_FINISH isn't required.
+ * as 'action' for lzma_code(), but the usage of LZMA_FINISH isn't required.
  */
  */
 #define LZMA_CONCATENATED               UINT32_C(0x08)
 #define LZMA_CONCATENATED               UINT32_C(0x08)
 
 
 
 
+/**
+ * This flag makes the threaded decoder report errors (like LZMA_DATA_ERROR)
+ * as soon as they are detected. This saves time when the application has no
+ * interest in a partially decompressed truncated or corrupt file. Note that
+ * due to timing randomness, if the same truncated or corrupt input is
+ * decompressed multiple times with this flag, a different amount of output
+ * may be produced by different runs, and even the error code might vary.
+ *
+ * When using LZMA_FAIL_FAST, it is recommended to use LZMA_FINISH to tell
+ * the decoder when no more input will be coming because it can help fast
+ * detection and reporting of truncated files. Note that in this situation
+ * truncated files might be diagnosed with LZMA_DATA_ERROR instead of
+ * LZMA_OK or LZMA_BUF_ERROR!
+ *
+ * Without this flag the threaded decoder will provide as much output as
+ * possible at first and then report the pending error. This default behavior
+ * matches the single-threaded decoder and provides repeatable behavior
+ * with truncated or corrupt input. There are a few special cases where the
+ * behavior can still differ like memory allocation failures (LZMA_MEM_ERROR).
+ *
+ * Single-threaded decoders currently ignore this flag.
+ *
+ * Support for this flag was added in liblzma 5.3.3alpha. Note that in older
+ * versions this flag isn't supported (LZMA_OPTIONS_ERROR) even by functions
+ * that ignore this flag in newer liblzma versions.
+ */
+#define LZMA_FAIL_FAST                  UINT32_C(0x20)
+
+
 /**
 /**
  * \brief       Initialize .xz Stream decoder
  * \brief       Initialize .xz Stream decoder
  *
  *
- * \param       strm        Pointer to properly prepared lzma_stream
+ * \param       strm        Pointer to lzma_stream that is at least initialized
+ *                          with LZMA_STREAM_INIT.
  * \param       memlimit    Memory usage limit as bytes. Use UINT64_MAX
  * \param       memlimit    Memory usage limit as bytes. Use UINT64_MAX
  *                          to effectively disable the limiter. liblzma
  *                          to effectively disable the limiter. liblzma
  *                          5.2.3 and earlier don't allow 0 here and return
  *                          5.2.3 and earlier don't allow 0 here and return
@@ -526,9 +730,11 @@ extern LZMA_API(lzma_ret) lzma_stream_buffer_encode(
  *                          had been specified.
  *                          had been specified.
  * \param       flags       Bitwise-or of zero or more of the decoder flags:
  * \param       flags       Bitwise-or of zero or more of the decoder flags:
  *                          LZMA_TELL_NO_CHECK, LZMA_TELL_UNSUPPORTED_CHECK,
  *                          LZMA_TELL_NO_CHECK, LZMA_TELL_UNSUPPORTED_CHECK,
- *                          LZMA_TELL_ANY_CHECK, LZMA_CONCATENATED
+ *                          LZMA_TELL_ANY_CHECK, LZMA_IGNORE_CHECK,
+ *                          LZMA_CONCATENATED, LZMA_FAIL_FAST
  *
  *
- * \return      - LZMA_OK: Initialization was successful.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Initialization was successful.
  *              - LZMA_MEM_ERROR: Cannot allocate memory.
  *              - LZMA_MEM_ERROR: Cannot allocate memory.
  *              - LZMA_OPTIONS_ERROR: Unsupported flags
  *              - LZMA_OPTIONS_ERROR: Unsupported flags
  *              - LZMA_PROG_ERROR
  *              - LZMA_PROG_ERROR
@@ -539,21 +745,67 @@ extern LZMA_API(lzma_ret) lzma_stream_decoder(
 
 
 
 
 /**
 /**
- * \brief       Decode .xz Streams and .lzma files with autodetection
+ * \brief       Initialize multithreaded .xz Stream decoder
+ *
+ * The decoder can decode multiple Blocks in parallel. This requires that each
+ * Block Header contains the Compressed Size and Uncompressed size fields
+ * which are added by the multi-threaded encoder, see lzma_stream_encoder_mt().
+ *
+ * A Stream with one Block will only utilize one thread. A Stream with multiple
+ * Blocks but without size information in Block Headers will be processed in
+ * single-threaded mode in the same way as done by lzma_stream_decoder().
+ * Concatenated Streams are processed one Stream at a time; no inter-Stream
+ * parallelization is done.
+ *
+ * This function behaves like lzma_stream_decoder() when options->threads == 1
+ * and options->memlimit_threading <= 1.
+ *
+ * \param       strm        Pointer to lzma_stream that is at least initialized
+ *                          with LZMA_STREAM_INIT.
+ * \param       options     Pointer to multithreaded compression options
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Initialization was successful.
+ *              - LZMA_MEM_ERROR: Cannot allocate memory.
+ *              - LZMA_MEMLIMIT_ERROR: Memory usage limit was reached.
+ *              - LZMA_OPTIONS_ERROR: Unsupported flags.
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_stream_decoder_mt(
+		lzma_stream *strm, const lzma_mt *options)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Decode .xz, .lzma, and .lz (lzip) files with autodetection
+ *
+ * This decoder autodetects between the .xz, .lzma, and .lz file formats,
+ * and calls lzma_stream_decoder(), lzma_alone_decoder(), or
+ * lzma_lzip_decoder() once the type of the input file has been detected.
  *
  *
- * This decoder autodetects between the .xz and .lzma file formats, and
- * calls lzma_stream_decoder() or lzma_alone_decoder() once the type
- * of the input file has been detected.
+ * Support for .lz was added in 5.4.0.
  *
  *
- * \param       strm        Pointer to properly prepared lzma_stream
+ * If the flag LZMA_CONCATENATED is used and the input is a .lzma file:
+ * For historical reasons concatenated .lzma files aren't supported.
+ * If there is trailing data after one .lzma stream, lzma_code() will
+ * return LZMA_DATA_ERROR. (lzma_alone_decoder() doesn't have such a check
+ * as it doesn't support any decoder flags. It will return LZMA_STREAM_END
+ * after one .lzma stream.)
+ *
+ * \param       strm        Pointer to lzma_stream that is at least initialized
+ *                          with LZMA_STREAM_INIT.
  * \param       memlimit    Memory usage limit as bytes. Use UINT64_MAX
  * \param       memlimit    Memory usage limit as bytes. Use UINT64_MAX
  *                          to effectively disable the limiter. liblzma
  *                          to effectively disable the limiter. liblzma
  *                          5.2.3 and earlier don't allow 0 here and return
  *                          5.2.3 and earlier don't allow 0 here and return
  *                          LZMA_PROG_ERROR; later versions treat 0 as if 1
  *                          LZMA_PROG_ERROR; later versions treat 0 as if 1
  *                          had been specified.
  *                          had been specified.
- * \param       flags       Bitwise-or of flags, or zero for no flags.
+ * \param       flags       Bitwise-or of zero or more of the decoder flags:
+ *                          LZMA_TELL_NO_CHECK, LZMA_TELL_UNSUPPORTED_CHECK,
+ *                          LZMA_TELL_ANY_CHECK, LZMA_IGNORE_CHECK,
+ *                          LZMA_CONCATENATED, LZMA_FAIL_FAST
  *
  *
- * \return      - LZMA_OK: Initialization was successful.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Initialization was successful.
  *              - LZMA_MEM_ERROR: Cannot allocate memory.
  *              - LZMA_MEM_ERROR: Cannot allocate memory.
  *              - LZMA_OPTIONS_ERROR: Unsupported flags
  *              - LZMA_OPTIONS_ERROR: Unsupported flags
  *              - LZMA_PROG_ERROR
  *              - LZMA_PROG_ERROR
@@ -566,18 +818,20 @@ extern LZMA_API(lzma_ret) lzma_auto_decoder(
 /**
 /**
  * \brief       Initialize .lzma decoder (legacy file format)
  * \brief       Initialize .lzma decoder (legacy file format)
  *
  *
- * \param       strm        Pointer to properly prepared lzma_stream
+ * Valid 'action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH.
+ * There is no need to use LZMA_FINISH, but it's allowed because it may
+ * simplify certain types of applications.
+ *
+ * \param       strm        Pointer to lzma_stream that is at least initialized
+ *                          with LZMA_STREAM_INIT.
  * \param       memlimit    Memory usage limit as bytes. Use UINT64_MAX
  * \param       memlimit    Memory usage limit as bytes. Use UINT64_MAX
  *                          to effectively disable the limiter. liblzma
  *                          to effectively disable the limiter. liblzma
  *                          5.2.3 and earlier don't allow 0 here and return
  *                          5.2.3 and earlier don't allow 0 here and return
  *                          LZMA_PROG_ERROR; later versions treat 0 as if 1
  *                          LZMA_PROG_ERROR; later versions treat 0 as if 1
  *                          had been specified.
  *                          had been specified.
  *
  *
- * Valid `action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH.
- * There is no need to use LZMA_FINISH, but it's allowed because it may
- * simplify certain types of applications.
- *
- * \return      - LZMA_OK
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_PROG_ERROR
  *              - LZMA_PROG_ERROR
  */
  */
@@ -586,6 +840,66 @@ extern LZMA_API(lzma_ret) lzma_alone_decoder(
 		lzma_nothrow lzma_attr_warn_unused_result;
 		lzma_nothrow lzma_attr_warn_unused_result;
 
 
 
 
+/**
+ * \brief       Initialize .lz (lzip) decoder (a foreign file format)
+ *
+ * This decoder supports the .lz format version 0 and the unextended .lz
+ * format version 1:
+ *
+ *   - Files in the format version 0 were produced by lzip 1.3 and older.
+ *     Such files aren't common but may be found from file archives
+ *     as a few source packages were released in this format. People
+ *     might have old personal files in this format too. Decompression
+ *     support for the format version 0 was removed in lzip 1.18.
+ *
+ *   - lzip 1.3 added decompression support for .lz format version 1 files.
+ *     Compression support was added in lzip 1.4. In lzip 1.6 the .lz format
+ *     version 1 was extended to support the Sync Flush marker. This extension
+ *     is not supported by liblzma. lzma_code() will return LZMA_DATA_ERROR
+ *     at the location of the Sync Flush marker. In practice files with
+ *     the Sync Flush marker are very rare and thus liblzma can decompress
+ *     almost all .lz files.
+ *
+ * Just like with lzma_stream_decoder() for .xz files, LZMA_CONCATENATED
+ * should be used when decompressing normal standalone .lz files.
+ *
+ * The .lz format allows putting non-.lz data at the end of a file after at
+ * least one valid .lz member. That is, one can append custom data at the end
+ * of a .lz file and the decoder is required to ignore it. In liblzma this
+ * is relevant only when LZMA_CONCATENATED is used. In that case lzma_code()
+ * will return LZMA_STREAM_END and leave lzma_stream.next_in pointing to
+ * the first byte of the non-.lz data. An exception to this is if the first
+ * 1-3 bytes of the non-.lz data are identical to the .lz magic bytes
+ * (0x4C, 0x5A, 0x49, 0x50; "LZIP" in US-ASCII). In such a case the 1-3 bytes
+ * will have been ignored by lzma_code(). If one wishes to locate the non-.lz
+ * data reliably, one must ensure that the first byte isn't 0x4C. Actually
+ * one should ensure that none of the first four bytes of trailing data are
+ * equal to the magic bytes because lzip >= 1.20 requires it by default.
+ *
+ * \param       strm        Pointer to lzma_stream that is at least initialized
+ *                          with LZMA_STREAM_INIT.
+ * \param       memlimit    Memory usage limit as bytes. Use UINT64_MAX
+ *                          to effectively disable the limiter.
+ * \param       flags       Bitwise-or of flags, or zero for no flags.
+ *                          All decoder flags listed above are supported
+ *                          although only LZMA_CONCATENATED and (in very rare
+ *                          cases) LZMA_IGNORE_CHECK are actually useful.
+ *                          LZMA_TELL_NO_CHECK, LZMA_TELL_UNSUPPORTED_CHECK,
+ *                          and LZMA_FAIL_FAST do nothing. LZMA_TELL_ANY_CHECK
+ *                          is supported for consistency only as CRC32 is
+ *                          always used in the .lz format.
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Initialization was successful.
+ *              - LZMA_MEM_ERROR: Cannot allocate memory.
+ *              - LZMA_OPTIONS_ERROR: Unsupported flags
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_lzip_decoder(
+		lzma_stream *strm, uint64_t memlimit, uint32_t flags)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
 /**
 /**
  * \brief       Single-call .xz Stream decoder
  * \brief       Single-call .xz Stream decoder
  *
  *
@@ -595,7 +909,8 @@ extern LZMA_API(lzma_ret) lzma_alone_decoder(
  *                          returned.
  *                          returned.
  * \param       flags       Bitwise-or of zero or more of the decoder flags:
  * \param       flags       Bitwise-or of zero or more of the decoder flags:
  *                          LZMA_TELL_NO_CHECK, LZMA_TELL_UNSUPPORTED_CHECK,
  *                          LZMA_TELL_NO_CHECK, LZMA_TELL_UNSUPPORTED_CHECK,
- *                          LZMA_CONCATENATED. Note that LZMA_TELL_ANY_CHECK
+ *                          LZMA_IGNORE_CHECK, LZMA_CONCATENATED,
+ *                          LZMA_FAIL_FAST. Note that LZMA_TELL_ANY_CHECK
  *                          is not allowed and will return LZMA_PROG_ERROR.
  *                          is not allowed and will return LZMA_PROG_ERROR.
  * \param       allocator   lzma_allocator for custom allocator functions.
  * \param       allocator   lzma_allocator for custom allocator functions.
  *                          Set to NULL to use malloc() and free().
  *                          Set to NULL to use malloc() and free().
@@ -604,13 +919,14 @@ extern LZMA_API(lzma_ret) lzma_alone_decoder(
  *                          *in_pos is updated only if decoding succeeds.
  *                          *in_pos is updated only if decoding succeeds.
  * \param       in_size     Size of the input buffer; the first byte that
  * \param       in_size     Size of the input buffer; the first byte that
  *                          won't be read is in[in_size].
  *                          won't be read is in[in_size].
- * \param       out         Beginning of the output buffer
- * \param       out_pos     The next byte will be written to out[*out_pos].
+ * \param[out]  out         Beginning of the output buffer
+ * \param[out]  out_pos     The next byte will be written to out[*out_pos].
  *                          *out_pos is updated only if decoding succeeds.
  *                          *out_pos is updated only if decoding succeeds.
  * \param       out_size    Size of the out buffer; the first byte into
  * \param       out_size    Size of the out buffer; the first byte into
  *                          which no data is written to is out[out_size].
  *                          which no data is written to is out[out_size].
  *
  *
- * \return      - LZMA_OK: Decoding was successful.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Decoding was successful.
  *              - LZMA_FORMAT_ERROR
  *              - LZMA_FORMAT_ERROR
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_DATA_ERROR
  *              - LZMA_DATA_ERROR
@@ -630,3 +946,50 @@ extern LZMA_API(lzma_ret) lzma_stream_buffer_decode(
 		const uint8_t *in, size_t *in_pos, size_t in_size,
 		const uint8_t *in, size_t *in_pos, size_t in_size,
 		uint8_t *out, size_t *out_pos, size_t out_size)
 		uint8_t *out, size_t *out_pos, size_t out_size)
 		lzma_nothrow lzma_attr_warn_unused_result;
 		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       MicroLZMA decoder
+ *
+ * See lzma_microlzma_encoder() for more information.
+ *
+ * The lzma_code() usage with this decoder is completely normal. The
+ * special behavior of lzma_code() applies to lzma_microlzma_encoder() only.
+ *
+ * \param       strm        Pointer to lzma_stream that is at least initialized
+ *                          with LZMA_STREAM_INIT.
+ * \param       comp_size   Compressed size of the MicroLZMA stream.
+ *                          The caller must somehow know this exactly.
+ * \param       uncomp_size Uncompressed size of the MicroLZMA stream.
+ *                          If the exact uncompressed size isn't known, this
+ *                          can be set to a value that is at most as big as
+ *                          the exact uncompressed size would be, but then the
+ *                          next argument uncomp_size_is_exact must be false.
+ * \param       uncomp_size_is_exact
+ *                          If true, uncomp_size must be exactly correct.
+ *                          This will improve error detection at the end of
+ *                          the stream. If the exact uncompressed size isn't
+ *                          known, this must be false. uncomp_size must still
+ *                          be at most as big as the exact uncompressed size
+ *                          is. Setting this to false when the exact size is
+ *                          known will work but error detection at the end of
+ *                          the stream will be weaker.
+ * \param       dict_size   LZMA dictionary size that was used when
+ *                          compressing the data. It is OK to use a bigger
+ *                          value too but liblzma will then allocate more
+ *                          memory than would actually be required and error
+ *                          detection will be slightly worse. (Note that with
+ *                          the implementation in XZ Embedded it doesn't
+ *                          affect the memory usage if one specifies bigger
+ *                          dictionary than actually required.)
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_microlzma_decoder(
+		lzma_stream *strm, uint64_t comp_size,
+		uint64_t uncomp_size, lzma_bool uncomp_size_is_exact,
+		uint32_t dict_size) lzma_nothrow;

+ 23 - 5
Utilities/cmliblzma/liblzma/api/lzma/delta.h

@@ -1,15 +1,13 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /**
 /**
  * \file        lzma/delta.h
  * \file        lzma/delta.h
  * \brief       Delta filter
  * \brief       Delta filter
+ * \note        Never include this file directly. Use <lzma.h> instead.
  */
  */
 
 
 /*
 /*
  * Author: Lasse Collin
  * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
- * See ../lzma.h for information about liblzma as a whole.
  */
  */
 
 
 #ifndef LZMA_H_INTERNAL
 #ifndef LZMA_H_INTERNAL
@@ -57,7 +55,15 @@ typedef struct {
 	 *  - 24-bit RGB image data: distance = 3 bytes
 	 *  - 24-bit RGB image data: distance = 3 bytes
 	 */
 	 */
 	uint32_t dist;
 	uint32_t dist;
+
+	/**
+	 * \brief       Minimum value for lzma_options_delta.dist.
+	 */
 #	define LZMA_DELTA_DIST_MIN 1
 #	define LZMA_DELTA_DIST_MIN 1
+
+	/**
+	 * \brief       Maximum value for lzma_options_delta.dist.
+	 */
 #	define LZMA_DELTA_DIST_MAX 256
 #	define LZMA_DELTA_DIST_MAX 256
 
 
 	/*
 	/*
@@ -67,11 +73,23 @@ typedef struct {
 	 * when type is LZMA_DELTA_TYPE_BYTE, so it is safe to leave these
 	 * when type is LZMA_DELTA_TYPE_BYTE, so it is safe to leave these
 	 * uninitialized.
 	 * uninitialized.
 	 */
 	 */
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int1;
 	uint32_t reserved_int1;
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int2;
 	uint32_t reserved_int2;
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int3;
 	uint32_t reserved_int3;
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int4;
 	uint32_t reserved_int4;
+
+	/** \private     Reserved member. */
 	void *reserved_ptr1;
 	void *reserved_ptr1;
+
+	/** \private     Reserved member. */
 	void *reserved_ptr2;
 	void *reserved_ptr2;
 
 
 } lzma_options_delta;
 } lzma_options_delta;

+ 432 - 89
Utilities/cmliblzma/liblzma/api/lzma/filter.h

@@ -1,15 +1,13 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /**
 /**
  * \file        lzma/filter.h
  * \file        lzma/filter.h
  * \brief       Common filter related types and functions
  * \brief       Common filter related types and functions
+ * \note        Never include this file directly. Use <lzma.h> instead.
  */
  */
 
 
 /*
 /*
  * Author: Lasse Collin
  * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
- * See ../lzma.h for information about liblzma as a whole.
  */
  */
 
 
 #ifndef LZMA_H_INTERNAL
 #ifndef LZMA_H_INTERNAL
@@ -29,7 +27,7 @@
 /**
 /**
  * \brief       Filter options
  * \brief       Filter options
  *
  *
- * This structure is used to pass Filter ID and a pointer filter's
+ * This structure is used to pass a Filter ID and a pointer to the filter's
  * options to liblzma. A few functions work with a single lzma_filter
  * options to liblzma. A few functions work with a single lzma_filter
  * structure, while most functions expect a filter chain.
  * structure, while most functions expect a filter chain.
  *
  *
@@ -37,14 +35,14 @@
  * The array is terminated with .id = LZMA_VLI_UNKNOWN. Thus, the filter
  * The array is terminated with .id = LZMA_VLI_UNKNOWN. Thus, the filter
  * array must have LZMA_FILTERS_MAX + 1 elements (that is, five) to
  * array must have LZMA_FILTERS_MAX + 1 elements (that is, five) to
  * be able to hold any arbitrary filter chain. This is important when
  * be able to hold any arbitrary filter chain. This is important when
- * using lzma_block_header_decode() from block.h, because too small
- * array would make liblzma write past the end of the filters array.
+ * using lzma_block_header_decode() from block.h, because a filter array
+ * that is too small would make liblzma write past the end of the array.
  */
  */
 typedef struct {
 typedef struct {
 	/**
 	/**
 	 * \brief       Filter ID
 	 * \brief       Filter ID
 	 *
 	 *
-	 * Use constants whose name begin with `LZMA_FILTER_' to specify
+	 * Use constants whose name begin with 'LZMA_FILTER_' to specify
 	 * different filters. In an array of lzma_filter structures, use
 	 * different filters. In an array of lzma_filter structures, use
 	 * LZMA_VLI_UNKNOWN to indicate end of filters.
 	 * LZMA_VLI_UNKNOWN to indicate end of filters.
 	 *
 	 *
@@ -68,12 +66,12 @@ typedef struct {
 /**
 /**
  * \brief       Test if the given Filter ID is supported for encoding
  * \brief       Test if the given Filter ID is supported for encoding
  *
  *
- * Return true if the give Filter ID is supported for encoding by this
- * liblzma build. Otherwise false is returned.
+ * \param       id      Filter ID
  *
  *
- * There is no way to list which filters are available in this particular
- * liblzma version and build. It would be useless, because the application
- * couldn't know what kind of options the filter would need.
+ * \return      lzma_bool:
+ *              - true if the Filter ID is supported for encoding by this
+ *                liblzma build.
+  *             - false otherwise.
  */
  */
 extern LZMA_API(lzma_bool) lzma_filter_encoder_is_supported(lzma_vli id)
 extern LZMA_API(lzma_bool) lzma_filter_encoder_is_supported(lzma_vli id)
 		lzma_nothrow lzma_attr_const;
 		lzma_nothrow lzma_attr_const;
@@ -82,8 +80,12 @@ extern LZMA_API(lzma_bool) lzma_filter_encoder_is_supported(lzma_vli id)
 /**
 /**
  * \brief       Test if the given Filter ID is supported for decoding
  * \brief       Test if the given Filter ID is supported for decoding
  *
  *
- * Return true if the give Filter ID is supported for decoding by this
- * liblzma build. Otherwise false is returned.
+ * \param       id      Filter ID
+ *
+ * \return      lzma_bool:
+ *              - true if the Filter ID is supported for decoding by this
+ *                liblzma build.
+ *              - false otherwise.
  */
  */
 extern LZMA_API(lzma_bool) lzma_filter_decoder_is_supported(lzma_vli id)
 extern LZMA_API(lzma_bool) lzma_filter_decoder_is_supported(lzma_vli id)
 		lzma_nothrow lzma_attr_const;
 		lzma_nothrow lzma_attr_const;
@@ -108,9 +110,18 @@ extern LZMA_API(lzma_bool) lzma_filter_decoder_is_supported(lzma_vli id)
  * need to be initialized by the caller in any way.
  * need to be initialized by the caller in any way.
  *
  *
  * If an error occurs, memory possibly already allocated by this function
  * If an error occurs, memory possibly already allocated by this function
- * is always freed.
+ * is always freed. liblzma versions older than 5.2.7 may modify the dest
+ * array and leave its contents in an undefined state if an error occurs.
+ * liblzma 5.2.7 and newer only modify the dest array when returning LZMA_OK.
+ *
+ * \param       src         Array of filters terminated with
+ *                          .id == LZMA_VLI_UNKNOWN.
+ * \param[out]  dest        Destination filter array
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
  *
  *
- * \return      - LZMA_OK
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_OPTIONS_ERROR: Unsupported Filter ID and its options
  *              - LZMA_OPTIONS_ERROR: Unsupported Filter ID and its options
  *                is not NULL.
  *                is not NULL.
@@ -118,7 +129,34 @@ extern LZMA_API(lzma_bool) lzma_filter_decoder_is_supported(lzma_vli id)
  */
  */
 extern LZMA_API(lzma_ret) lzma_filters_copy(
 extern LZMA_API(lzma_ret) lzma_filters_copy(
 		const lzma_filter *src, lzma_filter *dest,
 		const lzma_filter *src, lzma_filter *dest,
-		const lzma_allocator *allocator) lzma_nothrow;
+		const lzma_allocator *allocator)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Free the options in the array of lzma_filter structures
+ *
+ * This frees the filter chain options. The filters array itself is not freed.
+ *
+ * The filters array must have at most LZMA_FILTERS_MAX + 1 elements
+ * including the terminating element which must have .id = LZMA_VLI_UNKNOWN.
+ * For all elements before the terminating element:
+ *   - options will be freed using the given lzma_allocator or,
+ *     if allocator is NULL, using free().
+ *   - options will be set to NULL.
+ *   - id will be set to LZMA_VLI_UNKNOWN.
+ *
+ * If filters is NULL, this does nothing. Again, this never frees the
+ * filters array itself.
+ *
+ * \param       filters     Array of filters terminated with
+ *                          .id == LZMA_VLI_UNKNOWN.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ */
+extern LZMA_API(void) lzma_filters_free(
+		lzma_filter *filters, const lzma_allocator *allocator)
+		lzma_nothrow;
 
 
 
 
 /**
 /**
@@ -132,9 +170,7 @@ extern LZMA_API(lzma_ret) lzma_filters_copy(
  *                          .id == LZMA_VLI_UNKNOWN.
  *                          .id == LZMA_VLI_UNKNOWN.
  *
  *
  * \return      Number of bytes of memory required for the given
  * \return      Number of bytes of memory required for the given
- *              filter chain when encoding. If an error occurs,
- *              for example due to unsupported filter chain,
- *              UINT64_MAX is returned.
+ *              filter chain when encoding or UINT64_MAX on error.
  */
  */
 extern LZMA_API(uint64_t) lzma_raw_encoder_memusage(const lzma_filter *filters)
 extern LZMA_API(uint64_t) lzma_raw_encoder_memusage(const lzma_filter *filters)
 		lzma_nothrow lzma_attr_pure;
 		lzma_nothrow lzma_attr_pure;
@@ -151,9 +187,7 @@ extern LZMA_API(uint64_t) lzma_raw_encoder_memusage(const lzma_filter *filters)
  *                          .id == LZMA_VLI_UNKNOWN.
  *                          .id == LZMA_VLI_UNKNOWN.
  *
  *
  * \return      Number of bytes of memory required for the given
  * \return      Number of bytes of memory required for the given
- *              filter chain when decoding. If an error occurs,
- *              for example due to unsupported filter chain,
- *              UINT64_MAX is returned.
+ *              filter chain when decoding or UINT64_MAX on error.
  */
  */
 extern LZMA_API(uint64_t) lzma_raw_decoder_memusage(const lzma_filter *filters)
 extern LZMA_API(uint64_t) lzma_raw_decoder_memusage(const lzma_filter *filters)
 		lzma_nothrow lzma_attr_pure;
 		lzma_nothrow lzma_attr_pure;
@@ -164,14 +198,16 @@ extern LZMA_API(uint64_t) lzma_raw_decoder_memusage(const lzma_filter *filters)
  *
  *
  * This function may be useful when implementing custom file formats.
  * This function may be useful when implementing custom file formats.
  *
  *
- * \param       strm    Pointer to properly prepared lzma_stream
- * \param       filters Array of lzma_filter structures. The end of the
- *                      array must be marked with .id = LZMA_VLI_UNKNOWN.
- *
- * The `action' with lzma_code() can be LZMA_RUN, LZMA_SYNC_FLUSH (if the
+ * The 'action' with lzma_code() can be LZMA_RUN, LZMA_SYNC_FLUSH (if the
  * filter chain supports it), or LZMA_FINISH.
  * filter chain supports it), or LZMA_FINISH.
  *
  *
- * \return      - LZMA_OK
+ * \param       strm      Pointer to lzma_stream that is at least
+ *                        initialized with LZMA_STREAM_INIT.
+ * \param       filters   Array of filters terminated with
+ *                        .id == LZMA_VLI_UNKNOWN.
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_PROG_ERROR
  *              - LZMA_PROG_ERROR
@@ -186,10 +222,16 @@ extern LZMA_API(lzma_ret) lzma_raw_encoder(
  *
  *
  * The initialization of raw decoder goes similarly to raw encoder.
  * The initialization of raw decoder goes similarly to raw encoder.
  *
  *
- * The `action' with lzma_code() can be LZMA_RUN or LZMA_FINISH. Using
+ * The 'action' with lzma_code() can be LZMA_RUN or LZMA_FINISH. Using
  * LZMA_FINISH is not required, it is supported just for convenience.
  * LZMA_FINISH is not required, it is supported just for convenience.
  *
  *
- * \return      - LZMA_OK
+ * \param       strm      Pointer to lzma_stream that is at least
+ *                        initialized with LZMA_STREAM_INIT.
+ * \param       filters   Array of filters terminated with
+ *                        .id == LZMA_VLI_UNKNOWN.
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_PROG_ERROR
  *              - LZMA_PROG_ERROR
@@ -202,24 +244,36 @@ extern LZMA_API(lzma_ret) lzma_raw_decoder(
 /**
 /**
  * \brief       Update the filter chain in the encoder
  * \brief       Update the filter chain in the encoder
  *
  *
- * This function is for advanced users only. This function has two slightly
- * different purposes:
+ * This function may be called after lzma_code() has returned LZMA_STREAM_END
+ * when LZMA_FULL_BARRIER, LZMA_FULL_FLUSH, or LZMA_SYNC_FLUSH was used:
+ *
+ *  - After LZMA_FULL_BARRIER or LZMA_FULL_FLUSH: Single-threaded .xz Stream
+ *    encoder (lzma_stream_encoder()) and (since liblzma 5.4.0) multi-threaded
+ *    Stream encoder (lzma_stream_encoder_mt()) allow setting a new filter
+ *    chain to be used for the next Block(s).
  *
  *
- *  - After LZMA_FULL_FLUSH when using Stream encoder: Set a new filter
- *    chain, which will be used starting from the next Block.
+ *  - After LZMA_SYNC_FLUSH: Raw encoder (lzma_raw_encoder()),
+ *    Block encoder (lzma_block_encoder()), and single-threaded .xz Stream
+ *    encoder (lzma_stream_encoder()) allow changing certain filter-specific
+ *    options in the middle of encoding. The actual filters in the chain
+ *    (Filter IDs) must not be changed! Currently only the lc, lp, and pb
+ *    options of LZMA2 (not LZMA1) can be changed this way.
  *
  *
- *  - After LZMA_SYNC_FLUSH using Raw, Block, or Stream encoder: Change
- *    the filter-specific options in the middle of encoding. The actual
- *    filters in the chain (Filter IDs) cannot be changed. In the future,
- *    it might become possible to change the filter options without
- *    using LZMA_SYNC_FLUSH.
+ *  - In the future some filters might allow changing some of their options
+ *    without any barrier or flushing but currently such filters don't exist.
  *
  *
- * While rarely useful, this function may be called also when no data has
- * been compressed yet. In that case, this function will behave as if
- * LZMA_FULL_FLUSH (Stream encoder) or LZMA_SYNC_FLUSH (Raw or Block
+ * This function may also be called when no data has been compressed yet
+ * although this is rarely useful. In that case, this function will behave
+ * as if LZMA_FULL_FLUSH (Stream encoders) or LZMA_SYNC_FLUSH (Raw or Block
  * encoder) had been used right before calling this function.
  * encoder) had been used right before calling this function.
  *
  *
- * \return      - LZMA_OK
+ * \param       strm      Pointer to lzma_stream that is at least
+ *                        initialized with LZMA_STREAM_INIT.
+ * \param       filters   Array of filters terminated with
+ *                        .id == LZMA_VLI_UNKNOWN.
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEMLIMIT_ERROR
  *              - LZMA_MEMLIMIT_ERROR
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_OPTIONS_ERROR
@@ -232,29 +286,30 @@ extern LZMA_API(lzma_ret) lzma_filters_update(
 /**
 /**
  * \brief       Single-call raw encoder
  * \brief       Single-call raw encoder
  *
  *
- * \param       filters     Array of lzma_filter structures. The end of the
- *                          array must be marked with .id = LZMA_VLI_UNKNOWN.
+ * \note        There is no function to calculate how big output buffer
+ *              would surely be big enough. (lzma_stream_buffer_bound()
+ *              works only for lzma_stream_buffer_encode(); raw encoder
+ *              won't necessarily meet that bound.)
+ *
+ * \param       filters     Array of filters terminated with
+ *                          .id == LZMA_VLI_UNKNOWN.
  * \param       allocator   lzma_allocator for custom allocator functions.
  * \param       allocator   lzma_allocator for custom allocator functions.
  *                          Set to NULL to use malloc() and free().
  *                          Set to NULL to use malloc() and free().
  * \param       in          Beginning of the input buffer
  * \param       in          Beginning of the input buffer
  * \param       in_size     Size of the input buffer
  * \param       in_size     Size of the input buffer
- * \param       out         Beginning of the output buffer
- * \param       out_pos     The next byte will be written to out[*out_pos].
+ * \param[out]  out         Beginning of the output buffer
+ * \param[out]  out_pos     The next byte will be written to out[*out_pos].
  *                          *out_pos is updated only if encoding succeeds.
  *                          *out_pos is updated only if encoding succeeds.
  * \param       out_size    Size of the out buffer; the first byte into
  * \param       out_size    Size of the out buffer; the first byte into
  *                          which no data is written to is out[out_size].
  *                          which no data is written to is out[out_size].
  *
  *
- * \return      - LZMA_OK: Encoding was successful.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Encoding was successful.
  *              - LZMA_BUF_ERROR: Not enough output buffer space.
  *              - LZMA_BUF_ERROR: Not enough output buffer space.
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_DATA_ERROR
  *              - LZMA_DATA_ERROR
  *              - LZMA_PROG_ERROR
  *              - LZMA_PROG_ERROR
- *
- * \note        There is no function to calculate how big output buffer
- *              would surely be big enough. (lzma_stream_buffer_bound()
- *              works only for lzma_stream_buffer_encode(); raw encoder
- *              won't necessarily meet that bound.)
  */
  */
 extern LZMA_API(lzma_ret) lzma_raw_buffer_encode(
 extern LZMA_API(lzma_ret) lzma_raw_buffer_encode(
 		const lzma_filter *filters, const lzma_allocator *allocator,
 		const lzma_filter *filters, const lzma_allocator *allocator,
@@ -265,8 +320,8 @@ extern LZMA_API(lzma_ret) lzma_raw_buffer_encode(
 /**
 /**
  * \brief       Single-call raw decoder
  * \brief       Single-call raw decoder
  *
  *
- * \param       filters     Array of lzma_filter structures. The end of the
- *                          array must be marked with .id = LZMA_VLI_UNKNOWN.
+ * \param       filters     Array of filters terminated with
+ *                          .id == LZMA_VLI_UNKNOWN.
  * \param       allocator   lzma_allocator for custom allocator functions.
  * \param       allocator   lzma_allocator for custom allocator functions.
  *                          Set to NULL to use malloc() and free().
  *                          Set to NULL to use malloc() and free().
  * \param       in          Beginning of the input buffer
  * \param       in          Beginning of the input buffer
@@ -274,11 +329,19 @@ extern LZMA_API(lzma_ret) lzma_raw_buffer_encode(
  *                          *in_pos is updated only if decoding succeeds.
  *                          *in_pos is updated only if decoding succeeds.
  * \param       in_size     Size of the input buffer; the first byte that
  * \param       in_size     Size of the input buffer; the first byte that
  *                          won't be read is in[in_size].
  *                          won't be read is in[in_size].
- * \param       out         Beginning of the output buffer
- * \param       out_pos     The next byte will be written to out[*out_pos].
+ * \param[out]  out         Beginning of the output buffer
+ * \param[out]  out_pos     The next byte will be written to out[*out_pos].
  *                          *out_pos is updated only if encoding succeeds.
  *                          *out_pos is updated only if encoding succeeds.
  * \param       out_size    Size of the out buffer; the first byte into
  * \param       out_size    Size of the out buffer; the first byte into
  *                          which no data is written to is out[out_size].
  *                          which no data is written to is out[out_size].
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Decoding was successful.
+ *              - LZMA_BUF_ERROR: Not enough output buffer space.
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_DATA_ERROR
+ *              - LZMA_PROG_ERROR
  */
  */
 extern LZMA_API(lzma_ret) lzma_raw_buffer_decode(
 extern LZMA_API(lzma_ret) lzma_raw_buffer_decode(
 		const lzma_filter *filters, const lzma_allocator *allocator,
 		const lzma_filter *filters, const lzma_allocator *allocator,
@@ -292,18 +355,19 @@ extern LZMA_API(lzma_ret) lzma_raw_buffer_decode(
  * This function may be useful when implementing custom file formats
  * This function may be useful when implementing custom file formats
  * using the raw encoder and decoder.
  * using the raw encoder and decoder.
  *
  *
- * \param       size    Pointer to uint32_t to hold the size of the properties
+ * \note        This function validates the Filter ID, but does not
+ *              necessarily validate the options. Thus, it is possible
+ *              that this returns LZMA_OK while the following call to
+ *              lzma_properties_encode() returns LZMA_OPTIONS_ERROR.
+ *
+ * \param[out]  size    Pointer to uint32_t to hold the size of the properties
  * \param       filter  Filter ID and options (the size of the properties may
  * \param       filter  Filter ID and options (the size of the properties may
  *                      vary depending on the options)
  *                      vary depending on the options)
  *
  *
- * \return      - LZMA_OK
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_PROG_ERROR
  *              - LZMA_PROG_ERROR
- *
- * \note        This function validates the Filter ID, but does not
- *              necessarily validate the options. Thus, it is possible
- *              that this returns LZMA_OK while the following call to
- *              lzma_properties_encode() returns LZMA_OPTIONS_ERROR.
  */
  */
 extern LZMA_API(lzma_ret) lzma_properties_size(
 extern LZMA_API(lzma_ret) lzma_properties_size(
 		uint32_t *size, const lzma_filter *filter) lzma_nothrow;
 		uint32_t *size, const lzma_filter *filter) lzma_nothrow;
@@ -312,15 +376,6 @@ extern LZMA_API(lzma_ret) lzma_properties_size(
 /**
 /**
  * \brief       Encode the Filter Properties field
  * \brief       Encode the Filter Properties field
  *
  *
- * \param       filter  Filter ID and options
- * \param       props   Buffer to hold the encoded options. The size of
- *                      buffer must have been already determined with
- *                      lzma_properties_size().
- *
- * \return      - LZMA_OK
- *              - LZMA_OPTIONS_ERROR
- *              - LZMA_PROG_ERROR
- *
  * \note        Even this function won't validate more options than actually
  * \note        Even this function won't validate more options than actually
  *              necessary. Thus, it is possible that encoding the properties
  *              necessary. Thus, it is possible that encoding the properties
  *              succeeds but using the same options to initialize the encoder
  *              succeeds but using the same options to initialize the encoder
@@ -330,6 +385,15 @@ extern LZMA_API(lzma_ret) lzma_properties_size(
  *              of the Filter Properties field is zero, calling
  *              of the Filter Properties field is zero, calling
  *              lzma_properties_encode() is not required, but it
  *              lzma_properties_encode() is not required, but it
  *              won't do any harm either.
  *              won't do any harm either.
+ *
+ * \param       filter  Filter ID and options
+ * \param[out]  props   Buffer to hold the encoded options. The size of
+ *                      the buffer must have been already determined with
+ *                      lzma_properties_size().
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
+ *              - LZMA_PROG_ERROR
  */
  */
 extern LZMA_API(lzma_ret) lzma_properties_encode(
 extern LZMA_API(lzma_ret) lzma_properties_encode(
 		const lzma_filter *filter, uint8_t *props) lzma_nothrow;
 		const lzma_filter *filter, uint8_t *props) lzma_nothrow;
@@ -345,15 +409,16 @@ extern LZMA_API(lzma_ret) lzma_properties_encode(
  *                          it's application's responsibility to free it when
  *                          it's application's responsibility to free it when
  *                          appropriate. filter->options is set to NULL if
  *                          appropriate. filter->options is set to NULL if
  *                          there are no properties or if an error occurs.
  *                          there are no properties or if an error occurs.
- * \param       allocator   Custom memory allocator used to allocate the
- *                          options. Set to NULL to use the default malloc(),
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
  *                          and in case of an error, also free().
  *                          and in case of an error, also free().
  * \param       props       Input buffer containing the properties.
  * \param       props       Input buffer containing the properties.
  * \param       props_size  Size of the properties. This must be the exact
  * \param       props_size  Size of the properties. This must be the exact
  *                          size; giving too much or too little input will
  *                          size; giving too much or too little input will
  *                          return LZMA_OPTIONS_ERROR.
  *                          return LZMA_OPTIONS_ERROR.
  *
  *
- * \return      - LZMA_OK
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
  */
  */
@@ -368,18 +433,19 @@ extern LZMA_API(lzma_ret) lzma_properties_decode(
  * Knowing the size of Filter Flags is useful to know when allocating
  * Knowing the size of Filter Flags is useful to know when allocating
  * memory to hold the encoded Filter Flags.
  * memory to hold the encoded Filter Flags.
  *
  *
- * \param       size    Pointer to integer to hold the calculated size
+ * \note        If you need to calculate size of List of Filter Flags,
+ *              you need to loop over every lzma_filter entry.
+ *
+ * \param[out]  size    Pointer to integer to hold the calculated size
  * \param       filter  Filter ID and associated options whose encoded
  * \param       filter  Filter ID and associated options whose encoded
  *                      size is to be calculated
  *                      size is to be calculated
  *
  *
- * \return      - LZMA_OK: *size set successfully. Note that this doesn't
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: *size set successfully. Note that this doesn't
  *                guarantee that filter->options is valid, thus
  *                guarantee that filter->options is valid, thus
  *                lzma_filter_flags_encode() may still fail.
  *                lzma_filter_flags_encode() may still fail.
  *              - LZMA_OPTIONS_ERROR: Unknown Filter ID or unsupported options.
  *              - LZMA_OPTIONS_ERROR: Unknown Filter ID or unsupported options.
  *              - LZMA_PROG_ERROR: Invalid options
  *              - LZMA_PROG_ERROR: Invalid options
- *
- * \note        If you need to calculate size of List of Filter Flags,
- *              you need to loop over every lzma_filter entry.
  */
  */
 extern LZMA_API(lzma_ret) lzma_filter_flags_size(
 extern LZMA_API(lzma_ret) lzma_filter_flags_size(
 		uint32_t *size, const lzma_filter *filter)
 		uint32_t *size, const lzma_filter *filter)
@@ -393,12 +459,13 @@ extern LZMA_API(lzma_ret) lzma_filter_flags_size(
  * This is due to how this function is used internally by liblzma.
  * This is due to how this function is used internally by liblzma.
  *
  *
  * \param       filter      Filter ID and options to be encoded
  * \param       filter      Filter ID and options to be encoded
- * \param       out         Beginning of the output buffer
- * \param       out_pos     out[*out_pos] is the next write position. This
+ * \param[out]  out         Beginning of the output buffer
+ * \param[out]  out_pos     out[*out_pos] is the next write position. This
  *                          is updated by the encoder.
  *                          is updated by the encoder.
  * \param       out_size    out[out_size] is the first byte to not write.
  * \param       out_size    out[out_size] is the first byte to not write.
  *
  *
- * \return      - LZMA_OK: Encoding was successful.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Encoding was successful.
  *              - LZMA_OPTIONS_ERROR: Invalid or unsupported options.
  *              - LZMA_OPTIONS_ERROR: Invalid or unsupported options.
  *              - LZMA_PROG_ERROR: Invalid options or not enough output
  *              - LZMA_PROG_ERROR: Invalid options or not enough output
  *                buffer space (you should have checked it with
  *                buffer space (you should have checked it with
@@ -413,14 +480,290 @@ extern LZMA_API(lzma_ret) lzma_filter_flags_encode(const lzma_filter *filter,
  * \brief       Decode Filter Flags from given buffer
  * \brief       Decode Filter Flags from given buffer
  *
  *
  * The decoded result is stored into *filter. The old value of
  * The decoded result is stored into *filter. The old value of
- * filter->options is not free()d.
+ * filter->options is not free()d. If anything other than LZMA_OK
+ * is returned, filter->options is set to NULL.
  *
  *
- * \return      - LZMA_OK
+ * \param[out]  filter      Destination filter. The decoded Filter ID will
+ *                          be stored in filter->id. If options are needed
+ *                          they will be allocated and the pointer will be
+ *                          stored in filter->options.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ * \param       in          Beginning of the input buffer
+ * \param[out]  in_pos      The next byte will be read from in[*in_pos].
+ *                          *in_pos is updated only if decoding succeeds.
+ * \param       in_size     Size of the input buffer; the first byte that
+ *                          won't be read is in[in_size].
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_OPTIONS_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
+ *              - LZMA_DATA_ERROR
  *              - LZMA_PROG_ERROR
  *              - LZMA_PROG_ERROR
  */
  */
 extern LZMA_API(lzma_ret) lzma_filter_flags_decode(
 extern LZMA_API(lzma_ret) lzma_filter_flags_decode(
 		lzma_filter *filter, const lzma_allocator *allocator,
 		lzma_filter *filter, const lzma_allocator *allocator,
 		const uint8_t *in, size_t *in_pos, size_t in_size)
 		const uint8_t *in, size_t *in_pos, size_t in_size)
 		lzma_nothrow lzma_attr_warn_unused_result;
 		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/***********
+ * Strings *
+ ***********/
+
+/**
+ * \brief       Allow or show all filters
+ *
+ * By default only the filters supported in the .xz format are accept by
+ * lzma_str_to_filters() or shown by lzma_str_list_filters().
+ */
+#define LZMA_STR_ALL_FILTERS    UINT32_C(0x01)
+
+
+/**
+ * \brief       Do not validate the filter chain in lzma_str_to_filters()
+ *
+ * By default lzma_str_to_filters() can return an error if the filter chain
+ * as a whole isn't usable in the .xz format or in the raw encoder or decoder.
+ * With this flag, this validation is skipped. This flag doesn't affect the
+ * handling of the individual filter options. To allow non-.xz filters also
+ * LZMA_STR_ALL_FILTERS is needed.
+ */
+#define LZMA_STR_NO_VALIDATION  UINT32_C(0x02)
+
+
+/**
+ * \brief       Stringify encoder options
+ *
+ * Show the filter-specific options that the encoder will use.
+ * This may be useful for verbose diagnostic messages.
+ *
+ * Note that if options were decoded from .xz headers then the encoder options
+ * may be undefined. This flag shouldn't be used in such a situation.
+ */
+#define LZMA_STR_ENCODER        UINT32_C(0x10)
+
+
+/**
+ * \brief       Stringify decoder options
+ *
+ * Show the filter-specific options that the decoder will use.
+ * This may be useful for showing what filter options were decoded
+ * from file headers.
+ */
+#define LZMA_STR_DECODER        UINT32_C(0x20)
+
+
+/**
+ * \brief       Produce xz-compatible getopt_long() syntax
+ *
+ * That is, "delta:dist=2 lzma2:dict=4MiB,pb=1,lp=1" becomes
+ * "--delta=dist=2 --lzma2=dict=4MiB,pb=1,lp=1".
+ *
+ * This syntax is compatible with xz 5.0.0 as long as the filters and
+ * their options are supported too.
+ */
+#define LZMA_STR_GETOPT_LONG    UINT32_C(0x40)
+
+
+/**
+ * \brief       Use two dashes "--" instead of a space to separate filters
+ *
+ * That is, "delta:dist=2 lzma2:pb=1,lp=1" becomes
+ * "delta:dist=2--lzma2:pb=1,lp=1". This looks slightly odd but this
+ * kind of strings should be usable on the command line without quoting.
+ * However, it is possible that future versions with new filter options
+ * might produce strings that require shell quoting anyway as the exact
+ * set of possible characters isn't frozen for now.
+ *
+ * It is guaranteed that the single quote (') will never be used in
+ * filter chain strings (even if LZMA_STR_NO_SPACES isn't used).
+ */
+#define LZMA_STR_NO_SPACES      UINT32_C(0x80)
+
+
+/**
+ * \brief       Convert a string to a filter chain
+ *
+ * This tries to make it easier to write applications that allow users
+ * to set custom compression options. This only handles the filter
+ * configuration (including presets) but not the number of threads,
+ * block size, check type, or memory limits.
+ *
+ * The input string can be either a preset or a filter chain. Presets
+ * begin with a digit 0-9 and may be followed by zero or more flags
+ * which are lower-case letters. Currently only "e" is supported, matching
+ * LZMA_PRESET_EXTREME. For partial xz command line syntax compatibility,
+ * a preset string may start with a single dash "-".
+ *
+ * A filter chain consists of one or more "filtername:opt1=value1,opt2=value2"
+ * strings separated by one or more spaces. Leading and trailing spaces are
+ * ignored. All names and values must be lower-case. Extra commas in the
+ * option list are ignored. The order of filters is significant: when
+ * encoding, the uncompressed input data goes to the leftmost filter first.
+ * Normally "lzma2" is the last filter in the chain.
+ *
+ * If one wishes to avoid spaces, for example, to avoid shell quoting,
+ * it is possible to use two dashes "--" instead of spaces to separate
+ * the filters.
+ *
+ * For xz command line compatibility, each filter may be prefixed with
+ * two dashes "--" and the colon ":" separating the filter name from
+ * the options may be replaced with an equals sign "=".
+ *
+ * By default, only filters that can be used in the .xz format are accepted.
+ * To allow all filters (LZMA1) use the flag LZMA_STR_ALL_FILTERS.
+ *
+ * By default, very basic validation is done for the filter chain as a whole,
+ * for example, that LZMA2 is only used as the last filter in the chain.
+ * The validation isn't perfect though and it's possible that this function
+ * succeeds but using the filter chain for encoding or decoding will still
+ * result in LZMA_OPTIONS_ERROR. To disable this validation, use the flag
+ * LZMA_STR_NO_VALIDATION.
+ *
+ * The available filter names and their options are available via
+ * lzma_str_list_filters(). See the xz man page for the description
+ * of filter names and options.
+ *
+ * For command line applications, below is an example how an error message
+ * can be displayed. Note the use of an empty string for the field width.
+ * If "^" was used there it would create an off-by-one error except at
+ * the very beginning of the line.
+ *
+ * \code{.c}
+ * const char *str = ...; // From user
+ * lzma_filter filters[LZMA_FILTERS_MAX + 1];
+ * int pos;
+ * const char *msg = lzma_str_to_filters(str, &pos, filters, 0, NULL);
+ * if (msg != NULL) {
+ *     printf("%s: Error in XZ compression options:\n", argv[0]);
+ *     printf("%s: %s\n", argv[0], str);
+ *     printf("%s: %*s^\n", argv[0], errpos, "");
+ *     printf("%s: %s\n", argv[0], msg);
+ * }
+ * \endcode
+ *
+ * \param       str         User-supplied string describing a preset or
+ *                          a filter chain. If a default value is needed and
+ *                          you don't know what would be good, use "6" since
+ *                          that is the default preset in xz too.
+ * \param[out]  error_pos   If this isn't NULL, this value will be set on
+ *                          both success and on all errors. This tells the
+ *                          location of the error in the string. This is
+ *                          an int to make it straightforward to use this
+ *                          as printf() field width. The value is guaranteed
+ *                          to be in the range [0, INT_MAX] even if strlen(str)
+ *                          somehow was greater than INT_MAX.
+ * \param[out]  filters     An array of lzma_filter structures. There must
+ *                          be LZMA_FILTERS_MAX + 1 (that is, five) elements
+ *                          in the array. The old contents are ignored so it
+ *                          doesn't need to be initialized. This array is
+ *                          modified only if this function returns NULL.
+ *                          Once the allocated filter options are no longer
+ *                          needed, lzma_filters_free() can be used to free the
+ *                          options (it doesn't free the filters array itself).
+ * \param       flags       Bitwise-or of zero or more of the flags
+ *                          LZMA_STR_ALL_FILTERS and LZMA_STR_NO_VALIDATION.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ *
+ * \return      On success, NULL is returned. On error, a statically-allocated
+ *              error message is returned which together with the error_pos
+ *              should give some idea what is wrong.
+ */
+extern LZMA_API(const char *) lzma_str_to_filters(
+		const char *str, int *error_pos, lzma_filter *filters,
+		uint32_t flags, const lzma_allocator *allocator)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Convert a filter chain to a string
+ *
+ * Use cases:
+ *
+ *   - Verbose output showing the full encoder options to the user
+ *     (use LZMA_STR_ENCODER in flags)
+ *
+ *   - Showing the filters and options that are required to decode a file
+ *     (use LZMA_STR_DECODER in flags)
+ *
+ *   - Showing the filter names without any options in informational messages
+ *     where the technical details aren't important (no flags). In this case
+ *     the .options in the filters array are ignored and may be NULL even if
+ *     a filter has a mandatory options structure.
+ *
+ * Note that even if the filter chain was specified using a preset,
+ * the resulting filter chain isn't reversed to a preset. So if you
+ * specify "6" to lzma_str_to_filters() then lzma_str_from_filters()
+ * will produce a string containing "lzma2".
+ *
+ * \param[out]  str         On success *str will be set to point to an
+ *                          allocated string describing the given filter
+ *                          chain. Old value is ignored. On error *str is
+ *                          always set to NULL.
+ * \param       filters     Array of filters terminated with
+ *                          .id == LZMA_VLI_UNKNOWN.
+ * \param       flags       Bitwise-or of zero or more of the flags
+ *                          LZMA_STR_ENCODER, LZMA_STR_DECODER,
+ *                          LZMA_STR_GETOPT_LONG, and LZMA_STR_NO_SPACES.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
+ *              - LZMA_OPTIONS_ERROR: Empty filter chain
+ *                (filters[0].id == LZMA_VLI_UNKNOWN) or the filter chain
+ *                includes a Filter ID that is not supported by this function.
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_str_from_filters(
+		char **str, const lzma_filter *filters, uint32_t flags,
+		const lzma_allocator *allocator)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       List available filters and/or their options (for help message)
+ *
+ * If a filter_id is given then only one line is created which contains the
+ * filter name. If LZMA_STR_ENCODER or LZMA_STR_DECODER is used then the
+ * options read by the encoder or decoder are printed on the same line.
+ *
+ * If filter_id is LZMA_VLI_UNKNOWN then all supported .xz-compatible filters
+ * are listed:
+ *
+ *   - If neither LZMA_STR_ENCODER nor LZMA_STR_DECODER is used then
+ *     the supported filter names are listed on a single line separated
+ *     by spaces.
+ *
+ *   - If LZMA_STR_ENCODER or LZMA_STR_DECODER is used then filters and
+ *     the supported options are listed one filter per line. There won't
+ *     be a newline after the last filter.
+ *
+ *   - If LZMA_STR_ALL_FILTERS is used then the list will include also
+ *     those filters that cannot be used in the .xz format (LZMA1).
+ *
+ * \param       str         On success *str will be set to point to an
+ *                          allocated string listing the filters and options.
+ *                          Old value is ignored. On error *str is always set
+ *                          to NULL.
+ * \param       filter_id   Filter ID or LZMA_VLI_UNKNOWN.
+ * \param       flags       Bitwise-or of zero or more of the flags
+ *                          LZMA_STR_ALL_FILTERS, LZMA_STR_ENCODER,
+ *                          LZMA_STR_DECODER, and LZMA_STR_GETOPT_LONG.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
+ *              - LZMA_OPTIONS_ERROR: Unsupported filter_id or flags
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_str_list_filters(
+		char **str, lzma_vli filter_id, uint32_t flags,
+		const lzma_allocator *allocator)
+		lzma_nothrow lzma_attr_warn_unused_result;

+ 4 - 6
Utilities/cmliblzma/liblzma/api/lzma/hardware.h

@@ -1,6 +1,9 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /**
 /**
  * \file        lzma/hardware.h
  * \file        lzma/hardware.h
  * \brief       Hardware information
  * \brief       Hardware information
+ * \note        Never include this file directly. Use <lzma.h> instead.
  *
  *
  * Since liblzma can consume a lot of system resources, it also provides
  * Since liblzma can consume a lot of system resources, it also provides
  * ways to limit the resource usage. Applications linking against liblzma
  * ways to limit the resource usage. Applications linking against liblzma
@@ -22,11 +25,6 @@
 
 
 /*
 /*
  * Author: Lasse Collin
  * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
- * See ../lzma.h for information about liblzma as a whole.
  */
  */
 
 
 #ifndef LZMA_H_INTERNAL
 #ifndef LZMA_H_INTERNAL
@@ -57,7 +55,7 @@ extern LZMA_API(uint64_t) lzma_physmem(void) lzma_nothrow;
  * If the hardware supports more than one thread per CPU core, the number
  * If the hardware supports more than one thread per CPU core, the number
  * of hardware threads is returned if that information is available.
  * of hardware threads is returned if that information is available.
  *
  *
- * \brief       On success, the number of available CPU threads or cores is
+ * \return      On success, the number of available CPU threads or cores is
  *              returned. If this information isn't available or an error
  *              returned. If this information isn't available or an error
  *              occurs, zero is returned.
  *              occurs, zero is returned.
  */
  */

+ 247 - 51
Utilities/cmliblzma/liblzma/api/lzma/index.h

@@ -1,15 +1,13 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /**
 /**
  * \file        lzma/index.h
  * \file        lzma/index.h
  * \brief       Handling of .xz Index and related information
  * \brief       Handling of .xz Index and related information
+ * \note        Never include this file directly. Use <lzma.h> instead.
  */
  */
 
 
 /*
 /*
  * Author: Lasse Collin
  * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
- * See ../lzma.h for information about liblzma as a whole.
  */
  */
 
 
 #ifndef LZMA_H_INTERNAL
 #ifndef LZMA_H_INTERNAL
@@ -50,8 +48,13 @@ typedef struct {
 		 */
 		 */
 		const lzma_stream_flags *flags;
 		const lzma_stream_flags *flags;
 
 
+		/** \private     Reserved member. */
 		const void *reserved_ptr1;
 		const void *reserved_ptr1;
+
+		/** \private     Reserved member. */
 		const void *reserved_ptr2;
 		const void *reserved_ptr2;
+
+		/** \private     Reserved member. */
 		const void *reserved_ptr3;
 		const void *reserved_ptr3;
 
 
 		/**
 		/**
@@ -107,9 +110,17 @@ typedef struct {
 		 */
 		 */
 		lzma_vli padding;
 		lzma_vli padding;
 
 
+
+		/** \private     Reserved member. */
 		lzma_vli reserved_vli1;
 		lzma_vli reserved_vli1;
+
+		/** \private     Reserved member. */
 		lzma_vli reserved_vli2;
 		lzma_vli reserved_vli2;
+
+		/** \private     Reserved member. */
 		lzma_vli reserved_vli3;
 		lzma_vli reserved_vli3;
+
+		/** \private     Reserved member. */
 		lzma_vli reserved_vli4;
 		lzma_vli reserved_vli4;
 	} stream;
 	} stream;
 
 
@@ -196,25 +207,46 @@ typedef struct {
 		 */
 		 */
 		lzma_vli total_size;
 		lzma_vli total_size;
 
 
+		/** \private     Reserved member. */
 		lzma_vli reserved_vli1;
 		lzma_vli reserved_vli1;
+
+		/** \private     Reserved member. */
 		lzma_vli reserved_vli2;
 		lzma_vli reserved_vli2;
+
+		/** \private     Reserved member. */
 		lzma_vli reserved_vli3;
 		lzma_vli reserved_vli3;
+
+		/** \private     Reserved member. */
 		lzma_vli reserved_vli4;
 		lzma_vli reserved_vli4;
 
 
+		/** \private     Reserved member. */
 		const void *reserved_ptr1;
 		const void *reserved_ptr1;
+
+		/** \private     Reserved member. */
 		const void *reserved_ptr2;
 		const void *reserved_ptr2;
+
+		/** \private     Reserved member. */
 		const void *reserved_ptr3;
 		const void *reserved_ptr3;
+
+		/** \private     Reserved member. */
 		const void *reserved_ptr4;
 		const void *reserved_ptr4;
 	} block;
 	} block;
 
 
-	/*
+	/**
+	 * \private     Internal data
+	 *
 	 * Internal data which is used to store the state of the iterator.
 	 * Internal data which is used to store the state of the iterator.
 	 * The exact format may vary between liblzma versions, so don't
 	 * The exact format may vary between liblzma versions, so don't
 	 * touch these in any way.
 	 * touch these in any way.
 	 */
 	 */
 	union {
 	union {
+		/** \private     Internal member. */
 		const void *p;
 		const void *p;
+
+		/** \private     Internal member. */
 		size_t s;
 		size_t s;
+
+		/** \private     Internal member. */
 		lzma_vli v;
 		lzma_vli v;
 	} internal[6];
 	} internal[6];
 } lzma_index_iter;
 } lzma_index_iter;
@@ -268,20 +300,47 @@ typedef enum {
 } lzma_index_iter_mode;
 } lzma_index_iter_mode;
 
 
 
 
+/**
+ * \brief       Mask for return value from lzma_index_checks() for check none
+ *
+ * \note        This and the other CHECK_MASK macros were added in 5.5.1alpha.
+ */
+#define LZMA_INDEX_CHECK_MASK_NONE (UINT32_C(1) << LZMA_CHECK_NONE)
+
+/**
+ * \brief       Mask for return value from lzma_index_checks() for check CRC32
+ */
+#define LZMA_INDEX_CHECK_MASK_CRC32 (UINT32_C(1) << LZMA_CHECK_CRC32)
+
+/**
+ * \brief       Mask for return value from lzma_index_checks() for check CRC64
+ */
+#define LZMA_INDEX_CHECK_MASK_CRC64 (UINT32_C(1) << LZMA_CHECK_CRC64)
+
+/**
+ * \brief       Mask for return value from lzma_index_checks() for check SHA256
+ */
+#define LZMA_INDEX_CHECK_MASK_SHA256 (UINT32_C(1) << LZMA_CHECK_SHA256)
+
 /**
 /**
  * \brief       Calculate memory usage of lzma_index
  * \brief       Calculate memory usage of lzma_index
  *
  *
  * On disk, the size of the Index field depends on both the number of Records
  * On disk, the size of the Index field depends on both the number of Records
- * stored and how big values the Records store (due to variable-length integer
+ * stored and the size of the Records (due to variable-length integer
  * encoding). When the Index is kept in lzma_index structure, the memory usage
  * encoding). When the Index is kept in lzma_index structure, the memory usage
  * depends only on the number of Records/Blocks stored in the Index(es), and
  * depends only on the number of Records/Blocks stored in the Index(es), and
  * in case of concatenated lzma_indexes, the number of Streams. The size in
  * in case of concatenated lzma_indexes, the number of Streams. The size in
  * RAM is almost always significantly bigger than in the encoded form on disk.
  * RAM is almost always significantly bigger than in the encoded form on disk.
  *
  *
- * This function calculates an approximate amount of memory needed hold
+ * This function calculates an approximate amount of memory needed to hold
  * the given number of Streams and Blocks in lzma_index structure. This
  * the given number of Streams and Blocks in lzma_index structure. This
  * value may vary between CPU architectures and also between liblzma versions
  * value may vary between CPU architectures and also between liblzma versions
  * if the internal implementation is modified.
  * if the internal implementation is modified.
+ *
+ * \param       streams Number of Streams
+ * \param       blocks  Number of Blocks
+ *
+ * \return      Approximate memory in bytes needed in a lzma_index structure.
  */
  */
 extern LZMA_API(uint64_t) lzma_index_memusage(
 extern LZMA_API(uint64_t) lzma_index_memusage(
 		lzma_vli streams, lzma_vli blocks) lzma_nothrow;
 		lzma_vli streams, lzma_vli blocks) lzma_nothrow;
@@ -292,6 +351,10 @@ extern LZMA_API(uint64_t) lzma_index_memusage(
  *
  *
  * This is a shorthand for lzma_index_memusage(lzma_index_stream_count(i),
  * This is a shorthand for lzma_index_memusage(lzma_index_stream_count(i),
  * lzma_index_block_count(i)).
  * lzma_index_block_count(i)).
+ *
+ * \param       i   Pointer to lzma_index structure
+ *
+ * \return      Approximate memory in bytes used by the lzma_index structure.
  */
  */
 extern LZMA_API(uint64_t) lzma_index_memused(const lzma_index *i)
 extern LZMA_API(uint64_t) lzma_index_memused(const lzma_index *i)
 		lzma_nothrow;
 		lzma_nothrow;
@@ -300,6 +363,9 @@ extern LZMA_API(uint64_t) lzma_index_memused(const lzma_index *i)
 /**
 /**
  * \brief       Allocate and initialize a new lzma_index structure
  * \brief       Allocate and initialize a new lzma_index structure
  *
  *
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ *
  * \return      On success, a pointer to an empty initialized lzma_index is
  * \return      On success, a pointer to an empty initialized lzma_index is
  *              returned. If allocation fails, NULL is returned.
  *              returned. If allocation fails, NULL is returned.
  */
  */
@@ -311,6 +377,10 @@ extern LZMA_API(lzma_index *) lzma_index_init(const lzma_allocator *allocator)
  * \brief       Deallocate lzma_index
  * \brief       Deallocate lzma_index
  *
  *
  * If i is NULL, this does nothing.
  * If i is NULL, this does nothing.
+ *
+ * \param       i           Pointer to lzma_index structure to deallocate
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
  */
  */
 extern LZMA_API(void) lzma_index_end(
 extern LZMA_API(void) lzma_index_end(
 		lzma_index *i, const lzma_allocator *allocator) lzma_nothrow;
 		lzma_index *i, const lzma_allocator *allocator) lzma_nothrow;
@@ -320,8 +390,9 @@ extern LZMA_API(void) lzma_index_end(
  * \brief       Add a new Block to lzma_index
  * \brief       Add a new Block to lzma_index
  *
  *
  * \param       i                 Pointer to a lzma_index structure
  * \param       i                 Pointer to a lzma_index structure
- * \param       allocator         Pointer to lzma_allocator, or NULL to
- *                                use malloc()
+ * \param       allocator         lzma_allocator for custom allocator
+ *                                functions. Set to NULL to use malloc()
+ *                                and free().
  * \param       unpadded_size     Unpadded Size of a Block. This can be
  * \param       unpadded_size     Unpadded Size of a Block. This can be
  *                                calculated with lzma_block_unpadded_size()
  *                                calculated with lzma_block_unpadded_size()
  *                                after encoding or decoding the Block.
  *                                after encoding or decoding the Block.
@@ -334,7 +405,8 @@ extern LZMA_API(void) lzma_index_end(
  * lzma_index_append() it is possible to read the next Block with
  * lzma_index_append() it is possible to read the next Block with
  * an existing iterator.
  * an existing iterator.
  *
  *
- * \return      - LZMA_OK
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_DATA_ERROR: Compressed or uncompressed size of the
  *              - LZMA_DATA_ERROR: Compressed or uncompressed size of the
  *                Stream or size of the Index field would grow too big.
  *                Stream or size of the Index field would grow too big.
@@ -354,11 +426,15 @@ extern LZMA_API(lzma_ret) lzma_index_append(
  * lzma_index, because to decode Blocks, knowing the integrity check type
  * lzma_index, because to decode Blocks, knowing the integrity check type
  * is needed.
  * is needed.
  *
  *
- * The given Stream Flags are copied into internal preallocated structure
- * in the lzma_index, thus the caller doesn't need to keep the *stream_flags
- * available after calling this function.
+ * \param       i              Pointer to lzma_index structure
+ * \param       stream_flags   Pointer to lzma_stream_flags structure. This
+ *                             is copied into the internal preallocated
+ *                             structure, so the caller doesn't need to keep
+ *                             the flags' data available after calling this
+ *                             function.
  *
  *
- * \return      - LZMA_OK
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
  *              - LZMA_OPTIONS_ERROR: Unsupported stream_flags->version.
  *              - LZMA_OPTIONS_ERROR: Unsupported stream_flags->version.
  *              - LZMA_PROG_ERROR
  *              - LZMA_PROG_ERROR
  */
  */
@@ -376,6 +452,11 @@ extern LZMA_API(lzma_ret) lzma_index_stream_flags(
  * showing the Check types to the user.
  * showing the Check types to the user.
  *
  *
  * The bitmask is 1 << check_id, e.g. CRC32 is 1 << 1 and SHA-256 is 1 << 10.
  * The bitmask is 1 << check_id, e.g. CRC32 is 1 << 1 and SHA-256 is 1 << 10.
+ * These masks are defined for convenience as LZMA_INDEX_CHECK_MASK_XXX
+ *
+ * \param       i   Pointer to lzma_index structure
+ *
+ * \return      Bitmask indicating which Check types are used in the lzma_index
  */
  */
 extern LZMA_API(uint32_t) lzma_index_checks(const lzma_index *i)
 extern LZMA_API(uint32_t) lzma_index_checks(const lzma_index *i)
 		lzma_nothrow lzma_attr_pure;
 		lzma_nothrow lzma_attr_pure;
@@ -390,7 +471,8 @@ extern LZMA_API(uint32_t) lzma_index_checks(const lzma_index *i)
  *
  *
  * By default, the amount of Stream Padding is assumed to be zero bytes.
  * By default, the amount of Stream Padding is assumed to be zero bytes.
  *
  *
- * \return      - LZMA_OK
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
  *              - LZMA_DATA_ERROR: The file size would grow too big.
  *              - LZMA_DATA_ERROR: The file size would grow too big.
  *              - LZMA_PROG_ERROR
  *              - LZMA_PROG_ERROR
  */
  */
@@ -401,6 +483,10 @@ extern LZMA_API(lzma_ret) lzma_index_stream_padding(
 
 
 /**
 /**
  * \brief       Get the number of Streams
  * \brief       Get the number of Streams
+ *
+ * \param       i   Pointer to lzma_index structure
+ *
+ * \return      Number of Streams in the lzma_index
  */
  */
 extern LZMA_API(lzma_vli) lzma_index_stream_count(const lzma_index *i)
 extern LZMA_API(lzma_vli) lzma_index_stream_count(const lzma_index *i)
 		lzma_nothrow lzma_attr_pure;
 		lzma_nothrow lzma_attr_pure;
@@ -411,6 +497,10 @@ extern LZMA_API(lzma_vli) lzma_index_stream_count(const lzma_index *i)
  *
  *
  * This returns the total number of Blocks in lzma_index. To get number
  * This returns the total number of Blocks in lzma_index. To get number
  * of Blocks in individual Streams, use lzma_index_iter.
  * of Blocks in individual Streams, use lzma_index_iter.
+ *
+ * \param       i   Pointer to lzma_index structure
+ *
+ * \return      Number of blocks in the lzma_index
  */
  */
 extern LZMA_API(lzma_vli) lzma_index_block_count(const lzma_index *i)
 extern LZMA_API(lzma_vli) lzma_index_block_count(const lzma_index *i)
 		lzma_nothrow lzma_attr_pure;
 		lzma_nothrow lzma_attr_pure;
@@ -420,6 +510,10 @@ extern LZMA_API(lzma_vli) lzma_index_block_count(const lzma_index *i)
  * \brief       Get the size of the Index field as bytes
  * \brief       Get the size of the Index field as bytes
  *
  *
  * This is needed to verify the Backward Size field in the Stream Footer.
  * This is needed to verify the Backward Size field in the Stream Footer.
+ *
+ * \param       i   Pointer to lzma_index structure
+ *
+ * \return      Size in bytes of the Index
  */
  */
 extern LZMA_API(lzma_vli) lzma_index_size(const lzma_index *i)
 extern LZMA_API(lzma_vli) lzma_index_size(const lzma_index *i)
 		lzma_nothrow lzma_attr_pure;
 		lzma_nothrow lzma_attr_pure;
@@ -431,6 +525,11 @@ extern LZMA_API(lzma_vli) lzma_index_size(const lzma_index *i)
  * If multiple lzma_indexes have been combined, this works as if the Blocks
  * If multiple lzma_indexes have been combined, this works as if the Blocks
  * were in a single Stream. This is useful if you are going to combine
  * were in a single Stream. This is useful if you are going to combine
  * Blocks from multiple Streams into a single new Stream.
  * Blocks from multiple Streams into a single new Stream.
+ *
+ * \param       i   Pointer to lzma_index structure
+ *
+ * \return      Size in bytes of the Stream (if all Blocks are combined
+ *              into one Stream).
  */
  */
 extern LZMA_API(lzma_vli) lzma_index_stream_size(const lzma_index *i)
 extern LZMA_API(lzma_vli) lzma_index_stream_size(const lzma_index *i)
 		lzma_nothrow lzma_attr_pure;
 		lzma_nothrow lzma_attr_pure;
@@ -441,6 +540,10 @@ extern LZMA_API(lzma_vli) lzma_index_stream_size(const lzma_index *i)
  *
  *
  * This doesn't include the Stream Header, Stream Footer, Stream Padding,
  * This doesn't include the Stream Header, Stream Footer, Stream Padding,
  * or Index fields.
  * or Index fields.
+ *
+ * \param       i   Pointer to lzma_index structure
+ *
+ * \return      Size in bytes of all Blocks in the Stream(s)
  */
  */
 extern LZMA_API(lzma_vli) lzma_index_total_size(const lzma_index *i)
 extern LZMA_API(lzma_vli) lzma_index_total_size(const lzma_index *i)
 		lzma_nothrow lzma_attr_pure;
 		lzma_nothrow lzma_attr_pure;
@@ -453,6 +556,10 @@ extern LZMA_API(lzma_vli) lzma_index_total_size(const lzma_index *i)
  * no Stream Padding, this function is identical to lzma_index_stream_size().
  * no Stream Padding, this function is identical to lzma_index_stream_size().
  * If multiple lzma_indexes have been combined, this includes also the headers
  * If multiple lzma_indexes have been combined, this includes also the headers
  * of each separate Stream and the possible Stream Padding fields.
  * of each separate Stream and the possible Stream Padding fields.
+ *
+ * \param       i   Pointer to lzma_index structure
+ *
+ * \return      Total size of the .xz file in bytes
  */
  */
 extern LZMA_API(lzma_vli) lzma_index_file_size(const lzma_index *i)
 extern LZMA_API(lzma_vli) lzma_index_file_size(const lzma_index *i)
 		lzma_nothrow lzma_attr_pure;
 		lzma_nothrow lzma_attr_pure;
@@ -460,6 +567,10 @@ extern LZMA_API(lzma_vli) lzma_index_file_size(const lzma_index *i)
 
 
 /**
 /**
  * \brief       Get the uncompressed size of the file
  * \brief       Get the uncompressed size of the file
+ *
+ * \param       i   Pointer to lzma_index structure
+ *
+ * \return      Size in bytes of the uncompressed data in the file
  */
  */
 extern LZMA_API(lzma_vli) lzma_index_uncompressed_size(const lzma_index *i)
 extern LZMA_API(lzma_vli) lzma_index_uncompressed_size(const lzma_index *i)
 		lzma_nothrow lzma_attr_pure;
 		lzma_nothrow lzma_attr_pure;
@@ -468,9 +579,6 @@ extern LZMA_API(lzma_vli) lzma_index_uncompressed_size(const lzma_index *i)
 /**
 /**
  * \brief       Initialize an iterator
  * \brief       Initialize an iterator
  *
  *
- * \param       iter    Pointer to a lzma_index_iter structure
- * \param       i       lzma_index to which the iterator will be associated
- *
  * This function associates the iterator with the given lzma_index, and calls
  * This function associates the iterator with the given lzma_index, and calls
  * lzma_index_iter_rewind() on the iterator.
  * lzma_index_iter_rewind() on the iterator.
  *
  *
@@ -483,6 +591,9 @@ extern LZMA_API(lzma_vli) lzma_index_uncompressed_size(const lzma_index *i)
  *
  *
  * It is safe to make copies of an initialized lzma_index_iter, for example,
  * It is safe to make copies of an initialized lzma_index_iter, for example,
  * to easily restart reading at some particular position.
  * to easily restart reading at some particular position.
+ *
+ * \param       iter    Pointer to a lzma_index_iter structure
+ * \param       i       lzma_index to which the iterator will be associated
  */
  */
 extern LZMA_API(void) lzma_index_iter_init(
 extern LZMA_API(void) lzma_index_iter_init(
 		lzma_index_iter *iter, const lzma_index *i) lzma_nothrow;
 		lzma_index_iter *iter, const lzma_index *i) lzma_nothrow;
@@ -493,6 +604,8 @@ extern LZMA_API(void) lzma_index_iter_init(
  *
  *
  * Rewind the iterator so that next call to lzma_index_iter_next() will
  * Rewind the iterator so that next call to lzma_index_iter_next() will
  * return the first Block or Stream.
  * return the first Block or Stream.
+ *
+ * \param       iter    Pointer to a lzma_index_iter structure
  */
  */
 extern LZMA_API(void) lzma_index_iter_rewind(lzma_index_iter *iter)
 extern LZMA_API(void) lzma_index_iter_rewind(lzma_index_iter *iter)
 		lzma_nothrow;
 		lzma_nothrow;
@@ -505,11 +618,11 @@ extern LZMA_API(void) lzma_index_iter_rewind(lzma_index_iter *iter)
  * \param       mode    Specify what kind of information the caller wants
  * \param       mode    Specify what kind of information the caller wants
  *                      to get. See lzma_index_iter_mode for details.
  *                      to get. See lzma_index_iter_mode for details.
  *
  *
- * \return      If next Block or Stream matching the mode was found, *iter
- *              is updated and this function returns false. If no Block or
- *              Stream matching the mode is found, *iter is not modified
- *              and this function returns true. If mode is set to an unknown
- *              value, *iter is not modified and this function returns true.
+ * \return      lzma_bool:
+ *              - true if no Block or Stream matching the mode is found.
+ *                *iter is not updated (failure).
+ *              - false if the next Block or Stream matching the mode was
+ *                found. *iter is updated (success).
  */
  */
 extern LZMA_API(lzma_bool) lzma_index_iter_next(
 extern LZMA_API(lzma_bool) lzma_index_iter_next(
 		lzma_index_iter *iter, lzma_index_iter_mode mode)
 		lzma_index_iter *iter, lzma_index_iter_mode mode)
@@ -523,21 +636,26 @@ extern LZMA_API(lzma_bool) lzma_index_iter_next(
  * the Index field(s) and use lzma_index_iter_locate() to do random-access
  * the Index field(s) and use lzma_index_iter_locate() to do random-access
  * reading with granularity of Block size.
  * reading with granularity of Block size.
  *
  *
- * \param       iter    Iterator that was earlier initialized with
- *                      lzma_index_iter_init().
- * \param       target  Uncompressed target offset which the caller would
- *                      like to locate from the Stream
- *
  * If the target is smaller than the uncompressed size of the Stream (can be
  * If the target is smaller than the uncompressed size of the Stream (can be
  * checked with lzma_index_uncompressed_size()):
  * checked with lzma_index_uncompressed_size()):
  *  - Information about the Stream and Block containing the requested
  *  - Information about the Stream and Block containing the requested
  *    uncompressed offset is stored into *iter.
  *    uncompressed offset is stored into *iter.
  *  - Internal state of the iterator is adjusted so that
  *  - Internal state of the iterator is adjusted so that
  *    lzma_index_iter_next() can be used to read subsequent Blocks or Streams.
  *    lzma_index_iter_next() can be used to read subsequent Blocks or Streams.
- *  - This function returns false.
  *
  *
- * If target is greater than the uncompressed size of the Stream, *iter
- * is not modified, and this function returns true.
+ * If the target is greater than the uncompressed size of the Stream, *iter
+ * is not modified.
+ *
+ * \param       iter    Iterator that was earlier initialized with
+ *                      lzma_index_iter_init().
+ * \param       target  Uncompressed target offset which the caller would
+ *                      like to locate from the Stream
+ *
+ * \return      lzma_bool:
+ *              - true if the target is greater than or equal to the
+ *                uncompressed size of the Stream (failure)
+ *              - false if the target is smaller than the uncompressed size
+ *                of the Stream (success)
  */
  */
 extern LZMA_API(lzma_bool) lzma_index_iter_locate(
 extern LZMA_API(lzma_bool) lzma_index_iter_locate(
 		lzma_index_iter *iter, lzma_vli target) lzma_nothrow;
 		lzma_index_iter *iter, lzma_vli target) lzma_nothrow;
@@ -550,15 +668,16 @@ extern LZMA_API(lzma_bool) lzma_index_iter_locate(
  * multi-Stream .xz file, or when combining multiple Streams into single
  * multi-Stream .xz file, or when combining multiple Streams into single
  * Stream.
  * Stream.
  *
  *
- * \param       dest      lzma_index after which src is appended
+ * \param[out]  dest      lzma_index after which src is appended
  * \param       src       lzma_index to be appended after dest. If this
  * \param       src       lzma_index to be appended after dest. If this
  *                        function succeeds, the memory allocated for src
  *                        function succeeds, the memory allocated for src
  *                        is freed or moved to be part of dest, and all
  *                        is freed or moved to be part of dest, and all
  *                        iterators pointing to src will become invalid.
  *                        iterators pointing to src will become invalid.
- * \param       allocator Custom memory allocator; can be NULL to use
- *                        malloc() and free().
+ * \param       allocator lzma_allocator for custom allocator functions.
+ *                        Set to NULL to use malloc() and free().
  *
  *
- * \return      - LZMA_OK: lzma_indexes were concatenated successfully.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: lzma_indexes were concatenated successfully.
  *                src is now a dangling pointer.
  *                src is now a dangling pointer.
  *              - LZMA_DATA_ERROR: *dest would grow too big.
  *              - LZMA_DATA_ERROR: *dest would grow too big.
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
@@ -572,6 +691,10 @@ extern LZMA_API(lzma_ret) lzma_index_cat(lzma_index *dest, lzma_index *src,
 /**
 /**
  * \brief       Duplicate lzma_index
  * \brief       Duplicate lzma_index
  *
  *
+ * \param       i         Pointer to lzma_index structure to be duplicated
+ * \param       allocator lzma_allocator for custom allocator functions.
+ *                        Set to NULL to use malloc() and free().
+ *
  * \return      A copy of the lzma_index, or NULL if memory allocation failed.
  * \return      A copy of the lzma_index, or NULL if memory allocation failed.
  */
  */
 extern LZMA_API(lzma_index *) lzma_index_dup(
 extern LZMA_API(lzma_index *) lzma_index_dup(
@@ -585,10 +708,11 @@ extern LZMA_API(lzma_index *) lzma_index_dup(
  * \param       strm        Pointer to properly prepared lzma_stream
  * \param       strm        Pointer to properly prepared lzma_stream
  * \param       i           Pointer to lzma_index which should be encoded.
  * \param       i           Pointer to lzma_index which should be encoded.
  *
  *
- * The valid `action' values for lzma_code() are LZMA_RUN and LZMA_FINISH.
+ * The valid 'action' values for lzma_code() are LZMA_RUN and LZMA_FINISH.
  * It is enough to use only one of them (you can choose freely).
  * It is enough to use only one of them (you can choose freely).
  *
  *
- * \return      - LZMA_OK: Initialization succeeded, continue with lzma_code().
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Initialization succeeded, continue with lzma_code().
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_PROG_ERROR
  *              - LZMA_PROG_ERROR
  */
  */
@@ -601,7 +725,7 @@ extern LZMA_API(lzma_ret) lzma_index_encoder(
  * \brief       Initialize .xz Index decoder
  * \brief       Initialize .xz Index decoder
  *
  *
  * \param       strm        Pointer to properly prepared lzma_stream
  * \param       strm        Pointer to properly prepared lzma_stream
- * \param       i           The decoded Index will be made available via
+ * \param[out]  i           The decoded Index will be made available via
  *                          this pointer. Initially this function will
  *                          this pointer. Initially this function will
  *                          set *i to NULL (the old value is ignored). If
  *                          set *i to NULL (the old value is ignored). If
  *                          decoding succeeds (lzma_code() returns
  *                          decoding succeeds (lzma_code() returns
@@ -613,15 +737,16 @@ extern LZMA_API(lzma_ret) lzma_index_encoder(
  *                          don't allow 0 here and return LZMA_PROG_ERROR;
  *                          don't allow 0 here and return LZMA_PROG_ERROR;
  *                          later versions treat 0 as if 1 had been specified.
  *                          later versions treat 0 as if 1 had been specified.
  *
  *
- * Valid `action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH.
+ * Valid 'action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH.
  * There is no need to use LZMA_FINISH, but it's allowed because it may
  * There is no need to use LZMA_FINISH, but it's allowed because it may
  * simplify certain types of applications.
  * simplify certain types of applications.
  *
  *
- * \return      - LZMA_OK: Initialization succeeded, continue with lzma_code().
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Initialization succeeded, continue with lzma_code().
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_PROG_ERROR
  *              - LZMA_PROG_ERROR
  *
  *
- *              liblzma 5.2.3 and older list also LZMA_MEMLIMIT_ERROR here
+ * \note        liblzma 5.2.3 and older list also LZMA_MEMLIMIT_ERROR here
  *              but that error code has never been possible from this
  *              but that error code has never been possible from this
  *              initialization function.
  *              initialization function.
  */
  */
@@ -633,21 +758,23 @@ extern LZMA_API(lzma_ret) lzma_index_decoder(
 /**
 /**
  * \brief       Single-call .xz Index encoder
  * \brief       Single-call .xz Index encoder
  *
  *
+ * \note        This function doesn't take allocator argument since all
+ *              the internal data is allocated on stack.
+ *
  * \param       i         lzma_index to be encoded
  * \param       i         lzma_index to be encoded
- * \param       out       Beginning of the output buffer
- * \param       out_pos   The next byte will be written to out[*out_pos].
+ * \param[out]  out       Beginning of the output buffer
+ * \param[out]  out_pos   The next byte will be written to out[*out_pos].
  *                        *out_pos is updated only if encoding succeeds.
  *                        *out_pos is updated only if encoding succeeds.
  * \param       out_size  Size of the out buffer; the first byte into
  * \param       out_size  Size of the out buffer; the first byte into
  *                        which no data is written to is out[out_size].
  *                        which no data is written to is out[out_size].
  *
  *
- * \return      - LZMA_OK: Encoding was successful.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Encoding was successful.
  *              - LZMA_BUF_ERROR: Output buffer is too small. Use
  *              - LZMA_BUF_ERROR: Output buffer is too small. Use
  *                lzma_index_size() to find out how much output
  *                lzma_index_size() to find out how much output
  *                space is needed.
  *                space is needed.
  *              - LZMA_PROG_ERROR
  *              - LZMA_PROG_ERROR
  *
  *
- * \note        This function doesn't take allocator argument since all
- *              the internal data is allocated on stack.
  */
  */
 extern LZMA_API(lzma_ret) lzma_index_buffer_encode(const lzma_index *i,
 extern LZMA_API(lzma_ret) lzma_index_buffer_encode(const lzma_index *i,
 		uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
 		uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
@@ -656,24 +783,26 @@ extern LZMA_API(lzma_ret) lzma_index_buffer_encode(const lzma_index *i,
 /**
 /**
  * \brief       Single-call .xz Index decoder
  * \brief       Single-call .xz Index decoder
  *
  *
- * \param       i           If decoding succeeds, *i will point to a new
+ * \param[out]  i           If decoding succeeds, *i will point to a new
  *                          lzma_index, which the application has to
  *                          lzma_index, which the application has to
  *                          later free with lzma_index_end(). If an error
  *                          later free with lzma_index_end(). If an error
  *                          occurs, *i will be NULL. The old value of *i
  *                          occurs, *i will be NULL. The old value of *i
  *                          is always ignored and thus doesn't need to be
  *                          is always ignored and thus doesn't need to be
  *                          initialized by the caller.
  *                          initialized by the caller.
- * \param       memlimit    Pointer to how much memory the resulting
+ * \param[out]  memlimit    Pointer to how much memory the resulting
  *                          lzma_index is allowed to require. The value
  *                          lzma_index is allowed to require. The value
  *                          pointed by this pointer is modified if and only
  *                          pointed by this pointer is modified if and only
  *                          if LZMA_MEMLIMIT_ERROR is returned.
  *                          if LZMA_MEMLIMIT_ERROR is returned.
- * \param       allocator   Pointer to lzma_allocator, or NULL to use malloc()
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
  * \param       in          Beginning of the input buffer
  * \param       in          Beginning of the input buffer
  * \param       in_pos      The next byte will be read from in[*in_pos].
  * \param       in_pos      The next byte will be read from in[*in_pos].
  *                          *in_pos is updated only if decoding succeeds.
  *                          *in_pos is updated only if decoding succeeds.
  * \param       in_size     Size of the input buffer; the first byte that
  * \param       in_size     Size of the input buffer; the first byte that
  *                          won't be read is in[in_size].
  *                          won't be read is in[in_size].
  *
  *
- * \return      - LZMA_OK: Decoding was successful.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Decoding was successful.
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEM_ERROR
  *              - LZMA_MEMLIMIT_ERROR: Memory usage limit was reached.
  *              - LZMA_MEMLIMIT_ERROR: Memory usage limit was reached.
  *                The minimum required memlimit value was stored to *memlimit.
  *                The minimum required memlimit value was stored to *memlimit.
@@ -684,3 +813,70 @@ extern LZMA_API(lzma_ret) lzma_index_buffer_decode(lzma_index **i,
 		uint64_t *memlimit, const lzma_allocator *allocator,
 		uint64_t *memlimit, const lzma_allocator *allocator,
 		const uint8_t *in, size_t *in_pos, size_t in_size)
 		const uint8_t *in, size_t *in_pos, size_t in_size)
 		lzma_nothrow;
 		lzma_nothrow;
+
+
+/**
+ * \brief       Initialize a .xz file information decoder
+ *
+ * This decoder decodes the Stream Header, Stream Footer, Index, and
+ * Stream Padding field(s) from the input .xz file and stores the resulting
+ * combined index in *dest_index. This information can be used to get the
+ * uncompressed file size with lzma_index_uncompressed_size(*dest_index) or,
+ * for example, to implement random access reading by locating the Blocks
+ * in the Streams.
+ *
+ * To get the required information from the .xz file, lzma_code() may ask
+ * the application to seek in the input file by returning LZMA_SEEK_NEEDED
+ * and having the target file position specified in lzma_stream.seek_pos.
+ * The number of seeks required depends on the input file and how big buffers
+ * the application provides. When possible, the decoder will seek backward
+ * and forward in the given buffer to avoid useless seek requests. Thus, if
+ * the application provides the whole file at once, no external seeking will
+ * be required (that is, lzma_code() won't return LZMA_SEEK_NEEDED).
+ *
+ * The value in lzma_stream.total_in can be used to estimate how much data
+ * liblzma had to read to get the file information. However, due to seeking
+ * and the way total_in is updated, the value of total_in will be somewhat
+ * inaccurate (a little too big). Thus, total_in is a good estimate but don't
+ * expect to see the same exact value for the same file if you change the
+ * input buffer size or switch to a different liblzma version.
+ *
+ * Valid 'action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH.
+ * You only need to use LZMA_RUN; LZMA_FINISH is only supported because it
+ * might be convenient for some applications. If you use LZMA_FINISH and if
+ * lzma_code() asks the application to seek, remember to reset 'action' back
+ * to LZMA_RUN unless you hit the end of the file again.
+ *
+ * Possible return values from lzma_code():
+ *   - LZMA_OK: All OK so far, more input needed
+ *   - LZMA_SEEK_NEEDED: Provide more input starting from the absolute
+ *     file position strm->seek_pos
+ *   - LZMA_STREAM_END: Decoding was successful, *dest_index has been set
+ *   - LZMA_FORMAT_ERROR: The input file is not in the .xz format (the
+ *     expected magic bytes were not found from the beginning of the file)
+ *   - LZMA_OPTIONS_ERROR: File looks valid but contains headers that aren't
+ *     supported by this version of liblzma
+ *   - LZMA_DATA_ERROR: File is corrupt
+ *   - LZMA_BUF_ERROR
+ *   - LZMA_MEM_ERROR
+ *   - LZMA_MEMLIMIT_ERROR
+ *   - LZMA_PROG_ERROR
+ *
+ * \param       strm        Pointer to a properly prepared lzma_stream
+ * \param[out]  dest_index  Pointer to a pointer where the decoder will put
+ *                          the decoded lzma_index. The old value
+ *                          of *dest_index is ignored (not freed).
+ * \param       memlimit    How much memory the resulting lzma_index is
+ *                          allowed to require. Use UINT64_MAX to
+ *                          effectively disable the limiter.
+ * \param       file_size   Size of the input .xz file
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_file_info_decoder(
+		lzma_stream *strm, lzma_index **dest_index,
+		uint64_t memlimit, uint64_t file_size)
+		lzma_nothrow;

+ 31 - 15
Utilities/cmliblzma/liblzma/api/lzma/index_hash.h

@@ -1,6 +1,9 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /**
 /**
  * \file        lzma/index_hash.h
  * \file        lzma/index_hash.h
  * \brief       Validate Index by using a hash function
  * \brief       Validate Index by using a hash function
+ * \note        Never include this file directly. Use <lzma.h> instead.
  *
  *
  * Hashing makes it possible to use constant amount of memory to validate
  * Hashing makes it possible to use constant amount of memory to validate
  * Index of arbitrary size.
  * Index of arbitrary size.
@@ -8,11 +11,6 @@
 
 
 /*
 /*
  * Author: Lasse Collin
  * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
- * See ../lzma.h for information about liblzma as a whole.
  */
  */
 
 
 #ifndef LZMA_H_INTERNAL
 #ifndef LZMA_H_INTERNAL
@@ -28,13 +26,21 @@ typedef struct lzma_index_hash_s lzma_index_hash;
 /**
 /**
  * \brief       Allocate and initialize a new lzma_index_hash structure
  * \brief       Allocate and initialize a new lzma_index_hash structure
  *
  *
- * If index_hash is NULL, a new lzma_index_hash structure is allocated,
- * initialized, and a pointer to it returned. If allocation fails, NULL
- * is returned.
+ * If index_hash is NULL, this function allocates and initializes a new
+ * lzma_index_hash structure and returns a pointer to it. If allocation
+ * fails, NULL is returned.
+ *
+ * If index_hash is non-NULL, this function reinitializes the lzma_index_hash
+ * structure and returns the same pointer. In this case, return value cannot
+ * be NULL or a different pointer than the index_hash that was given as
+ * an argument.
+ *
+ * \param       index_hash  Pointer to a lzma_index_hash structure or NULL.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
  *
  *
- * If index_hash is non-NULL, it is reinitialized and the same pointer
- * returned. In this case, return value cannot be NULL or a different
- * pointer than the index_hash that was given as an argument.
+ * \return      Initialized lzma_index_hash structure on success or
+ *              NULL on failure.
  */
  */
 extern LZMA_API(lzma_index_hash *) lzma_index_hash_init(
 extern LZMA_API(lzma_index_hash *) lzma_index_hash_init(
 		lzma_index_hash *index_hash, const lzma_allocator *allocator)
 		lzma_index_hash *index_hash, const lzma_allocator *allocator)
@@ -43,6 +49,10 @@ extern LZMA_API(lzma_index_hash *) lzma_index_hash_init(
 
 
 /**
 /**
  * \brief       Deallocate lzma_index_hash structure
  * \brief       Deallocate lzma_index_hash structure
+ *
+ * \param       index_hash  Pointer to a lzma_index_hash structure to free.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
  */
  */
 extern LZMA_API(void) lzma_index_hash_end(
 extern LZMA_API(void) lzma_index_hash_end(
 		lzma_index_hash *index_hash, const lzma_allocator *allocator)
 		lzma_index_hash *index_hash, const lzma_allocator *allocator)
@@ -52,11 +62,12 @@ extern LZMA_API(void) lzma_index_hash_end(
 /**
 /**
  * \brief       Add a new Record to an Index hash
  * \brief       Add a new Record to an Index hash
  *
  *
- * \param       index             Pointer to a lzma_index_hash structure
+ * \param       index_hash        Pointer to a lzma_index_hash structure
  * \param       unpadded_size     Unpadded Size of a Block
  * \param       unpadded_size     Unpadded Size of a Block
  * \param       uncompressed_size Uncompressed Size of a Block
  * \param       uncompressed_size Uncompressed Size of a Block
  *
  *
- * \return      - LZMA_OK
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK
  *              - LZMA_DATA_ERROR: Compressed or uncompressed size of the
  *              - LZMA_DATA_ERROR: Compressed or uncompressed size of the
  *                Stream or size of the Index field would grow too big.
  *                Stream or size of the Index field would grow too big.
  *              - LZMA_PROG_ERROR: Invalid arguments or this function is being
  *              - LZMA_PROG_ERROR: Invalid arguments or this function is being
@@ -81,10 +92,11 @@ extern LZMA_API(lzma_ret) lzma_index_hash_append(lzma_index_hash *index_hash,
  *
  *
  * \param       index_hash      Pointer to a lzma_index_hash structure
  * \param       index_hash      Pointer to a lzma_index_hash structure
  * \param       in              Pointer to the beginning of the input buffer
  * \param       in              Pointer to the beginning of the input buffer
- * \param       in_pos          in[*in_pos] is the next byte to process
+ * \param[out]  in_pos          in[*in_pos] is the next byte to process
  * \param       in_size         in[in_size] is the first byte not to process
  * \param       in_size         in[in_size] is the first byte not to process
  *
  *
- * \return      - LZMA_OK: So far good, but more input is needed.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: So far good, but more input is needed.
  *              - LZMA_STREAM_END: Index decoded successfully and it matches
  *              - LZMA_STREAM_END: Index decoded successfully and it matches
  *                the Records given with lzma_index_hash_append().
  *                the Records given with lzma_index_hash_append().
  *              - LZMA_DATA_ERROR: Index is corrupt or doesn't match the
  *              - LZMA_DATA_ERROR: Index is corrupt or doesn't match the
@@ -101,6 +113,10 @@ extern LZMA_API(lzma_ret) lzma_index_hash_decode(lzma_index_hash *index_hash,
  * \brief       Get the size of the Index field as bytes
  * \brief       Get the size of the Index field as bytes
  *
  *
  * This is needed to verify the Backward Size field in the Stream Footer.
  * This is needed to verify the Backward Size field in the Stream Footer.
+ *
+ * \param       index_hash      Pointer to a lzma_index_hash structure
+ *
+ * \return      Size of the Index field in bytes.
  */
  */
 extern LZMA_API(lzma_vli) lzma_index_hash_size(
 extern LZMA_API(lzma_vli) lzma_index_hash_size(
 		const lzma_index_hash *index_hash)
 		const lzma_index_hash *index_hash)

+ 172 - 24
Utilities/cmliblzma/liblzma/api/lzma/lzma12.h

@@ -1,15 +1,13 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /**
 /**
  * \file        lzma/lzma12.h
  * \file        lzma/lzma12.h
  * \brief       LZMA1 and LZMA2 filters
  * \brief       LZMA1 and LZMA2 filters
+ * \note        Never include this file directly. Use <lzma.h> instead.
  */
  */
 
 
 /*
 /*
  * Author: Lasse Collin
  * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
- * See ../lzma.h for information about liblzma as a whole.
  */
  */
 
 
 #ifndef LZMA_H_INTERNAL
 #ifndef LZMA_H_INTERNAL
@@ -18,23 +16,46 @@
 
 
 
 
 /**
 /**
- * \brief       LZMA1 Filter ID
+ * \brief       LZMA1 Filter ID (for raw encoder/decoder only, not in .xz)
  *
  *
  * LZMA1 is the very same thing as what was called just LZMA in LZMA Utils,
  * LZMA1 is the very same thing as what was called just LZMA in LZMA Utils,
  * 7-Zip, and LZMA SDK. It's called LZMA1 here to prevent developers from
  * 7-Zip, and LZMA SDK. It's called LZMA1 here to prevent developers from
  * accidentally using LZMA when they actually want LZMA2.
  * accidentally using LZMA when they actually want LZMA2.
- *
- * LZMA1 shouldn't be used for new applications unless you _really_ know
- * what you are doing. LZMA2 is almost always a better choice.
  */
  */
 #define LZMA_FILTER_LZMA1       LZMA_VLI_C(0x4000000000000001)
 #define LZMA_FILTER_LZMA1       LZMA_VLI_C(0x4000000000000001)
 
 
+/**
+ * \brief       LZMA1 Filter ID with extended options (for raw encoder/decoder)
+ *
+ * This is like LZMA_FILTER_LZMA1 but with this ID a few extra options
+ * are supported in the lzma_options_lzma structure:
+ *
+ *   - A flag to tell the encoder if the end of payload marker (EOPM) alias
+ *     end of stream (EOS) marker must be written at the end of the stream.
+ *     In contrast, LZMA_FILTER_LZMA1 always writes the end marker.
+ *
+ *   - Decoder needs to be told the uncompressed size of the stream
+ *     or that it is unknown (using the special value UINT64_MAX).
+ *     If the size is known, a flag can be set to allow the presence of
+ *     the end marker anyway. In contrast, LZMA_FILTER_LZMA1 always
+ *     behaves as if the uncompressed size was unknown.
+ *
+ * This allows handling file formats where LZMA1 streams are used but where
+ * the end marker isn't allowed or where it might not (always) be present.
+ * This extended LZMA1 functionality is provided as a Filter ID for raw
+ * encoder and decoder instead of adding new encoder and decoder initialization
+ * functions because this way it is possible to also use extra filters,
+ * for example, LZMA_FILTER_X86 in a filter chain with LZMA_FILTER_LZMA1EXT,
+ * which might be needed to handle some file formats.
+ */
+#define LZMA_FILTER_LZMA1EXT    LZMA_VLI_C(0x4000000000000002)
+
 /**
 /**
  * \brief       LZMA2 Filter ID
  * \brief       LZMA2 Filter ID
  *
  *
  * Usually you want this instead of LZMA1. Compared to LZMA1, LZMA2 adds
  * Usually you want this instead of LZMA1. Compared to LZMA1, LZMA2 adds
  * support for LZMA_SYNC_FLUSH, uncompressed chunks (smaller expansion
  * support for LZMA_SYNC_FLUSH, uncompressed chunks (smaller expansion
- * when trying to compress uncompressible data), possibility to change
+ * when trying to compress incompressible data), possibility to change
  * lc/lp/pb in the middle of encoding, and some other internal improvements.
  * lc/lp/pb in the middle of encoding, and some other internal improvements.
  */
  */
 #define LZMA_FILTER_LZMA2       LZMA_VLI_C(0x21)
 #define LZMA_FILTER_LZMA2       LZMA_VLI_C(0x21)
@@ -114,16 +135,20 @@ typedef enum {
 /**
 /**
  * \brief       Test if given match finder is supported
  * \brief       Test if given match finder is supported
  *
  *
- * Return true if the given match finder is supported by this liblzma build.
- * Otherwise false is returned. It is safe to call this with a value that
- * isn't listed in lzma_match_finder enumeration; the return value will be
- * false.
+ * It is safe to call this with a value that isn't listed in
+ * lzma_match_finder enumeration; the return value will be false.
  *
  *
  * There is no way to list which match finders are available in this
  * There is no way to list which match finders are available in this
  * particular liblzma version and build. It would be useless, because
  * particular liblzma version and build. It would be useless, because
  * a new match finder, which the application developer wasn't aware,
  * a new match finder, which the application developer wasn't aware,
  * could require giving additional options to the encoder that the older
  * could require giving additional options to the encoder that the older
  * match finders don't need.
  * match finders don't need.
+ *
+ * \param       match_finder    Match finder ID
+ *
+ * \return      lzma_bool:
+ *              - true if the match finder is supported by this liblzma build.
+ *              - false otherwise.
  */
  */
 extern LZMA_API(lzma_bool) lzma_mf_is_supported(lzma_match_finder match_finder)
 extern LZMA_API(lzma_bool) lzma_mf_is_supported(lzma_match_finder match_finder)
 		lzma_nothrow lzma_attr_const;
 		lzma_nothrow lzma_attr_const;
@@ -158,14 +183,20 @@ typedef enum {
 /**
 /**
  * \brief       Test if given compression mode is supported
  * \brief       Test if given compression mode is supported
  *
  *
- * Return true if the given compression mode is supported by this liblzma
- * build. Otherwise false is returned. It is safe to call this with a value
- * that isn't listed in lzma_mode enumeration; the return value will be false.
+ * It is safe to call this with a value that isn't listed in lzma_mode
+ * enumeration; the return value will be false.
  *
  *
  * There is no way to list which modes are available in this particular
  * There is no way to list which modes are available in this particular
  * liblzma version and build. It would be useless, because a new compression
  * liblzma version and build. It would be useless, because a new compression
  * mode, which the application developer wasn't aware, could require giving
  * mode, which the application developer wasn't aware, could require giving
  * additional options to the encoder that the older modes don't need.
  * additional options to the encoder that the older modes don't need.
+ *
+ * \param       mode    Mode ID.
+ *
+ * \return      lzma_bool:
+ *              - true if the compression mode is supported by this liblzma
+ *                build.
+ *              - false otherwise.
  */
  */
 extern LZMA_API(lzma_bool) lzma_mode_is_supported(lzma_mode mode)
 extern LZMA_API(lzma_bool) lzma_mode_is_supported(lzma_mode mode)
 		lzma_nothrow lzma_attr_const;
 		lzma_nothrow lzma_attr_const;
@@ -257,7 +288,7 @@ typedef struct {
 	 * \brief       Number of literal context bits
 	 * \brief       Number of literal context bits
 	 *
 	 *
 	 * How many of the highest bits of the previous uncompressed
 	 * How many of the highest bits of the previous uncompressed
-	 * eight-bit byte (also known as `literal') are taken into
+	 * eight-bit byte (also known as 'literal') are taken into
 	 * account when predicting the bits of the next literal.
 	 * account when predicting the bits of the next literal.
 	 *
 	 *
 	 * E.g. in typical English text, an upper-case letter is
 	 * E.g. in typical English text, an upper-case letter is
@@ -374,6 +405,82 @@ typedef struct {
 	 */
 	 */
 	uint32_t depth;
 	uint32_t depth;
 
 
+	/**
+	 * \brief       For LZMA_FILTER_LZMA1EXT: Extended flags
+	 *
+	 * This is used only with LZMA_FILTER_LZMA1EXT.
+	 *
+	 * Currently only one flag is supported, LZMA_LZMA1EXT_ALLOW_EOPM:
+	 *
+	 *   - Encoder: If the flag is set, then end marker is written just
+	 *     like it is with LZMA_FILTER_LZMA1. Without this flag the
+	 *     end marker isn't written and the application has to store
+	 *     the uncompressed size somewhere outside the compressed stream.
+	 *     To decompress streams without the end marker, the application
+	 *     has to set the correct uncompressed size in ext_size_low and
+	 *     ext_size_high.
+	 *
+	 *   - Decoder: If the uncompressed size in ext_size_low and
+	 *     ext_size_high is set to the special value UINT64_MAX
+	 *     (indicating unknown uncompressed size) then this flag is
+	 *     ignored and the end marker must always be present, that is,
+	 *     the behavior is identical to LZMA_FILTER_LZMA1.
+	 *
+	 *     Otherwise, if this flag isn't set, then the input stream
+	 *     must not have the end marker; if the end marker is detected
+	 *     then it will result in LZMA_DATA_ERROR. This is useful when
+	 *     it is known that the stream must not have the end marker and
+	 *     strict validation is wanted.
+	 *
+	 *     If this flag is set, then it is autodetected if the end marker
+	 *     is present after the specified number of uncompressed bytes
+	 *     has been decompressed (ext_size_low and ext_size_high). The
+	 *     end marker isn't allowed in any other position. This behavior
+	 *     is useful when uncompressed size is known but the end marker
+	 *     may or may not be present. This is the case, for example,
+	 *     in .7z files (valid .7z files that have the end marker in
+	 *     LZMA1 streams are rare but they do exist).
+	 */
+	uint32_t ext_flags;
+#	define LZMA_LZMA1EXT_ALLOW_EOPM   UINT32_C(0x01)
+
+	/**
+	 * \brief       For LZMA_FILTER_LZMA1EXT: Uncompressed size (low bits)
+	 *
+	 * The 64-bit uncompressed size is needed for decompression with
+	 * LZMA_FILTER_LZMA1EXT. The size is ignored by the encoder.
+	 *
+	 * The special value UINT64_MAX indicates that the uncompressed size
+	 * is unknown and that the end of payload marker (also known as
+	 * end of stream marker) must be present to indicate the end of
+	 * the LZMA1 stream. Any other value indicates the expected
+	 * uncompressed size of the LZMA1 stream. (If LZMA1 was used together
+	 * with filters that change the size of the data then the uncompressed
+	 * size of the LZMA1 stream could be different than the final
+	 * uncompressed size of the filtered stream.)
+	 *
+	 * ext_size_low holds the least significant 32 bits of the
+	 * uncompressed size. The most significant 32 bits must be set
+	 * in ext_size_high. The macro lzma_ext_size_set(opt_lzma, u64size)
+	 * can be used to set these members.
+	 *
+	 * The 64-bit uncompressed size is split into two uint32_t variables
+	 * because there were no reserved uint64_t members and using the
+	 * same options structure for LZMA_FILTER_LZMA1, LZMA_FILTER_LZMA1EXT,
+	 * and LZMA_FILTER_LZMA2 was otherwise more convenient than having
+	 * a new options structure for LZMA_FILTER_LZMA1EXT. (Replacing two
+	 * uint32_t members with one uint64_t changes the ABI on some systems
+	 * as the alignment of this struct can increase from 4 bytes to 8.)
+	 */
+	uint32_t ext_size_low;
+
+	/**
+	 * \brief       For LZMA_FILTER_LZMA1EXT: Uncompressed size (high bits)
+	 *
+	 * This holds the most significant 32 bits of the uncompressed size.
+	 */
+	uint32_t ext_size_high;
+
 	/*
 	/*
 	 * Reserved space to allow possible future extensions without
 	 * Reserved space to allow possible future extensions without
 	 * breaking the ABI. You should not touch these, because the names
 	 * breaking the ABI. You should not touch these, because the names
@@ -381,24 +488,56 @@ typedef struct {
 	 * with the currently supported options, so it is safe to leave these
 	 * with the currently supported options, so it is safe to leave these
 	 * uninitialized.
 	 * uninitialized.
 	 */
 	 */
-	uint32_t reserved_int1;
-	uint32_t reserved_int2;
-	uint32_t reserved_int3;
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int4;
 	uint32_t reserved_int4;
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int5;
 	uint32_t reserved_int5;
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int6;
 	uint32_t reserved_int6;
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int7;
 	uint32_t reserved_int7;
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int8;
 	uint32_t reserved_int8;
+
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum1;
 	lzma_reserved_enum reserved_enum1;
+
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum2;
 	lzma_reserved_enum reserved_enum2;
+
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum3;
 	lzma_reserved_enum reserved_enum3;
+
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum4;
 	lzma_reserved_enum reserved_enum4;
+
+	/** \private     Reserved member. */
 	void *reserved_ptr1;
 	void *reserved_ptr1;
+
+	/** \private     Reserved member. */
 	void *reserved_ptr2;
 	void *reserved_ptr2;
 
 
 } lzma_options_lzma;
 } lzma_options_lzma;
 
 
 
 
+/**
+ * \brief       Macro to set the 64-bit uncompressed size in ext_size_*
+ *
+ * This might be convenient when decoding using LZMA_FILTER_LZMA1EXT.
+ * This isn't used with LZMA_FILTER_LZMA1 or LZMA_FILTER_LZMA2.
+ */
+#define lzma_set_ext_size(opt_lzma2, u64size) \
+do { \
+	(opt_lzma2).ext_size_low = (uint32_t)(u64size); \
+	(opt_lzma2).ext_size_high = (uint32_t)((uint64_t)(u64size) >> 32); \
+} while (0)
+
+
 /**
 /**
  * \brief       Set a compression preset to lzma_options_lzma structure
  * \brief       Set a compression preset to lzma_options_lzma structure
  *
  *
@@ -408,13 +547,22 @@ typedef struct {
  * The flags are defined in container.h, because the flags are used also
  * The flags are defined in container.h, because the flags are used also
  * with lzma_easy_encoder().
  * with lzma_easy_encoder().
  *
  *
- * The preset values are subject to changes between liblzma versions.
+ * The preset levels are subject to changes between liblzma versions.
  *
  *
  * This function is available only if LZMA1 or LZMA2 encoder has been enabled
  * This function is available only if LZMA1 or LZMA2 encoder has been enabled
  * when building liblzma.
  * when building liblzma.
  *
  *
- * \return      On success, false is returned. If the preset is not
- *              supported, true is returned.
+ * If features (like certain match finders) have been disabled at build time,
+ * then the function may return success (false) even though the resulting
+ * LZMA1/LZMA2 options may not be usable for encoder initialization
+ * (LZMA_OPTIONS_ERROR).
+ *
+ * \param[out]  options Pointer to LZMA1 or LZMA2 options to be filled
+ * \param       preset  Preset level bitwse-ORed with preset flags
+ *
+ * \return      lzma_bool:
+ *              - true if the preset is not supported (failure).
+ *              - false otherwise (success).
  */
  */
 extern LZMA_API(lzma_bool) lzma_lzma_preset(
 extern LZMA_API(lzma_bool) lzma_lzma_preset(
 		lzma_options_lzma *options, uint32_t preset) lzma_nothrow;
 		lzma_options_lzma *options, uint32_t preset) lzma_nothrow;

+ 78 - 36
Utilities/cmliblzma/liblzma/api/lzma/stream_flags.h

@@ -1,15 +1,13 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /**
 /**
  * \file        lzma/stream_flags.h
  * \file        lzma/stream_flags.h
  * \brief       .xz Stream Header and Stream Footer encoder and decoder
  * \brief       .xz Stream Header and Stream Footer encoder and decoder
+ * \note        Never include this file directly. Use <lzma.h> instead.
  */
  */
 
 
 /*
 /*
  * Author: Lasse Collin
  * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
- * See ../lzma.h for information about liblzma as a whole.
  */
  */
 
 
 #ifndef LZMA_H_INTERNAL
 #ifndef LZMA_H_INTERNAL
@@ -36,7 +34,7 @@ typedef struct {
 	 *
 	 *
 	 * To prevent API and ABI breakages if new features are needed in
 	 * To prevent API and ABI breakages if new features are needed in
 	 * Stream Header or Stream Footer, a version number is used to
 	 * Stream Header or Stream Footer, a version number is used to
-	 * indicate which fields in this structure are in use. For now,
+	 * indicate which members in this structure are in use. For now,
 	 * version must always be zero. With non-zero version, the
 	 * version must always be zero. With non-zero version, the
 	 * lzma_stream_header_encode() and lzma_stream_footer_encode()
 	 * lzma_stream_header_encode() and lzma_stream_footer_encode()
 	 * will return LZMA_OPTIONS_ERROR.
 	 * will return LZMA_OPTIONS_ERROR.
@@ -67,7 +65,15 @@ typedef struct {
 	 * Footer have been decoded.
 	 * Footer have been decoded.
 	 */
 	 */
 	lzma_vli backward_size;
 	lzma_vli backward_size;
+
+	/**
+	 * \brief       Minimum value for lzma_stream_flags.backward_size
+	 */
 #	define LZMA_BACKWARD_SIZE_MIN 4
 #	define LZMA_BACKWARD_SIZE_MIN 4
+
+	/**
+	 * \brief       Maximum value for lzma_stream_flags.backward_size
+	 */
 #	define LZMA_BACKWARD_SIZE_MAX (LZMA_VLI_C(1) << 34)
 #	define LZMA_BACKWARD_SIZE_MAX (LZMA_VLI_C(1) << 34)
 
 
 	/**
 	/**
@@ -87,19 +93,47 @@ typedef struct {
 	 * is just two bytes plus Backward Size of four bytes. But it's
 	 * is just two bytes plus Backward Size of four bytes. But it's
 	 * nice to have the proper types when they are needed.)
 	 * nice to have the proper types when they are needed.)
 	 */
 	 */
+
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum1;
 	lzma_reserved_enum reserved_enum1;
+
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum2;
 	lzma_reserved_enum reserved_enum2;
+
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum3;
 	lzma_reserved_enum reserved_enum3;
+
+	/** \private     Reserved member. */
 	lzma_reserved_enum reserved_enum4;
 	lzma_reserved_enum reserved_enum4;
+
+	/** \private     Reserved member. */
 	lzma_bool reserved_bool1;
 	lzma_bool reserved_bool1;
+
+	/** \private     Reserved member. */
 	lzma_bool reserved_bool2;
 	lzma_bool reserved_bool2;
+
+	/** \private     Reserved member. */
 	lzma_bool reserved_bool3;
 	lzma_bool reserved_bool3;
+
+	/** \private     Reserved member. */
 	lzma_bool reserved_bool4;
 	lzma_bool reserved_bool4;
+
+	/** \private     Reserved member. */
 	lzma_bool reserved_bool5;
 	lzma_bool reserved_bool5;
+
+	/** \private     Reserved member. */
 	lzma_bool reserved_bool6;
 	lzma_bool reserved_bool6;
+
+	/** \private     Reserved member. */
 	lzma_bool reserved_bool7;
 	lzma_bool reserved_bool7;
+
+	/** \private     Reserved member. */
 	lzma_bool reserved_bool8;
 	lzma_bool reserved_bool8;
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int1;
 	uint32_t reserved_int1;
+
+	/** \private     Reserved member. */
 	uint32_t reserved_int2;
 	uint32_t reserved_int2;
 
 
 } lzma_stream_flags;
 } lzma_stream_flags;
@@ -111,10 +145,11 @@ typedef struct {
  * \param       options     Stream Header options to be encoded.
  * \param       options     Stream Header options to be encoded.
  *                          options->backward_size is ignored and doesn't
  *                          options->backward_size is ignored and doesn't
  *                          need to be initialized.
  *                          need to be initialized.
- * \param       out         Beginning of the output buffer of
+ * \param[out]  out         Beginning of the output buffer of
  *                          LZMA_STREAM_HEADER_SIZE bytes.
  *                          LZMA_STREAM_HEADER_SIZE bytes.
  *
  *
- * \return      - LZMA_OK: Encoding was successful.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Encoding was successful.
  *              - LZMA_OPTIONS_ERROR: options->version is not supported by
  *              - LZMA_OPTIONS_ERROR: options->version is not supported by
  *                this liblzma version.
  *                this liblzma version.
  *              - LZMA_PROG_ERROR: Invalid options.
  *              - LZMA_PROG_ERROR: Invalid options.
@@ -128,10 +163,11 @@ extern LZMA_API(lzma_ret) lzma_stream_header_encode(
  * \brief       Encode Stream Footer
  * \brief       Encode Stream Footer
  *
  *
  * \param       options     Stream Footer options to be encoded.
  * \param       options     Stream Footer options to be encoded.
- * \param       out         Beginning of the output buffer of
+ * \param[out]  out         Beginning of the output buffer of
  *                          LZMA_STREAM_HEADER_SIZE bytes.
  *                          LZMA_STREAM_HEADER_SIZE bytes.
  *
  *
- * \return      - LZMA_OK: Encoding was successful.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Encoding was successful.
  *              - LZMA_OPTIONS_ERROR: options->version is not supported by
  *              - LZMA_OPTIONS_ERROR: options->version is not supported by
  *                this liblzma version.
  *                this liblzma version.
  *              - LZMA_PROG_ERROR: Invalid options.
  *              - LZMA_PROG_ERROR: Invalid options.
@@ -144,32 +180,33 @@ extern LZMA_API(lzma_ret) lzma_stream_footer_encode(
 /**
 /**
  * \brief       Decode Stream Header
  * \brief       Decode Stream Header
  *
  *
- * \param       options     Target for the decoded Stream Header options.
- * \param       in          Beginning of the input buffer of
- *                          LZMA_STREAM_HEADER_SIZE bytes.
- *
  * options->backward_size is always set to LZMA_VLI_UNKNOWN. This is to
  * options->backward_size is always set to LZMA_VLI_UNKNOWN. This is to
  * help comparing Stream Flags from Stream Header and Stream Footer with
  * help comparing Stream Flags from Stream Header and Stream Footer with
  * lzma_stream_flags_compare().
  * lzma_stream_flags_compare().
  *
  *
- * \return      - LZMA_OK: Decoding was successful.
- *              - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given
- *                buffer cannot be Stream Header.
- *              - LZMA_DATA_ERROR: CRC32 doesn't match, thus the header
- *                is corrupt.
- *              - LZMA_OPTIONS_ERROR: Unsupported options are present
- *                in the header.
- *
  * \note        When decoding .xz files that contain multiple Streams, it may
  * \note        When decoding .xz files that contain multiple Streams, it may
  *              make sense to print "file format not recognized" only if
  *              make sense to print "file format not recognized" only if
- *              decoding of the Stream Header of the _first_ Stream gives
+ *              decoding of the Stream Header of the \a first Stream gives
  *              LZMA_FORMAT_ERROR. If non-first Stream Header gives
  *              LZMA_FORMAT_ERROR. If non-first Stream Header gives
  *              LZMA_FORMAT_ERROR, the message used for LZMA_DATA_ERROR is
  *              LZMA_FORMAT_ERROR, the message used for LZMA_DATA_ERROR is
  *              probably more appropriate.
  *              probably more appropriate.
+ *              For example, the Stream decoder in liblzma uses
+ *              LZMA_DATA_ERROR if LZMA_FORMAT_ERROR is returned by
+ *              lzma_stream_header_decode() when decoding non-first Stream.
+ *
+ * \param[out]  options     Target for the decoded Stream Header options.
+ * \param       in          Beginning of the input buffer of
+ *                          LZMA_STREAM_HEADER_SIZE bytes.
  *
  *
- *              For example, Stream decoder in liblzma uses LZMA_DATA_ERROR if
- *              LZMA_FORMAT_ERROR is returned by lzma_stream_header_decode()
- *              when decoding non-first Stream.
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Decoding was successful.
+ *              - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given
+ *                buffer cannot be Stream Header.
+ *              - LZMA_DATA_ERROR: CRC32 doesn't match, thus the header
+ *                is corrupt.
+ *              - LZMA_OPTIONS_ERROR: Unsupported options are present
+ *                in the header.
  */
  */
 extern LZMA_API(lzma_ret) lzma_stream_header_decode(
 extern LZMA_API(lzma_ret) lzma_stream_header_decode(
 		lzma_stream_flags *options, const uint8_t *in)
 		lzma_stream_flags *options, const uint8_t *in)
@@ -179,24 +216,25 @@ extern LZMA_API(lzma_ret) lzma_stream_header_decode(
 /**
 /**
  * \brief       Decode Stream Footer
  * \brief       Decode Stream Footer
  *
  *
- * \param       options     Target for the decoded Stream Header options.
+ * \note        If Stream Header was already decoded successfully, but
+ *              decoding Stream Footer returns LZMA_FORMAT_ERROR, the
+ *              application should probably report some other error message
+ *              than "file format not recognized". The file likely
+ *              is corrupt (possibly truncated). The Stream decoder in liblzma
+ *              uses LZMA_DATA_ERROR in this situation.
+ *
+ * \param[out]  options     Target for the decoded Stream Footer options.
  * \param       in          Beginning of the input buffer of
  * \param       in          Beginning of the input buffer of
  *                          LZMA_STREAM_HEADER_SIZE bytes.
  *                          LZMA_STREAM_HEADER_SIZE bytes.
  *
  *
- * \return      - LZMA_OK: Decoding was successful.
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Decoding was successful.
  *              - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given
  *              - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given
  *                buffer cannot be Stream Footer.
  *                buffer cannot be Stream Footer.
  *              - LZMA_DATA_ERROR: CRC32 doesn't match, thus the Stream Footer
  *              - LZMA_DATA_ERROR: CRC32 doesn't match, thus the Stream Footer
  *                is corrupt.
  *                is corrupt.
  *              - LZMA_OPTIONS_ERROR: Unsupported options are present
  *              - LZMA_OPTIONS_ERROR: Unsupported options are present
  *                in Stream Footer.
  *                in Stream Footer.
- *
- * \note        If Stream Header was already decoded successfully, but
- *              decoding Stream Footer returns LZMA_FORMAT_ERROR, the
- *              application should probably report some other error message
- *              than "file format not recognized", since the file more likely
- *              is corrupt (possibly truncated). Stream decoder in liblzma
- *              uses LZMA_DATA_ERROR in this situation.
  */
  */
 extern LZMA_API(lzma_ret) lzma_stream_footer_decode(
 extern LZMA_API(lzma_ret) lzma_stream_footer_decode(
 		lzma_stream_flags *options, const uint8_t *in)
 		lzma_stream_flags *options, const uint8_t *in)
@@ -209,7 +247,11 @@ extern LZMA_API(lzma_ret) lzma_stream_footer_decode(
  * backward_size values are compared only if both are not
  * backward_size values are compared only if both are not
  * LZMA_VLI_UNKNOWN.
  * LZMA_VLI_UNKNOWN.
  *
  *
- * \return      - LZMA_OK: Both are equal. If either had backward_size set
+ * \param       a       Pointer to lzma_stream_flags structure
+ * \param       b       Pointer to lzma_stream_flags structure
+ *
+ * \return      Possible lzma_ret values:
+ *              - LZMA_OK: Both are equal. If either had backward_size set
  *                to LZMA_VLI_UNKNOWN, backward_size values were not
  *                to LZMA_VLI_UNKNOWN, backward_size values were not
  *                compared or validated.
  *                compared or validated.
  *              - LZMA_DATA_ERROR: The structures differ.
  *              - LZMA_DATA_ERROR: The structures differ.

+ 28 - 15
Utilities/cmliblzma/liblzma/api/lzma/version.h

@@ -1,15 +1,13 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /**
 /**
  * \file        lzma/version.h
  * \file        lzma/version.h
  * \brief       Version number
  * \brief       Version number
+ * \note        Never include this file directly. Use <lzma.h> instead.
  */
  */
 
 
 /*
 /*
  * Author: Lasse Collin
  * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
- * See ../lzma.h for information about liblzma as a whole.
  */
  */
 
 
 #ifndef LZMA_H_INTERNAL
 #ifndef LZMA_H_INTERNAL
@@ -17,14 +15,26 @@
 #endif
 #endif
 
 
 
 
-/*
- * Version number split into components
- */
+/** \brief Major version number of the liblzma release. */
 #define LZMA_VERSION_MAJOR 5
 #define LZMA_VERSION_MAJOR 5
-#define LZMA_VERSION_MINOR 2
-#define LZMA_VERSION_PATCH 5
+
+/** \brief Minor version number of the liblzma release. */
+#define LZMA_VERSION_MINOR 6
+
+/** \brief Patch version number of the liblzma release. */
+#define LZMA_VERSION_PATCH 3
+
+/**
+ * \brief Version stability marker
+ *
+ * This will always be one of three values:
+ *   - LZMA_VERSION_STABILITY_ALPHA
+ *   - LZMA_VERSION_STABILITY_BETA
+ *   - LZMA_VERSION_STABILITY_STABLE
+ */
 #define LZMA_VERSION_STABILITY LZMA_VERSION_STABILITY_STABLE
 #define LZMA_VERSION_STABILITY LZMA_VERSION_STABILITY_STABLE
 
 
+/** \brief Commit version number of the liblzma release */
 #ifndef LZMA_VERSION_COMMIT
 #ifndef LZMA_VERSION_COMMIT
 #	define LZMA_VERSION_COMMIT ""
 #	define LZMA_VERSION_COMMIT ""
 #endif
 #endif
@@ -95,15 +105,16 @@
 		LZMA_VERSION_COMMIT)
 		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
 #ifndef LZMA_H_INTERNAL_RC
 
 
 /**
 /**
  * \brief       Run-time version number as an integer
  * \brief       Run-time version number as an integer
  *
  *
- * Return the value of LZMA_VERSION macro at the compile time of liblzma.
- * This allows the application to compare if it was built against the same,
+ * This allows an application to compare if it was built against the same,
  * older, or newer version of liblzma that is currently running.
  * older, or newer version of liblzma that is currently running.
+ *
+ * \return The value of LZMA_VERSION macro at the compile time of liblzma
  */
  */
 extern LZMA_API(uint32_t) lzma_version_number(void)
 extern LZMA_API(uint32_t) lzma_version_number(void)
 		lzma_nothrow lzma_attr_const;
 		lzma_nothrow lzma_attr_const;
@@ -112,8 +123,10 @@ extern LZMA_API(uint32_t) lzma_version_number(void)
 /**
 /**
  * \brief       Run-time version as a string
  * \brief       Run-time version as a string
  *
  *
- * This function may be useful if you want to display which version of
- * liblzma your application is currently using.
+ * This function may be useful to display which version of liblzma an
+ * application is currently using.
+ *
+ * \return      Run-time version of liblzma
  */
  */
 extern LZMA_API(const char *) lzma_version_string(void)
 extern LZMA_API(const char *) lzma_version_string(void)
 		lzma_nothrow lzma_attr_const;
 		lzma_nothrow lzma_attr_const;

+ 13 - 13
Utilities/cmliblzma/liblzma/api/lzma/vli.h

@@ -1,6 +1,9 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /**
 /**
  * \file        lzma/vli.h
  * \file        lzma/vli.h
  * \brief       Variable-length integer handling
  * \brief       Variable-length integer handling
+ * \note        Never include this file directly. Use <lzma.h> instead.
  *
  *
  * In the .xz format, most integers are encoded in a variable-length
  * In the .xz format, most integers are encoded in a variable-length
  * representation, which is sometimes called little endian base-128 encoding.
  * representation, which is sometimes called little endian base-128 encoding.
@@ -16,11 +19,6 @@
 
 
 /*
 /*
  * Author: Lasse Collin
  * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
- * See ../lzma.h for information about liblzma as a whole.
  */
  */
 
 
 #ifndef LZMA_H_INTERNAL
 #ifndef LZMA_H_INTERNAL
@@ -69,8 +67,8 @@ typedef uint64_t lzma_vli;
  * This is useful to test that application has given acceptable values
  * This is useful to test that application has given acceptable values
  * for example in the uncompressed_size and compressed_size variables.
  * for example in the uncompressed_size and compressed_size variables.
  *
  *
- * \return      True if the integer is representable as VLI or if it
- *              indicates unknown value.
+ * \return      True if the integer is representable as a VLI or if it
+ *              indicates an unknown value. False otherwise.
  */
  */
 #define lzma_vli_is_valid(vli) \
 #define lzma_vli_is_valid(vli) \
 	((vli) <= LZMA_VLI_MAX || (vli) == LZMA_VLI_UNKNOWN)
 	((vli) <= LZMA_VLI_MAX || (vli) == LZMA_VLI_UNKNOWN)
@@ -86,12 +84,12 @@ typedef uint64_t lzma_vli;
  * integer has been encoded.
  * integer has been encoded.
  *
  *
  * \param       vli       Integer to be encoded
  * \param       vli       Integer to be encoded
- * \param       vli_pos   How many VLI-encoded bytes have already been written
+ * \param[out]  vli_pos   How many VLI-encoded bytes have already been written
  *                        out. When starting to encode a new integer in
  *                        out. When starting to encode a new integer in
  *                        multi-call mode, *vli_pos must be set to zero.
  *                        multi-call mode, *vli_pos must be set to zero.
  *                        To use single-call encoding, set vli_pos to NULL.
  *                        To use single-call encoding, set vli_pos to NULL.
- * \param       out       Beginning of the output buffer
- * \param       out_pos   The next byte will be written to out[*out_pos].
+ * \param[out]  out       Beginning of the output buffer
+ * \param[out]  out_pos   The next byte will be written to out[*out_pos].
  * \param       out_size  Size of the out buffer; the first byte into
  * \param       out_size  Size of the out buffer; the first byte into
  *                        which no data is written to is out[out_size].
  *                        which no data is written to is out[out_size].
  *
  *
@@ -121,15 +119,15 @@ extern LZMA_API(lzma_ret) lzma_vli_encode(lzma_vli vli, size_t *vli_pos,
  *
  *
  * Like lzma_vli_encode(), this function has single-call and multi-call modes.
  * Like lzma_vli_encode(), this function has single-call and multi-call modes.
  *
  *
- * \param       vli       Pointer to decoded integer. The decoder will
+ * \param[out]  vli       Pointer to decoded integer. The decoder will
  *                        initialize it to zero when *vli_pos == 0, so
  *                        initialize it to zero when *vli_pos == 0, so
  *                        application isn't required to initialize *vli.
  *                        application isn't required to initialize *vli.
- * \param       vli_pos   How many bytes have already been decoded. When
+ * \param[out]  vli_pos   How many bytes have already been decoded. When
  *                        starting to decode a new integer in multi-call
  *                        starting to decode a new integer in multi-call
  *                        mode, *vli_pos must be initialized to zero. To
  *                        mode, *vli_pos must be initialized to zero. To
  *                        use single-call decoding, set vli_pos to NULL.
  *                        use single-call decoding, set vli_pos to NULL.
  * \param       in        Beginning of the input buffer
  * \param       in        Beginning of the input buffer
- * \param       in_pos    The next byte will be read from in[*in_pos].
+ * \param[out]  in_pos    The next byte will be read from in[*in_pos].
  * \param       in_size   Size of the input buffer; the first byte that
  * \param       in_size   Size of the input buffer; the first byte that
  *                        won't be read is in[in_size].
  *                        won't be read is in[in_size].
  *
  *
@@ -159,6 +157,8 @@ extern LZMA_API(lzma_ret) lzma_vli_decode(lzma_vli *vli, size_t *vli_pos,
 /**
 /**
  * \brief       Get the number of bytes required to encode a VLI
  * \brief       Get the number of bytes required to encode a VLI
  *
  *
+ * \param       vli       Integer whose encoded size is to be determined
+ *
  * \return      Number of bytes on success (1-9). If vli isn't valid,
  * \return      Number of bytes on success (1-9). If vli isn't valid,
  *              zero is returned.
  *              zero is returned.
  */
  */

+ 2 - 3
Utilities/cmliblzma/liblzma/check/check.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       check.c
 /// \file       check.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "check.h"
 #include "check.h"

+ 9 - 7
Utilities/cmliblzma/liblzma/check/check.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       check.h
 /// \file       check.h
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef LZMA_CHECK_H
 #ifndef LZMA_CHECK_H
@@ -99,19 +98,22 @@ typedef struct {
 /// lzma_crc32_table[0] is needed by LZ encoder so we need to keep
 /// lzma_crc32_table[0] is needed by LZ encoder so we need to keep
 /// the array two-dimensional.
 /// the array two-dimensional.
 #ifdef HAVE_SMALL
 #ifdef HAVE_SMALL
+lzma_attr_visibility_hidden
 extern uint32_t lzma_crc32_table[1][256];
 extern uint32_t lzma_crc32_table[1][256];
+
 extern void lzma_crc32_init(void);
 extern void lzma_crc32_init(void);
+
 #else
 #else
+
+lzma_attr_visibility_hidden
 extern const uint32_t lzma_crc32_table[8][256];
 extern const uint32_t lzma_crc32_table[8][256];
+
+lzma_attr_visibility_hidden
 extern const uint64_t lzma_crc64_table[4][256];
 extern const uint64_t lzma_crc64_table[4][256];
 #endif
 #endif
 
 
 
 
 /// \brief      Initialize *check depending on type
 /// \brief      Initialize *check depending on type
-///
-/// \return     LZMA_OK on success. LZMA_UNSUPPORTED_CHECK if the type is not
-///             supported by the current version or build of liblzma.
-///             LZMA_PROG_ERROR if type > LZMA_CHECK_ID_MAX.
 extern void lzma_check_init(lzma_check_state *check, lzma_check type);
 extern void lzma_check_init(lzma_check_state *check, lzma_check type);
 
 
 /// Update the check state
 /// Update the check state

+ 122 - 0
Utilities/cmliblzma/liblzma/check/crc32_arm64.h

@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: 0BSD
+
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc32_arm64.h
+/// \brief      CRC32 calculation with ARM64 optimization
+//
+//  Authors:    Chenxi Mao
+//              Jia Tan
+//              Hans Jansen
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_CRC32_ARM64_H
+#define LZMA_CRC32_ARM64_H
+
+// MSVC always has the CRC intrinsics available when building for ARM64
+// there is no need to include any header files.
+#ifndef _MSC_VER
+#	include <arm_acle.h>
+#endif
+
+// If both versions are going to be built, we need runtime detection
+// to check if the instructions are supported.
+#if defined(CRC32_GENERIC) && defined(CRC32_ARCH_OPTIMIZED)
+#	if defined(HAVE_GETAUXVAL) || defined(HAVE_ELF_AUX_INFO)
+#		include <sys/auxv.h>
+#	elif defined(_WIN32)
+#		include <processthreadsapi.h>
+#	elif defined(__APPLE__) && defined(HAVE_SYSCTLBYNAME)
+#		include <sys/sysctl.h>
+#	endif
+#endif
+
+// Some EDG-based compilers support ARM64 and define __GNUC__
+// (such as Nvidia's nvcc), but do not support function attributes.
+//
+// NOTE: Build systems check for this too, keep them in sync with this.
+#if (defined(__GNUC__) || defined(__clang__)) && !defined(__EDG__)
+#	define crc_attr_target __attribute__((__target__("+crc")))
+#else
+#	define crc_attr_target
+#endif
+
+
+crc_attr_target
+static uint32_t
+crc32_arch_optimized(const uint8_t *buf, size_t size, uint32_t crc)
+{
+	crc = ~crc;
+
+	// Align the input buffer because this was shown to be
+	// significantly faster than unaligned accesses.
+	const size_t align_amount = my_min(size, (0U - (uintptr_t)buf) & 7);
+
+	for (const uint8_t *limit = buf + align_amount; buf < limit; ++buf)
+		crc = __crc32b(crc, *buf);
+
+	size -= align_amount;
+
+	// Process 8 bytes at a time. The end point is determined by
+	// ignoring the least significant three bits of size to ensure
+	// we do not process past the bounds of the buffer. This guarantees
+	// that limit is a multiple of 8 and is strictly less than size.
+	for (const uint8_t *limit = buf + (size & ~(size_t)7);
+			buf < limit; buf += 8)
+		crc = __crc32d(crc, aligned_read64le(buf));
+
+	// Process the remaining bytes that are not 8 byte aligned.
+	for (const uint8_t *limit = buf + (size & 7); buf < limit; ++buf)
+		crc = __crc32b(crc, *buf);
+
+	return ~crc;
+}
+
+
+#if defined(CRC32_GENERIC) && defined(CRC32_ARCH_OPTIMIZED)
+static inline bool
+is_arch_extension_supported(void)
+{
+#if defined(HAVE_GETAUXVAL)
+	return (getauxval(AT_HWCAP) & HWCAP_CRC32) != 0;
+
+#elif defined(HAVE_ELF_AUX_INFO)
+	unsigned long feature_flags;
+
+	if (elf_aux_info(AT_HWCAP, &feature_flags, sizeof(feature_flags)) != 0)
+		return false;
+
+	return (feature_flags & HWCAP_CRC32) != 0;
+
+#elif defined(_WIN32)
+	return IsProcessorFeaturePresent(
+			PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE);
+
+#elif defined(__APPLE__) && defined(HAVE_SYSCTLBYNAME)
+	int has_crc32 = 0;
+	size_t size = sizeof(has_crc32);
+
+	// The sysctlbyname() function requires a string identifier for the
+	// CPU feature it tests. The Apple documentation lists the string
+	// "hw.optional.armv8_crc32", which can be found here:
+	// https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3915619
+	if (sysctlbyname("hw.optional.armv8_crc32", &has_crc32,
+			&size, NULL, 0) != 0)
+		return false;
+
+	return has_crc32;
+
+#else
+	// If a runtime detection method cannot be found, then this must
+	// be a compile time error. The checks in crc_common.h should ensure
+	// a runtime detection method is always found if this function is
+	// built. It would be possible to just return false here, but this
+	// is inefficient for binary size and runtime since only the generic
+	// method could ever be used.
+#	error Runtime detection method unavailable.
+#endif
+}
+#endif
+
+#endif // LZMA_CRC32_ARM64_H

+ 140 - 18
Utilities/cmliblzma/liblzma/check/crc32_fast.c

@@ -1,35 +1,40 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       crc32.c
 /// \file       crc32.c
 /// \brief      CRC32 calculation
 /// \brief      CRC32 calculation
-///
-/// Calculate the CRC32 using the slice-by-eight algorithm.
-/// It is explained in this document:
-/// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
-/// The code in this file is not the same as in Intel's paper, but
-/// the basic principle is identical.
-//
-//  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
+//  Authors:    Lasse Collin
+//              Ilya Kurdyukov
+//              Hans Jansen
 //
 //
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "check.h"
 #include "check.h"
-#include "crc_macros.h"
+#include "crc_common.h"
+
+#if defined(CRC_X86_CLMUL)
+#	define BUILDING_CRC32_CLMUL
+#	include "crc_x86_clmul.h"
+#elif defined(CRC32_ARM64)
+#	include "crc32_arm64.h"
+#endif
 
 
 
 
-// If you make any changes, do some benchmarking! Seemingly unrelated
-// changes can very easily ruin the performance (and very probably is
-// very compiler dependent).
-extern LZMA_API(uint32_t)
-lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
+#ifdef CRC32_GENERIC
+
+///////////////////
+// Generic CRC32 //
+///////////////////
+
+static uint32_t
+crc32_generic(const uint8_t *buf, size_t size, uint32_t crc)
 {
 {
 	crc = ~crc;
 	crc = ~crc;
 
 
 #ifdef WORDS_BIGENDIAN
 #ifdef WORDS_BIGENDIAN
-	crc = bswap32(crc);
+	crc = byteswap32(crc);
 #endif
 #endif
 
 
 	if (size > 8) {
 	if (size > 8) {
@@ -75,8 +80,125 @@ lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
 		crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc);
 		crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc);
 
 
 #ifdef WORDS_BIGENDIAN
 #ifdef WORDS_BIGENDIAN
-	crc = bswap32(crc);
+	crc = byteswap32(crc);
 #endif
 #endif
 
 
 	return ~crc;
 	return ~crc;
 }
 }
+#endif
+
+
+#if defined(CRC32_GENERIC) && defined(CRC32_ARCH_OPTIMIZED)
+
+//////////////////////////
+// Function dispatching //
+//////////////////////////
+
+// If both the generic and arch-optimized implementations are built, then
+// the function to use is selected at runtime because the system running
+// the binary might not have the arch-specific instruction set extension(s)
+// available. The dispatch methods in order of priority:
+//
+// 1. Constructor. This method uses __attribute__((__constructor__)) to
+//    set crc32_func at load time. This avoids extra computation (and any
+//    unlikely threading bugs) on the first call to lzma_crc32() to decide
+//    which implementation should be used.
+//
+// 2. First Call Resolution. On the very first call to lzma_crc32(), the
+//    call will be directed to crc32_dispatch() instead. This will set the
+//    appropriate implementation function and will not be called again.
+//    This method does not use any kind of locking but is safe because if
+//    multiple threads run the dispatcher simultaneously then they will all
+//    set crc32_func to the same value.
+
+typedef uint32_t (*crc32_func_type)(
+		const uint8_t *buf, size_t size, uint32_t crc);
+
+// This resolver is shared between all dispatch methods.
+static crc32_func_type
+crc32_resolve(void)
+{
+	return is_arch_extension_supported()
+			? &crc32_arch_optimized : &crc32_generic;
+}
+
+
+#ifdef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
+// Constructor method.
+#	define CRC32_SET_FUNC_ATTR __attribute__((__constructor__))
+static crc32_func_type crc32_func;
+#else
+// First Call Resolution method.
+#	define CRC32_SET_FUNC_ATTR
+static uint32_t crc32_dispatch(const uint8_t *buf, size_t size, uint32_t crc);
+static crc32_func_type crc32_func = &crc32_dispatch;
+#endif
+
+CRC32_SET_FUNC_ATTR
+static void
+crc32_set_func(void)
+{
+	crc32_func = crc32_resolve();
+	return;
+}
+
+#ifndef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
+static uint32_t
+crc32_dispatch(const uint8_t *buf, size_t size, uint32_t crc)
+{
+	// When __attribute__((__constructor__)) isn't supported, set the
+	// function pointer without any locking. If multiple threads run
+	// the detection code in parallel, they will all end up setting
+	// the pointer to the same value. This avoids the use of
+	// mythread_once() on every call to lzma_crc32() but this likely
+	// isn't strictly standards compliant. Let's change it if it breaks.
+	crc32_set_func();
+	return crc32_func(buf, size, crc);
+}
+
+#endif
+#endif
+
+
+extern LZMA_API(uint32_t)
+lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
+{
+#if defined(CRC32_GENERIC) && defined(CRC32_ARCH_OPTIMIZED)
+	// On x86-64, if CLMUL is available, it is the best for non-tiny
+	// inputs, being over twice as fast as the generic slice-by-four
+	// version. However, for size <= 16 it's different. In the extreme
+	// case of size == 1 the generic version can be five times faster.
+	// At size >= 8 the CLMUL starts to become reasonable. It
+	// varies depending on the alignment of buf too.
+	//
+	// The above doesn't include the overhead of mythread_once().
+	// At least on x86-64 GNU/Linux, pthread_once() is very fast but
+	// it still makes lzma_crc32(buf, 1, crc) 50-100 % slower. When
+	// size reaches 12-16 bytes the overhead becomes negligible.
+	//
+	// So using the generic version for size <= 16 may give better
+	// performance with tiny inputs but if such inputs happen rarely
+	// it's not so obvious because then the lookup table of the
+	// generic version may not be in the processor cache.
+#ifdef CRC_USE_GENERIC_FOR_SMALL_INPUTS
+	if (size <= 16)
+		return crc32_generic(buf, size, crc);
+#endif
+
+/*
+#ifndef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
+	// See crc32_dispatch(). This would be the alternative which uses
+	// locking and doesn't use crc32_dispatch(). Note that on Windows
+	// this method needs Vista threads.
+	mythread_once(crc64_set_func);
+#endif
+*/
+	return crc32_func(buf, size, crc);
+
+#elif defined(CRC32_ARCH_OPTIMIZED)
+	return crc32_arch_optimized(buf, size, crc);
+
+#else
+	return crc32_generic(buf, size, crc);
+#endif
+}

+ 9 - 3
Utilities/cmliblzma/liblzma/check/crc32_small.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       crc32_small.c
 /// \file       crc32_small.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "check.h"
 #include "check.h"
@@ -16,6 +15,9 @@
 uint32_t lzma_crc32_table[1][256];
 uint32_t lzma_crc32_table[1][256];
 
 
 
 
+#ifdef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
+__attribute__((__constructor__))
+#endif
 static void
 static void
 crc32_init(void)
 crc32_init(void)
 {
 {
@@ -37,18 +39,22 @@ crc32_init(void)
 }
 }
 
 
 
 
+#ifndef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
 extern void
 extern void
 lzma_crc32_init(void)
 lzma_crc32_init(void)
 {
 {
 	mythread_once(crc32_init);
 	mythread_once(crc32_init);
 	return;
 	return;
 }
 }
+#endif
 
 
 
 
 extern LZMA_API(uint32_t)
 extern LZMA_API(uint32_t)
 lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
 lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
 {
 {
+#ifndef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
 	lzma_crc32_init();
 	lzma_crc32_init();
+#endif
 
 
 	crc = ~crc;
 	crc = ~crc;
 
 

+ 27 - 7
Utilities/cmliblzma/liblzma/check/crc32_table.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       crc32_table.c
 /// \file       crc32_table.c
@@ -5,18 +7,36 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "common.h"
 #include "common.h"
 
 
+
+// FIXME: Compared to crc_common.h this has to check for __x86_64__ too
+// so that in 32-bit builds crc32_x86.S won't break due to a missing table.
+#if defined(HAVE_USABLE_CLMUL) && ((defined(__x86_64__) && defined(__SSSE3__) \
+			&& defined(__SSE4_1__) && defined(__PCLMUL__)) \
+		|| (defined(__e2k__) && __iset__ >= 6))
+#	define NO_CRC32_TABLE
+
+#elif defined(HAVE_ARM64_CRC32) \
+		&& !defined(WORDS_BIGENDIAN) \
+		&& defined(__ARM_FEATURE_CRC32)
+#	define NO_CRC32_TABLE
+#endif
+
+
+#if !defined(HAVE_ENCODERS) && defined(NO_CRC32_TABLE)
+// No table needed. Use a typedef to avoid an empty translation unit.
+typedef void lzma_crc32_dummy;
+
+#else
 // Having the declaration here silences clang -Wmissing-variable-declarations.
 // Having the declaration here silences clang -Wmissing-variable-declarations.
 extern const uint32_t lzma_crc32_table[8][256];
 extern const uint32_t lzma_crc32_table[8][256];
 
 
-#ifdef WORDS_BIGENDIAN
-#	include "crc32_table_be.h"
-#else
-#	include "crc32_table_le.h"
+#	ifdef WORDS_BIGENDIAN
+#		include "crc32_table_be.h"
+#	else
+#		include "crc32_table_le.h"
+#	endif
 #endif
 #endif

+ 3 - 1
Utilities/cmliblzma/liblzma/check/crc32_table_be.h

@@ -1,4 +1,6 @@
-/* This file has been automatically generated by crc32_tablegen.c. */
+// SPDX-License-Identifier: 0BSD
+
+// This file has been generated by crc32_tablegen.c.
 
 
 const uint32_t lzma_crc32_table[8][256] = {
 const uint32_t lzma_crc32_table[8][256] = {
 	{
 	{

+ 3 - 1
Utilities/cmliblzma/liblzma/check/crc32_table_le.h

@@ -1,4 +1,6 @@
-/* This file has been automatically generated by crc32_tablegen.c. */
+// SPDX-License-Identifier: 0BSD
+
+// This file has been generated by crc32_tablegen.c.
 
 
 const uint32_t lzma_crc32_table[8][256] = {
 const uint32_t lzma_crc32_table[8][256] = {
 	{
 	{

+ 13 - 10
Utilities/cmliblzma/liblzma/check/crc32_tablegen.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       crc32_tablegen.c
 /// \file       crc32_tablegen.c
@@ -9,9 +11,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include <stdio.h>
 #include <stdio.h>
@@ -44,7 +43,7 @@ init_crc32_table(void)
 #ifdef WORDS_BIGENDIAN
 #ifdef WORDS_BIGENDIAN
 	for (size_t s = 0; s < 8; ++s)
 	for (size_t s = 0; s < 8; ++s)
 		for (size_t b = 0; b < 256; ++b)
 		for (size_t b = 0; b < 256; ++b)
-			crc32_table[s][b] = bswap32(crc32_table[s][b]);
+			crc32_table[s][b] = byteswap32(crc32_table[s][b]);
 #endif
 #endif
 
 
 	return;
 	return;
@@ -54,9 +53,11 @@ init_crc32_table(void)
 static void
 static void
 print_crc32_table(void)
 print_crc32_table(void)
 {
 {
-	printf("/* This file has been automatically generated by "
-			"crc32_tablegen.c. */\n\n"
-			"const uint32_t lzma_crc32_table[8][256] = {\n\t{");
+	// Split the SPDX string so that it won't accidentally match
+	// when tools search for the string.
+	printf("// SPDX" "-License-Identifier" ": 0BSD\n\n"
+		"// This file has been generated by crc32_tablegen.c.\n\n"
+		"const uint32_t lzma_crc32_table[8][256] = {\n\t{");
 
 
 	for (size_t s = 0; s < 8; ++s) {
 	for (size_t s = 0; s < 8; ++s) {
 		for (size_t b = 0; b < 256; ++b) {
 		for (size_t b = 0; b < 256; ++b) {
@@ -82,9 +83,11 @@ print_crc32_table(void)
 static void
 static void
 print_lz_table(void)
 print_lz_table(void)
 {
 {
-	printf("/* This file has been automatically generated by "
-			"crc32_tablegen.c. */\n\n"
-			"const uint32_t lzma_lz_hash_table[256] = {");
+	// Split the SPDX string so that it won't accidentally match
+	// when tools search for the string.
+	printf("// SPDX" "-License-Identifier" ": 0BSD\n\n"
+		"// This file has been generated by crc32_tablegen.c.\n\n"
+		"const uint32_t lzma_lz_hash_table[256] = {");
 
 
 	for (size_t b = 0; b < 256; ++b) {
 	for (size_t b = 0; b < 256; ++b) {
 		if ((b % 4) == 0)
 		if ((b % 4) == 0)

+ 14 - 6
Utilities/cmliblzma/liblzma/check/crc32_x86.S

@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /*
 /*
  * Speed-optimized CRC32 using slicing-by-eight algorithm
  * Speed-optimized CRC32 using slicing-by-eight algorithm
  *
  *
@@ -11,9 +13,6 @@
  * Authors: Igor Pavlov (original version)
  * Authors: Igor Pavlov (original version)
  *          Lasse Collin (AT&T syntax, PIC support, better portability)
  *          Lasse Collin (AT&T syntax, PIC support, better portability)
  *
  *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
  * This code needs lzma_crc32_table, which can be created using the
  * This code needs lzma_crc32_table, which can be created using the
  * following C code:
  * following C code:
 
 
@@ -51,6 +50,14 @@ init_table(void)
  * extern uint32_t lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc);
  * extern uint32_t lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc);
  */
  */
 
 
+/* When Intel CET is enabled, include <cet.h> in assembly code to mark
+   Intel CET support.  */
+#ifdef __CET__
+# include <cet.h>
+#else
+# define _CET_ENDBR
+#endif
+
 /*
 /*
  * On some systems, the functions need to be prefixed. The prefix is
  * On some systems, the functions need to be prefixed. The prefix is
  * usually an underscore.
  * usually an underscore.
@@ -83,6 +90,7 @@ init_table(void)
 
 
 	ALIGN(4, 16)
 	ALIGN(4, 16)
 LZMA_CRC32:
 LZMA_CRC32:
+	_CET_ENDBR
 	/*
 	/*
 	 * Register usage:
 	 * Register usage:
 	 * %eax crc
 	 * %eax crc
@@ -195,7 +203,7 @@ LZMA_CRC32:
 
 
 	/*
 	/*
 	 * Read the next four bytes, for which the CRC is calculated
 	 * Read the next four bytes, for which the CRC is calculated
-	 * on the next interation of the loop.
+	 * on the next iteration of the loop.
 	 */
 	 */
 	movl	12(%esi), %ecx
 	movl	12(%esi), %ecx
 
 
@@ -296,9 +304,9 @@ LZMA_CRC32:
 
 
 /*
 /*
  * This is needed to support non-executable stack. It's ugly to
  * This is needed to support non-executable stack. It's ugly to
- * use __linux__ here, but I don't know a way to detect when
+ * use __FreeBSD__ and __linux__ here, but I don't know a way to detect when
  * we are using GNU assembler.
  * we are using GNU assembler.
  */
  */
-#if defined(__ELF__) && defined(__linux__)
+#if defined(__ELF__) && (defined(__FreeBSD__) || defined(__linux__))
 	.section	.note.GNU-stack,"",@progbits
 	.section	.note.GNU-stack,"",@progbits
 #endif
 #endif

+ 99 - 15
Utilities/cmliblzma/liblzma/check/crc64_fast.c

@@ -1,22 +1,29 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       crc64.c
 /// \file       crc64.c
 /// \brief      CRC64 calculation
 /// \brief      CRC64 calculation
-///
-/// Calculate the CRC64 using the slice-by-four algorithm. This is the same
-/// idea that is used in crc32_fast.c, but for CRC64 we use only four tables
-/// instead of eight to avoid increasing CPU cache usage.
-//
-//  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
+//  Authors:    Lasse Collin
+//              Ilya Kurdyukov
 //
 //
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "check.h"
 #include "check.h"
-#include "crc_macros.h"
+#include "crc_common.h"
+
+#if defined(CRC_X86_CLMUL)
+#	define BUILDING_CRC64_CLMUL
+#	include "crc_x86_clmul.h"
+#endif
+
+
+#ifdef CRC64_GENERIC
 
 
+/////////////////////////////////
+// Generic slice-by-four CRC64 //
+/////////////////////////////////
 
 
 #ifdef WORDS_BIGENDIAN
 #ifdef WORDS_BIGENDIAN
 #	define A1(x) ((x) >> 56)
 #	define A1(x) ((x) >> 56)
@@ -26,13 +33,13 @@
 
 
 
 
 // See the comments in crc32_fast.c. They aren't duplicated here.
 // See the comments in crc32_fast.c. They aren't duplicated here.
-extern LZMA_API(uint64_t)
-lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
+static uint64_t
+crc64_generic(const uint8_t *buf, size_t size, uint64_t crc)
 {
 {
 	crc = ~crc;
 	crc = ~crc;
 
 
 #ifdef WORDS_BIGENDIAN
 #ifdef WORDS_BIGENDIAN
-	crc = bswap64(crc);
+	crc = byteswap64(crc);
 #endif
 #endif
 
 
 	if (size > 4) {
 	if (size > 4) {
@@ -46,10 +53,11 @@ lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
 
 
 		while (buf < limit) {
 		while (buf < limit) {
 #ifdef WORDS_BIGENDIAN
 #ifdef WORDS_BIGENDIAN
-			const uint32_t tmp = (crc >> 32)
+			const uint32_t tmp = (uint32_t)(crc >> 32)
 					^ aligned_read32ne(buf);
 					^ aligned_read32ne(buf);
 #else
 #else
-			const uint32_t tmp = crc ^ aligned_read32ne(buf);
+			const uint32_t tmp = (uint32_t)crc
+					^ aligned_read32ne(buf);
 #endif
 #endif
 			buf += 4;
 			buf += 4;
 
 
@@ -65,8 +73,84 @@ lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
 		crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc);
 		crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc);
 
 
 #ifdef WORDS_BIGENDIAN
 #ifdef WORDS_BIGENDIAN
-	crc = bswap64(crc);
+	crc = byteswap64(crc);
 #endif
 #endif
 
 
 	return ~crc;
 	return ~crc;
 }
 }
+#endif
+
+
+#if defined(CRC64_GENERIC) && defined(CRC64_ARCH_OPTIMIZED)
+
+//////////////////////////
+// Function dispatching //
+//////////////////////////
+
+// If both the generic and arch-optimized implementations are usable, then
+// the function that is used is selected at runtime. See crc32_fast.c.
+
+typedef uint64_t (*crc64_func_type)(
+		const uint8_t *buf, size_t size, uint64_t crc);
+
+static crc64_func_type
+crc64_resolve(void)
+{
+	return is_arch_extension_supported()
+			? &crc64_arch_optimized : &crc64_generic;
+}
+
+#ifdef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
+#	define CRC64_SET_FUNC_ATTR __attribute__((__constructor__))
+static crc64_func_type crc64_func;
+#else
+#	define CRC64_SET_FUNC_ATTR
+static uint64_t crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc);
+static crc64_func_type crc64_func = &crc64_dispatch;
+#endif
+
+
+CRC64_SET_FUNC_ATTR
+static void
+crc64_set_func(void)
+{
+	crc64_func = crc64_resolve();
+	return;
+}
+
+
+#ifndef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
+static uint64_t
+crc64_dispatch(const uint8_t *buf, size_t size, uint64_t crc)
+{
+	crc64_set_func();
+	return crc64_func(buf, size, crc);
+}
+#endif
+#endif
+
+
+extern LZMA_API(uint64_t)
+lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
+{
+#if defined(CRC64_GENERIC) && defined(CRC64_ARCH_OPTIMIZED)
+
+#ifdef CRC_USE_GENERIC_FOR_SMALL_INPUTS
+	if (size <= 16)
+		return crc64_generic(buf, size, crc);
+#endif
+	return crc64_func(buf, size, crc);
+
+#elif defined(CRC64_ARCH_OPTIMIZED)
+	// If arch-optimized version is used unconditionally without runtime
+	// CPU detection then omitting the generic version and its 8 KiB
+	// lookup table makes the library smaller.
+	//
+	// FIXME: Lookup table isn't currently omitted on 32-bit x86,
+	// see crc64_table.c.
+	return crc64_arch_optimized(buf, size, crc);
+
+#else
+	return crc64_generic(buf, size, crc);
+#endif
+}

+ 7 - 3
Utilities/cmliblzma/liblzma/check/crc64_small.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       crc64_small.c
 /// \file       crc64_small.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "check.h"
 #include "check.h"
@@ -16,6 +15,9 @@
 static uint64_t crc64_table[256];
 static uint64_t crc64_table[256];
 
 
 
 
+#ifdef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
+__attribute__((__constructor__))
+#endif
 static void
 static void
 crc64_init(void)
 crc64_init(void)
 {
 {
@@ -40,7 +42,9 @@ crc64_init(void)
 extern LZMA_API(uint64_t)
 extern LZMA_API(uint64_t)
 lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
 lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
 {
 {
+#ifndef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR
 	mythread_once(crc64_init);
 	mythread_once(crc64_init);
+#endif
 
 
 	crc = ~crc;
 	crc = ~crc;
 
 

+ 22 - 7
Utilities/cmliblzma/liblzma/check/crc64_table.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       crc64_table.c
 /// \file       crc64_table.c
@@ -5,18 +7,31 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "common.h"
 #include "common.h"
 
 
+
+// FIXME: Compared to crc_common.h this has to check for __x86_64__ too
+// so that in 32-bit builds crc64_x86.S won't break due to a missing table.
+#if defined(HAVE_USABLE_CLMUL) && ((defined(__x86_64__) && defined(__SSSE3__) \
+			&& defined(__SSE4_1__) && defined(__PCLMUL__)) \
+		|| (defined(__e2k__) && __iset__ >= 6))
+#	define NO_CRC64_TABLE
+#endif
+
+
+#ifdef NO_CRC64_TABLE
+// 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.
 // Having the declaration here silences clang -Wmissing-variable-declarations.
 extern const uint64_t lzma_crc64_table[4][256];
 extern const uint64_t lzma_crc64_table[4][256];
 
 
-#ifdef WORDS_BIGENDIAN
-#	include "crc64_table_be.h"
-#else
-#	include "crc64_table_le.h"
+#	if defined(WORDS_BIGENDIAN)
+#		include "crc64_table_be.h"
+#	else
+#		include "crc64_table_le.h"
+#	endif
 #endif
 #endif

+ 3 - 1
Utilities/cmliblzma/liblzma/check/crc64_table_be.h

@@ -1,4 +1,6 @@
-/* This file has been automatically generated by crc64_tablegen.c. */
+// SPDX-License-Identifier: 0BSD
+
+// This file has been generated by crc64_tablegen.c.
 
 
 const uint64_t lzma_crc64_table[4][256] = {
 const uint64_t lzma_crc64_table[4][256] = {
 	{
 	{

+ 3 - 1
Utilities/cmliblzma/liblzma/check/crc64_table_le.h

@@ -1,4 +1,6 @@
-/* This file has been automatically generated by crc64_tablegen.c. */
+// SPDX-License-Identifier: 0BSD
+
+// This file has been generated by crc64_tablegen.c.
 
 
 const uint64_t lzma_crc64_table[4][256] = {
 const uint64_t lzma_crc64_table[4][256] = {
 	{
 	{

+ 8 - 7
Utilities/cmliblzma/liblzma/check/crc64_tablegen.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       crc64_tablegen.c
 /// \file       crc64_tablegen.c
@@ -8,9 +10,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include <stdio.h>
 #include <stdio.h>
@@ -43,7 +42,7 @@ init_crc64_table(void)
 #ifdef WORDS_BIGENDIAN
 #ifdef WORDS_BIGENDIAN
 	for (size_t s = 0; s < 4; ++s)
 	for (size_t s = 0; s < 4; ++s)
 		for (size_t b = 0; b < 256; ++b)
 		for (size_t b = 0; b < 256; ++b)
-			crc64_table[s][b] = bswap64(crc64_table[s][b]);
+			crc64_table[s][b] = byteswap64(crc64_table[s][b]);
 #endif
 #endif
 
 
 	return;
 	return;
@@ -53,9 +52,11 @@ init_crc64_table(void)
 static void
 static void
 print_crc64_table(void)
 print_crc64_table(void)
 {
 {
-	printf("/* This file has been automatically generated by "
-			"crc64_tablegen.c. */\n\n"
-			"const uint64_t lzma_crc64_table[4][256] = {\n\t{");
+	// Split the SPDX string so that it won't accidentally match
+	// when tools search for the string.
+	printf("// SPDX" "-License-Identifier" ": 0BSD\n\n"
+		"// This file has been generated by crc64_tablegen.c.\n\n"
+		"const uint64_t lzma_crc64_table[4][256] = {\n\t{");
 
 
 	for (size_t s = 0; s < 4; ++s) {
 	for (size_t s = 0; s < 4; ++s) {
 		for (size_t b = 0; b < 256; ++b) {
 		for (size_t b = 0; b < 256; ++b) {

+ 13 - 5
Utilities/cmliblzma/liblzma/check/crc64_x86.S

@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: 0BSD */
+
 /*
 /*
  * Speed-optimized CRC64 using slicing-by-four algorithm
  * Speed-optimized CRC64 using slicing-by-four algorithm
  *
  *
@@ -7,9 +9,6 @@
  * Authors: Igor Pavlov (original CRC32 assembly code)
  * Authors: Igor Pavlov (original CRC32 assembly code)
  *          Lasse Collin (CRC64 adaptation of the modified CRC32 code)
  *          Lasse Collin (CRC64 adaptation of the modified CRC32 code)
  *
  *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
  * This code needs lzma_crc64_table, which can be created using the
  * This code needs lzma_crc64_table, which can be created using the
  * following C code:
  * following C code:
 
 
@@ -41,6 +40,14 @@ init_table(void)
  * extern uint64_t lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc);
  * extern uint64_t lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc);
  */
  */
 
 
+/* When Intel CET is enabled, include <cet.h> in assembly code to mark
+   Intel CET support.  */
+#ifdef __CET__
+# include <cet.h>
+#else
+# define _CET_ENDBR
+#endif
+
 /*
 /*
  * On some systems, the functions need to be prefixed. The prefix is
  * On some systems, the functions need to be prefixed. The prefix is
  * usually an underscore.
  * usually an underscore.
@@ -73,6 +80,7 @@ init_table(void)
 
 
 	ALIGN(4, 16)
 	ALIGN(4, 16)
 LZMA_CRC64:
 LZMA_CRC64:
+	_CET_ENDBR
 	/*
 	/*
 	 * Register usage:
 	 * Register usage:
 	 * %eax crc LSB
 	 * %eax crc LSB
@@ -279,9 +287,9 @@ LZMA_CRC64:
 
 
 /*
 /*
  * This is needed to support non-executable stack. It's ugly to
  * This is needed to support non-executable stack. It's ugly to
- * use __linux__ here, but I don't know a way to detect when
+ * use __FreeBSD__ and __linux__ here, but I don't know a way to detect when
  * we are using GNU assembler.
  * we are using GNU assembler.
  */
  */
-#if defined(__ELF__) && defined(__linux__)
+#if defined(__ELF__) && (defined(__FreeBSD__) || defined(__linux__))
 	.section	.note.GNU-stack,"",@progbits
 	.section	.note.GNU-stack,"",@progbits
 #endif
 #endif

+ 137 - 0
Utilities/cmliblzma/liblzma/check/crc_common.h

@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: 0BSD
+
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc_common.h
+/// \brief      Some functions and macros for CRC32 and CRC64
+//
+//  Authors:    Lasse Collin
+//              Ilya Kurdyukov
+//              Hans Jansen
+//              Jia Tan
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_CRC_COMMON_H
+#define LZMA_CRC_COMMON_H
+
+#include "common.h"
+
+
+#ifdef WORDS_BIGENDIAN
+#	define A(x) ((x) >> 24)
+#	define B(x) (((x) >> 16) & 0xFF)
+#	define C(x) (((x) >> 8) & 0xFF)
+#	define D(x) ((x) & 0xFF)
+
+#	define S8(x) ((x) << 8)
+#	define S32(x) ((x) << 32)
+
+#else
+#	define A(x) ((x) & 0xFF)
+#	define B(x) (((x) >> 8) & 0xFF)
+#	define C(x) (((x) >> 16) & 0xFF)
+#	define D(x) ((x) >> 24)
+
+#	define S8(x) ((x) >> 8)
+#	define S32(x) ((x) >> 32)
+#endif
+
+
+// CRC CLMUL code needs this because accessing input buffers that aren't
+// aligned to the vector size will inherently trip the address sanitizer.
+#if lzma_has_attribute(__no_sanitize_address__)
+#	define crc_attr_no_sanitize_address \
+			__attribute__((__no_sanitize_address__))
+#else
+#	define crc_attr_no_sanitize_address
+#endif
+
+// Keep this in sync with changes to crc32_arm64.h
+#if defined(_WIN32) || defined(HAVE_GETAUXVAL) \
+		|| defined(HAVE_ELF_AUX_INFO) \
+		|| (defined(__APPLE__) && defined(HAVE_SYSCTLBYNAME))
+#	define ARM64_RUNTIME_DETECTION 1
+#endif
+
+
+#undef CRC32_GENERIC
+#undef CRC64_GENERIC
+
+#undef CRC32_ARCH_OPTIMIZED
+#undef CRC64_ARCH_OPTIMIZED
+
+// The x86 CLMUL is used for both CRC32 and CRC64.
+#undef CRC_X86_CLMUL
+
+#undef CRC32_ARM64
+#undef CRC64_ARM64_CLMUL
+
+#undef CRC_USE_GENERIC_FOR_SMALL_INPUTS
+
+// ARM64 CRC32 instruction is only useful for CRC32. Currently, only
+// little endian is supported since we were unable to test on a big
+// endian machine.
+//
+// NOTE: Keep this and the next check in sync with the macro
+//       NO_CRC32_TABLE in crc32_table.c
+#if defined(HAVE_ARM64_CRC32) && !defined(WORDS_BIGENDIAN)
+	// Allow ARM64 CRC32 instruction without a runtime check if
+	// __ARM_FEATURE_CRC32 is defined. GCC and Clang only define
+	// this if the proper compiler options are used.
+#	if defined(__ARM_FEATURE_CRC32)
+#		define CRC32_ARCH_OPTIMIZED 1
+#		define CRC32_ARM64 1
+#	elif defined(ARM64_RUNTIME_DETECTION)
+#		define CRC32_ARCH_OPTIMIZED 1
+#		define CRC32_ARM64 1
+#		define CRC32_GENERIC 1
+#	endif
+#endif
+
+#if defined(HAVE_USABLE_CLMUL)
+// If CLMUL is allowed unconditionally in the compiler options then the
+// generic version can be omitted. Note that this doesn't work with MSVC
+// as I don't know how to detect the features here.
+//
+// NOTE: Keep this in sync with the NO_CRC32_TABLE macro in crc32_table.c
+// and NO_CRC64_TABLE in crc64_table.c.
+#	if (defined(__SSSE3__) && defined(__SSE4_1__) && defined(__PCLMUL__)) \
+		|| (defined(__e2k__) && __iset__ >= 6)
+#		define CRC32_ARCH_OPTIMIZED 1
+#		define CRC64_ARCH_OPTIMIZED 1
+#		define CRC_X86_CLMUL 1
+#	else
+#		define CRC32_GENERIC 1
+#		define CRC64_GENERIC 1
+#		define CRC32_ARCH_OPTIMIZED 1
+#		define CRC64_ARCH_OPTIMIZED 1
+#		define CRC_X86_CLMUL 1
+
+/*
+		// The generic code is much faster with 1-8-byte inputs and
+		// has similar performance up to 16 bytes  at least in
+		// microbenchmarks (it depends on input buffer alignment
+		// too). If both versions are built, this #define will use
+		// the generic version for inputs up to 16 bytes and CLMUL
+		// for bigger inputs. It saves a little in code size since
+		// the special cases for 0-16-byte inputs will be omitted
+		// from the CLMUL code.
+#		define CRC_USE_GENERIC_FOR_SMALL_INPUTS 1
+*/
+#	endif
+#endif
+
+// For CRC32 use the generic slice-by-eight implementation if no optimized
+// version is available.
+#if !defined(CRC32_ARCH_OPTIMIZED) && !defined(CRC32_GENERIC)
+#	define CRC32_GENERIC 1
+#endif
+
+// For CRC64 use the generic slice-by-four implementation if no optimized
+// version is available.
+#if !defined(CRC64_ARCH_OPTIMIZED) && !defined(CRC64_GENERIC)
+#	define CRC64_GENERIC 1
+#endif
+
+#endif

+ 0 - 30
Utilities/cmliblzma/liblzma/check/crc_macros.h

@@ -1,30 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file       crc_macros.h
-/// \brief      Some endian-dependent macros for CRC32 and CRC64
-//
-//  Author:     Lasse Collin
-//
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifdef WORDS_BIGENDIAN
-#	define A(x) ((x) >> 24)
-#	define B(x) (((x) >> 16) & 0xFF)
-#	define C(x) (((x) >> 8) & 0xFF)
-#	define D(x) ((x) & 0xFF)
-
-#	define S8(x) ((x) << 8)
-#	define S32(x) ((x) << 32)
-
-#else
-#	define A(x) ((x) & 0xFF)
-#	define B(x) (((x) >> 8) & 0xFF)
-#	define C(x) (((x) >> 16) & 0xFF)
-#	define D(x) ((x) >> 24)
-
-#	define S8(x) ((x) >> 8)
-#	define S32(x) ((x) >> 32)
-#endif

+ 432 - 0
Utilities/cmliblzma/liblzma/check/crc_x86_clmul.h

@@ -0,0 +1,432 @@
+// SPDX-License-Identifier: 0BSD
+
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc_x86_clmul.h
+/// \brief      CRC32 and CRC64 implementations using CLMUL instructions.
+///
+/// The CRC32 and CRC64 implementations use 32/64-bit x86 SSSE3, SSE4.1, and
+/// CLMUL instructions. This is compatible with Elbrus 2000 (E2K) too.
+///
+/// They were derived from
+/// https://www.researchgate.net/publication/263424619_Fast_CRC_computation
+/// and the public domain code from https://github.com/rawrunprotected/crc
+/// (URLs were checked on 2023-10-14).
+///
+/// While this file has both CRC32 and CRC64 implementations, only one
+/// should be built at a time to ensure that crc_simd_body() is inlined
+/// even with compilers with which lzma_always_inline expands to plain inline.
+/// The version to build is selected by defining BUILDING_CRC32_CLMUL or
+/// BUILDING_CRC64_CLMUL before including this file.
+///
+/// FIXME: Builds for 32-bit x86 use the assembly .S files by default
+/// unless configured with --disable-assembler. Even then the lookup table
+/// isn't omitted in crc64_table.c since it doesn't know that assembly
+/// code has been disabled.
+//
+//  Authors:    Ilya Kurdyukov
+//              Hans Jansen
+//              Lasse Collin
+//              Jia Tan
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// This file must not be included more than once.
+#ifdef LZMA_CRC_X86_CLMUL_H
+#	error crc_x86_clmul.h was included twice.
+#endif
+#define LZMA_CRC_X86_CLMUL_H
+
+#include <immintrin.h>
+
+#if defined(_MSC_VER)
+#	include <intrin.h>
+#elif defined(HAVE_CPUID_H)
+#	include <cpuid.h>
+#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.
+//
+// NOTE: Build systems check for this too, keep them in sync with this.
+#if (defined(__GNUC__) || defined(__clang__)) && !defined(__EDG__)
+#	define crc_attr_target \
+		__attribute__((__target__("ssse3,sse4.1,pclmul")))
+#else
+#	define crc_attr_target
+#endif
+
+
+#define MASK_L(in, mask, r) r = _mm_shuffle_epi8(in, mask)
+
+#define MASK_H(in, mask, r) \
+	r = _mm_shuffle_epi8(in, _mm_xor_si128(mask, vsign))
+
+#define MASK_LH(in, mask, low, high) \
+	MASK_L(in, mask, low); \
+	MASK_H(in, mask, high)
+
+
+crc_attr_target
+crc_attr_no_sanitize_address
+static lzma_always_inline void
+crc_simd_body(const uint8_t *buf, const size_t size, __m128i *v0, __m128i *v1,
+		const __m128i vfold16, const __m128i initial_crc)
+{
+	// Create a vector with 8-bit values 0 to 15. This is used to
+	// construct control masks for _mm_blendv_epi8 and _mm_shuffle_epi8.
+	const __m128i vramp = _mm_setr_epi32(
+			0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c);
+
+	// This is used to inverse the control mask of _mm_shuffle_epi8
+	// so that bytes that wouldn't be picked with the original mask
+	// will be picked and vice versa.
+	const __m128i vsign = _mm_set1_epi8(-0x80);
+
+	// Memory addresses A to D and the distances between them:
+	//
+	//     A           B     C         D
+	//     [skip_start][size][skip_end]
+	//     [     size2      ]
+	//
+	// A and D are 16-byte aligned. B and C are 1-byte aligned.
+	// skip_start and skip_end are 0-15 bytes. size is at least 1 byte.
+	//
+	// A = aligned_buf will initially point to this address.
+	// B = The address pointed by the caller-supplied buf.
+	// C = buf + size == aligned_buf + size2
+	// D = buf + size + skip_end == aligned_buf + size2 + skip_end
+	const size_t skip_start = (size_t)((uintptr_t)buf & 15);
+	const size_t skip_end = (size_t)((0U - (uintptr_t)(buf + size)) & 15);
+	const __m128i *aligned_buf = (const __m128i *)(
+			(uintptr_t)buf & ~(uintptr_t)15);
+
+	// If size2 <= 16 then the whole input fits into a single 16-byte
+	// vector. If size2 > 16 then at least two 16-byte vectors must
+	// be processed. If size2 > 16 && size <= 16 then there is only
+	// one 16-byte vector's worth of input but it is unaligned in memory.
+	//
+	// NOTE: There is no integer overflow here if the arguments
+	// are valid. If this overflowed, buf + size would too.
+	const size_t size2 = skip_start + size;
+
+	// Masks to be used with _mm_blendv_epi8 and _mm_shuffle_epi8:
+	// The first skip_start or skip_end bytes in the vectors will have
+	// the high bit (0x80) set. _mm_blendv_epi8 and _mm_shuffle_epi8
+	// will produce zeros for these positions. (Bitwise-xor of these
+	// masks with vsign will produce the opposite behavior.)
+	const __m128i mask_start
+			= _mm_sub_epi8(vramp, _mm_set1_epi8((char)skip_start));
+	const __m128i mask_end
+			= _mm_sub_epi8(vramp, _mm_set1_epi8((char)skip_end));
+
+	// Get the first 1-16 bytes into data0. If loading less than 16
+	// bytes, the bytes are loaded to the high bits of the vector and
+	// the least significant positions are filled with zeros.
+	const __m128i data0 = _mm_blendv_epi8(_mm_load_si128(aligned_buf),
+			_mm_setzero_si128(), mask_start);
+	aligned_buf++;
+
+	__m128i v2, v3;
+
+#ifndef CRC_USE_GENERIC_FOR_SMALL_INPUTS
+	if (size <= 16) {
+		// Right-shift initial_crc by 1-16 bytes based on "size"
+		// and store the result in v1 (high bytes) and v0 (low bytes).
+		//
+		// NOTE: The highest 8 bytes of initial_crc are zeros so
+		// v1 will be filled with zeros if size >= 8. The highest
+		// 8 bytes of v1 will always become zeros.
+		//
+		// [      v1      ][      v0      ]
+		//  [ initial_crc  ]                  size == 1
+		//   [ initial_crc  ]                 size == 2
+		//                [ initial_crc  ]    size == 15
+		//                 [ initial_crc  ]   size == 16 (all in v0)
+		const __m128i mask_low = _mm_add_epi8(
+				vramp, _mm_set1_epi8((char)(size - 16)));
+		MASK_LH(initial_crc, mask_low, *v0, *v1);
+
+		if (size2 <= 16) {
+			// There are 1-16 bytes of input and it is all
+			// in data0. Copy the input bytes to v3. If there
+			// are fewer than 16 bytes, the low bytes in v3
+			// will be filled with zeros. That is, the input
+			// bytes are stored to the same position as
+			// (part of) initial_crc is in v0.
+			MASK_L(data0, mask_end, v3);
+		} else {
+			// There are 2-16 bytes of input but not all bytes
+			// are in data0.
+			const __m128i data1 = _mm_load_si128(aligned_buf);
+
+			// Collect the 2-16 input bytes from data0 and data1
+			// to v2 and v3, and bitwise-xor them with the
+			// low bits of initial_crc in v0. Note that the
+			// the second xor is below this else-block as it
+			// is shared with the other branch.
+			MASK_H(data0, mask_end, v2);
+			MASK_L(data1, mask_end, v3);
+			*v0 = _mm_xor_si128(*v0, v2);
+		}
+
+		*v0 = _mm_xor_si128(*v0, v3);
+		*v1 = _mm_alignr_epi8(*v1, *v0, 8);
+	} else
+#endif
+	{
+		// There is more than 16 bytes of input.
+		const __m128i data1 = _mm_load_si128(aligned_buf);
+		const __m128i *end = (const __m128i*)(
+				(const char *)aligned_buf - 16 + size2);
+		aligned_buf++;
+
+		MASK_LH(initial_crc, mask_start, *v0, *v1);
+		*v0 = _mm_xor_si128(*v0, data0);
+		*v1 = _mm_xor_si128(*v1, data1);
+
+		while (aligned_buf < end) {
+			*v1 = _mm_xor_si128(*v1, _mm_clmulepi64_si128(
+					*v0, vfold16, 0x00));
+			*v0 = _mm_xor_si128(*v1, _mm_clmulepi64_si128(
+					*v0, vfold16, 0x11));
+			*v1 = _mm_load_si128(aligned_buf++);
+		}
+
+		if (aligned_buf != end) {
+			MASK_H(*v0, mask_end, v2);
+			MASK_L(*v0, mask_end, *v0);
+			MASK_L(*v1, mask_end, v3);
+			*v1 = _mm_or_si128(v2, v3);
+		}
+
+		*v1 = _mm_xor_si128(*v1, _mm_clmulepi64_si128(
+				*v0, vfold16, 0x00));
+		*v0 = _mm_xor_si128(*v1, _mm_clmulepi64_si128(
+				*v0, vfold16, 0x11));
+		*v1 = _mm_srli_si128(*v0, 8);
+	}
+}
+
+
+/////////////////////
+// x86 CLMUL CRC32 //
+/////////////////////
+
+/*
+// These functions were used to generate the constants
+// at the top of crc32_arch_optimized().
+static uint64_t
+calc_lo(uint64_t p, uint64_t a, int n)
+{
+	uint64_t b = 0; int i;
+	for (i = 0; i < n; i++) {
+		b = b >> 1 | (a & 1) << (n - 1);
+		a = (a >> 1) ^ ((0 - (a & 1)) & p);
+	}
+	return b;
+}
+
+// same as ~crc(&a, sizeof(a), ~0)
+static uint64_t
+calc_hi(uint64_t p, uint64_t a, int n)
+{
+	int i;
+	for (i = 0; i < n; i++)
+		a = (a >> 1) ^ ((0 - (a & 1)) & p);
+	return a;
+}
+*/
+
+#ifdef BUILDING_CRC32_CLMUL
+
+crc_attr_target
+crc_attr_no_sanitize_address
+static uint32_t
+crc32_arch_optimized(const uint8_t *buf, size_t size, uint32_t crc)
+{
+#ifndef CRC_USE_GENERIC_FOR_SMALL_INPUTS
+	// The code assumes that there is at least one byte of input.
+	if (size == 0)
+		return crc;
+#endif
+
+	// uint32_t poly = 0xedb88320;
+	const int64_t p = 0x1db710640; // p << 1
+	const int64_t mu = 0x1f7011641; // calc_lo(p, p, 32) << 1 | 1
+	const int64_t k5 = 0x163cd6124; // calc_hi(p, p, 32) << 1
+	const int64_t k4 = 0x0ccaa009e; // calc_hi(p, p, 64) << 1
+	const int64_t k3 = 0x1751997d0; // calc_hi(p, p, 128) << 1
+
+	const __m128i vfold4 = _mm_set_epi64x(mu, p);
+	const __m128i vfold8 = _mm_set_epi64x(0, k5);
+	const __m128i vfold16 = _mm_set_epi64x(k4, k3);
+
+	__m128i v0, v1, v2;
+
+	crc_simd_body(buf, size, &v0, &v1, vfold16,
+			_mm_cvtsi32_si128((int32_t)~crc));
+
+	v1 = _mm_xor_si128(
+			_mm_clmulepi64_si128(v0, vfold16, 0x10), v1); // xxx0
+	v2 = _mm_shuffle_epi32(v1, 0xe7); // 0xx0
+	v0 = _mm_slli_epi64(v1, 32);  // [0]
+	v0 = _mm_clmulepi64_si128(v0, vfold8, 0x00);
+	v0 = _mm_xor_si128(v0, v2);   // [1] [2]
+	v2 = _mm_clmulepi64_si128(v0, vfold4, 0x10);
+	v2 = _mm_clmulepi64_si128(v2, vfold4, 0x00);
+	v0 = _mm_xor_si128(v0, v2);   // [2]
+	return ~(uint32_t)_mm_extract_epi32(v0, 2);
+}
+#endif // BUILDING_CRC32_CLMUL
+
+
+/////////////////////
+// x86 CLMUL CRC64 //
+/////////////////////
+
+/*
+// These functions were used to generate the constants
+// at the top of crc64_arch_optimized().
+static uint64_t
+calc_lo(uint64_t poly)
+{
+	uint64_t a = poly;
+	uint64_t b = 0;
+
+	for (unsigned i = 0; i < 64; ++i) {
+		b = (b >> 1) | (a << 63);
+		a = (a >> 1) ^ (a & 1 ? poly : 0);
+	}
+
+	return b;
+}
+
+static uint64_t
+calc_hi(uint64_t poly, uint64_t a)
+{
+	for (unsigned i = 0; i < 64; ++i)
+		a = (a >> 1) ^ (a & 1 ? poly : 0);
+
+	return a;
+}
+*/
+
+#ifdef BUILDING_CRC64_CLMUL
+
+// 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
+// and CRC32 CLMUL aren't affected by this problem. The problem does not
+// happen in crc_simd_body() either (which is shared with CRC32 CLMUL anyway).
+//
+// NOTE: Another pragma after crc64_arch_optimized() 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
+
+crc_attr_target
+crc_attr_no_sanitize_address
+static uint64_t
+crc64_arch_optimized(const uint8_t *buf, size_t size, uint64_t crc)
+{
+#ifndef CRC_USE_GENERIC_FOR_SMALL_INPUTS
+	// The code assumes that there is at least one byte of input.
+	if (size == 0)
+		return crc;
+#endif
+
+	// const uint64_t poly = 0xc96c5795d7870f42; // CRC polynomial
+	const uint64_t p  = 0x92d8af2baf0e1e85; // (poly << 1) | 1
+	const uint64_t mu = 0x9c3e466c172963d5; // (calc_lo(poly) << 1) | 1
+	const uint64_t k2 = 0xdabe95afc7875f40; // calc_hi(poly, 1)
+	const uint64_t k1 = 0xe05dd497ca393ae4; // calc_hi(poly, k2)
+
+	const __m128i vfold8 = _mm_set_epi64x((int64_t)p, (int64_t)mu);
+	const __m128i vfold16 = _mm_set_epi64x((int64_t)k2, (int64_t)k1);
+
+	__m128i v0, v1, v2;
+
+#if defined(__i386__) || defined(_M_IX86)
+	crc_simd_body(buf, size, &v0, &v1, vfold16,
+			_mm_set_epi64x(0, (int64_t)~crc));
+#else
+	// GCC and Clang would produce good code with _mm_set_epi64x
+	// but MSVC needs _mm_cvtsi64_si128 on x86-64.
+	crc_simd_body(buf, size, &v0, &v1, vfold16,
+			_mm_cvtsi64_si128((int64_t)~crc));
+#endif
+
+	v1 = _mm_xor_si128(_mm_clmulepi64_si128(v0, vfold16, 0x10), v1);
+	v0 = _mm_clmulepi64_si128(v1, vfold8, 0x00);
+	v2 = _mm_clmulepi64_si128(v0, vfold8, 0x10);
+	v0 = _mm_xor_si128(_mm_xor_si128(v1, _mm_slli_si128(v0, 8)), v2);
+
+#if defined(__i386__) || defined(_M_IX86)
+	return ~(((uint64_t)(uint32_t)_mm_extract_epi32(v0, 3) << 32) |
+			(uint64_t)(uint32_t)_mm_extract_epi32(v0, 2));
+#else
+	return ~(uint64_t)_mm_extract_epi64(v0, 1);
+#endif
+}
+
+#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__) \
+		&& defined(_M_IX86)
+#	pragma optimize("", on)
+#endif
+
+#endif // BUILDING_CRC64_CLMUL
+
+
+// Even though this is an inline function, compile it only when needed.
+// This way it won't appear in E2K builds at all.
+#if defined(CRC32_GENERIC) || defined(CRC64_GENERIC)
+// Inlining this function duplicates the function body in crc32_resolve() and
+// crc64_resolve(), but this is acceptable because this is a tiny function.
+static inline bool
+is_arch_extension_supported(void)
+{
+	int success = 1;
+	uint32_t r[4]; // eax, ebx, ecx, edx
+
+#if defined(_MSC_VER)
+	// This needs <intrin.h> with MSVC. ICC has it as a built-in
+	// on all platforms.
+	__cpuid(r, 1);
+#elif defined(HAVE_CPUID_H)
+	// Compared to just using __asm__ to run CPUID, this also checks
+	// that CPUID is supported and saves and restores ebx as that is
+	// needed with GCC < 5 with position-independent code (PIC).
+	success = __get_cpuid(1, &r[0], &r[1], &r[2], &r[3]);
+#else
+	// Just a fallback that shouldn't be needed.
+	__asm__("cpuid\n\t"
+			: "=a"(r[0]), "=b"(r[1]), "=c"(r[2]), "=d"(r[3])
+			: "a"(1), "c"(0));
+#endif
+
+	// Returns true if these are supported:
+	// CLMUL (bit 1 in ecx)
+	// SSSE3 (bit 9 in ecx)
+	// SSE4.1 (bit 19 in ecx)
+	const uint32_t ecx_mask = (1 << 1) | (1 << 9) | (1 << 19);
+	return success && (r[2] & ecx_mask) == ecx_mask;
+
+	// Alternative methods that weren't used:
+	//   - ICC's _may_i_use_cpu_feature: the other methods should work too.
+	//   - GCC >= 6 / Clang / ICX __builtin_cpu_supports("pclmul")
+	//
+	// CPUID decoding is needed with MSVC anyway and older GCC. This keeps
+	// the feature checks in the build system simpler too. The nice thing
+	// about __builtin_cpu_supports would be that it generates very short
+	// code as is it only reads a variable set at startup but a few bytes
+	// doesn't matter here.
+}
+#endif

+ 7 - 14
Utilities/cmliblzma/liblzma/check/sha256.c

@@ -1,24 +1,17 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       sha256.c
 /// \file       sha256.c
 /// \brief      SHA-256
 /// \brief      SHA-256
-///
-/// \todo       Crypto++ has x86 ASM optimizations. They use SSE so if they
-///             are imported to liblzma, SSE instructions need to be used
-///             conditionally to keep the code working on older boxes.
 //
 //
-//  This code is based on the code found from 7-Zip, which has a modified
-//  version of the SHA-256 found from Crypto++ <http://www.cryptopp.com/>.
-//  The code was modified a little to fit into liblzma.
+//  The C code is based on the public domain SHA-256 code found from
+//  Crypto++ Library 5.5.1 released in 2007: https://www.cryptopp.com/
+//  A few minor tweaks have been made in liblzma.
 //
 //
-//  Authors:    Kevin Springle
-//              Wei Dai
-//              Igor Pavlov
+//  Authors:    Wei Dai
 //              Lasse Collin
 //              Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "check.h"
 #include "check.h"
@@ -28,7 +21,7 @@
 static inline uint32_t
 static inline uint32_t
 rotr_32(uint32_t num, unsigned amount)
 rotr_32(uint32_t num, unsigned amount)
 {
 {
-        return (num >> amount) | (num << (32 - amount));
+	return (num >> amount) | (num << (32 - amount));
 }
 }
 
 
 #define blk0(i) (W[i] = conv32be(data[i]))
 #define blk0(i) (W[i] = conv32be(data[i]))

+ 17 - 11
Utilities/cmliblzma/liblzma/common/alone_decoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       alone_decoder.c
 /// \file       alone_decoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "alone_decoder.h"
 #include "alone_decoder.h"
@@ -110,12 +109,24 @@ alone_decode(void *coder_ptr, const lzma_allocator *allocator,
 		// Another hack to ditch false positives: Assume that
 		// Another hack to ditch false positives: Assume that
 		// if the uncompressed size is known, it must be less
 		// if the uncompressed size is known, it must be less
 		// than 256 GiB.
 		// than 256 GiB.
+		//
+		// FIXME? Without picky we allow > LZMA_VLI_MAX which doesn't
+		// really matter in this specific situation (> LZMA_VLI_MAX is
+		// safe in the LZMA decoder) but it's somewhat weird still.
 		if (coder->picky
 		if (coder->picky
 				&& coder->uncompressed_size != LZMA_VLI_UNKNOWN
 				&& coder->uncompressed_size != LZMA_VLI_UNKNOWN
 				&& coder->uncompressed_size
 				&& coder->uncompressed_size
 					>= (LZMA_VLI_C(1) << 38))
 					>= (LZMA_VLI_C(1) << 38))
 			return LZMA_FORMAT_ERROR;
 			return LZMA_FORMAT_ERROR;
 
 
+		// Use LZMA_FILTER_LZMA1EXT features to specify the
+		// uncompressed size and that the end marker is allowed
+		// even when the uncompressed size is known. Both .lzma
+		// header and LZMA1EXT use UINT64_MAX indicate that size
+		// is unknown.
+		coder->options.ext_flags = LZMA_LZMA1EXT_ALLOW_EOPM;
+		lzma_set_ext_size(coder->options, coder->uncompressed_size);
+
 		// Calculate the memory usage so that it is ready
 		// Calculate the memory usage so that it is ready
 		// for SEQ_CODER_INIT.
 		// for SEQ_CODER_INIT.
 		coder->memusage = lzma_lzma_decoder_memusage(&coder->options)
 		coder->memusage = lzma_lzma_decoder_memusage(&coder->options)
@@ -132,6 +143,7 @@ alone_decode(void *coder_ptr, const lzma_allocator *allocator,
 
 
 		lzma_filter_info filters[2] = {
 		lzma_filter_info filters[2] = {
 			{
 			{
+				.id = LZMA_FILTER_LZMA1EXT,
 				.init = &lzma_lzma_decoder_init,
 				.init = &lzma_lzma_decoder_init,
 				.options = &coder->options,
 				.options = &coder->options,
 			}, {
 			}, {
@@ -139,14 +151,8 @@ alone_decode(void *coder_ptr, const lzma_allocator *allocator,
 			}
 			}
 		};
 		};
 
 
-		const lzma_ret ret = lzma_next_filter_init(&coder->next,
-				allocator, filters);
-		if (ret != LZMA_OK)
-			return ret;
-
-		// Use a hack to set the uncompressed size.
-		lzma_lz_decoder_uncompressed(coder->next.coder,
-				coder->uncompressed_size);
+		return_if_error(lzma_next_filter_init(&coder->next,
+				allocator, filters));
 
 
 		coder->sequence = SEQ_CODE;
 		coder->sequence = SEQ_CODE;
 		break;
 		break;

+ 2 - 3
Utilities/cmliblzma/liblzma/common/alone_decoder.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       alone_decoder.h
 /// \file       alone_decoder.h
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef LZMA_ALONE_DECODER_H
 #ifndef LZMA_ALONE_DECODER_H

+ 3 - 14
Utilities/cmliblzma/liblzma/common/alone_encoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       alone_encoder.c
 /// \file       alone_encoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "common.h"
 #include "common.h"
@@ -75,7 +74,6 @@ alone_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
 }
 }
 
 
 
 
-// At least for now, this is not used by any internal function.
 static lzma_ret
 static lzma_ret
 alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
 alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
 		const lzma_options_lzma *options)
 		const lzma_options_lzma *options)
@@ -129,6 +127,7 @@ alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
 	// Initialize the LZMA encoder.
 	// Initialize the LZMA encoder.
 	const lzma_filter_info filters[2] = {
 	const lzma_filter_info filters[2] = {
 		{
 		{
+			.id = LZMA_FILTER_LZMA1,
 			.init = &lzma_lzma_encoder_init,
 			.init = &lzma_lzma_encoder_init,
 			.options = (void *)(options),
 			.options = (void *)(options),
 		}, {
 		}, {
@@ -140,16 +139,6 @@ alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
 }
 }
 
 
 
 
-/*
-extern lzma_ret
-lzma_alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
-		const lzma_options_alone *options)
-{
-	lzma_next_coder_init(&alone_encoder_init, next, allocator, options);
-}
-*/
-
-
 extern LZMA_API(lzma_ret)
 extern LZMA_API(lzma_ret)
 lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options)
 lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options)
 {
 {

+ 21 - 11
Utilities/cmliblzma/liblzma/common/auto_decoder.c

@@ -1,21 +1,23 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       auto_decoder.c
 /// \file       auto_decoder.c
-/// \brief      Autodetect between .xz Stream and .lzma (LZMA_Alone) formats
+/// \brief      Autodetect between .xz, .lzma (LZMA_Alone), and .lz (lzip)
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "stream_decoder.h"
 #include "stream_decoder.h"
 #include "alone_decoder.h"
 #include "alone_decoder.h"
+#ifdef HAVE_LZIP_DECODER
+#	include "lzip_decoder.h"
+#endif
 
 
 
 
 typedef struct {
 typedef struct {
-	/// Stream decoder or LZMA_Alone decoder
+	/// .xz Stream decoder, LZMA_Alone decoder, or lzip decoder
 	lzma_next_coder next;
 	lzma_next_coder next;
 
 
 	uint64_t memlimit;
 	uint64_t memlimit;
@@ -46,14 +48,22 @@ auto_decode(void *coder_ptr, const lzma_allocator *allocator,
 		// SEQ_CODE even if we return some LZMA_*_CHECK.
 		// SEQ_CODE even if we return some LZMA_*_CHECK.
 		coder->sequence = SEQ_CODE;
 		coder->sequence = SEQ_CODE;
 
 
-		// Detect the file format. For now this is simple, since if
-		// it doesn't start with 0xFD (the first magic byte of the
-		// new format), it has to be LZMA_Alone, or something that
-		// we don't support at all.
+		// Detect the file format. .xz files start with 0xFD which
+		// cannot be the first byte of .lzma (LZMA_Alone) format.
+		// The .lz format starts with 0x4C which could be the
+		// first byte of a .lzma file but luckily it would mean
+		// lc/lp/pb being 4/3/1 which liblzma doesn't support because
+		// lc + lp > 4. So using just 0x4C to detect .lz is OK here.
 		if (in[*in_pos] == 0xFD) {
 		if (in[*in_pos] == 0xFD) {
 			return_if_error(lzma_stream_decoder_init(
 			return_if_error(lzma_stream_decoder_init(
 					&coder->next, allocator,
 					&coder->next, allocator,
 					coder->memlimit, coder->flags));
 					coder->memlimit, coder->flags));
+#ifdef HAVE_LZIP_DECODER
+		} else if (in[*in_pos] == 0x4C) {
+			return_if_error(lzma_lzip_decoder_init(
+					&coder->next, allocator,
+					coder->memlimit, coder->flags));
+#endif
 		} else {
 		} else {
 			return_if_error(lzma_alone_decoder_init(&coder->next,
 			return_if_error(lzma_alone_decoder_init(&coder->next,
 					allocator, coder->memlimit, true));
 					allocator, coder->memlimit, true));
@@ -86,8 +96,8 @@ auto_decode(void *coder_ptr, const lzma_allocator *allocator,
 	// Fall through
 	// Fall through
 
 
 	case SEQ_FINISH:
 	case SEQ_FINISH:
-		// When LZMA_DECODE_CONCATENATED was used and we were decoding
-		// LZMA_Alone file, we need to check check that there is no
+		// When LZMA_CONCATENATED was used and we were decoding
+		// a LZMA_Alone file, we need to check that there is no
 		// trailing garbage and wait for LZMA_FINISH.
 		// trailing garbage and wait for LZMA_FINISH.
 		if (*in_pos < in_size)
 		if (*in_pos < in_size)
 			return LZMA_DATA_ERROR;
 			return LZMA_DATA_ERROR;

+ 2 - 3
Utilities/cmliblzma/liblzma/common/block_buffer_decoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       block_buffer_decoder.c
 /// \file       block_buffer_decoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "block_decoder.h"
 #include "block_decoder.h"

+ 21 - 4
Utilities/cmliblzma/liblzma/common/block_buffer_encoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       block_buffer_encoder.c
 /// \file       block_buffer_encoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "block_buffer_encoder.h"
 #include "block_buffer_encoder.h"
@@ -277,7 +276,7 @@ block_buffer_encode(lzma_block *block, const lzma_allocator *allocator,
 		if (ret != LZMA_BUF_ERROR)
 		if (ret != LZMA_BUF_ERROR)
 			return ret;
 			return ret;
 
 
-		// The data was uncompressible (at least with the options
+		// The data was incompressible (at least with the options
 		// given to us) or the output buffer was too small. Use the
 		// given to us) or the output buffer was too small. Use the
 		// uncompressed chunks of LZMA2 to wrap the data into a valid
 		// uncompressed chunks of LZMA2 to wrap the data into a valid
 		// Block. If we haven't been given enough output space, even
 		// Block. If we haven't been given enough output space, even
@@ -325,6 +324,24 @@ lzma_block_buffer_encode(lzma_block *block, const lzma_allocator *allocator,
 }
 }
 
 
 
 
+#ifdef HAVE_SYMBOL_VERSIONS_LINUX
+// This is for compatibility with binaries linked against liblzma that
+// has been patched with xz-5.2.2-compat-libs.patch from RHEL/CentOS 7.
+LZMA_SYMVER_API("lzma_block_uncomp_encode@XZ_5.2.2",
+	lzma_ret, lzma_block_uncomp_encode_522)(lzma_block *block,
+		const uint8_t *in, size_t in_size,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+		lzma_nothrow lzma_attr_warn_unused_result
+		__attribute__((__alias__("lzma_block_uncomp_encode_52")));
+
+LZMA_SYMVER_API("lzma_block_uncomp_encode@@XZ_5.2",
+	lzma_ret, lzma_block_uncomp_encode_52)(lzma_block *block,
+		const uint8_t *in, size_t in_size,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+#define lzma_block_uncomp_encode lzma_block_uncomp_encode_52
+#endif
 extern LZMA_API(lzma_ret)
 extern LZMA_API(lzma_ret)
 lzma_block_uncomp_encode(lzma_block *block,
 lzma_block_uncomp_encode(lzma_block *block,
 		const uint8_t *in, size_t in_size,
 		const uint8_t *in, size_t in_size,

+ 2 - 3
Utilities/cmliblzma/liblzma/common/block_buffer_encoder.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       block_buffer_encoder.h
 /// \file       block_buffer_encoder.h
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef LZMA_BLOCK_BUFFER_ENCODER_H
 #ifndef LZMA_BLOCK_BUFFER_ENCODER_H

+ 60 - 29
Utilities/cmliblzma/liblzma/common/block_decoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       block_decoder.c
 /// \file       block_decoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "block_decoder.h"
 #include "block_decoder.h"
@@ -40,6 +39,9 @@ typedef struct {
 	/// is unknown.
 	/// is unknown.
 	lzma_vli compressed_limit;
 	lzma_vli compressed_limit;
 
 
+	/// Maximum allowed Uncompressed Size.
+	lzma_vli uncompressed_limit;
+
 	/// Position when reading the Check field
 	/// Position when reading the Check field
 	size_t check_pos;
 	size_t check_pos;
 
 
@@ -51,21 +53,6 @@ typedef struct {
 } lzma_block_coder;
 } lzma_block_coder;
 
 
 
 
-static inline bool
-update_size(lzma_vli *size, lzma_vli add, lzma_vli limit)
-{
-	if (limit > LZMA_VLI_MAX)
-		limit = LZMA_VLI_MAX;
-
-	if (limit < *size || limit - *size < add)
-		return true;
-
-	*size += add;
-
-	return false;
-}
-
-
 static inline bool
 static inline bool
 is_size_valid(lzma_vli size, lzma_vli reference)
 is_size_valid(lzma_vli size, lzma_vli reference)
 {
 {
@@ -86,23 +73,59 @@ block_decode(void *coder_ptr, const lzma_allocator *allocator,
 		const size_t in_start = *in_pos;
 		const size_t in_start = *in_pos;
 		const size_t out_start = *out_pos;
 		const size_t out_start = *out_pos;
 
 
+		// Limit the amount of input and output space that we give
+		// to the raw decoder based on the information we have
+		// (or don't have) from Block Header.
+		const size_t in_stop = *in_pos + (size_t)my_min(
+			in_size - *in_pos,
+			coder->compressed_limit - coder->compressed_size);
+		const size_t out_stop = *out_pos + (size_t)my_min(
+			out_size - *out_pos,
+			coder->uncompressed_limit - coder->uncompressed_size);
+
 		const lzma_ret ret = coder->next.code(coder->next.coder,
 		const lzma_ret ret = coder->next.code(coder->next.coder,
-				allocator, in, in_pos, in_size,
-				out, out_pos, out_size, action);
+				allocator, in, in_pos, in_stop,
+				out, out_pos, out_stop, action);
 
 
 		const size_t in_used = *in_pos - in_start;
 		const size_t in_used = *in_pos - in_start;
 		const size_t out_used = *out_pos - out_start;
 		const size_t out_used = *out_pos - out_start;
 
 
-		// NOTE: We compare to compressed_limit here, which prevents
-		// the total size of the Block growing past LZMA_VLI_MAX.
-		if (update_size(&coder->compressed_size, in_used,
-					coder->compressed_limit)
-				|| update_size(&coder->uncompressed_size,
-					out_used,
-					coder->block->uncompressed_size))
-			return LZMA_DATA_ERROR;
+		// Because we have limited the input and output sizes,
+		// we know that these cannot grow too big or overflow.
+		coder->compressed_size += in_used;
+		coder->uncompressed_size += out_used;
+
+		if (ret == LZMA_OK) {
+			const bool comp_done = coder->compressed_size
+					== coder->block->compressed_size;
+			const bool uncomp_done = coder->uncompressed_size
+					== coder->block->uncompressed_size;
+
+			// If both input and output amounts match the sizes
+			// in Block Header but we still got LZMA_OK instead
+			// of LZMA_STREAM_END, the file is broken.
+			if (comp_done && uncomp_done)
+				return LZMA_DATA_ERROR;
 
 
-		if (!coder->ignore_check)
+			// If the decoder has consumed all the input that it
+			// needs but it still couldn't fill the output buffer
+			// or return LZMA_STREAM_END, the file is broken.
+			if (comp_done && *out_pos < out_size)
+				return LZMA_DATA_ERROR;
+
+			// If the decoder has produced all the output but
+			// it still didn't return LZMA_STREAM_END or consume
+			// more input (for example, detecting an end of
+			// payload marker may need more input but produce
+			// no output) the file is broken.
+			if (uncomp_done && *in_pos < in_size)
+				return LZMA_DATA_ERROR;
+		}
+
+		// Don't waste time updating the integrity check if it will be
+		// ignored. Also skip it if no new output was produced. This
+		// avoids null pointer + 0 (undefined behavior) when out == 0.
+		if (!coder->ignore_check && out_used > 0)
 			lzma_check_update(&coder->check, coder->block->check,
 			lzma_check_update(&coder->check, coder->block->check,
 					out + out_start, out_used);
 					out + out_start, out_used);
 
 
@@ -230,6 +253,14 @@ lzma_block_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
 					- lzma_check_size(block->check)
 					- lzma_check_size(block->check)
 				: block->compressed_size;
 				: block->compressed_size;
 
 
+	// With Uncompressed Size this is simpler. If Block Header lacks
+	// the size info, then LZMA_VLI_MAX is the maximum possible
+	// Uncompressed Size.
+	coder->uncompressed_limit
+			= block->uncompressed_size == LZMA_VLI_UNKNOWN
+				? LZMA_VLI_MAX
+				: block->uncompressed_size;
+
 	// Initialize the check. It's caller's problem if the Check ID is not
 	// Initialize the check. It's caller's problem if the Check ID is not
 	// supported, and the Block decoder cannot verify the Check field.
 	// supported, and the Block decoder cannot verify the Check field.
 	// Caller can test lzma_check_is_supported(block->check).
 	// Caller can test lzma_check_is_supported(block->check).

+ 2 - 3
Utilities/cmliblzma/liblzma/common/block_decoder.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       block_decoder.h
 /// \file       block_decoder.h
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef LZMA_BLOCK_DECODER_H
 #ifndef LZMA_BLOCK_DECODER_H

+ 8 - 5
Utilities/cmliblzma/liblzma/common/block_encoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       block_encoder.c
 /// \file       block_encoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "block_encoder.h"
 #include "block_encoder.h"
@@ -77,8 +76,11 @@ block_encode(void *coder_ptr, const lzma_allocator *allocator,
 		// checked it at the beginning of this function.
 		// checked it at the beginning of this function.
 		coder->uncompressed_size += in_used;
 		coder->uncompressed_size += in_used;
 
 
-		lzma_check_update(&coder->check, coder->block->check,
-				in + in_start, in_used);
+		// Call lzma_check_update() only if input was consumed. This
+		// avoids null pointer + 0 (undefined behavior) when in == 0.
+		if (in_used > 0)
+			lzma_check_update(&coder->check, coder->block->check,
+					in + in_start, in_used);
 
 
 		if (ret != LZMA_STREAM_END || action == LZMA_SYNC_FLUSH)
 		if (ret != LZMA_STREAM_END || action == LZMA_SYNC_FLUSH)
 			return ret;
 			return ret;
@@ -217,6 +219,7 @@ lzma_block_encoder(lzma_stream *strm, lzma_block *block)
 	lzma_next_strm_init(lzma_block_encoder_init, strm, block);
 	lzma_next_strm_init(lzma_block_encoder_init, strm, block);
 
 
 	strm->internal->supported_actions[LZMA_RUN] = true;
 	strm->internal->supported_actions[LZMA_RUN] = true;
+	strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
 	strm->internal->supported_actions[LZMA_FINISH] = true;
 	strm->internal->supported_actions[LZMA_FINISH] = true;
 
 
 	return LZMA_OK;
 	return LZMA_OK;

+ 2 - 3
Utilities/cmliblzma/liblzma/common/block_encoder.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       block_encoder.h
 /// \file       block_encoder.h
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef LZMA_BLOCK_ENCODER_H
 #ifndef LZMA_BLOCK_ENCODER_H

+ 12 - 22
Utilities/cmliblzma/liblzma/common/block_header_decoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       block_header_decoder.c
 /// \file       block_header_decoder.c
@@ -5,31 +7,12 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "common.h"
 #include "common.h"
 #include "check.h"
 #include "check.h"
 
 
 
 
-static void
-free_properties(lzma_block *block, const lzma_allocator *allocator)
-{
-	// Free allocated filter options. The last array member is not
-	// touched after the initialization in the beginning of
-	// lzma_block_header_decode(), so we don't need to touch that here.
-	for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i) {
-		lzma_free(block->filters[i].options, allocator);
-		block->filters[i].id = LZMA_VLI_UNKNOWN;
-		block->filters[i].options = NULL;
-	}
-
-	return;
-}
-
-
 extern LZMA_API(lzma_ret)
 extern LZMA_API(lzma_ret)
 lzma_block_header_decode(lzma_block *block,
 lzma_block_header_decode(lzma_block *block,
 		const lzma_allocator *allocator, const uint8_t *in)
 		const lzma_allocator *allocator, const uint8_t *in)
@@ -39,6 +22,10 @@ lzma_block_header_decode(lzma_block *block,
 	// are invalid or over 63 bits, or if the header is too small
 	// are invalid or over 63 bits, or if the header is too small
 	// to contain the claimed information.
 	// to contain the claimed information.
 
 
+	// Catch unexpected NULL pointers.
+	if (block == NULL || block->filters == NULL || in == NULL)
+		return LZMA_PROG_ERROR;
+
 	// Initialize the filter options array. This way the caller can
 	// Initialize the filter options array. This way the caller can
 	// safely free() the options even if an error occurs in this function.
 	// safely free() the options even if an error occurs in this function.
 	for (size_t i = 0; i <= LZMA_FILTERS_MAX; ++i) {
 	for (size_t i = 0; i <= LZMA_FILTERS_MAX; ++i) {
@@ -67,8 +54,11 @@ lzma_block_header_decode(lzma_block *block,
 	const size_t in_size = block->header_size - 4;
 	const size_t in_size = block->header_size - 4;
 
 
 	// Verify CRC32
 	// Verify CRC32
-	if (lzma_crc32(in, in_size, 0) != read32le(in + in_size))
+	if (lzma_crc32(in, in_size, 0) != read32le(in + in_size)) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
 		return LZMA_DATA_ERROR;
 		return LZMA_DATA_ERROR;
+#endif
+	}
 
 
 	// Check for unsupported flags.
 	// Check for unsupported flags.
 	if (in[1] & 0x3C)
 	if (in[1] & 0x3C)
@@ -104,7 +94,7 @@ lzma_block_header_decode(lzma_block *block,
 				&block->filters[i], allocator,
 				&block->filters[i], allocator,
 				in, &in_pos, in_size);
 				in, &in_pos, in_size);
 		if (ret != LZMA_OK) {
 		if (ret != LZMA_OK) {
-			free_properties(block, allocator);
+			lzma_filters_free(block->filters, allocator);
 			return ret;
 			return ret;
 		}
 		}
 	}
 	}
@@ -112,7 +102,7 @@ lzma_block_header_decode(lzma_block *block,
 	// Padding
 	// Padding
 	while (in_pos < in_size) {
 	while (in_pos < in_size) {
 		if (in[in_pos++] != 0x00) {
 		if (in[in_pos++] != 0x00) {
-			free_properties(block, allocator);
+			lzma_filters_free(block->filters, allocator);
 
 
 			// Possibly some new field present so use
 			// Possibly some new field present so use
 			// LZMA_OPTIONS_ERROR instead of LZMA_DATA_ERROR.
 			// LZMA_OPTIONS_ERROR instead of LZMA_DATA_ERROR.

+ 2 - 3
Utilities/cmliblzma/liblzma/common/block_header_encoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       block_header_encoder.c
 /// \file       block_header_encoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "common.h"
 #include "common.h"

+ 2 - 3
Utilities/cmliblzma/liblzma/common/block_util.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       block_util.c
 /// \file       block_util.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "common.h"
 #include "common.h"

+ 46 - 15
Utilities/cmliblzma/liblzma/common/common.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       common.c
 /// \file       common.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "common.h"
 #include "common.h"
@@ -35,7 +34,8 @@ lzma_version_string(void)
 // Memory allocation //
 // 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)
 lzma_alloc(size_t size, const lzma_allocator *allocator)
 {
 {
 	// Some malloc() variants return NULL if called with size == 0.
 	// Some malloc() variants return NULL if called with size == 0.
@@ -53,7 +53,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)
 lzma_alloc_zero(size_t size, const lzma_allocator *allocator)
 {
 {
 	// Some calloc() variants return NULL if called with size == 0.
 	// Some calloc() variants return NULL if called with size == 0.
@@ -211,7 +212,6 @@ lzma_code(lzma_stream *strm, lzma_action action)
 			|| strm->reserved_ptr2 != NULL
 			|| strm->reserved_ptr2 != NULL
 			|| strm->reserved_ptr3 != NULL
 			|| strm->reserved_ptr3 != NULL
 			|| strm->reserved_ptr4 != NULL
 			|| strm->reserved_ptr4 != NULL
-			|| strm->reserved_int1 != 0
 			|| strm->reserved_int2 != 0
 			|| strm->reserved_int2 != 0
 			|| strm->reserved_int3 != 0
 			|| strm->reserved_int3 != 0
 			|| strm->reserved_int4 != 0
 			|| strm->reserved_int4 != 0
@@ -289,19 +289,25 @@ lzma_code(lzma_stream *strm, lzma_action action)
 			strm->next_in, &in_pos, strm->avail_in,
 			strm->next_in, &in_pos, strm->avail_in,
 			strm->next_out, &out_pos, strm->avail_out, action);
 			strm->next_out, &out_pos, strm->avail_out, action);
 
 
-	strm->next_in += in_pos;
-	strm->avail_in -= in_pos;
-	strm->total_in += in_pos;
+	// Updating next_in and next_out has to be skipped when they are NULL
+	// to avoid null pointer + 0 (undefined behavior). Do this by checking
+	// in_pos > 0 and out_pos > 0 because this way NULL + non-zero (a bug)
+	// will get caught one way or other.
+	if (in_pos > 0) {
+		strm->next_in += in_pos;
+		strm->avail_in -= in_pos;
+		strm->total_in += in_pos;
+	}
 
 
-	strm->next_out += out_pos;
-	strm->avail_out -= out_pos;
-	strm->total_out += out_pos;
+	if (out_pos > 0) {
+		strm->next_out += out_pos;
+		strm->avail_out -= out_pos;
+		strm->total_out += out_pos;
+	}
 
 
 	strm->internal->avail_in = strm->avail_in;
 	strm->internal->avail_in = strm->avail_in;
 
 
-	// Cast is needed to silence a warning about LZMA_TIMED_OUT, which
-	// isn't part of lzma_ret enumeration.
-	switch ((unsigned int)(ret)) {
+	switch (ret) {
 	case LZMA_OK:
 	case LZMA_OK:
 		// Don't return LZMA_BUF_ERROR when it happens the first time.
 		// Don't return LZMA_BUF_ERROR when it happens the first time.
 		// This is to avoid returning LZMA_BUF_ERROR when avail_out
 		// This is to avoid returning LZMA_BUF_ERROR when avail_out
@@ -322,6 +328,17 @@ lzma_code(lzma_stream *strm, lzma_action action)
 		ret = LZMA_OK;
 		ret = LZMA_OK;
 		break;
 		break;
 
 
+	case LZMA_SEEK_NEEDED:
+		strm->internal->allow_buf_error = false;
+
+		// If LZMA_FINISH was used, reset it back to the
+		// LZMA_RUN-based state so that new input can be supplied
+		// by the application.
+		if (strm->internal->sequence == ISEQ_FINISH)
+			strm->internal->sequence = ISEQ_RUN;
+
+		break;
+
 	case LZMA_STREAM_END:
 	case LZMA_STREAM_END:
 		if (strm->internal->sequence == ISEQ_SYNC_FLUSH
 		if (strm->internal->sequence == ISEQ_SYNC_FLUSH
 				|| strm->internal->sequence == ISEQ_FULL_FLUSH
 				|| strm->internal->sequence == ISEQ_FULL_FLUSH
@@ -366,6 +383,20 @@ lzma_end(lzma_stream *strm)
 }
 }
 
 
 
 
+#ifdef HAVE_SYMBOL_VERSIONS_LINUX
+// This is for compatibility with binaries linked against liblzma that
+// has been patched with xz-5.2.2-compat-libs.patch from RHEL/CentOS 7.
+LZMA_SYMVER_API("lzma_get_progress@XZ_5.2.2",
+	void, lzma_get_progress_522)(lzma_stream *strm,
+		uint64_t *progress_in, uint64_t *progress_out) lzma_nothrow
+		__attribute__((__alias__("lzma_get_progress_52")));
+
+LZMA_SYMVER_API("lzma_get_progress@@XZ_5.2",
+	void, lzma_get_progress_52)(lzma_stream *strm,
+		uint64_t *progress_in, uint64_t *progress_out) lzma_nothrow;
+
+#define lzma_get_progress lzma_get_progress_52
+#endif
 extern LZMA_API(void)
 extern LZMA_API(void)
 lzma_get_progress(lzma_stream *strm,
 lzma_get_progress(lzma_stream *strm,
 		uint64_t *progress_in, uint64_t *progress_out)
 		uint64_t *progress_in, uint64_t *progress_out)

+ 113 - 15
Utilities/cmliblzma/liblzma/common/common.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       common.h
 /// \file       common.h
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef LZMA_COMMON_H
 #ifndef LZMA_COMMON_H
@@ -17,23 +16,104 @@
 #include "mythread.h"
 #include "mythread.h"
 #include "tuklib_integer.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__)
 #if defined(_WIN32) || defined(__CYGWIN__)
 #	ifdef DLL_EXPORT
 #	ifdef DLL_EXPORT
 #		define LZMA_API_EXPORT __declspec(dllexport)
 #		define LZMA_API_EXPORT __declspec(dllexport)
 #	else
 #	else
 #		define LZMA_API_EXPORT
 #		define LZMA_API_EXPORT
 #	endif
 #	endif
+#	define lzma_attr_visibility_hidden
 // Don't use ifdef or defined() below.
 // Don't use ifdef or defined() below.
 #elif HAVE_VISIBILITY
 #elif HAVE_VISIBILITY
 #	define LZMA_API_EXPORT __attribute__((__visibility__("default")))
 #	define LZMA_API_EXPORT __attribute__((__visibility__("default")))
+#	define lzma_attr_visibility_hidden \
+			__attribute__((__visibility__("hidden")))
 #else
 #else
 #	define LZMA_API_EXPORT
 #	define LZMA_API_EXPORT
+#	define lzma_attr_visibility_hidden
 #endif
 #endif
 
 
 #define LZMA_API(type) LZMA_API_EXPORT type LZMA_API_CALL
 #define LZMA_API(type) LZMA_API_EXPORT type LZMA_API_CALL
 
 
 #include "lzma.h"
 #include "lzma.h"
 
 
+// This is for detecting modern GCC and Clang attributes
+// like __symver__ in GCC >= 10.
+#ifdef __has_attribute
+#	define lzma_has_attribute(attr) __has_attribute(attr)
+#else
+#	define lzma_has_attribute(attr) 0
+#endif
+
+// The extra symbol versioning in the C files may only be used when
+// building a shared library. If HAVE_SYMBOL_VERSIONS_LINUX is defined
+// to 2 then symbol versioning is done only if also PIC is defined.
+// By default Libtool defines PIC when building a shared library and
+// doesn't define it when building a static library but it can be
+// overridden with --with-pic and --without-pic. configure let's rely
+// on PIC if neither --with-pic or --without-pic was used.
+#if defined(HAVE_SYMBOL_VERSIONS_LINUX) \
+		&& (HAVE_SYMBOL_VERSIONS_LINUX == 2 && !defined(PIC))
+#	undef HAVE_SYMBOL_VERSIONS_LINUX
+#endif
+
+#ifdef HAVE_SYMBOL_VERSIONS_LINUX
+// To keep link-time optimization (LTO, -flto) working with GCC,
+// the __symver__ attribute must be used instead of __asm__(".symver ...").
+// Otherwise the symbol versions may be lost, resulting in broken liblzma
+// that has wrong default versions in the exported symbol list!
+// The attribute was added in GCC 10; LTO with older GCC is not supported.
+//
+// To keep -Wmissing-prototypes happy, use LZMA_SYMVER_API only with function
+// declarations (including those with __alias__ attribute) and LZMA_API with
+// the function definitions. This means a little bit of silly copy-and-paste
+// between declarations and definitions though.
+//
+// As of GCC 12.2, the __symver__ attribute supports only @ and @@ but the
+// very convenient @@@ isn't supported (it's supported by GNU assembler
+// since 2000). When using @@ instead of @@@, the internal name must not be
+// the same as the external name to avoid problems in some situations. This
+// is why "#define foo_52 foo" is needed for the default symbol versions.
+//
+// __has_attribute is supported before GCC 10 and it is supported in Clang 14
+// too (which doesn't support __symver__) so use it to detect if __symver__
+// is available. This should be far more reliable than looking at compiler
+// version macros as nowadays especially __GNUC__ is defined by many compilers.
+#	if lzma_has_attribute(__symver__)
+#		define LZMA_SYMVER_API(extnamever, type, intname) \
+			extern __attribute__((__symver__(extnamever))) \
+					LZMA_API(type) intname
+#	else
+#		define LZMA_SYMVER_API(extnamever, type, intname) \
+			__asm__(".symver " #intname "," extnamever); \
+			extern LZMA_API(type) intname
+#	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
 // These allow helping the compiler in some often-executed branches, whose
 // result is almost always the same.
 // result is almost always the same.
 #ifdef __GNUC__
 #ifdef __GNUC__
@@ -67,14 +147,15 @@
 #define LZMA_FILTER_RESERVED_START (LZMA_VLI_C(1) << 62)
 #define LZMA_FILTER_RESERVED_START (LZMA_VLI_C(1) << 62)
 
 
 
 
-/// Supported flags that can be passed to lzma_stream_decoder()
-/// or lzma_auto_decoder().
+/// Supported flags that can be passed to lzma_stream_decoder(),
+/// lzma_auto_decoder(), or lzma_stream_decoder_mt().
 #define LZMA_SUPPORTED_FLAGS \
 #define LZMA_SUPPORTED_FLAGS \
 	( LZMA_TELL_NO_CHECK \
 	( LZMA_TELL_NO_CHECK \
 	| LZMA_TELL_UNSUPPORTED_CHECK \
 	| LZMA_TELL_UNSUPPORTED_CHECK \
 	| LZMA_TELL_ANY_CHECK \
 	| LZMA_TELL_ANY_CHECK \
 	| LZMA_IGNORE_CHECK \
 	| LZMA_IGNORE_CHECK \
-	| LZMA_CONCATENATED )
+	| LZMA_CONCATENATED \
+	| LZMA_FAIL_FAST )
 
 
 
 
 /// Largest valid lzma_action value as unsigned integer.
 /// Largest valid lzma_action value as unsigned integer.
@@ -83,9 +164,12 @@
 
 
 /// Special return value (lzma_ret) to indicate that a timeout was reached
 /// Special return value (lzma_ret) to indicate that a timeout was reached
 /// and lzma_code() must not return LZMA_BUF_ERROR. This is converted to
 /// and lzma_code() must not return LZMA_BUF_ERROR. This is converted to
-/// LZMA_OK in lzma_code(). This is not in the lzma_ret enumeration because
-/// there's no need to have it in the public API.
-#define LZMA_TIMED_OUT 32
+/// LZMA_OK in lzma_code().
+#define LZMA_TIMED_OUT LZMA_RET_INTERNAL1
+
+/// Special return value (lzma_ret) for use in stream_decoder_mt.c to
+/// indicate Index was detected instead of a Block Header.
+#define LZMA_INDEX_DETECTED LZMA_RET_INTERNAL2
 
 
 
 
 typedef struct lzma_next_coder_s lzma_next_coder;
 typedef struct lzma_next_coder_s lzma_next_coder;
@@ -118,8 +202,11 @@ typedef void (*lzma_end_function)(
 /// an array of lzma_filter_info structures. This array is used with
 /// an array of lzma_filter_info structures. This array is used with
 /// lzma_next_filter_init to initialize the filter chain.
 /// lzma_next_filter_init to initialize the filter chain.
 struct lzma_filter_info_s {
 struct lzma_filter_info_s {
-	/// Filter ID. This is used only by the encoder
-	/// with lzma_filters_update().
+	/// Filter ID. This can be used to share the same initiazation
+	/// function *and* data structures with different Filter IDs
+	/// (LZMA_FILTER_LZMA1EXT does it), and also by the encoder
+	/// with lzma_filters_update() if filter chain is updated
+	/// in the middle of a raw stream or Block (LZMA_SYNC_FLUSH).
 	lzma_vli id;
 	lzma_vli id;
 
 
 	/// Pointer to function used to initialize the filter.
 	/// Pointer to function used to initialize the filter.
@@ -173,6 +260,16 @@ struct lzma_next_coder_s {
 	lzma_ret (*update)(void *coder, const lzma_allocator *allocator,
 	lzma_ret (*update)(void *coder, const lzma_allocator *allocator,
 			const lzma_filter *filters,
 			const lzma_filter *filters,
 			const lzma_filter *reversed_filters);
 			const lzma_filter *reversed_filters);
+
+	/// Set how many bytes of output this coder may produce at maximum.
+	/// On success LZMA_OK must be returned.
+	/// If the filter chain as a whole cannot support this feature,
+	/// this must return LZMA_OPTIONS_ERROR.
+	/// If no input has been given to the coder and the requested limit
+	/// is too small, this must return LZMA_BUF_ERROR. If input has been
+	/// seen, LZMA_OK is allowed too.
+	lzma_ret (*set_out_limit)(void *coder, uint64_t *uncomp_size,
+			uint64_t out_limit);
 };
 };
 
 
 
 
@@ -188,6 +285,7 @@ struct lzma_next_coder_s {
 		.get_check = NULL, \
 		.get_check = NULL, \
 		.memconfig = NULL, \
 		.memconfig = NULL, \
 		.update = NULL, \
 		.update = NULL, \
+		.set_out_limit = NULL, \
 	}
 	}
 
 
 
 
@@ -226,14 +324,14 @@ struct lzma_internal_s {
 
 
 
 
 /// Allocates memory
 /// 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
 /// Allocates memory and zeroes it (like calloc()). This can be faster
 /// than lzma_alloc() + memzero() while being backward compatible with
 /// than lzma_alloc() + memzero() while being backward compatible with
 /// custom allocators.
 /// 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
 /// Frees memory
 extern void lzma_free(void *ptr, const lzma_allocator *allocator);
 extern void lzma_free(void *ptr, const lzma_allocator *allocator);

+ 2 - 3
Utilities/cmliblzma/liblzma/common/easy_buffer_encoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       easy_buffer_encoder.c
 /// \file       easy_buffer_encoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "easy_preset.h"
 #include "easy_preset.h"

+ 2 - 3
Utilities/cmliblzma/liblzma/common/easy_decoder_memusage.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       easy_decoder_memusage.c
 /// \file       easy_decoder_memusage.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "easy_preset.h"
 #include "easy_preset.h"

+ 2 - 3
Utilities/cmliblzma/liblzma/common/easy_encoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       easy_encoder.c
 /// \file       easy_encoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "easy_preset.h"
 #include "easy_preset.h"

+ 2 - 3
Utilities/cmliblzma/liblzma/common/easy_encoder_memusage.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       easy_encoder_memusage.c
 /// \file       easy_encoder_memusage.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "easy_preset.h"
 #include "easy_preset.h"

+ 2 - 3
Utilities/cmliblzma/liblzma/common/easy_preset.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       easy_preset.c
 /// \file       easy_preset.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "easy_preset.h"
 #include "easy_preset.h"

+ 7 - 3
Utilities/cmliblzma/liblzma/common/easy_preset.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       easy_preset.h
 /// \file       easy_preset.h
@@ -5,11 +7,11 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
+#ifndef LZMA_EASY_PRESET_H
+#define LZMA_EASY_PRESET_H
+
 #include "common.h"
 #include "common.h"
 
 
 
 
@@ -30,3 +32,5 @@ typedef struct {
 /// Set *easy to the settings given by the preset. Returns true on error,
 /// Set *easy to the settings given by the preset. Returns true on error,
 /// false on success.
 /// false on success.
 extern bool lzma_easy_preset(lzma_options_easy *easy, uint32_t preset);
 extern bool lzma_easy_preset(lzma_options_easy *easy, uint32_t preset);
+
+#endif

+ 854 - 0
Utilities/cmliblzma/liblzma/common/file_info.c

@@ -0,0 +1,854 @@
+// SPDX-License-Identifier: 0BSD
+
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       file_info.c
+/// \brief      Decode .xz file information into a lzma_index structure
+//
+//  Author:     Lasse Collin
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "index_decoder.h"
+
+
+typedef struct {
+	enum {
+		SEQ_MAGIC_BYTES,
+		SEQ_PADDING_SEEK,
+		SEQ_PADDING_DECODE,
+		SEQ_FOOTER,
+		SEQ_INDEX_INIT,
+		SEQ_INDEX_DECODE,
+		SEQ_HEADER_DECODE,
+		SEQ_HEADER_COMPARE,
+	} sequence;
+
+	/// Absolute position of in[*in_pos] in the file. All code that
+	/// modifies *in_pos also updates this. seek_to_pos() needs this
+	/// to determine if we need to request the application to seek for
+	/// us or if we can do the seeking internally by adjusting *in_pos.
+	uint64_t file_cur_pos;
+
+	/// This refers to absolute positions of interesting parts of the
+	/// input file. Sometimes it points to the *beginning* of a specific
+	/// field and sometimes to the *end* of a field. The current target
+	/// position at each moment is explained in the comments.
+	uint64_t file_target_pos;
+
+	/// Size of the .xz file (from the application).
+	uint64_t file_size;
+
+	/// Index decoder
+	lzma_next_coder index_decoder;
+
+	/// Number of bytes remaining in the Index field that is currently
+	/// being decoded.
+	lzma_vli index_remaining;
+
+	/// The Index decoder will store the decoded Index in this pointer.
+	lzma_index *this_index;
+
+	/// Amount of Stream Padding in the current Stream.
+	lzma_vli stream_padding;
+
+	/// The final combined index is collected here.
+	lzma_index *combined_index;
+
+	/// Pointer from the application where to store the index information
+	/// after successful decoding.
+	lzma_index **dest_index;
+
+	/// Pointer to lzma_stream.seek_pos to be used when returning
+	/// LZMA_SEEK_NEEDED. This is set by seek_to_pos() when needed.
+	uint64_t *external_seek_pos;
+
+	/// Memory usage limit
+	uint64_t memlimit;
+
+	/// Stream Flags from the very beginning of the file.
+	lzma_stream_flags first_header_flags;
+
+	/// Stream Flags from Stream Header of the current Stream.
+	lzma_stream_flags header_flags;
+
+	/// Stream Flags from Stream Footer of the current Stream.
+	lzma_stream_flags footer_flags;
+
+	size_t temp_pos;
+	size_t temp_size;
+	uint8_t temp[8192];
+
+} lzma_file_info_coder;
+
+
+/// Copies data from in[*in_pos] into coder->temp until
+/// coder->temp_pos == coder->temp_size. This also keeps coder->file_cur_pos
+/// in sync with *in_pos. Returns true if more input is needed.
+static bool
+fill_temp(lzma_file_info_coder *coder, const uint8_t *restrict in,
+		size_t *restrict in_pos, size_t in_size)
+{
+	coder->file_cur_pos += lzma_bufcpy(in, in_pos, in_size,
+			coder->temp, &coder->temp_pos, coder->temp_size);
+	return coder->temp_pos < coder->temp_size;
+}
+
+
+/// Seeks to the absolute file position specified by target_pos.
+/// This tries to do the seeking by only modifying *in_pos, if possible.
+/// The main benefit of this is that if one passes the whole file at once
+/// to lzma_code(), the decoder will never need to return LZMA_SEEK_NEEDED
+/// as all the seeking can be done by adjusting *in_pos in this function.
+///
+/// Returns true if an external seek is needed and the caller must return
+/// LZMA_SEEK_NEEDED.
+static bool
+seek_to_pos(lzma_file_info_coder *coder, uint64_t target_pos,
+		size_t in_start, size_t *in_pos, size_t in_size)
+{
+	// The input buffer doesn't extend beyond the end of the file.
+	// This has been checked by file_info_decode() already.
+	assert(coder->file_size - coder->file_cur_pos >= in_size - *in_pos);
+
+	const uint64_t pos_min = coder->file_cur_pos - (*in_pos - in_start);
+	const uint64_t pos_max = coder->file_cur_pos + (in_size - *in_pos);
+
+	bool external_seek_needed;
+
+	if (target_pos >= pos_min && target_pos <= pos_max) {
+		// The requested position is available in the current input
+		// buffer or right after it. That is, in a corner case we
+		// end up setting *in_pos == in_size and thus will immediately
+		// need new input bytes from the application.
+		*in_pos += (size_t)(target_pos - coder->file_cur_pos);
+		external_seek_needed = false;
+	} else {
+		// Ask the application to seek the input file.
+		*coder->external_seek_pos = target_pos;
+		external_seek_needed = true;
+
+		// Mark the whole input buffer as used. This way
+		// lzma_stream.total_in will have a better estimate
+		// of the amount of data read. It still won't be perfect
+		// as the value will depend on the input buffer size that
+		// the application uses, but it should be good enough for
+		// those few who want an estimate.
+		*in_pos = in_size;
+	}
+
+	// After seeking (internal or external) the current position
+	// will match the requested target position.
+	coder->file_cur_pos = target_pos;
+
+	return external_seek_needed;
+}
+
+
+/// The caller sets coder->file_target_pos so that it points to the *end*
+/// of the desired file position. This function then determines how far
+/// backwards from that position we can seek. After seeking fill_temp()
+/// can be used to read data into coder->temp. When fill_temp() has finished,
+/// coder->temp[coder->temp_size] will match coder->file_target_pos.
+///
+/// This also validates that coder->target_file_pos is sane in sense that
+/// we aren't trying to seek too far backwards (too close or beyond the
+/// beginning of the file).
+static lzma_ret
+reverse_seek(lzma_file_info_coder *coder,
+		size_t in_start, size_t *in_pos, size_t in_size)
+{
+	// Check that there is enough data before the target position
+	// to contain at least Stream Header and Stream Footer. If there
+	// isn't, the file cannot be valid.
+	if (coder->file_target_pos < 2 * LZMA_STREAM_HEADER_SIZE)
+		return LZMA_DATA_ERROR;
+
+	coder->temp_pos = 0;
+
+	// The Stream Header at the very beginning of the file gets handled
+	// specially in SEQ_MAGIC_BYTES and thus we will never need to seek
+	// there. By not seeking to the first LZMA_STREAM_HEADER_SIZE bytes
+	// we avoid a useless external seek after SEQ_MAGIC_BYTES if the
+	// application uses an extremely small input buffer and the input
+	// file is very small.
+	if (coder->file_target_pos - LZMA_STREAM_HEADER_SIZE
+			< sizeof(coder->temp))
+		coder->temp_size = (size_t)(coder->file_target_pos
+				- LZMA_STREAM_HEADER_SIZE);
+	else
+		coder->temp_size = sizeof(coder->temp);
+
+	// The above if-statements guarantee this. This is important because
+	// the Stream Header/Footer decoders assume that there's at least
+	// LZMA_STREAM_HEADER_SIZE bytes in coder->temp.
+	assert(coder->temp_size >= LZMA_STREAM_HEADER_SIZE);
+
+	if (seek_to_pos(coder, coder->file_target_pos - coder->temp_size,
+			in_start, in_pos, in_size))
+		return LZMA_SEEK_NEEDED;
+
+	return LZMA_OK;
+}
+
+
+/// Gets the number of zero-bytes at the end of the buffer.
+static size_t
+get_padding_size(const uint8_t *buf, size_t buf_size)
+{
+	size_t padding = 0;
+	while (buf_size > 0 && buf[--buf_size] == 0x00)
+		++padding;
+
+	return padding;
+}
+
+
+/// With the Stream Header at the very beginning of the file, LZMA_FORMAT_ERROR
+/// is used to tell the application that Magic Bytes didn't match. In other
+/// Stream Header/Footer fields (in the middle/end of the file) it could be
+/// a bit confusing to return LZMA_FORMAT_ERROR as we already know that there
+/// is a valid Stream Header at the beginning of the file. For those cases
+/// this function is used to convert LZMA_FORMAT_ERROR to LZMA_DATA_ERROR.
+static lzma_ret
+hide_format_error(lzma_ret ret)
+{
+	if (ret == LZMA_FORMAT_ERROR)
+		ret = LZMA_DATA_ERROR;
+
+	return ret;
+}
+
+
+/// Calls the Index decoder and updates coder->index_remaining.
+/// This is a separate function because the input can be either directly
+/// from the application or from coder->temp.
+static lzma_ret
+decode_index(lzma_file_info_coder *coder, const lzma_allocator *allocator,
+		const uint8_t *restrict in, size_t *restrict in_pos,
+		size_t in_size, bool update_file_cur_pos)
+{
+	const size_t in_start = *in_pos;
+
+	const lzma_ret ret = coder->index_decoder.code(
+			coder->index_decoder.coder,
+			allocator, in, in_pos, in_size,
+			NULL, NULL, 0, LZMA_RUN);
+
+	coder->index_remaining -= *in_pos - in_start;
+
+	if (update_file_cur_pos)
+		coder->file_cur_pos += *in_pos - in_start;
+
+	return ret;
+}
+
+
+static lzma_ret
+file_info_decode(void *coder_ptr, const lzma_allocator *allocator,
+		const uint8_t *restrict in, size_t *restrict in_pos,
+		size_t in_size,
+		uint8_t *restrict out lzma_attribute((__unused__)),
+		size_t *restrict out_pos lzma_attribute((__unused__)),
+		size_t out_size lzma_attribute((__unused__)),
+		lzma_action action lzma_attribute((__unused__)))
+{
+	lzma_file_info_coder *coder = coder_ptr;
+	const size_t in_start = *in_pos;
+
+	// If the caller provides input past the end of the file, trim
+	// the extra bytes from the buffer so that we won't read too far.
+	assert(coder->file_size >= coder->file_cur_pos);
+	if (coder->file_size - coder->file_cur_pos < in_size - in_start)
+		in_size = in_start
+			+ (size_t)(coder->file_size - coder->file_cur_pos);
+
+	while (true)
+	switch (coder->sequence) {
+	case SEQ_MAGIC_BYTES:
+		// Decode the Stream Header at the beginning of the file
+		// first to check if the Magic Bytes match. The flags
+		// are stored in coder->first_header_flags so that we
+		// don't need to seek to it again.
+		//
+		// Check that the file is big enough to contain at least
+		// Stream Header.
+		if (coder->file_size < LZMA_STREAM_HEADER_SIZE)
+			return LZMA_FORMAT_ERROR;
+
+		// Read the Stream Header field into coder->temp.
+		if (fill_temp(coder, in, in_pos, in_size))
+			return LZMA_OK;
+
+		// This is the only Stream Header/Footer decoding where we
+		// want to return LZMA_FORMAT_ERROR if the Magic Bytes don't
+		// match. Elsewhere it will be converted to LZMA_DATA_ERROR.
+		return_if_error(lzma_stream_header_decode(
+				&coder->first_header_flags, coder->temp));
+
+		// Now that we know that the Magic Bytes match, check the
+		// file size. It's better to do this here after checking the
+		// Magic Bytes since this way we can give LZMA_FORMAT_ERROR
+		// instead of LZMA_DATA_ERROR when the Magic Bytes don't
+		// match in a file that is too big or isn't a multiple of
+		// four bytes.
+		if (coder->file_size > LZMA_VLI_MAX || (coder->file_size & 3))
+			return LZMA_DATA_ERROR;
+
+		// Start looking for Stream Padding and Stream Footer
+		// at the end of the file.
+		coder->file_target_pos = coder->file_size;
+
+	// Fall through
+
+	case SEQ_PADDING_SEEK:
+		coder->sequence = SEQ_PADDING_DECODE;
+		return_if_error(reverse_seek(
+				coder, in_start, in_pos, in_size));
+
+	// Fall through
+
+	case SEQ_PADDING_DECODE: {
+		// Copy to coder->temp first. This keeps the code simpler if
+		// the application only provides input a few bytes at a time.
+		if (fill_temp(coder, in, in_pos, in_size))
+			return LZMA_OK;
+
+		// Scan the buffer backwards to get the size of the
+		// Stream Padding field (if any).
+		const size_t new_padding = get_padding_size(
+				coder->temp, coder->temp_size);
+		coder->stream_padding += new_padding;
+
+		// Set the target position to the beginning of Stream Padding
+		// that has been observed so far. If all Stream Padding has
+		// been seen, then the target position will be at the end
+		// of the Stream Footer field.
+		coder->file_target_pos -= new_padding;
+
+		if (new_padding == coder->temp_size) {
+			// The whole buffer was padding. Seek backwards in
+			// the file to get more input.
+			coder->sequence = SEQ_PADDING_SEEK;
+			break;
+		}
+
+		// Size of Stream Padding must be a multiple of 4 bytes.
+		if (coder->stream_padding & 3)
+			return LZMA_DATA_ERROR;
+
+		coder->sequence = SEQ_FOOTER;
+
+		// Calculate the amount of non-padding data in coder->temp.
+		coder->temp_size -= new_padding;
+		coder->temp_pos = coder->temp_size;
+
+		// We can avoid an external seek if the whole Stream Footer
+		// is already in coder->temp. In that case SEQ_FOOTER won't
+		// read more input and will find the Stream Footer from
+		// coder->temp[coder->temp_size - LZMA_STREAM_HEADER_SIZE].
+		//
+		// Otherwise we will need to seek. The seeking is done so
+		// that Stream Footer will be at the end of coder->temp.
+		// This way it's likely that we also get a complete Index
+		// field into coder->temp without needing a separate seek
+		// for that (unless the Index field is big).
+		if (coder->temp_size < LZMA_STREAM_HEADER_SIZE)
+			return_if_error(reverse_seek(
+					coder, in_start, in_pos, in_size));
+	}
+
+	// Fall through
+
+	case SEQ_FOOTER:
+		// Copy the Stream Footer field into coder->temp.
+		// If Stream Footer was already available in coder->temp
+		// in SEQ_PADDING_DECODE, then this does nothing.
+		if (fill_temp(coder, in, in_pos, in_size))
+			return LZMA_OK;
+
+		// Make coder->file_target_pos and coder->temp_size point
+		// to the beginning of Stream Footer and thus to the end
+		// of the Index field. coder->temp_pos will be updated
+		// a bit later.
+		coder->file_target_pos -= LZMA_STREAM_HEADER_SIZE;
+		coder->temp_size -= LZMA_STREAM_HEADER_SIZE;
+
+		// Decode Stream Footer.
+		return_if_error(hide_format_error(lzma_stream_footer_decode(
+				&coder->footer_flags,
+				coder->temp + coder->temp_size)));
+
+		// Check that we won't seek past the beginning of the file.
+		//
+		// LZMA_STREAM_HEADER_SIZE is added because there must be
+		// space for Stream Header too even though we won't seek
+		// there before decoding the Index field.
+		//
+		// There's no risk of integer overflow here because
+		// Backward Size cannot be greater than 2^34.
+		if (coder->file_target_pos < coder->footer_flags.backward_size
+				+ LZMA_STREAM_HEADER_SIZE)
+			return LZMA_DATA_ERROR;
+
+		// Set the target position to the beginning of the Index field.
+		coder->file_target_pos -= coder->footer_flags.backward_size;
+		coder->sequence = SEQ_INDEX_INIT;
+
+		// We can avoid an external seek if the whole Index field is
+		// already available in coder->temp.
+		if (coder->temp_size >= coder->footer_flags.backward_size) {
+			// Set coder->temp_pos to point to the beginning
+			// of the Index.
+			coder->temp_pos = coder->temp_size
+					- coder->footer_flags.backward_size;
+		} else {
+			// These are set to zero to indicate that there's no
+			// useful data (Index or anything else) in coder->temp.
+			coder->temp_pos = 0;
+			coder->temp_size = 0;
+
+			// Seek to the beginning of the Index field.
+			if (seek_to_pos(coder, coder->file_target_pos,
+					in_start, in_pos, in_size))
+				return LZMA_SEEK_NEEDED;
+		}
+
+	// Fall through
+
+	case SEQ_INDEX_INIT: {
+		// Calculate the amount of memory already used by the earlier
+		// Indexes so that we know how big memory limit to pass to
+		// the Index decoder.
+		//
+		// NOTE: When there are multiple Streams, the separate
+		// lzma_index structures can use more RAM (as measured by
+		// lzma_index_memused()) than the final combined lzma_index.
+		// Thus memlimit may need to be slightly higher than the final
+		// calculated memory usage will be. This is perhaps a bit
+		// confusing to the application, but I think it shouldn't
+		// cause problems in practice.
+		uint64_t memused = 0;
+		if (coder->combined_index != NULL) {
+			memused = lzma_index_memused(coder->combined_index);
+			assert(memused <= coder->memlimit);
+			if (memused > coder->memlimit) // Extra sanity check
+				return LZMA_PROG_ERROR;
+		}
+
+		// Initialize the Index decoder.
+		return_if_error(lzma_index_decoder_init(
+				&coder->index_decoder, allocator,
+				&coder->this_index,
+				coder->memlimit - memused));
+
+		coder->index_remaining = coder->footer_flags.backward_size;
+		coder->sequence = SEQ_INDEX_DECODE;
+	}
+
+	// Fall through
+
+	case SEQ_INDEX_DECODE: {
+		// Decode (a part of) the Index. If the whole Index is already
+		// in coder->temp, read it from there. Otherwise read from
+		// in[*in_pos] onwards. Note that index_decode() updates
+		// coder->index_remaining and optionally coder->file_cur_pos.
+		lzma_ret ret;
+		if (coder->temp_size != 0) {
+			assert(coder->temp_size - coder->temp_pos
+					== coder->index_remaining);
+			ret = decode_index(coder, allocator, coder->temp,
+					&coder->temp_pos, coder->temp_size,
+					false);
+		} else {
+			// Don't give the decoder more input than the known
+			// remaining size of the Index field.
+			size_t in_stop = in_size;
+			if (in_size - *in_pos > coder->index_remaining)
+				in_stop = *in_pos
+					+ (size_t)(coder->index_remaining);
+
+			ret = decode_index(coder, allocator,
+					in, in_pos, in_stop, true);
+		}
+
+		switch (ret) {
+		case LZMA_OK:
+			// If the Index docoder asks for more input when we
+			// have already given it as much input as Backward Size
+			// indicated, the file is invalid.
+			if (coder->index_remaining == 0)
+				return LZMA_DATA_ERROR;
+
+			// We cannot get here if we were reading Index from
+			// coder->temp because when reading from coder->temp
+			// we give the Index decoder exactly
+			// coder->index_remaining bytes of input.
+			assert(coder->temp_size == 0);
+
+			return LZMA_OK;
+
+		case LZMA_STREAM_END:
+			// If the decoding seems to be successful, check also
+			// that the Index decoder consumed as much input as
+			// indicated by the Backward Size field.
+			if (coder->index_remaining != 0)
+				return LZMA_DATA_ERROR;
+
+			break;
+
+		default:
+			return ret;
+		}
+
+		// Calculate how much the Index tells us to seek backwards
+		// (relative to the beginning of the Index): Total size of
+		// all Blocks plus the size of the Stream Header field.
+		// No integer overflow here because lzma_index_total_size()
+		// cannot return a value greater than LZMA_VLI_MAX.
+		const uint64_t seek_amount
+				= lzma_index_total_size(coder->this_index)
+					+ LZMA_STREAM_HEADER_SIZE;
+
+		// Check that Index is sane in sense that seek_amount won't
+		// make us seek past the beginning of the file when locating
+		// the Stream Header.
+		//
+		// coder->file_target_pos still points to the beginning of
+		// the Index field.
+		if (coder->file_target_pos < seek_amount)
+			return LZMA_DATA_ERROR;
+
+		// Set the target to the beginning of Stream Header.
+		coder->file_target_pos -= seek_amount;
+
+		if (coder->file_target_pos == 0) {
+			// We would seek to the beginning of the file, but
+			// since we already decoded that Stream Header in
+			// SEQ_MAGIC_BYTES, we can use the cached value from
+			// coder->first_header_flags to avoid the seek.
+			coder->header_flags = coder->first_header_flags;
+			coder->sequence = SEQ_HEADER_COMPARE;
+			break;
+		}
+
+		coder->sequence = SEQ_HEADER_DECODE;
+
+		// Make coder->file_target_pos point to the end of
+		// the Stream Header field.
+		coder->file_target_pos += LZMA_STREAM_HEADER_SIZE;
+
+		// If coder->temp_size is non-zero, it points to the end
+		// of the Index field. Then the beginning of the Index
+		// field is at coder->temp[coder->temp_size
+		// - coder->footer_flags.backward_size].
+		assert(coder->temp_size == 0 || coder->temp_size
+				>= coder->footer_flags.backward_size);
+
+		// If coder->temp contained the whole Index, see if it has
+		// enough data to contain also the Stream Header. If so,
+		// we avoid an external seek.
+		//
+		// NOTE: This can happen only with small .xz files and only
+		// for the non-first Stream as the Stream Flags of the first
+		// Stream are cached and already handled a few lines above.
+		// So this isn't as useful as the other seek-avoidance cases.
+		if (coder->temp_size != 0 && coder->temp_size
+				- coder->footer_flags.backward_size
+				>= seek_amount) {
+			// Make temp_pos and temp_size point to the *end* of
+			// Stream Header so that SEQ_HEADER_DECODE will find
+			// the start of Stream Header from coder->temp[
+			// coder->temp_size - LZMA_STREAM_HEADER_SIZE].
+			coder->temp_pos = coder->temp_size
+					- coder->footer_flags.backward_size
+					- seek_amount
+					+ LZMA_STREAM_HEADER_SIZE;
+			coder->temp_size = coder->temp_pos;
+		} else {
+			// Seek so that Stream Header will be at the end of
+			// coder->temp. With typical multi-Stream files we
+			// will usually also get the Stream Footer and Index
+			// of the *previous* Stream in coder->temp and thus
+			// won't need a separate seek for them.
+			return_if_error(reverse_seek(coder,
+					in_start, in_pos, in_size));
+		}
+	}
+
+	// Fall through
+
+	case SEQ_HEADER_DECODE:
+		// Copy the Stream Header field into coder->temp.
+		// If Stream Header was already available in coder->temp
+		// in SEQ_INDEX_DECODE, then this does nothing.
+		if (fill_temp(coder, in, in_pos, in_size))
+			return LZMA_OK;
+
+		// Make all these point to the beginning of Stream Header.
+		coder->file_target_pos -= LZMA_STREAM_HEADER_SIZE;
+		coder->temp_size -= LZMA_STREAM_HEADER_SIZE;
+		coder->temp_pos = coder->temp_size;
+
+		// Decode the Stream Header.
+		return_if_error(hide_format_error(lzma_stream_header_decode(
+				&coder->header_flags,
+				coder->temp + coder->temp_size)));
+
+		coder->sequence = SEQ_HEADER_COMPARE;
+
+	// Fall through
+
+	case SEQ_HEADER_COMPARE:
+		// Compare Stream Header against Stream Footer. They must
+		// match.
+		return_if_error(lzma_stream_flags_compare(
+				&coder->header_flags, &coder->footer_flags));
+
+		// Store the decoded Stream Flags into the Index. Use the
+		// Footer Flags because it contains Backward Size, although
+		// it shouldn't matter in practice.
+		if (lzma_index_stream_flags(coder->this_index,
+				&coder->footer_flags) != LZMA_OK)
+			return LZMA_PROG_ERROR;
+
+		// Store also the size of the Stream Padding field. It is
+		// needed to calculate the offsets of the Streams correctly.
+		if (lzma_index_stream_padding(coder->this_index,
+				coder->stream_padding) != LZMA_OK)
+			return LZMA_PROG_ERROR;
+
+		// Reset it so that it's ready for the next Stream.
+		coder->stream_padding = 0;
+
+		// Append the earlier decoded Indexes after this_index.
+		if (coder->combined_index != NULL)
+			return_if_error(lzma_index_cat(coder->this_index,
+					coder->combined_index, allocator));
+
+		coder->combined_index = coder->this_index;
+		coder->this_index = NULL;
+
+		// If the whole file was decoded, tell the caller that we
+		// are finished.
+		if (coder->file_target_pos == 0) {
+			// The combined index must indicate the same file
+			// size as was told to us at initialization.
+			assert(lzma_index_file_size(coder->combined_index)
+					== coder->file_size);
+
+			// Make the combined index available to
+			// the application.
+			*coder->dest_index = coder->combined_index;
+			coder->combined_index = NULL;
+
+			// Mark the input buffer as used since we may have
+			// done internal seeking and thus don't know how
+			// many input bytes were actually used. This way
+			// lzma_stream.total_in gets a slightly better
+			// estimate of the amount of input used.
+			*in_pos = in_size;
+			return LZMA_STREAM_END;
+		}
+
+		// We didn't hit the beginning of the file yet, so continue
+		// reading backwards in the file. If we have unprocessed
+		// data in coder->temp, use it before requesting more data
+		// from the application.
+		//
+		// coder->file_target_pos, coder->temp_size, and
+		// coder->temp_pos all point to the beginning of Stream Header
+		// and thus the end of the previous Stream in the file.
+		coder->sequence = coder->temp_size > 0
+				? SEQ_PADDING_DECODE : SEQ_PADDING_SEEK;
+		break;
+
+	default:
+		assert(0);
+		return LZMA_PROG_ERROR;
+	}
+}
+
+
+static lzma_ret
+file_info_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
+		uint64_t *old_memlimit, uint64_t new_memlimit)
+{
+	lzma_file_info_coder *coder = coder_ptr;
+
+	// The memory usage calculation comes from three things:
+	//
+	// (1) The Indexes that have already been decoded and processed into
+	//     coder->combined_index.
+	//
+	// (2) The latest Index in coder->this_index that has been decoded but
+	//     not yet put into coder->combined_index.
+	//
+	// (3) The latest Index that we have started decoding but haven't
+	//     finished and thus isn't available in coder->this_index yet.
+	//     Memory usage and limit information needs to be communicated
+	//     from/to coder->index_decoder.
+	//
+	// Care has to be taken to not do both (2) and (3) when calculating
+	// the memory usage.
+	uint64_t combined_index_memusage = 0;
+	uint64_t this_index_memusage = 0;
+
+	// (1) If we have already successfully decoded one or more Indexes,
+	// get their memory usage.
+	if (coder->combined_index != NULL)
+		combined_index_memusage = lzma_index_memused(
+				coder->combined_index);
+
+	// Choose between (2), (3), or neither.
+	if (coder->this_index != NULL) {
+		// (2) The latest Index is available. Use its memory usage.
+		this_index_memusage = lzma_index_memused(coder->this_index);
+
+	} else if (coder->sequence == SEQ_INDEX_DECODE) {
+		// (3) The Index decoder is activate and hasn't yet stored
+		// the new index in coder->this_index. Get the memory usage
+		// information from the Index decoder.
+		//
+		// NOTE: If the Index decoder doesn't yet know how much memory
+		// it will eventually need, it will return a tiny value here.
+		uint64_t dummy;
+		if (coder->index_decoder.memconfig(coder->index_decoder.coder,
+					&this_index_memusage, &dummy, 0)
+				!= LZMA_OK) {
+			assert(0);
+			return LZMA_PROG_ERROR;
+		}
+	}
+
+	// Now we know the total memory usage/requirement. If we had neither
+	// old Indexes nor a new Index, this will be zero which isn't
+	// acceptable as lzma_memusage() has to return non-zero on success
+	// and even with an empty .xz file we will end up with a lzma_index
+	// that takes some memory.
+	*memusage = combined_index_memusage + this_index_memusage;
+	if (*memusage == 0)
+		*memusage = lzma_index_memusage(1, 0);
+
+	*old_memlimit = coder->memlimit;
+
+	// If requested, set a new memory usage limit.
+	if (new_memlimit != 0) {
+		if (new_memlimit < *memusage)
+			return LZMA_MEMLIMIT_ERROR;
+
+		// In the condition (3) we need to tell the Index decoder
+		// its new memory usage limit.
+		if (coder->this_index == NULL
+				&& coder->sequence == SEQ_INDEX_DECODE) {
+			const uint64_t idec_new_memlimit = new_memlimit
+					- combined_index_memusage;
+
+			assert(this_index_memusage > 0);
+			assert(idec_new_memlimit > 0);
+
+			uint64_t dummy1;
+			uint64_t dummy2;
+
+			if (coder->index_decoder.memconfig(
+					coder->index_decoder.coder,
+					&dummy1, &dummy2, idec_new_memlimit)
+					!= LZMA_OK) {
+				assert(0);
+				return LZMA_PROG_ERROR;
+			}
+		}
+
+		coder->memlimit = new_memlimit;
+	}
+
+	return LZMA_OK;
+}
+
+
+static void
+file_info_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
+{
+	lzma_file_info_coder *coder = coder_ptr;
+
+	lzma_next_end(&coder->index_decoder, allocator);
+	lzma_index_end(coder->this_index, allocator);
+	lzma_index_end(coder->combined_index, allocator);
+
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+static lzma_ret
+lzma_file_info_decoder_init(lzma_next_coder *next,
+		const lzma_allocator *allocator, uint64_t *seek_pos,
+		lzma_index **dest_index,
+		uint64_t memlimit, uint64_t file_size)
+{
+	lzma_next_coder_init(&lzma_file_info_decoder_init, next, allocator);
+
+	if (dest_index == NULL)
+		return LZMA_PROG_ERROR;
+
+	lzma_file_info_coder *coder = next->coder;
+	if (coder == NULL) {
+		coder = lzma_alloc(sizeof(lzma_file_info_coder), allocator);
+		if (coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->coder = coder;
+		next->code = &file_info_decode;
+		next->end = &file_info_decoder_end;
+		next->memconfig = &file_info_decoder_memconfig;
+
+		coder->index_decoder = LZMA_NEXT_CODER_INIT;
+		coder->this_index = NULL;
+		coder->combined_index = NULL;
+	}
+
+	coder->sequence = SEQ_MAGIC_BYTES;
+	coder->file_cur_pos = 0;
+	coder->file_target_pos = 0;
+	coder->file_size = file_size;
+
+	lzma_index_end(coder->this_index, allocator);
+	coder->this_index = NULL;
+
+	lzma_index_end(coder->combined_index, allocator);
+	coder->combined_index = NULL;
+
+	coder->stream_padding = 0;
+
+	coder->dest_index = dest_index;
+	coder->external_seek_pos = seek_pos;
+
+	// If memlimit is 0, make it 1 to ensure that lzma_memlimit_get()
+	// won't return 0 (which would indicate an error).
+	coder->memlimit = my_max(1, memlimit);
+
+	// Prepare these for reading the first Stream Header into coder->temp.
+	coder->temp_pos = 0;
+	coder->temp_size = LZMA_STREAM_HEADER_SIZE;
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_file_info_decoder(lzma_stream *strm, lzma_index **dest_index,
+		uint64_t memlimit, uint64_t file_size)
+{
+	lzma_next_strm_init(lzma_file_info_decoder_init, strm, &strm->seek_pos,
+			dest_index, memlimit, file_size);
+
+	// We allow LZMA_FINISH in addition to LZMA_RUN for convenience.
+	// lzma_code() is able to handle the LZMA_FINISH + LZMA_SEEK_NEEDED
+	// combination in a sane way. Applications still need to be careful
+	// if they use LZMA_FINISH so that they remember to reset it back
+	// to LZMA_RUN after seeking if needed.
+	strm->internal->supported_actions[LZMA_RUN] = true;
+	strm->internal->supported_actions[LZMA_FINISH] = true;
+
+	return LZMA_OK;
+}

+ 3 - 4
Utilities/cmliblzma/liblzma/common/filter_buffer_decoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       filter_buffer_decoder.c
 /// \file       filter_buffer_decoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "filter_decoder.h"
 #include "filter_decoder.h"
@@ -24,7 +23,7 @@ lzma_raw_buffer_decode(
 			|| out_pos == NULL || *out_pos > out_size)
 			|| out_pos == NULL || *out_pos > out_size)
 		return LZMA_PROG_ERROR;
 		return LZMA_PROG_ERROR;
 
 
-	// Initialize the decoer.
+	// Initialize the decoder.
 	lzma_next_coder next = LZMA_NEXT_CODER_INIT;
 	lzma_next_coder next = LZMA_NEXT_CODER_INIT;
 	return_if_error(lzma_raw_decoder_init(&next, allocator, filters));
 	return_if_error(lzma_raw_decoder_init(&next, allocator, filters));
 
 

+ 2 - 3
Utilities/cmliblzma/liblzma/common/filter_buffer_encoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       filter_buffer_encoder.c
 /// \file       filter_buffer_encoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "filter_encoder.h"
 #include "filter_encoder.h"

+ 69 - 13
Utilities/cmliblzma/liblzma/common/filter_common.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       filter_common.c
 /// \file       filter_common.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "filter_common.h"
 #include "filter_common.h"
@@ -42,6 +41,13 @@ static const struct {
 		.last_ok = true,
 		.last_ok = true,
 		.changes_size = true,
 		.changes_size = true,
 	},
 	},
+	{
+		.id = LZMA_FILTER_LZMA1EXT,
+		.options_size = sizeof(lzma_options_lzma),
+		.non_last_ok = false,
+		.last_ok = true,
+		.changes_size = true,
+	},
 #endif
 #endif
 #if defined(HAVE_ENCODER_LZMA2) || defined(HAVE_DECODER_LZMA2)
 #if defined(HAVE_ENCODER_LZMA2) || defined(HAVE_DECODER_LZMA2)
 	{
 	{
@@ -97,6 +103,15 @@ static const struct {
 		.changes_size = false,
 		.changes_size = false,
 	},
 	},
 #endif
 #endif
+#if defined(HAVE_ENCODER_ARM64) || defined(HAVE_DECODER_ARM64)
+	{
+		.id = LZMA_FILTER_ARM64,
+		.options_size = sizeof(lzma_options_bcj),
+		.non_last_ok = true,
+		.last_ok = false,
+		.changes_size = false,
+	},
+#endif
 #if defined(HAVE_ENCODER_SPARC) || defined(HAVE_DECODER_SPARC)
 #if defined(HAVE_ENCODER_SPARC) || defined(HAVE_DECODER_SPARC)
 	{
 	{
 		.id = LZMA_FILTER_SPARC,
 		.id = LZMA_FILTER_SPARC,
@@ -106,6 +121,15 @@ static const struct {
 		.changes_size = false,
 		.changes_size = false,
 	},
 	},
 #endif
 #endif
+#if defined(HAVE_ENCODER_RISCV) || defined(HAVE_DECODER_RISCV)
+	{
+		.id = LZMA_FILTER_RISCV,
+		.options_size = sizeof(lzma_options_bcj),
+		.non_last_ok = true,
+		.last_ok = false,
+		.changes_size = false,
+	},
+#endif
 #if defined(HAVE_ENCODER_DELTA) || defined(HAVE_DECODER_DELTA)
 #if defined(HAVE_ENCODER_DELTA) || defined(HAVE_DECODER_DELTA)
 	{
 	{
 		.id = LZMA_FILTER_DELTA,
 		.id = LZMA_FILTER_DELTA,
@@ -122,12 +146,16 @@ static const struct {
 
 
 
 
 extern LZMA_API(lzma_ret)
 extern LZMA_API(lzma_ret)
-lzma_filters_copy(const lzma_filter *src, lzma_filter *dest,
+lzma_filters_copy(const lzma_filter *src, lzma_filter *real_dest,
 		const lzma_allocator *allocator)
 		const lzma_allocator *allocator)
 {
 {
-	if (src == NULL || dest == NULL)
+	if (src == NULL || real_dest == NULL)
 		return LZMA_PROG_ERROR;
 		return LZMA_PROG_ERROR;
 
 
+	// Use a temporary destination so that the real destination
+	// will never be modified if an error occurs.
+	lzma_filter dest[LZMA_FILTERS_MAX + 1];
+
 	lzma_ret ret;
 	lzma_ret ret;
 	size_t i;
 	size_t i;
 	for (i = 0; src[i].id != LZMA_VLI_UNKNOWN; ++i) {
 	for (i = 0; src[i].id != LZMA_VLI_UNKNOWN; ++i) {
@@ -173,25 +201,53 @@ lzma_filters_copy(const lzma_filter *src, lzma_filter *dest,
 	}
 	}
 
 
 	// Terminate the filter array.
 	// Terminate the filter array.
-	assert(i <= LZMA_FILTERS_MAX + 1);
+	assert(i < LZMA_FILTERS_MAX + 1);
 	dest[i].id = LZMA_VLI_UNKNOWN;
 	dest[i].id = LZMA_VLI_UNKNOWN;
 	dest[i].options = NULL;
 	dest[i].options = NULL;
 
 
+	// Copy it to the caller-supplied array now that we know that
+	// no errors occurred.
+	memcpy(real_dest, dest, (i + 1) * sizeof(lzma_filter));
+
 	return LZMA_OK;
 	return LZMA_OK;
 
 
 error:
 error:
 	// Free the options which we have already allocated.
 	// Free the options which we have already allocated.
-	while (i-- > 0) {
+	while (i-- > 0)
 		lzma_free(dest[i].options, allocator);
 		lzma_free(dest[i].options, allocator);
-		dest[i].options = NULL;
-	}
 
 
 	return ret;
 	return ret;
 }
 }
 
 
 
 
-static lzma_ret
-validate_chain(const lzma_filter *filters, size_t *count)
+extern LZMA_API(void)
+lzma_filters_free(lzma_filter *filters, const lzma_allocator *allocator)
+{
+	if (filters == NULL)
+		return;
+
+	for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
+		if (i == LZMA_FILTERS_MAX) {
+			// The API says that LZMA_FILTERS_MAX + 1 is the
+			// maximum allowed size including the terminating
+			// element. Thus, we should never get here but in
+			// case there is a bug and we do anyway, don't go
+			// past the (probable) end of the array.
+			assert(0);
+			break;
+		}
+
+		lzma_free(filters[i].options, allocator);
+		filters[i].options = NULL;
+		filters[i].id = LZMA_VLI_UNKNOWN;
+	}
+
+	return;
+}
+
+
+extern lzma_ret
+lzma_validate_chain(const lzma_filter *filters, size_t *count)
 {
 {
 	// There must be at least one filter.
 	// There must be at least one filter.
 	if (filters == NULL || filters[0].id == LZMA_VLI_UNKNOWN)
 	if (filters == NULL || filters[0].id == LZMA_VLI_UNKNOWN)
@@ -245,7 +301,7 @@ lzma_raw_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
 {
 {
 	// Do some basic validation and get the number of filters.
 	// Do some basic validation and get the number of filters.
 	size_t count;
 	size_t count;
-	return_if_error(validate_chain(options, &count));
+	return_if_error(lzma_validate_chain(options, &count));
 
 
 	// Set the filter functions and copy the options pointer.
 	// Set the filter functions and copy the options pointer.
 	lzma_filter_info filters[LZMA_FILTERS_MAX + 1];
 	lzma_filter_info filters[LZMA_FILTERS_MAX + 1];
@@ -298,7 +354,7 @@ lzma_raw_coder_memusage(lzma_filter_find coder_find,
 	// The chain has to have at least one filter.
 	// The chain has to have at least one filter.
 	{
 	{
 		size_t tmp;
 		size_t tmp;
-		if (validate_chain(filters, &tmp) != LZMA_OK)
+		if (lzma_validate_chain(filters, &tmp) != LZMA_OK)
 			return UINT64_MAX;
 			return UINT64_MAX;
 	}
 	}
 
 

+ 5 - 3
Utilities/cmliblzma/liblzma/common/filter_common.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       filter_common.h
 /// \file       filter_common.h
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef LZMA_FILTER_COMMON_H
 #ifndef LZMA_FILTER_COMMON_H
@@ -35,6 +34,9 @@ typedef struct {
 typedef const lzma_filter_coder *(*lzma_filter_find)(lzma_vli id);
 typedef const lzma_filter_coder *(*lzma_filter_find)(lzma_vli id);
 
 
 
 
+extern lzma_ret lzma_validate_chain(const lzma_filter *filters, size_t *count);
+
+
 extern lzma_ret lzma_raw_coder_init(
 extern lzma_ret lzma_raw_coder_init(
 		lzma_next_coder *next, const lzma_allocator *allocator,
 		lzma_next_coder *next, const lzma_allocator *allocator,
 		const lzma_filter *filters,
 		const lzma_filter *filters,

+ 36 - 6
Utilities/cmliblzma/liblzma/common/filter_decoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       filter_decoder.c
 /// \file       filter_decoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "filter_decoder.h"
 #include "filter_decoder.h"
@@ -50,6 +49,12 @@ static const lzma_filter_decoder decoders[] = {
 		.memusage = &lzma_lzma_decoder_memusage,
 		.memusage = &lzma_lzma_decoder_memusage,
 		.props_decode = &lzma_lzma_props_decode,
 		.props_decode = &lzma_lzma_props_decode,
 	},
 	},
+	{
+		.id = LZMA_FILTER_LZMA1EXT,
+		.init = &lzma_lzma_decoder_init,
+		.memusage = &lzma_lzma_decoder_memusage,
+		.props_decode = &lzma_lzma_props_decode,
+	},
 #endif
 #endif
 #ifdef HAVE_DECODER_LZMA2
 #ifdef HAVE_DECODER_LZMA2
 	{
 	{
@@ -99,6 +104,14 @@ static const lzma_filter_decoder decoders[] = {
 		.props_decode = &lzma_simple_props_decode,
 		.props_decode = &lzma_simple_props_decode,
 	},
 	},
 #endif
 #endif
+#ifdef HAVE_DECODER_ARM64
+	{
+		.id = LZMA_FILTER_ARM64,
+		.init = &lzma_simple_arm64_decoder_init,
+		.memusage = NULL,
+		.props_decode = &lzma_simple_props_decode,
+	},
+#endif
 #ifdef HAVE_DECODER_SPARC
 #ifdef HAVE_DECODER_SPARC
 	{
 	{
 		.id = LZMA_FILTER_SPARC,
 		.id = LZMA_FILTER_SPARC,
@@ -107,6 +120,14 @@ static const lzma_filter_decoder decoders[] = {
 		.props_decode = &lzma_simple_props_decode,
 		.props_decode = &lzma_simple_props_decode,
 	},
 	},
 #endif
 #endif
+#ifdef HAVE_DECODER_RISCV
+	{
+		.id = LZMA_FILTER_RISCV,
+		.init = &lzma_simple_riscv_decoder_init,
+		.memusage = NULL,
+		.props_decode = &lzma_simple_props_decode,
+	},
+#endif
 #ifdef HAVE_DECODER_DELTA
 #ifdef HAVE_DECODER_DELTA
 	{
 	{
 		.id = LZMA_FILTER_DELTA,
 		.id = LZMA_FILTER_DELTA,
@@ -129,6 +150,16 @@ decoder_find(lzma_vli id)
 }
 }
 
 
 
 
+// lzma_filter_coder begins with the same members as lzma_filter_decoder.
+// This function is a wrapper with a type that is compatible with the
+// typedef of lzma_filter_find in filter_common.h.
+static const lzma_filter_coder *
+coder_find(lzma_vli id)
+{
+	return (const lzma_filter_coder *)decoder_find(id);
+}
+
+
 extern LZMA_API(lzma_bool)
 extern LZMA_API(lzma_bool)
 lzma_filter_decoder_is_supported(lzma_vli id)
 lzma_filter_decoder_is_supported(lzma_vli id)
 {
 {
@@ -141,7 +172,7 @@ lzma_raw_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
 		const lzma_filter *options)
 		const lzma_filter *options)
 {
 {
 	return lzma_raw_coder_init(next, allocator,
 	return lzma_raw_coder_init(next, allocator,
-			options, (lzma_filter_find)(&decoder_find), false);
+			options, &coder_find, false);
 }
 }
 
 
 
 
@@ -160,8 +191,7 @@ lzma_raw_decoder(lzma_stream *strm, const lzma_filter *options)
 extern LZMA_API(uint64_t)
 extern LZMA_API(uint64_t)
 lzma_raw_decoder_memusage(const lzma_filter *filters)
 lzma_raw_decoder_memusage(const lzma_filter *filters)
 {
 {
-	return lzma_raw_coder_memusage(
-			(lzma_filter_find)(&decoder_find), filters);
+	return lzma_raw_coder_memusage(&coder_find, filters);
 }
 }
 
 
 
 

+ 2 - 3
Utilities/cmliblzma/liblzma/common/filter_decoder.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       filter_decoder.h
 /// \file       filter_decoder.h
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef LZMA_FILTER_DECODER_H
 #ifndef LZMA_FILTER_DECODER_H

+ 64 - 20
Utilities/cmliblzma/liblzma/common/filter_encoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       filter_decoder.c
 /// \file       filter_decoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "filter_encoder.h"
 #include "filter_encoder.h"
@@ -33,13 +32,17 @@ typedef struct {
 	/// Calculates the recommended Uncompressed Size for .xz Blocks to
 	/// Calculates the recommended Uncompressed Size for .xz Blocks to
 	/// which the input data can be split to make multithreaded
 	/// which the input data can be split to make multithreaded
 	/// encoding possible. If this is NULL, it is assumed that
 	/// encoding possible. If this is NULL, it is assumed that
-	/// the encoder is fast enough with single thread.
+	/// the encoder is fast enough with single thread. If the options
+	/// are invalid, UINT64_MAX is returned.
 	uint64_t (*block_size)(const void *options);
 	uint64_t (*block_size)(const void *options);
 
 
 	/// Tells the size of the Filter Properties field. If options are
 	/// 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);
 	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;
 	uint32_t props_size_fixed;
 
 
 	/// Encodes Filter Properties.
 	/// Encodes Filter Properties.
@@ -59,7 +62,16 @@ static const lzma_filter_encoder encoders[] = {
 		.id = LZMA_FILTER_LZMA1,
 		.id = LZMA_FILTER_LZMA1,
 		.init = &lzma_lzma_encoder_init,
 		.init = &lzma_lzma_encoder_init,
 		.memusage = &lzma_lzma_encoder_memusage,
 		.memusage = &lzma_lzma_encoder_memusage,
-		.block_size = NULL, // FIXME
+		.block_size = NULL, // Not needed for LZMA1
+		.props_size_get = NULL,
+		.props_size_fixed = 5,
+		.props_encode = &lzma_lzma_props_encode,
+	},
+	{
+		.id = LZMA_FILTER_LZMA1EXT,
+		.init = &lzma_lzma_encoder_init,
+		.memusage = &lzma_lzma_encoder_memusage,
+		.block_size = NULL, // Not needed for LZMA1
 		.props_size_get = NULL,
 		.props_size_get = NULL,
 		.props_size_fixed = 5,
 		.props_size_fixed = 5,
 		.props_encode = &lzma_lzma_props_encode,
 		.props_encode = &lzma_lzma_props_encode,
@@ -70,7 +82,7 @@ static const lzma_filter_encoder encoders[] = {
 		.id = LZMA_FILTER_LZMA2,
 		.id = LZMA_FILTER_LZMA2,
 		.init = &lzma_lzma2_encoder_init,
 		.init = &lzma_lzma2_encoder_init,
 		.memusage = &lzma_lzma2_encoder_memusage,
 		.memusage = &lzma_lzma2_encoder_memusage,
-		.block_size = &lzma_lzma2_block_size, // FIXME
+		.block_size = &lzma_lzma2_block_size,
 		.props_size_get = NULL,
 		.props_size_get = NULL,
 		.props_size_fixed = 1,
 		.props_size_fixed = 1,
 		.props_encode = &lzma_lzma2_props_encode,
 		.props_encode = &lzma_lzma2_props_encode,
@@ -126,6 +138,16 @@ static const lzma_filter_encoder encoders[] = {
 		.props_encode = &lzma_simple_props_encode,
 		.props_encode = &lzma_simple_props_encode,
 	},
 	},
 #endif
 #endif
+#ifdef HAVE_ENCODER_ARM64
+	{
+		.id = LZMA_FILTER_ARM64,
+		.init = &lzma_simple_arm64_encoder_init,
+		.memusage = NULL,
+		.block_size = NULL,
+		.props_size_get = &lzma_simple_props_size,
+		.props_encode = &lzma_simple_props_encode,
+	},
+#endif
 #ifdef HAVE_ENCODER_SPARC
 #ifdef HAVE_ENCODER_SPARC
 	{
 	{
 		.id = LZMA_FILTER_SPARC,
 		.id = LZMA_FILTER_SPARC,
@@ -136,6 +158,16 @@ static const lzma_filter_encoder encoders[] = {
 		.props_encode = &lzma_simple_props_encode,
 		.props_encode = &lzma_simple_props_encode,
 	},
 	},
 #endif
 #endif
+#ifdef HAVE_ENCODER_RISCV
+	{
+		.id = LZMA_FILTER_RISCV,
+		.init = &lzma_simple_riscv_encoder_init,
+		.memusage = NULL,
+		.block_size = NULL,
+		.props_size_get = &lzma_simple_props_size,
+		.props_encode = &lzma_simple_props_encode,
+	},
+#endif
 #ifdef HAVE_ENCODER_DELTA
 #ifdef HAVE_ENCODER_DELTA
 	{
 	{
 		.id = LZMA_FILTER_DELTA,
 		.id = LZMA_FILTER_DELTA,
@@ -161,6 +193,16 @@ encoder_find(lzma_vli id)
 }
 }
 
 
 
 
+// lzma_filter_coder begins with the same members as lzma_filter_encoder.
+// This function is a wrapper with a type that is compatible with the
+// typedef of lzma_filter_find in filter_common.h.
+static const lzma_filter_coder *
+coder_find(lzma_vli id)
+{
+	return (const lzma_filter_coder *)encoder_find(id);
+}
+
+
 extern LZMA_API(lzma_bool)
 extern LZMA_API(lzma_bool)
 lzma_filter_encoder_is_supported(lzma_vli id)
 lzma_filter_encoder_is_supported(lzma_vli id)
 {
 {
@@ -197,18 +239,18 @@ lzma_filters_update(lzma_stream *strm, const lzma_filter *filters)
 
 
 extern lzma_ret
 extern lzma_ret
 lzma_raw_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
 lzma_raw_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
-		const lzma_filter *options)
+		const lzma_filter *filters)
 {
 {
 	return lzma_raw_coder_init(next, allocator,
 	return lzma_raw_coder_init(next, allocator,
-			options, (lzma_filter_find)(&encoder_find), true);
+			filters, &coder_find, true);
 }
 }
 
 
 
 
 extern LZMA_API(lzma_ret)
 extern LZMA_API(lzma_ret)
-lzma_raw_encoder(lzma_stream *strm, const lzma_filter *options)
+lzma_raw_encoder(lzma_stream *strm, const lzma_filter *filters)
 {
 {
-	lzma_next_strm_init(lzma_raw_coder_init, strm, options,
-			(lzma_filter_find)(&encoder_find), true);
+	lzma_next_strm_init(lzma_raw_coder_init, strm, filters,
+			&coder_find, true);
 
 
 	strm->internal->supported_actions[LZMA_RUN] = true;
 	strm->internal->supported_actions[LZMA_RUN] = true;
 	strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
 	strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
@@ -221,31 +263,33 @@ lzma_raw_encoder(lzma_stream *strm, const lzma_filter *options)
 extern LZMA_API(uint64_t)
 extern LZMA_API(uint64_t)
 lzma_raw_encoder_memusage(const lzma_filter *filters)
 lzma_raw_encoder_memusage(const lzma_filter *filters)
 {
 {
-	return lzma_raw_coder_memusage(
-			(lzma_filter_find)(&encoder_find), filters);
+	return lzma_raw_coder_memusage(&coder_find, filters);
 }
 }
 
 
 
 
-extern uint64_t
+extern LZMA_API(uint64_t)
 lzma_mt_block_size(const lzma_filter *filters)
 lzma_mt_block_size(const lzma_filter *filters)
 {
 {
+	if (filters == NULL)
+		return UINT64_MAX;
+
 	uint64_t max = 0;
 	uint64_t max = 0;
 
 
 	for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
 	for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
 		const lzma_filter_encoder *const fe
 		const lzma_filter_encoder *const fe
 				= encoder_find(filters[i].id);
 				= encoder_find(filters[i].id);
+		if (fe == NULL)
+			return UINT64_MAX;
+
 		if (fe->block_size != NULL) {
 		if (fe->block_size != NULL) {
 			const uint64_t size
 			const uint64_t size
 					= fe->block_size(filters[i].options);
 					= fe->block_size(filters[i].options);
-			if (size == 0)
-				return 0;
-
 			if (size > max)
 			if (size > max)
 				max = size;
 				max = size;
 		}
 		}
 	}
 	}
 
 
-	return max;
+	return max == 0 ? UINT64_MAX : max;
 }
 }
 
 
 
 

+ 3 - 8
Utilities/cmliblzma/liblzma/common/filter_encoder.h

@@ -1,13 +1,12 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
-/// \file       filter_encoder.c
+/// \file       filter_encoder.h
 /// \brief      Filter ID mapping to filter-specific functions
 /// \brief      Filter ID mapping to filter-specific functions
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef LZMA_FILTER_ENCODER_H
 #ifndef LZMA_FILTER_ENCODER_H
@@ -16,10 +15,6 @@
 #include "common.h"
 #include "common.h"
 
 
 
 
-// FIXME: Might become a part of the public API.
-extern uint64_t lzma_mt_block_size(const lzma_filter *filters);
-
-
 extern lzma_ret lzma_raw_encoder_init(
 extern lzma_ret lzma_raw_encoder_init(
 		lzma_next_coder *next, const lzma_allocator *allocator,
 		lzma_next_coder *next, const lzma_allocator *allocator,
 		const lzma_filter *filters);
 		const lzma_filter *filters);

+ 2 - 3
Utilities/cmliblzma/liblzma/common/filter_flags_decoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       filter_flags_decoder.c
 /// \file       filter_flags_decoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "filter_decoder.h"
 #include "filter_decoder.h"

+ 2 - 3
Utilities/cmliblzma/liblzma/common/filter_flags_encoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       filter_flags_encoder.c
 /// \file       filter_flags_encoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "filter_encoder.h"
 #include "filter_encoder.h"

+ 14 - 3
Utilities/cmliblzma/liblzma/common/hardware_cputhreads.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       hardware_cputhreads.c
 /// \file       hardware_cputhreads.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "common.h"
 #include "common.h"
@@ -15,6 +14,18 @@
 #include "tuklib_cpucores.h"
 #include "tuklib_cpucores.h"
 
 
 
 
+#ifdef HAVE_SYMBOL_VERSIONS_LINUX
+// This is for compatibility with binaries linked against liblzma that
+// has been patched with xz-5.2.2-compat-libs.patch from RHEL/CentOS 7.
+LZMA_SYMVER_API("lzma_cputhreads@XZ_5.2.2",
+	uint32_t, lzma_cputhreads_522)(void) lzma_nothrow
+		__attribute__((__alias__("lzma_cputhreads_52")));
+
+LZMA_SYMVER_API("lzma_cputhreads@@XZ_5.2",
+	uint32_t, lzma_cputhreads_52)(void) lzma_nothrow;
+
+#define lzma_cputhreads lzma_cputhreads_52
+#endif
 extern LZMA_API(uint32_t)
 extern LZMA_API(uint32_t)
 lzma_cputhreads(void)
 lzma_cputhreads(void)
 {
 {

+ 2 - 3
Utilities/cmliblzma/liblzma/common/hardware_physmem.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       hardware_physmem.c
 /// \file       hardware_physmem.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Jonathan Nieder
 //  Author:     Jonathan Nieder
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "common.h"
 #include "common.h"

+ 23 - 5
Utilities/cmliblzma/liblzma/common/index.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       index.c
 /// \file       index.c
@@ -5,11 +7,9 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
+#include "common.h"
 #include "index.h"
 #include "index.h"
 #include "stream_flags_common.h"
 #include "stream_flags_common.h"
 
 
@@ -659,6 +659,16 @@ lzma_index_append(lzma_index *i, const lzma_allocator *allocator,
 	const uint32_t index_list_size_add = lzma_vli_size(unpadded_size)
 	const uint32_t index_list_size_add = lzma_vli_size(unpadded_size)
 			+ lzma_vli_size(uncompressed_size);
 			+ lzma_vli_size(uncompressed_size);
 
 
+	// Check that uncompressed size will not overflow.
+	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.
 	// Check that the file size will stay within limits.
 	if (index_file_size(s->node.compressed_base,
 	if (index_file_size(s->node.compressed_base,
 			compressed_base + unpadded_size, s->record_count + 1,
 			compressed_base + unpadded_size, s->record_count + 1,
@@ -770,6 +780,9 @@ extern LZMA_API(lzma_ret)
 lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src,
 lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src,
 		const lzma_allocator *allocator)
 		const lzma_allocator *allocator)
 {
 {
+	if (dest == NULL || src == NULL)
+		return LZMA_PROG_ERROR;
+
 	const lzma_vli dest_file_size = lzma_index_file_size(dest);
 	const lzma_vli dest_file_size = lzma_index_file_size(dest);
 
 
 	// Check that we don't exceed the file size limits.
 	// Check that we don't exceed the file size limits.
@@ -838,6 +851,11 @@ lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src,
 		}
 		}
 	}
 	}
 
 
+	// dest->checks includes the check types of all except the last Stream
+	// in dest. Set the bit for the check type of the last Stream now so
+	// that it won't get lost when Stream(s) from src are appended to dest.
+	dest->checks = lzma_index_checks(dest);
+
 	// Add all the Streams from src to dest. Update the base offsets
 	// Add all the Streams from src to dest. Update the base offsets
 	// of each Stream from src.
 	// of each Stream from src.
 	const index_cat_info info = {
 	const index_cat_info info = {
@@ -854,7 +872,7 @@ lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src,
 	dest->total_size += src->total_size;
 	dest->total_size += src->total_size;
 	dest->record_count += src->record_count;
 	dest->record_count += src->record_count;
 	dest->index_list_size += src->index_list_size;
 	dest->index_list_size += src->index_list_size;
-	dest->checks = lzma_index_checks(dest) | src->checks;
+	dest->checks |= src->checks;
 
 
 	// There's nothing else left in src than the base structure.
 	// There's nothing else left in src than the base structure.
 	lzma_free(src, allocator);
 	lzma_free(src, allocator);
@@ -1229,7 +1247,7 @@ lzma_index_iter_locate(lzma_index_iter *iter, lzma_vli target)
 
 
 	// Use binary search to locate the exact Record. It is the first
 	// Use binary search to locate the exact Record. It is the first
 	// Record whose uncompressed_sum is greater than target.
 	// Record whose uncompressed_sum is greater than target.
-	// This is because we want the rightmost Record that fullfills the
+	// This is because we want the rightmost Record that fulfills the
 	// search criterion. It is possible that there are empty Blocks;
 	// search criterion. It is possible that there are empty Blocks;
 	// we don't want to return them.
 	// we don't want to return them.
 	size_t left = 0;
 	size_t left = 0;

+ 13 - 6
Utilities/cmliblzma/liblzma/common/index.h

@@ -1,20 +1,24 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       index.h
 /// \file       index.h
 /// \brief      Handling of Index
 /// \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
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef LZMA_INDEX_H
 #ifndef LZMA_INDEX_H
 #define LZMA_INDEX_H
 #define LZMA_INDEX_H
 
 
-#include "common.h"
-
 
 
 /// Minimum Unpadded Size
 /// Minimum Unpadded Size
 #define UNPADDED_SIZE_MIN LZMA_VLI_C(5)
 #define UNPADDED_SIZE_MIN LZMA_VLI_C(5)
@@ -22,6 +26,9 @@
 /// Maximum Unpadded Size
 /// Maximum Unpadded Size
 #define UNPADDED_SIZE_MAX (LZMA_VLI_MAX & ~LZMA_VLI_C(3))
 #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
 /// Get the size of the Index Padding field. This is needed by Index encoder
 /// and decoder, but applications should have no use for this.
 /// and decoder, but applications should have no use for this.
@@ -38,7 +45,7 @@ extern void lzma_index_prealloc(lzma_index *i, lzma_vli records);
 static inline lzma_vli
 static inline lzma_vli
 vli_ceil4(lzma_vli vli)
 vli_ceil4(lzma_vli vli)
 {
 {
-	assert(vli <= LZMA_VLI_MAX);
+	assert(vli <= UNPADDED_SIZE_MAX);
 	return (vli + 3) & ~LZMA_VLI_C(3);
 	return (vli + 3) & ~LZMA_VLI_C(3);
 }
 }
 
 

+ 33 - 13
Utilities/cmliblzma/liblzma/common/index_decoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       index_decoder.c
 /// \file       index_decoder.c
@@ -5,12 +7,9 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
-#include "index.h"
+#include "index_decoder.h"
 #include "check.h"
 #include "check.h"
 
 
 
 
@@ -80,7 +79,7 @@ index_decode(void *coder_ptr, const lzma_allocator *allocator,
 		// format". One could argue that the application should
 		// format". One could argue that the application should
 		// verify the Index Indicator before trying to decode the
 		// verify the Index Indicator before trying to decode the
 		// Index, but well, I suppose it is simpler this way.
 		// 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;
 			return LZMA_DATA_ERROR;
 
 
 		coder->sequence = SEQ_COUNT;
 		coder->sequence = SEQ_COUNT;
@@ -180,8 +179,11 @@ index_decode(void *coder_ptr, const lzma_allocator *allocator,
 				return LZMA_OK;
 				return LZMA_OK;
 
 
 			if (((coder->crc32 >> (coder->pos * 8)) & 0xFF)
 			if (((coder->crc32 >> (coder->pos * 8)) & 0xFF)
-					!= in[(*in_pos)++])
+					!= in[(*in_pos)++]) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
 				return LZMA_DATA_ERROR;
 				return LZMA_DATA_ERROR;
+#endif
+			}
 
 
 		} while (++coder->pos < 4);
 		} while (++coder->pos < 4);
 
 
@@ -200,9 +202,16 @@ index_decode(void *coder_ptr, const lzma_allocator *allocator,
 	}
 	}
 
 
 out:
 out:
-	// Update the CRC32,
-	coder->crc32 = lzma_crc32(in + in_start,
-			*in_pos - in_start, coder->crc32);
+	// Update the CRC32.
+	//
+	// Avoid null pointer + 0 (undefined behavior) in "in + in_start".
+	// In such a case we had no input and thus in_used == 0.
+	{
+		const size_t in_used = *in_pos - in_start;
+		if (in_used > 0)
+			coder->crc32 = lzma_crc32(in + in_start,
+					in_used, coder->crc32);
+	}
 
 
 	return ret;
 	return ret;
 }
 }
@@ -265,11 +274,11 @@ index_decoder_reset(lzma_index_coder *coder, const lzma_allocator *allocator,
 }
 }
 
 
 
 
-static lzma_ret
-index_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+extern lzma_ret
+lzma_index_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
 		lzma_index **i, uint64_t memlimit)
 		lzma_index **i, uint64_t memlimit)
 {
 {
-	lzma_next_coder_init(&index_decoder_init, next, allocator);
+	lzma_next_coder_init(&lzma_index_decoder_init, next, allocator);
 
 
 	if (i == NULL)
 	if (i == NULL)
 		return LZMA_PROG_ERROR;
 		return LZMA_PROG_ERROR;
@@ -296,7 +305,13 @@ index_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
 extern LZMA_API(lzma_ret)
 extern LZMA_API(lzma_ret)
 lzma_index_decoder(lzma_stream *strm, lzma_index **i, uint64_t memlimit)
 lzma_index_decoder(lzma_stream *strm, lzma_index **i, uint64_t memlimit)
 {
 {
-	lzma_next_strm_init(index_decoder_init, strm, i, memlimit);
+	// If i isn't NULL, *i must always be initialized due to
+	// the wording in the API docs. This way it is initialized
+	// if we return LZMA_PROG_ERROR due to strm == NULL.
+	if (i != NULL)
+		*i = NULL;
+
+	lzma_next_strm_init(lzma_index_decoder_init, strm, i, memlimit);
 
 
 	strm->internal->supported_actions[LZMA_RUN] = true;
 	strm->internal->supported_actions[LZMA_RUN] = true;
 	strm->internal->supported_actions[LZMA_FINISH] = true;
 	strm->internal->supported_actions[LZMA_FINISH] = true;
@@ -310,6 +325,11 @@ lzma_index_buffer_decode(lzma_index **i, uint64_t *memlimit,
 		const lzma_allocator *allocator,
 		const lzma_allocator *allocator,
 		const uint8_t *in, size_t *in_pos, size_t in_size)
 		const uint8_t *in, size_t *in_pos, size_t in_size)
 {
 {
+	// If i isn't NULL, *i must always be initialized due to
+	// the wording in the API docs.
+	if (i != NULL)
+		*i = NULL;
+
 	// Sanity checks
 	// Sanity checks
 	if (i == NULL || memlimit == NULL
 	if (i == NULL || memlimit == NULL
 			|| in == NULL || in_pos == NULL || *in_pos > in_size)
 			|| in == NULL || in_pos == NULL || *in_pos > in_size)

+ 24 - 0
Utilities/cmliblzma/liblzma/common/index_decoder.h

@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: 0BSD
+
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       index_decoder.h
+/// \brief      Decodes the Index field
+//
+//  Author:     Lasse Collin
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_INDEX_DECODER_H
+#define LZMA_INDEX_DECODER_H
+
+#include "common.h"
+#include "index.h"
+
+
+extern lzma_ret lzma_index_decoder_init(lzma_next_coder *next,
+		const lzma_allocator *allocator,
+		lzma_index **i, uint64_t memlimit);
+
+
+#endif

+ 12 - 6
Utilities/cmliblzma/liblzma/common/index_encoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       index_encoder.c
 /// \file       index_encoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "index_encoder.h"
 #include "index_encoder.h"
@@ -65,7 +64,7 @@ index_encode(void *coder_ptr,
 	while (*out_pos < out_size)
 	while (*out_pos < out_size)
 	switch (coder->sequence) {
 	switch (coder->sequence) {
 	case SEQ_INDICATOR:
 	case SEQ_INDICATOR:
-		out[*out_pos] = 0x00;
+		out[*out_pos] = INDEX_INDICATOR;
 		++*out_pos;
 		++*out_pos;
 		coder->sequence = SEQ_COUNT;
 		coder->sequence = SEQ_COUNT;
 		break;
 		break;
@@ -153,8 +152,15 @@ index_encode(void *coder_ptr,
 
 
 out:
 out:
 	// Update the CRC32.
 	// Update the CRC32.
-	coder->crc32 = lzma_crc32(out + out_start,
-			*out_pos - out_start, coder->crc32);
+	//
+	// Avoid null pointer + 0 (undefined behavior) in "out + out_start".
+	// In such a case we had no input and thus out_used == 0.
+	{
+		const size_t out_used = *out_pos - out_start;
+		if (out_used > 0)
+			coder->crc32 = lzma_crc32(out + out_start,
+					out_used, coder->crc32);
+	}
 
 
 	return ret;
 	return ret;
 }
 }

+ 2 - 3
Utilities/cmliblzma/liblzma/common/index_encoder.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       index_encoder.h
 /// \file       index_encoder.h
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef LZMA_INDEX_ENCODER_H
 #ifndef LZMA_INDEX_ENCODER_H

+ 23 - 15
Utilities/cmliblzma/liblzma/common/index_hash.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       index_hash.c
 /// \file       index_hash.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "common.h"
 #include "common.h"
@@ -122,7 +121,7 @@ lzma_index_hash_size(const lzma_index_hash *index_hash)
 
 
 
 
 /// Updates the sizes and the hash without any validation.
 /// Updates the sizes and the hash without any validation.
-static lzma_ret
+static void
 hash_append(lzma_index_hash_info *info, lzma_vli unpadded_size,
 hash_append(lzma_index_hash_info *info, lzma_vli unpadded_size,
 		lzma_vli uncompressed_size)
 		lzma_vli uncompressed_size)
 {
 {
@@ -136,7 +135,7 @@ hash_append(lzma_index_hash_info *info, lzma_vli unpadded_size,
 	lzma_check_update(&info->check, LZMA_CHECK_BEST,
 	lzma_check_update(&info->check, LZMA_CHECK_BEST,
 			(const uint8_t *)(sizes), sizeof(sizes));
 			(const uint8_t *)(sizes), sizeof(sizes));
 
 
-	return LZMA_OK;
+	return;
 }
 }
 
 
 
 
@@ -145,15 +144,14 @@ lzma_index_hash_append(lzma_index_hash *index_hash, lzma_vli unpadded_size,
 		lzma_vli uncompressed_size)
 		lzma_vli uncompressed_size)
 {
 {
 	// Validate the arguments.
 	// 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_MIN
 			|| unpadded_size > UNPADDED_SIZE_MAX
 			|| unpadded_size > UNPADDED_SIZE_MAX
 			|| uncompressed_size > LZMA_VLI_MAX)
 			|| uncompressed_size > LZMA_VLI_MAX)
 		return LZMA_PROG_ERROR;
 		return LZMA_PROG_ERROR;
 
 
 	// Update the hash.
 	// Update the hash.
-	return_if_error(hash_append(&index_hash->blocks,
-			unpadded_size, uncompressed_size));
+	hash_append(&index_hash->blocks, unpadded_size, uncompressed_size);
 
 
 	// Validate the properties of *info are still in allowed limits.
 	// Validate the properties of *info are still in allowed limits.
 	if (index_hash->blocks.blocks_size > LZMA_VLI_MAX
 	if (index_hash->blocks.blocks_size > LZMA_VLI_MAX
@@ -191,7 +189,7 @@ lzma_index_hash_decode(lzma_index_hash *index_hash, const uint8_t *in,
 	switch (index_hash->sequence) {
 	switch (index_hash->sequence) {
 	case SEQ_BLOCK:
 	case SEQ_BLOCK:
 		// Check the Index Indicator is present.
 		// Check the Index Indicator is present.
-		if (in[(*in_pos)++] != 0x00)
+		if (in[(*in_pos)++] != INDEX_INDICATOR)
 			return LZMA_DATA_ERROR;
 			return LZMA_DATA_ERROR;
 
 
 		index_hash->sequence = SEQ_COUNT;
 		index_hash->sequence = SEQ_COUNT;
@@ -239,9 +237,9 @@ lzma_index_hash_decode(lzma_index_hash *index_hash, const uint8_t *in,
 			index_hash->sequence = SEQ_UNCOMPRESSED;
 			index_hash->sequence = SEQ_UNCOMPRESSED;
 		} else {
 		} else {
 			// Update the hash.
 			// Update the hash.
-			return_if_error(hash_append(&index_hash->records,
+			hash_append(&index_hash->records,
 					index_hash->unpadded_size,
 					index_hash->unpadded_size,
-					index_hash->uncompressed_size));
+					index_hash->uncompressed_size);
 
 
 			// Verify that we don't go over the known sizes. Note
 			// Verify that we don't go over the known sizes. Note
 			// that this validation is simpler than the one used
 			// that this validation is simpler than the one used
@@ -313,8 +311,11 @@ lzma_index_hash_decode(lzma_index_hash *index_hash, const uint8_t *in,
 				return LZMA_OK;
 				return LZMA_OK;
 
 
 			if (((index_hash->crc32 >> (index_hash->pos * 8))
 			if (((index_hash->crc32 >> (index_hash->pos * 8))
-					& 0xFF) != in[(*in_pos)++])
+					& 0xFF) != in[(*in_pos)++]) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
 				return LZMA_DATA_ERROR;
 				return LZMA_DATA_ERROR;
+#endif
+			}
 
 
 		} while (++index_hash->pos < 4);
 		} while (++index_hash->pos < 4);
 
 
@@ -326,9 +327,16 @@ lzma_index_hash_decode(lzma_index_hash *index_hash, const uint8_t *in,
 	}
 	}
 
 
 out:
 out:
-	// Update the CRC32,
-	index_hash->crc32 = lzma_crc32(in + in_start,
-			*in_pos - in_start, index_hash->crc32);
+	// Update the CRC32.
+	//
+	// Avoid null pointer + 0 (undefined behavior) in "in + in_start".
+	// In such a case we had no input and thus in_used == 0.
+	{
+		const size_t in_used = *in_pos - in_start;
+		if (in_used > 0)
+			index_hash->crc32 = lzma_crc32(in + in_start,
+					in_used, index_hash->crc32);
+	}
 
 
 	return ret;
 	return ret;
 }
 }

+ 417 - 0
Utilities/cmliblzma/liblzma/common/lzip_decoder.c

@@ -0,0 +1,417 @@
+// SPDX-License-Identifier: 0BSD
+
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzip_decoder.c
+/// \brief      Decodes .lz (lzip) files
+//
+//  Author:     Michał Górny
+//              Lasse Collin
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lzip_decoder.h"
+#include "lzma_decoder.h"
+#include "check.h"
+
+
+// .lz format version 0 lacks the 64-bit Member size field in the footer.
+#define LZIP_V0_FOOTER_SIZE 12
+#define LZIP_V1_FOOTER_SIZE 20
+#define LZIP_FOOTER_SIZE_MAX LZIP_V1_FOOTER_SIZE
+
+// lc/lp/pb are hardcoded in the .lz format.
+#define LZIP_LC 3
+#define LZIP_LP 0
+#define LZIP_PB 2
+
+
+typedef struct {
+	enum {
+		SEQ_ID_STRING,
+		SEQ_VERSION,
+		SEQ_DICT_SIZE,
+		SEQ_CODER_INIT,
+		SEQ_LZMA_STREAM,
+		SEQ_MEMBER_FOOTER,
+	} sequence;
+
+	/// .lz member format version
+	uint32_t version;
+
+	/// CRC32 of the uncompressed data in the .lz member
+	uint32_t crc32;
+
+	/// Uncompressed size of the .lz member
+	uint64_t uncompressed_size;
+
+	/// Compressed size of the .lz member
+	uint64_t member_size;
+
+	/// Memory usage limit
+	uint64_t memlimit;
+
+	/// Amount of memory actually needed
+	uint64_t memusage;
+
+	/// If true, LZMA_GET_CHECK is returned after decoding the header
+	/// fields. As all files use CRC32 this is redundant but it's
+	/// implemented anyway since the initialization functions supports
+	/// all other flags in addition to LZMA_TELL_ANY_CHECK.
+	bool tell_any_check;
+
+	/// If true, we won't calculate or verify the CRC32 of
+	/// the uncompressed data.
+	bool ignore_check;
+
+	/// If true, we will decode concatenated .lz members and stop if
+	/// non-.lz data is seen after at least one member has been
+	/// successfully decoded.
+	bool concatenated;
+
+	/// When decoding concatenated .lz members, this is true as long as
+	/// we are decoding the first .lz member. This is needed to avoid
+	/// incorrect LZMA_FORMAT_ERROR in case there is non-.lz data at
+	/// the end of the file.
+	bool first_member;
+
+	/// Reading position in the header and footer fields
+	size_t pos;
+
+	/// Buffer to hold the .lz footer fields
+	uint8_t buffer[LZIP_FOOTER_SIZE_MAX];
+
+	/// Options decoded from the .lz header that needed to initialize
+	/// the LZMA1 decoder.
+	lzma_options_lzma options;
+
+	/// LZMA1 decoder
+	lzma_next_coder lzma_decoder;
+
+} lzma_lzip_coder;
+
+
+static lzma_ret
+lzip_decode(void *coder_ptr, const lzma_allocator *allocator,
+		const uint8_t *restrict in, size_t *restrict in_pos,
+		size_t in_size, uint8_t *restrict out,
+		size_t *restrict out_pos, size_t out_size, lzma_action action)
+{
+	lzma_lzip_coder *coder = coder_ptr;
+
+	while (true)
+	switch (coder->sequence) {
+	case SEQ_ID_STRING: {
+		// The "ID string" or magic bytes are "LZIP" in US-ASCII.
+		const uint8_t lzip_id_string[4] = { 0x4C, 0x5A, 0x49, 0x50 };
+
+		while (coder->pos < sizeof(lzip_id_string)) {
+			if (*in_pos >= in_size) {
+				// If we are on the 2nd+ concatenated member
+				// and the input ends before we can read
+				// the magic bytes, we discard the bytes that
+				// were already read (up to 3) and finish.
+				// See the reasoning below.
+				return !coder->first_member
+						&& action == LZMA_FINISH
+					? LZMA_STREAM_END : LZMA_OK;
+			}
+
+			if (in[*in_pos] != lzip_id_string[coder->pos]) {
+				// The .lz format allows putting non-.lz data
+				// at the end of the file. If we have seen
+				// at least one valid .lz member already,
+				// then we won't consume the byte at *in_pos
+				// and will return LZMA_STREAM_END. This way
+				// apps can easily locate and read the non-.lz
+				// data after the .lz member(s).
+				//
+				// NOTE: If the first 1-3 bytes of the non-.lz
+				// data match the .lz ID string then the first
+				// 1-3 bytes of the junk will get ignored by
+				// us. If apps want to properly locate the
+				// trailing data they must ensure that the
+				// first byte of their custom data isn't the
+				// same as the first byte of .lz ID string.
+				// With the liblzma API we cannot rewind the
+				// input position across calls to lzma_code().
+				return !coder->first_member
+					? LZMA_STREAM_END : LZMA_FORMAT_ERROR;
+			}
+
+			++*in_pos;
+			++coder->pos;
+		}
+
+		coder->pos = 0;
+
+		coder->crc32 = 0;
+		coder->uncompressed_size = 0;
+		coder->member_size = sizeof(lzip_id_string);
+
+		coder->sequence = SEQ_VERSION;
+	}
+
+	// Fall through
+
+	case SEQ_VERSION:
+		if (*in_pos >= in_size)
+			return LZMA_OK;
+
+		coder->version = in[(*in_pos)++];
+
+		// We support version 0 and unextended version 1.
+		if (coder->version > 1)
+			return LZMA_OPTIONS_ERROR;
+
+		++coder->member_size;
+		coder->sequence = SEQ_DICT_SIZE;
+
+		// .lz versions 0 and 1 use CRC32 as the integrity check
+		// so if the application wanted to know that
+		// (LZMA_TELL_ANY_CHECK) we can tell it now.
+		if (coder->tell_any_check)
+			return LZMA_GET_CHECK;
+
+	// Fall through
+
+	case SEQ_DICT_SIZE: {
+		if (*in_pos >= in_size)
+			return LZMA_OK;
+
+		const uint32_t ds = in[(*in_pos)++];
+		++coder->member_size;
+
+		// The five lowest bits are for the base-2 logarithm of
+		// the dictionary size and the highest three bits are
+		// the fractional part (0/16 to 7/16) that will be
+		// subtracted to get the final value.
+		//
+		// For example, with 0xB5:
+		//     b2log = 21
+		//     fracnum = 5
+		//     dict_size = 2^21 - 2^21 * 5 / 16 = 1408 KiB
+		const uint32_t b2log = ds & 0x1F;
+		const uint32_t fracnum = ds >> 5;
+
+		// The format versions 0 and 1 allow dictionary size in the
+		// range [4 KiB, 512 MiB].
+		if (b2log < 12 || b2log > 29 || (b2log == 12 && fracnum > 0))
+			return LZMA_DATA_ERROR;
+
+		//   2^[b2log] - 2^[b2log] * [fracnum] / 16
+		// = 2^[b2log] - [fracnum] * 2^([b2log] - 4)
+		coder->options.dict_size = (UINT32_C(1) << b2log)
+				- (fracnum << (b2log - 4));
+
+		assert(coder->options.dict_size >= 4096);
+		assert(coder->options.dict_size <= (UINT32_C(512) << 20));
+
+		coder->options.preset_dict = NULL;
+		coder->options.lc = LZIP_LC;
+		coder->options.lp = LZIP_LP;
+		coder->options.pb = LZIP_PB;
+
+		// Calculate the memory usage.
+		coder->memusage = lzma_lzma_decoder_memusage(&coder->options)
+				+ LZMA_MEMUSAGE_BASE;
+
+		// Initialization is a separate step because if we return
+		// LZMA_MEMLIMIT_ERROR we need to be able to restart after
+		// the memlimit has been increased.
+		coder->sequence = SEQ_CODER_INIT;
+	}
+
+	// Fall through
+
+	case SEQ_CODER_INIT: {
+		if (coder->memusage > coder->memlimit)
+			return LZMA_MEMLIMIT_ERROR;
+
+		const lzma_filter_info filters[2] = {
+			{
+				.id = LZMA_FILTER_LZMA1,
+				.init = &lzma_lzma_decoder_init,
+				.options = &coder->options,
+			}, {
+				.init = NULL,
+			}
+		};
+
+		return_if_error(lzma_next_filter_init(&coder->lzma_decoder,
+				allocator, filters));
+
+		coder->crc32 = 0;
+		coder->sequence = SEQ_LZMA_STREAM;
+	}
+
+	// Fall through
+
+	case SEQ_LZMA_STREAM: {
+		const size_t in_start = *in_pos;
+		const size_t out_start = *out_pos;
+
+		const lzma_ret ret = coder->lzma_decoder.code(
+				coder->lzma_decoder.coder, allocator,
+				in, in_pos, in_size, out, out_pos, out_size,
+				action);
+
+		const size_t out_used = *out_pos - out_start;
+
+		coder->member_size += *in_pos - in_start;
+		coder->uncompressed_size += out_used;
+
+		// Don't update the CRC32 if the integrity check will be
+		// ignored or if there was no new output. The latter is
+		// important in case out == NULL to avoid null pointer + 0
+		// which is undefined behavior.
+		if (!coder->ignore_check && out_used > 0)
+			coder->crc32 = lzma_crc32(out + out_start, out_used,
+					coder->crc32);
+
+		if (ret != LZMA_STREAM_END)
+			return ret;
+
+		coder->sequence = SEQ_MEMBER_FOOTER;
+	}
+
+	// Fall through
+
+	case SEQ_MEMBER_FOOTER: {
+		// The footer of .lz version 0 lacks the Member size field.
+		// This is the only difference between version 0 and
+		// unextended version 1 formats.
+		const size_t footer_size = coder->version == 0
+				? LZIP_V0_FOOTER_SIZE
+				: LZIP_V1_FOOTER_SIZE;
+
+		// Copy the CRC32, Data size, and Member size fields to
+		// the internal buffer.
+		lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
+				footer_size);
+
+		// Return if we didn't get the whole footer yet.
+		if (coder->pos < footer_size)
+			return LZMA_OK;
+
+		coder->pos = 0;
+		coder->member_size += footer_size;
+
+		// Check that the footer fields match the observed data.
+		if (!coder->ignore_check
+				&& coder->crc32 != read32le(&coder->buffer[0]))
+			return LZMA_DATA_ERROR;
+
+		if (coder->uncompressed_size != read64le(&coder->buffer[4]))
+			return LZMA_DATA_ERROR;
+
+		if (coder->version > 0) {
+			// .lz version 0 has no Member size field.
+			if (coder->member_size != read64le(&coder->buffer[12]))
+				return LZMA_DATA_ERROR;
+		}
+
+		// Decoding is finished if we weren't requested to decode
+		// more than one .lz member.
+		if (!coder->concatenated)
+			return LZMA_STREAM_END;
+
+		coder->first_member = false;
+		coder->sequence = SEQ_ID_STRING;
+		break;
+	}
+
+	default:
+		assert(0);
+		return LZMA_PROG_ERROR;
+	}
+
+	// Never reached
+}
+
+
+static void
+lzip_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
+{
+	lzma_lzip_coder *coder = coder_ptr;
+	lzma_next_end(&coder->lzma_decoder, allocator);
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+static lzma_check
+lzip_decoder_get_check(const void *coder_ptr lzma_attribute((__unused__)))
+{
+	return LZMA_CHECK_CRC32;
+}
+
+
+static lzma_ret
+lzip_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
+		uint64_t *old_memlimit, uint64_t new_memlimit)
+{
+	lzma_lzip_coder *coder = coder_ptr;
+
+	*memusage = coder->memusage;
+	*old_memlimit = coder->memlimit;
+
+	if (new_memlimit != 0) {
+		if (new_memlimit < coder->memusage)
+			return LZMA_MEMLIMIT_ERROR;
+
+		coder->memlimit = new_memlimit;
+	}
+
+	return LZMA_OK;
+}
+
+
+extern lzma_ret
+lzma_lzip_decoder_init(
+		lzma_next_coder *next, const lzma_allocator *allocator,
+		uint64_t memlimit, uint32_t flags)
+{
+	lzma_next_coder_init(&lzma_lzip_decoder_init, next, allocator);
+
+	if (flags & ~LZMA_SUPPORTED_FLAGS)
+		return LZMA_OPTIONS_ERROR;
+
+	lzma_lzip_coder *coder = next->coder;
+	if (coder == NULL) {
+		coder = lzma_alloc(sizeof(lzma_lzip_coder), allocator);
+		if (coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->coder = coder;
+		next->code = &lzip_decode;
+		next->end = &lzip_decoder_end;
+		next->get_check = &lzip_decoder_get_check;
+		next->memconfig = &lzip_decoder_memconfig;
+
+		coder->lzma_decoder = LZMA_NEXT_CODER_INIT;
+	}
+
+	coder->sequence = SEQ_ID_STRING;
+	coder->memlimit = my_max(1, memlimit);
+	coder->memusage = LZMA_MEMUSAGE_BASE;
+	coder->tell_any_check = (flags & LZMA_TELL_ANY_CHECK) != 0;
+	coder->ignore_check = (flags & LZMA_IGNORE_CHECK) != 0;
+	coder->concatenated = (flags & LZMA_CONCATENATED) != 0;
+	coder->first_member = true;
+	coder->pos = 0;
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_lzip_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
+{
+	lzma_next_strm_init(lzma_lzip_decoder_init, strm, memlimit, flags);
+
+	strm->internal->supported_actions[LZMA_RUN] = true;
+	strm->internal->supported_actions[LZMA_FINISH] = true;
+
+	return LZMA_OK;
+}

+ 21 - 0
Utilities/cmliblzma/liblzma/common/lzip_decoder.h

@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: 0BSD
+
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzip_decoder.h
+/// \brief      Decodes .lz (lzip) files
+//
+//  Author:     Michał Górny
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZIP_DECODER_H
+#define LZMA_LZIP_DECODER_H
+
+#include "common.h"
+
+extern lzma_ret lzma_lzip_decoder_init(
+		lzma_next_coder *next, const lzma_allocator *allocator,
+		uint64_t memlimit, uint32_t flags);
+
+#endif

+ 44 - 20
Utilities/cmliblzma/liblzma/common/memcmplen.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       memcmplen.h
 /// \file       memcmplen.h
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef LZMA_MEMCMPLEN_H
 #ifndef LZMA_MEMCMPLEN_H
@@ -19,6 +18,17 @@
 #	include <immintrin.h>
 #	include <immintrin.h>
 #endif
 #endif
 
 
+// Only include <intrin.h> if it is needed. The header is only needed
+// on Windows when using an MSVC compatible compiler. The Intel compiler
+// can use the intrinsics without the header file.
+#if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
+		&& defined(_MSC_VER) \
+		&& (defined(_M_X64) \
+			|| defined(_M_ARM64) || defined(_M_ARM64EC)) \
+		&& !defined(__INTEL_COMPILER)
+#	include <intrin.h>
+#endif
+
 
 
 /// Find out how many equal bytes the two buffers have.
 /// Find out how many equal bytes the two buffers have.
 ///
 ///
@@ -39,7 +49,7 @@
 ///             It's rounded up to 2^n. This extra amount needs to be
 ///             It's rounded up to 2^n. This extra amount needs to be
 ///             allocated in the buffers being used. It needs to be
 ///             allocated in the buffers being used. It needs to be
 ///             initialized too to keep Valgrind quiet.
 ///             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,
 lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2,
 		uint32_t len, uint32_t limit)
 		uint32_t len, uint32_t limit)
 {
 {
@@ -47,27 +57,40 @@ lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2,
 	assert(limit <= UINT32_MAX / 2);
 	assert(limit <= UINT32_MAX / 2);
 
 
 #if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
 #if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
-		&& ((TUKLIB_GNUC_REQ(3, 4) && defined(__x86_64__)) \
+		&& (((TUKLIB_GNUC_REQ(3, 4) || defined(__clang__)) \
+				&& (defined(__x86_64__) \
+					|| defined(__aarch64__))) \
 			|| (defined(__INTEL_COMPILER) && defined(__x86_64__)) \
 			|| (defined(__INTEL_COMPILER) && defined(__x86_64__)) \
 			|| (defined(__INTEL_COMPILER) && defined(_M_X64)) \
 			|| (defined(__INTEL_COMPILER) && defined(_M_X64)) \
-			|| (defined(_MSC_VER) && defined(_M_X64)))
-	// NOTE: This will use 64-bit unaligned access which
-	// TUKLIB_FAST_UNALIGNED_ACCESS wasn't meant to permit, but
-	// it's convenient here at least as long as it's x86-64 only.
+			|| (defined(_MSC_VER) && (defined(_M_X64) \
+				|| defined(_M_ARM64) || defined(_M_ARM64EC))))
+	// This is only for x86-64 and ARM64 for now. This might be fine on
+	// other 64-bit processors too. On big endian one should use xor
+	// instead of subtraction and switch to __builtin_clzll().
+	//
+	// Reasons to use subtraction instead of xor:
+	//
+	//   - On some x86-64 processors (Intel Sandy Bridge to Tiger Lake),
+	//     sub+jz and sub+jnz can be fused but xor+jz or xor+jnz cannot.
+	//     Thus using subtraction has potential to be a tiny amount faster
+	//     since the code checks if the quotient is non-zero.
+	//
+	//   - Some processors (Intel Pentium 4) used to have more ALU
+	//     resources for add/sub instructions than and/or/xor.
 	//
 	//
-	// I keep this x86-64 only for now since that's where I know this
-	// to be a good method. This may be fine on other 64-bit CPUs too.
-	// On big endian one should use xor instead of subtraction and switch
-	// to __builtin_clzll().
+	// The processor info is based on Agner Fog's microarchitecture.pdf
+	// version 2023-05-26. https://www.agner.org/optimize/
 #define LZMA_MEMCMPLEN_EXTRA 8
 #define LZMA_MEMCMPLEN_EXTRA 8
 	while (len < limit) {
 	while (len < limit) {
 		const uint64_t x = read64ne(buf1 + len) - read64ne(buf2 + len);
 		const uint64_t x = read64ne(buf1 + len) - read64ne(buf2 + len);
 		if (x != 0) {
 		if (x != 0) {
-#	if defined(_M_X64) // MSVC or Intel C compiler on Windows
+	// MSVC or Intel C compiler on Windows
+#	if defined(_MSC_VER) || defined(__INTEL_COMPILER)
 			unsigned long tmp;
 			unsigned long tmp;
 			_BitScanForward64(&tmp, x);
 			_BitScanForward64(&tmp, x);
 			len += (uint32_t)tmp >> 3;
 			len += (uint32_t)tmp >> 3;
-#	else // GCC, clang, or Intel C compiler
+	// GCC, Clang, or Intel C compiler
+#	else
 			len += (uint32_t)__builtin_ctzll(x) >> 3;
 			len += (uint32_t)__builtin_ctzll(x) >> 3;
 #	endif
 #	endif
 			return my_min(len, limit);
 			return my_min(len, limit);
@@ -80,12 +103,12 @@ lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2,
 
 
 #elif defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
 #elif defined(TUKLIB_FAST_UNALIGNED_ACCESS) \
 		&& defined(HAVE__MM_MOVEMASK_EPI8) \
 		&& defined(HAVE__MM_MOVEMASK_EPI8) \
-		&& ((defined(__GNUC__) && defined(__SSE2_MATH__)) \
-			|| (defined(__INTEL_COMPILER) && defined(__SSE2__)) \
+		&& (defined(__SSE2__) \
 			|| (defined(_MSC_VER) && defined(_M_IX86_FP) \
 			|| (defined(_MSC_VER) && defined(_M_IX86_FP) \
 				&& _M_IX86_FP >= 2))
 				&& _M_IX86_FP >= 2))
-	// NOTE: Like above, this will use 128-bit unaligned access which
-	// TUKLIB_FAST_UNALIGNED_ACCESS wasn't meant to permit.
+	// NOTE: This will use 128-bit unaligned access which
+	// TUKLIB_FAST_UNALIGNED_ACCESS wasn't meant to permit,
+	// but it's convenient here since this is x86-only.
 	//
 	//
 	// SSE2 version for 32-bit and 64-bit x86. On x86-64 the above
 	// SSE2 version for 32-bit and 64-bit x86. On x86-64 the above
 	// version is sometimes significantly faster and sometimes
 	// version is sometimes significantly faster and sometimes
@@ -93,7 +116,8 @@ lzma_memcmplen(const uint8_t *buf1, const uint8_t *buf2,
 	// version isn't used on x86-64.
 	// version isn't used on x86-64.
 #	define LZMA_MEMCMPLEN_EXTRA 16
 #	define LZMA_MEMCMPLEN_EXTRA 16
 	while (len < limit) {
 	while (len < limit) {
-		const uint32_t x = 0xFFFF ^ _mm_movemask_epi8(_mm_cmpeq_epi8(
+		const uint32_t x = 0xFFFF ^ (uint32_t)_mm_movemask_epi8(
+			_mm_cmpeq_epi8(
 			_mm_loadu_si128((const __m128i *)(buf1 + len)),
 			_mm_loadu_si128((const __m128i *)(buf1 + len)),
 			_mm_loadu_si128((const __m128i *)(buf2 + len))));
 			_mm_loadu_si128((const __m128i *)(buf2 + len))));
 
 

+ 220 - 0
Utilities/cmliblzma/liblzma/common/microlzma_decoder.c

@@ -0,0 +1,220 @@
+// SPDX-License-Identifier: 0BSD
+
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       microlzma_decoder.c
+/// \brief      Decode MicroLZMA format
+//
+//  Author:     Lasse Collin
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lzma_decoder.h"
+#include "lz_decoder.h"
+
+
+typedef struct {
+	/// LZMA1 decoder
+	lzma_next_coder lzma;
+
+	/// Compressed size of the stream as given by the application.
+	/// This must be exactly correct.
+	///
+	/// This will be decremented when input is read.
+	uint64_t comp_size;
+
+	/// Uncompressed size of the stream as given by the application.
+	/// This may be less than the actual uncompressed size if
+	/// uncomp_size_is_exact is false.
+	///
+	/// This will be decremented when output is produced.
+	lzma_vli uncomp_size;
+
+	/// LZMA dictionary size as given by the application
+	uint32_t dict_size;
+
+	/// If true, the exact uncompressed size is known. If false,
+	/// uncomp_size may be smaller than the real uncompressed size;
+	/// uncomp_size may never be bigger than the real uncompressed size.
+	bool uncomp_size_is_exact;
+
+	/// True once the first byte of the MicroLZMA stream
+	/// has been processed.
+	bool props_decoded;
+} lzma_microlzma_coder;
+
+
+static lzma_ret
+microlzma_decode(void *coder_ptr, const lzma_allocator *allocator,
+		const uint8_t *restrict in, size_t *restrict in_pos,
+		size_t in_size, uint8_t *restrict out,
+		size_t *restrict out_pos, size_t out_size, lzma_action action)
+{
+	lzma_microlzma_coder *coder = coder_ptr;
+
+	// Remember the in start position so that we can update comp_size.
+	const size_t in_start = *in_pos;
+
+	// Remember the out start position so that we can update uncomp_size.
+	const size_t out_start = *out_pos;
+
+	// Limit the amount of input so that the decoder won't read more than
+	// comp_size. This is required when uncomp_size isn't exact because
+	// in that case the LZMA decoder will try to decode more input even
+	// when it has no output space (it can be looking for EOPM).
+	if (in_size - *in_pos > coder->comp_size)
+		in_size = *in_pos + (size_t)(coder->comp_size);
+
+	// When the exact uncompressed size isn't known, we must limit
+	// the available output space to prevent the LZMA decoder from
+	// trying to decode too much.
+	if (!coder->uncomp_size_is_exact
+			&& out_size - *out_pos > coder->uncomp_size)
+		out_size = *out_pos + (size_t)(coder->uncomp_size);
+
+	if (!coder->props_decoded) {
+		// There must be at least one byte of input to decode
+		// the properties byte.
+		if (*in_pos >= in_size)
+			return LZMA_OK;
+
+		lzma_options_lzma options = {
+			.dict_size = coder->dict_size,
+			.preset_dict = NULL,
+			.preset_dict_size = 0,
+			.ext_flags = 0, // EOPM not allowed when size is known
+			.ext_size_low = UINT32_MAX, // Unknown size by default
+			.ext_size_high = UINT32_MAX,
+		};
+
+		if (coder->uncomp_size_is_exact)
+			lzma_set_ext_size(options, coder->uncomp_size);
+
+		// The properties are stored as bitwise-negation
+		// of the typical encoding.
+		if (lzma_lzma_lclppb_decode(&options, ~in[*in_pos]))
+			return LZMA_OPTIONS_ERROR;
+
+		++*in_pos;
+
+		// Initialize the decoder.
+		lzma_filter_info filters[2] = {
+			{
+				.id = LZMA_FILTER_LZMA1EXT,
+				.init = &lzma_lzma_decoder_init,
+				.options = &options,
+			}, {
+				.init = NULL,
+			}
+		};
+
+		return_if_error(lzma_next_filter_init(&coder->lzma,
+				allocator, filters));
+
+		// Pass one dummy 0x00 byte to the LZMA decoder since that
+		// is what it expects the first byte to be.
+		const uint8_t dummy_in = 0;
+		size_t dummy_in_pos = 0;
+		if (coder->lzma.code(coder->lzma.coder, allocator,
+				&dummy_in, &dummy_in_pos, 1,
+				out, out_pos, out_size, LZMA_RUN) != LZMA_OK)
+			return LZMA_PROG_ERROR;
+
+		assert(dummy_in_pos == 1);
+		coder->props_decoded = true;
+	}
+
+	// The rest is normal LZMA decoding.
+	lzma_ret ret = coder->lzma.code(coder->lzma.coder, allocator,
+				in, in_pos, in_size,
+				out, out_pos, out_size, action);
+
+	// Update the remaining compressed size.
+	assert(coder->comp_size >= *in_pos - in_start);
+	coder->comp_size -= *in_pos - in_start;
+
+	if (coder->uncomp_size_is_exact) {
+		// After successful decompression of the complete stream
+		// the compressed size must match.
+		if (ret == LZMA_STREAM_END && coder->comp_size != 0)
+			ret = LZMA_DATA_ERROR;
+	} else {
+		// Update the amount of output remaining.
+		assert(coder->uncomp_size >= *out_pos - out_start);
+		coder->uncomp_size -= *out_pos - out_start;
+
+		// - We must not get LZMA_STREAM_END because the stream
+		//   shouldn't have EOPM.
+		// - We must use uncomp_size to determine when to
+		//   return LZMA_STREAM_END.
+		if (ret == LZMA_STREAM_END)
+			ret = LZMA_DATA_ERROR;
+		else if (coder->uncomp_size == 0)
+			ret = LZMA_STREAM_END;
+	}
+
+	return ret;
+}
+
+
+static void
+microlzma_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
+{
+	lzma_microlzma_coder *coder = coder_ptr;
+	lzma_next_end(&coder->lzma, allocator);
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+static lzma_ret
+microlzma_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+		uint64_t comp_size,
+		uint64_t uncomp_size, bool uncomp_size_is_exact,
+		uint32_t dict_size)
+{
+	lzma_next_coder_init(&microlzma_decoder_init, next, allocator);
+
+	lzma_microlzma_coder *coder = next->coder;
+
+	if (coder == NULL) {
+		coder = lzma_alloc(sizeof(lzma_microlzma_coder), allocator);
+		if (coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->coder = coder;
+		next->code = &microlzma_decode;
+		next->end = &microlzma_decoder_end;
+
+		coder->lzma = LZMA_NEXT_CODER_INIT;
+	}
+
+	// The public API is uint64_t but the internal LZ decoder API uses
+	// lzma_vli.
+	if (uncomp_size > LZMA_VLI_MAX)
+		return LZMA_OPTIONS_ERROR;
+
+	coder->comp_size = comp_size;
+	coder->uncomp_size = uncomp_size;
+	coder->uncomp_size_is_exact = uncomp_size_is_exact;
+	coder->dict_size = dict_size;
+
+	coder->props_decoded = false;
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_microlzma_decoder(lzma_stream *strm, uint64_t comp_size,
+		uint64_t uncomp_size, lzma_bool uncomp_size_is_exact,
+		uint32_t dict_size)
+{
+	lzma_next_strm_init(microlzma_decoder_init, strm, comp_size,
+			uncomp_size, uncomp_size_is_exact, dict_size);
+
+	strm->internal->supported_actions[LZMA_RUN] = true;
+	strm->internal->supported_actions[LZMA_FINISH] = true;
+
+	return LZMA_OK;
+}

+ 140 - 0
Utilities/cmliblzma/liblzma/common/microlzma_encoder.c

@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: 0BSD
+
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       microlzma_encoder.c
+/// \brief      Encode into MicroLZMA format
+//
+//  Author:     Lasse Collin
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lzma_encoder.h"
+
+
+typedef struct {
+	/// LZMA1 encoder
+	lzma_next_coder lzma;
+
+	/// LZMA properties byte (lc/lp/pb)
+	uint8_t props;
+} lzma_microlzma_coder;
+
+
+static lzma_ret
+microlzma_encode(void *coder_ptr, const lzma_allocator *allocator,
+		const uint8_t *restrict in, size_t *restrict in_pos,
+		size_t in_size, uint8_t *restrict out,
+		size_t *restrict out_pos, size_t out_size, lzma_action action)
+{
+	lzma_microlzma_coder *coder = coder_ptr;
+
+	// Remember *out_pos so that we can overwrite the first byte with
+	// the LZMA properties byte.
+	const size_t out_start = *out_pos;
+
+	// Remember *in_pos so that we can set it based on how many
+	// uncompressed bytes were actually encoded.
+	const size_t in_start = *in_pos;
+
+	// Set the output size limit based on the available output space.
+	// We know that the encoder supports set_out_limit() so
+	// LZMA_OPTIONS_ERROR isn't possible. LZMA_BUF_ERROR is possible
+	// but lzma_code() has an assertion to not allow it to be returned
+	// from here and I don't want to change that for now, so
+	// LZMA_BUF_ERROR becomes LZMA_PROG_ERROR.
+	uint64_t uncomp_size;
+	if (coder->lzma.set_out_limit(coder->lzma.coder,
+			&uncomp_size, out_size - *out_pos) != LZMA_OK)
+		return LZMA_PROG_ERROR;
+
+	// set_out_limit fails if this isn't true.
+	assert(out_size - *out_pos >= 6);
+
+	// Encode as much as possible.
+	const lzma_ret ret = coder->lzma.code(coder->lzma.coder, allocator,
+			in, in_pos, in_size, out, out_pos, out_size, action);
+
+	if (ret != LZMA_STREAM_END) {
+		if (ret == LZMA_OK) {
+			assert(0);
+			return LZMA_PROG_ERROR;
+		}
+
+		return ret;
+	}
+
+	// The first output byte is bitwise-negation of the properties byte.
+	// We know that there is space for this byte because set_out_limit
+	// and the actual encoding succeeded.
+	out[out_start] = (uint8_t)(~coder->props);
+
+	// The LZMA encoder likely read more input than it was able to encode.
+	// Set *in_pos based on uncomp_size.
+	assert(uncomp_size <= in_size - in_start);
+	*in_pos = in_start + (size_t)(uncomp_size);
+
+	return ret;
+}
+
+
+static void
+microlzma_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
+{
+	lzma_microlzma_coder *coder = coder_ptr;
+	lzma_next_end(&coder->lzma, allocator);
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+static lzma_ret
+microlzma_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
+		const lzma_options_lzma *options)
+{
+	lzma_next_coder_init(&microlzma_encoder_init, next, allocator);
+
+	lzma_microlzma_coder *coder = next->coder;
+
+	if (coder == NULL) {
+		coder = lzma_alloc(sizeof(lzma_microlzma_coder), allocator);
+		if (coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->coder = coder;
+		next->code = &microlzma_encode;
+		next->end = &microlzma_encoder_end;
+
+		coder->lzma = LZMA_NEXT_CODER_INIT;
+	}
+
+	// Encode the properties byte. Bitwise-negation of it will be the
+	// first output byte.
+	if (lzma_lzma_lclppb_encode(options, &coder->props))
+		return LZMA_OPTIONS_ERROR;
+
+	// Initialize the LZMA encoder.
+	const lzma_filter_info filters[2] = {
+		{
+			.id = LZMA_FILTER_LZMA1,
+			.init = &lzma_lzma_encoder_init,
+			.options = (void *)(options),
+		}, {
+			.init = NULL,
+		}
+	};
+
+	return lzma_next_filter_init(&coder->lzma, allocator, filters);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_microlzma_encoder(lzma_stream *strm, const lzma_options_lzma *options)
+{
+	lzma_next_strm_init(microlzma_encoder_init, strm, options);
+
+	strm->internal->supported_actions[LZMA_FINISH] = true;
+
+	return LZMA_OK;
+
+}

+ 203 - 101
Utilities/cmliblzma/liblzma/common/outqueue.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       outqueue.c
 /// \file       outqueue.c
@@ -5,92 +7,126 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "outqueue.h"
 #include "outqueue.h"
 
 
 
 
-/// This is to ease integer overflow checking: We may allocate up to
-/// 2 * LZMA_THREADS_MAX buffers and we need some extra memory for other
-/// data structures (that's the second /2).
-#define BUF_SIZE_MAX (UINT64_MAX / LZMA_THREADS_MAX / 2 / 2)
+/// Get the maximum number of buffers that may be allocated based
+/// on the number of threads. For now this is twice the number of threads.
+/// It's a compromise between RAM usage and keeping the worker threads busy
+/// when buffers finish out of order.
+#define GET_BUFS_LIMIT(threads) (2 * (threads))
 
 
 
 
-static lzma_ret
-get_options(uint64_t *bufs_alloc_size, uint32_t *bufs_count,
-		uint64_t buf_size_max, uint32_t threads)
+extern uint64_t
+lzma_outq_memusage(uint64_t buf_size_max, uint32_t threads)
 {
 {
-	if (threads > LZMA_THREADS_MAX || buf_size_max > BUF_SIZE_MAX)
-		return LZMA_OPTIONS_ERROR;
-
-	// The number of buffers is twice the number of threads.
-	// This wastes RAM but keeps the threads busy when buffers
-	// finish out of order.
+	// This is to ease integer overflow checking: We may allocate up to
+	// GET_BUFS_LIMIT(LZMA_THREADS_MAX) buffers and we need some extra
+	// memory for other data structures too (that's the /2).
 	//
 	//
-	// NOTE: If this is changed, update BUF_SIZE_MAX too.
-	*bufs_count = threads * 2;
-	*bufs_alloc_size = *bufs_count * buf_size_max;
+	// lzma_outq_prealloc_buf() will still accept bigger buffers than this.
+	const uint64_t limit
+			= UINT64_MAX / GET_BUFS_LIMIT(LZMA_THREADS_MAX) / 2;
 
 
-	return LZMA_OK;
+	if (threads > LZMA_THREADS_MAX || buf_size_max > limit)
+		return UINT64_MAX;
+
+	return GET_BUFS_LIMIT(threads)
+			* lzma_outq_outbuf_memusage(buf_size_max);
 }
 }
 
 
 
 
-extern uint64_t
-lzma_outq_memusage(uint64_t buf_size_max, uint32_t threads)
+static void
+move_head_to_cache(lzma_outq *outq, const lzma_allocator *allocator)
 {
 {
-	uint64_t bufs_alloc_size;
-	uint32_t bufs_count;
+	assert(outq->head != NULL);
+	assert(outq->tail != NULL);
+	assert(outq->bufs_in_use > 0);
 
 
-	if (get_options(&bufs_alloc_size, &bufs_count, buf_size_max, threads)
-			!= LZMA_OK)
-		return UINT64_MAX;
+	lzma_outbuf *buf = outq->head;
+	outq->head = buf->next;
+	if (outq->head == NULL)
+		outq->tail = NULL;
+
+	if (outq->cache != NULL && outq->cache->allocated != buf->allocated)
+		lzma_outq_clear_cache(outq, allocator);
+
+	buf->next = outq->cache;
+	outq->cache = buf;
+
+	--outq->bufs_in_use;
+	outq->mem_in_use -= lzma_outq_outbuf_memusage(buf->allocated);
+
+	return;
+}
+
+
+static void
+free_one_cached_buffer(lzma_outq *outq, const lzma_allocator *allocator)
+{
+	assert(outq->cache != NULL);
+
+	lzma_outbuf *buf = outq->cache;
+	outq->cache = buf->next;
+
+	--outq->bufs_allocated;
+	outq->mem_allocated -= lzma_outq_outbuf_memusage(buf->allocated);
+
+	lzma_free(buf, allocator);
+	return;
+}
+
+
+extern void
+lzma_outq_clear_cache(lzma_outq *outq, const lzma_allocator *allocator)
+{
+	while (outq->cache != NULL)
+		free_one_cached_buffer(outq, allocator);
 
 
-	return sizeof(lzma_outq) + bufs_count * sizeof(lzma_outbuf)
-			+ bufs_alloc_size;
+	return;
+}
+
+
+extern void
+lzma_outq_clear_cache2(lzma_outq *outq, const lzma_allocator *allocator,
+		size_t keep_size)
+{
+	if (outq->cache == NULL)
+		return;
+
+	// Free all but one.
+	while (outq->cache->next != NULL)
+		free_one_cached_buffer(outq, allocator);
+
+	// Free the last one only if its size doesn't equal to keep_size.
+	if (outq->cache->allocated != keep_size)
+		free_one_cached_buffer(outq, allocator);
+
+	return;
 }
 }
 
 
 
 
 extern lzma_ret
 extern lzma_ret
 lzma_outq_init(lzma_outq *outq, const lzma_allocator *allocator,
 lzma_outq_init(lzma_outq *outq, const lzma_allocator *allocator,
-		uint64_t buf_size_max, uint32_t threads)
+		uint32_t threads)
 {
 {
-	uint64_t bufs_alloc_size;
-	uint32_t bufs_count;
-
-	// Set bufs_count and bufs_alloc_size.
-	return_if_error(get_options(&bufs_alloc_size, &bufs_count,
-			buf_size_max, threads));
-
-	// Allocate memory if needed.
-	if (outq->buf_size_max != buf_size_max
-			|| outq->bufs_allocated != bufs_count) {
-		lzma_outq_end(outq, allocator);
-
-#if SIZE_MAX < UINT64_MAX
-		if (bufs_alloc_size > SIZE_MAX)
-			return LZMA_MEM_ERROR;
-#endif
-
-		outq->bufs = lzma_alloc(bufs_count * sizeof(lzma_outbuf),
-				allocator);
-		outq->bufs_mem = lzma_alloc((size_t)(bufs_alloc_size),
-				allocator);
-
-		if (outq->bufs == NULL || outq->bufs_mem == NULL) {
-			lzma_outq_end(outq, allocator);
-			return LZMA_MEM_ERROR;
-		}
-	}
+	if (threads > LZMA_THREADS_MAX)
+		return LZMA_OPTIONS_ERROR;
+
+	const uint32_t bufs_limit = GET_BUFS_LIMIT(threads);
+
+	// Clear head/tail.
+	while (outq->head != NULL)
+		move_head_to_cache(outq, allocator);
+
+	// If new buf_limit is lower than the old one, we may need to free
+	// a few cached buffers.
+	while (bufs_limit < outq->bufs_allocated)
+		free_one_cached_buffer(outq, allocator);
 
 
-	// Initialize the rest of the main structure. Initialization of
-	// outq->bufs[] is done when they are actually needed.
-	outq->buf_size_max = (size_t)(buf_size_max);
-	outq->bufs_allocated = bufs_count;
-	outq->bufs_pos = 0;
-	outq->bufs_used = 0;
+	outq->bufs_limit = bufs_limit;
 	outq->read_pos = 0;
 	outq->read_pos = 0;
 
 
 	return LZMA_OK;
 	return LZMA_OK;
@@ -100,33 +136,81 @@ lzma_outq_init(lzma_outq *outq, const lzma_allocator *allocator,
 extern void
 extern void
 lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator)
 lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator)
 {
 {
-	lzma_free(outq->bufs, allocator);
-	outq->bufs = NULL;
-
-	lzma_free(outq->bufs_mem, allocator);
-	outq->bufs_mem = NULL;
+	while (outq->head != NULL)
+		move_head_to_cache(outq, allocator);
 
 
+	lzma_outq_clear_cache(outq, allocator);
 	return;
 	return;
 }
 }
 
 
 
 
-extern lzma_outbuf *
-lzma_outq_get_buf(lzma_outq *outq)
+extern lzma_ret
+lzma_outq_prealloc_buf(lzma_outq *outq, const lzma_allocator *allocator,
+		size_t size)
 {
 {
 	// Caller must have checked it with lzma_outq_has_buf().
 	// Caller must have checked it with lzma_outq_has_buf().
-	assert(outq->bufs_used < outq->bufs_allocated);
+	assert(outq->bufs_in_use < outq->bufs_limit);
+
+	// If there already is appropriately-sized buffer in the cache,
+	// we need to do nothing.
+	if (outq->cache != NULL && outq->cache->allocated == size)
+		return LZMA_OK;
+
+	if (size > SIZE_MAX - sizeof(lzma_outbuf))
+		return LZMA_MEM_ERROR;
+
+	const size_t alloc_size = lzma_outq_outbuf_memusage(size);
+
+	// The cache may have buffers but their size is wrong.
+	lzma_outq_clear_cache(outq, allocator);
+
+	outq->cache = lzma_alloc(alloc_size, allocator);
+	if (outq->cache == NULL)
+		return LZMA_MEM_ERROR;
+
+	outq->cache->next = NULL;
+	outq->cache->allocated = size;
+
+	++outq->bufs_allocated;
+	outq->mem_allocated += alloc_size;
+
+	return LZMA_OK;
+}
+
 
 
-	// Initialize the new buffer.
-	lzma_outbuf *buf = &outq->bufs[outq->bufs_pos];
-	buf->buf = outq->bufs_mem + outq->bufs_pos * outq->buf_size_max;
-	buf->size = 0;
+extern lzma_outbuf *
+lzma_outq_get_buf(lzma_outq *outq, void *worker)
+{
+	// Caller must have used lzma_outq_prealloc_buf() to ensure these.
+	assert(outq->bufs_in_use < outq->bufs_limit);
+	assert(outq->bufs_in_use < outq->bufs_allocated);
+	assert(outq->cache != NULL);
+
+	lzma_outbuf *buf = outq->cache;
+	outq->cache = buf->next;
+	buf->next = NULL;
+
+	if (outq->tail != NULL) {
+		assert(outq->head != NULL);
+		outq->tail->next = buf;
+	} else {
+		assert(outq->head == NULL);
+		outq->head = buf;
+	}
+
+	outq->tail = buf;
+
+	buf->worker = worker;
 	buf->finished = false;
 	buf->finished = false;
+	buf->finish_ret = LZMA_STREAM_END;
+	buf->pos = 0;
+	buf->decoder_in_pos = 0;
 
 
-	// Update the queue state.
-	if (++outq->bufs_pos == outq->bufs_allocated)
-		outq->bufs_pos = 0;
+	buf->unpadded_size = 0;
+	buf->uncompressed_size = 0;
 
 
-	++outq->bufs_used;
+	++outq->bufs_in_use;
+	outq->mem_in_use += lzma_outq_outbuf_memusage(buf->allocated);
 
 
 	return buf;
 	return buf;
 }
 }
@@ -135,50 +219,68 @@ lzma_outq_get_buf(lzma_outq *outq)
 extern bool
 extern bool
 lzma_outq_is_readable(const lzma_outq *outq)
 lzma_outq_is_readable(const lzma_outq *outq)
 {
 {
-	uint32_t i = outq->bufs_pos - outq->bufs_used;
-	if (outq->bufs_pos < outq->bufs_used)
-		i += outq->bufs_allocated;
+	if (outq->head == NULL)
+		return false;
 
 
-	return outq->bufs[i].finished;
+	return outq->read_pos < outq->head->pos || outq->head->finished;
 }
 }
 
 
 
 
 extern lzma_ret
 extern lzma_ret
-lzma_outq_read(lzma_outq *restrict outq, uint8_t *restrict out,
-		size_t *restrict out_pos, size_t out_size,
+lzma_outq_read(lzma_outq *restrict outq,
+		const lzma_allocator *restrict allocator,
+		uint8_t *restrict out, size_t *restrict out_pos,
+		size_t out_size,
 		lzma_vli *restrict unpadded_size,
 		lzma_vli *restrict unpadded_size,
 		lzma_vli *restrict uncompressed_size)
 		lzma_vli *restrict uncompressed_size)
 {
 {
 	// There must be at least one buffer from which to read.
 	// There must be at least one buffer from which to read.
-	if (outq->bufs_used == 0)
+	if (outq->bufs_in_use == 0)
 		return LZMA_OK;
 		return LZMA_OK;
 
 
 	// Get the buffer.
 	// Get the buffer.
-	uint32_t i = outq->bufs_pos - outq->bufs_used;
-	if (outq->bufs_pos < outq->bufs_used)
-		i += outq->bufs_allocated;
-
-	lzma_outbuf *buf = &outq->bufs[i];
-
-	// If it isn't finished yet, we cannot read from it.
-	if (!buf->finished)
-		return LZMA_OK;
+	lzma_outbuf *buf = outq->head;
 
 
 	// Copy from the buffer to output.
 	// Copy from the buffer to output.
-	lzma_bufcpy(buf->buf, &outq->read_pos, buf->size,
+	//
+	// FIXME? In threaded decoder it may be bad to do this copy while
+	// the mutex is being held.
+	lzma_bufcpy(buf->buf, &outq->read_pos, buf->pos,
 			out, out_pos, out_size);
 			out, out_pos, out_size);
 
 
 	// Return if we didn't get all the data from the buffer.
 	// Return if we didn't get all the data from the buffer.
-	if (outq->read_pos < buf->size)
+	if (!buf->finished || outq->read_pos < buf->pos)
 		return LZMA_OK;
 		return LZMA_OK;
 
 
 	// The buffer was finished. Tell the caller its size information.
 	// The buffer was finished. Tell the caller its size information.
-	*unpadded_size = buf->unpadded_size;
-	*uncompressed_size = buf->uncompressed_size;
+	if (unpadded_size != NULL)
+		*unpadded_size = buf->unpadded_size;
+
+	if (uncompressed_size != NULL)
+		*uncompressed_size = buf->uncompressed_size;
+
+	// Remember the return value.
+	const lzma_ret finish_ret = buf->finish_ret;
 
 
 	// Free this buffer for further use.
 	// Free this buffer for further use.
-	--outq->bufs_used;
+	move_head_to_cache(outq, allocator);
 	outq->read_pos = 0;
 	outq->read_pos = 0;
 
 
-	return LZMA_STREAM_END;
+	return finish_ret;
+}
+
+
+extern void
+lzma_outq_enable_partial_output(lzma_outq *outq,
+		void (*enable_partial_output)(void *worker))
+{
+	if (outq->head != NULL && !outq->head->finished
+			&& outq->head->worker != NULL) {
+		enable_partial_output(outq->head->worker);
+
+		// Set it to NULL since calling it twice is pointless.
+		outq->head->worker = NULL;
+	}
+
+	return;
 }
 }

+ 144 - 42
Utilities/cmliblzma/liblzma/common/outqueue.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       outqueue.h
 /// \file       outqueue.h
@@ -5,25 +7,45 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
+#ifndef LZMA_OUTQUEUE_H
+#define LZMA_OUTQUEUE_H
+
 #include "common.h"
 #include "common.h"
 
 
 
 
 /// Output buffer for a single thread
 /// Output buffer for a single thread
-typedef struct {
-	/// Pointer to the output buffer of lzma_outq.buf_size_max bytes
-	uint8_t *buf;
-
-	/// Amount of data written to buf
-	size_t size;
+typedef struct lzma_outbuf_s lzma_outbuf;
+struct lzma_outbuf_s {
+	/// Pointer to the next buffer. This is used for the cached buffers.
+	/// The worker thread must not modify this.
+	lzma_outbuf *next;
+
+	/// This initialized by lzma_outq_get_buf() and
+	/// is used by lzma_outq_enable_partial_output().
+	/// The worker thread must not modify this.
+	void *worker;
+
+	/// Amount of memory allocated for buf[].
+	/// The worker thread must not modify this.
+	size_t allocated;
+
+	/// Writing position in the worker thread or, in other words, the
+	/// amount of finished data written to buf[] which can be copied out
+	///
+	/// \note       This is read by another thread and thus access
+	///             to this variable needs a mutex.
+	size_t pos;
 
 
-	/// Additional size information
-	lzma_vli unpadded_size;
-	lzma_vli uncompressed_size;
+	/// Decompression: Position in the input buffer in the worker thread
+	/// that matches the output "pos" above. This is used to detect if
+	/// more output might be possible from the worker thread: if it has
+	/// consumed all its input, then more output isn't possible.
+	///
+	/// \note       This is read by another thread and thus access
+	///             to this variable needs a mutex.
+	size_t decoder_in_pos;
 
 
 	/// True when no more data will be written into this buffer.
 	/// True when no more data will be written into this buffer.
 	///
 	///
@@ -31,32 +53,55 @@ typedef struct {
 	///             to this variable needs a mutex.
 	///             to this variable needs a mutex.
 	bool finished;
 	bool finished;
 
 
-} lzma_outbuf;
+	/// Return value for lzma_outq_read() when the last byte from
+	/// a finished buffer has been read. Defaults to LZMA_STREAM_END.
+	/// This must *not* be LZMA_OK. The idea is to allow a decoder to
+	/// pass an error code to the main thread, setting the code here
+	/// together with finished = true.
+	lzma_ret finish_ret;
+
+	/// Additional size information. lzma_outq_read() may read these
+	/// when "finished" is true.
+	lzma_vli unpadded_size;
+	lzma_vli uncompressed_size;
+
+	/// Buffer of "allocated" bytes
+	uint8_t buf[];
+};
 
 
 
 
 typedef struct {
 typedef struct {
-	/// Array of buffers that are used cyclically.
-	lzma_outbuf *bufs;
+	/// Linked list of buffers in use. The next output byte will be
+	/// read from the head and buffers for the next thread will be
+	/// appended to the tail. tail->next is always NULL.
+	lzma_outbuf *head;
+	lzma_outbuf *tail;
 
 
-	/// Memory allocated for all the buffers
-	uint8_t *bufs_mem;
+	/// Number of bytes read from head->buf[] in lzma_outq_read()
+	size_t read_pos;
 
 
-	/// Amount of buffer space available in each buffer
-	size_t buf_size_max;
+	/// Linked list of allocated buffers that aren't currently used.
+	/// This way buffers of similar size can be reused and don't
+	/// need to be reallocated every time. For simplicity, all
+	/// cached buffers in the list have the same allocated size.
+	lzma_outbuf *cache;
 
 
-	/// Number of buffers allocated
-	uint32_t bufs_allocated;
+	/// Total amount of memory allocated for buffers
+	uint64_t mem_allocated;
 
 
-	/// Position in the bufs array. The next buffer to be taken
-	/// into use is bufs[bufs_pos].
-	uint32_t bufs_pos;
+	/// Amount of memory used by the buffers that are in use in
+	/// the head...tail linked list.
+	uint64_t mem_in_use;
 
 
-	/// Number of buffers in use
-	uint32_t bufs_used;
+	/// Number of buffers in use in the head...tail list. If and only if
+	/// this is zero, the pointers head and tail above are NULL.
+	uint32_t bufs_in_use;
 
 
-	/// Position in the buffer in lzma_outq_read()
-	size_t read_pos;
+	/// Number of buffers allocated (in use + cached)
+	uint32_t bufs_allocated;
 
 
+	/// Maximum allowed number of allocated buffers
+	uint32_t bufs_limit;
 } lzma_outq;
 } lzma_outq;
 
 
 
 
@@ -76,32 +121,60 @@ extern uint64_t lzma_outq_memusage(uint64_t buf_size_max, uint32_t threads);
 ///                             function knows that there are no previous
 ///                             function knows that there are no previous
 ///                             allocations to free.
 ///                             allocations to free.
 /// \param      allocator       Pointer to allocator or NULL
 /// \param      allocator       Pointer to allocator or NULL
-/// \param      buf_size_max    Maximum amount of data that a single buffer
-///                             in the queue may need to store.
 /// \param      threads         Number of buffers that may be in use
 /// \param      threads         Number of buffers that may be in use
 ///                             concurrently. Note that more than this number
 ///                             concurrently. Note that more than this number
-///                             of buffers will actually get allocated to
+///                             of buffers may actually get allocated to
 ///                             improve performance when buffers finish
 ///                             improve performance when buffers finish
-///                             out of order.
+///                             out of order. The actual maximum number of
+///                             allocated buffers is derived from the number
+///                             of threads.
 ///
 ///
 /// \return     - LZMA_OK
 /// \return     - LZMA_OK
 ///             - LZMA_MEM_ERROR
 ///             - LZMA_MEM_ERROR
 ///
 ///
-extern lzma_ret lzma_outq_init(
-		lzma_outq *outq, const lzma_allocator *allocator,
-		uint64_t buf_size_max, uint32_t threads);
+extern lzma_ret lzma_outq_init(lzma_outq *outq,
+		const lzma_allocator *allocator, uint32_t threads);
 
 
 
 
 /// \brief      Free the memory associated with the output queue
 /// \brief      Free the memory associated with the output queue
 extern void lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator);
 extern void lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator);
 
 
 
 
+/// \brief      Free all cached buffers that consume memory but aren't in use
+extern void lzma_outq_clear_cache(
+		lzma_outq *outq, const lzma_allocator *allocator);
+
+
+/// \brief      Like lzma_outq_clear_cache() but might keep one buffer
+///
+/// One buffer is not freed if its size is equal to keep_size.
+/// This is useful if the caller knows that it will soon need a buffer of
+/// keep_size bytes. This way it won't be freed and immediately reallocated.
+extern void lzma_outq_clear_cache2(
+		lzma_outq *outq, const lzma_allocator *allocator,
+		size_t keep_size);
+
+
+/// \brief      Preallocate a new buffer into cache
+///
+/// Splitting the buffer allocation into a separate function makes it
+/// possible to ensure that way lzma_outq_get_buf() cannot fail.
+/// If the preallocated buffer isn't actually used (for example, some
+/// other error occurs), the caller has to do nothing as the buffer will
+/// be used later or cleared from the cache when not needed.
+///
+/// \return     LZMA_OK on success, LZMA_MEM_ERROR if allocation fails
+///
+extern lzma_ret lzma_outq_prealloc_buf(
+		lzma_outq *outq, const lzma_allocator *allocator, size_t size);
+
+
 /// \brief      Get a new buffer
 /// \brief      Get a new buffer
 ///
 ///
-/// lzma_outq_has_buf() must be used to check that there is a buffer
+/// lzma_outq_prealloc_buf() must be used to ensure that there is a buffer
 /// available before calling lzma_outq_get_buf().
 /// available before calling lzma_outq_get_buf().
 ///
 ///
-extern lzma_outbuf *lzma_outq_get_buf(lzma_outq *outq);
+extern lzma_outbuf *lzma_outq_get_buf(lzma_outq *outq, void *worker);
 
 
 
 
 /// \brief      Test if there is data ready to be read
 /// \brief      Test if there is data ready to be read
@@ -126,17 +199,32 @@ extern bool lzma_outq_is_readable(const lzma_outq *outq);
 /// \return     - LZMA: All OK. Either no data was available or the buffer
 /// \return     - LZMA: All OK. Either no data was available or the buffer
 ///               being read didn't become empty yet.
 ///               being read didn't become empty yet.
 ///             - LZMA_STREAM_END: The buffer being read was finished.
 ///             - LZMA_STREAM_END: The buffer being read was finished.
-///               *unpadded_size and *uncompressed_size were set.
+///               *unpadded_size and *uncompressed_size were set if they
+///               were not NULL.
 ///
 ///
-/// \note       This reads lzma_outbuf.finished variables and thus call
-///             to this function needs to be protected with a mutex.
+/// \note       This reads lzma_outbuf.finished and .pos variables and thus
+///             calls to this function need to be protected with a mutex.
 ///
 ///
 extern lzma_ret lzma_outq_read(lzma_outq *restrict outq,
 extern lzma_ret lzma_outq_read(lzma_outq *restrict outq,
+		const lzma_allocator *restrict allocator,
 		uint8_t *restrict out, size_t *restrict out_pos,
 		uint8_t *restrict out, size_t *restrict out_pos,
 		size_t out_size, lzma_vli *restrict unpadded_size,
 		size_t out_size, lzma_vli *restrict unpadded_size,
 		lzma_vli *restrict uncompressed_size);
 		lzma_vli *restrict uncompressed_size);
 
 
 
 
+/// \brief      Enable partial output from a worker thread
+///
+/// If the buffer at the head of the output queue isn't finished,
+/// this will call enable_partial_output on the worker associated with
+/// that output buffer.
+///
+/// \note       This reads a lzma_outbuf.finished variable and thus
+///             calls to this function need to be protected with a mutex.
+///
+extern void lzma_outq_enable_partial_output(lzma_outq *outq,
+		void (*enable_partial_output)(void *worker));
+
+
 /// \brief      Test if there is at least one buffer free
 /// \brief      Test if there is at least one buffer free
 ///
 ///
 /// This must be used before getting a new buffer with lzma_outq_get_buf().
 /// This must be used before getting a new buffer with lzma_outq_get_buf().
@@ -144,7 +232,7 @@ extern lzma_ret lzma_outq_read(lzma_outq *restrict outq,
 static inline bool
 static inline bool
 lzma_outq_has_buf(const lzma_outq *outq)
 lzma_outq_has_buf(const lzma_outq *outq)
 {
 {
-	return outq->bufs_used < outq->bufs_allocated;
+	return outq->bufs_in_use < outq->bufs_limit;
 }
 }
 
 
 
 
@@ -152,5 +240,19 @@ lzma_outq_has_buf(const lzma_outq *outq)
 static inline bool
 static inline bool
 lzma_outq_is_empty(const lzma_outq *outq)
 lzma_outq_is_empty(const lzma_outq *outq)
 {
 {
-	return outq->bufs_used == 0;
+	return outq->bufs_in_use == 0;
 }
 }
+
+
+/// \brief      Get the amount of memory needed for a single lzma_outbuf
+///
+/// \note       Caller must check that the argument is significantly less
+///             than SIZE_MAX to avoid an integer overflow!
+static inline uint64_t
+lzma_outq_outbuf_memusage(size_t buf_size)
+{
+	assert(buf_size <= SIZE_MAX - sizeof(lzma_outbuf));
+	return sizeof(lzma_outbuf) + buf_size;
+}
+
+#endif

+ 2 - 3
Utilities/cmliblzma/liblzma/common/stream_buffer_decoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       stream_buffer_decoder.c
 /// \file       stream_buffer_decoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "stream_decoder.h"
 #include "stream_decoder.h"

+ 3 - 3
Utilities/cmliblzma/liblzma/common/stream_buffer_encoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       stream_buffer_encoder.c
 /// \file       stream_buffer_encoder.c
@@ -5,11 +7,9 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
+#include "common.h"
 #include "index.h"
 #include "index.h"
 
 
 
 

+ 23 - 17
Utilities/cmliblzma/liblzma/common/stream_decoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       stream_decoder.c
 /// \file       stream_decoder.c
@@ -5,28 +7,25 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "stream_decoder.h"
 #include "stream_decoder.h"
 #include "block_decoder.h"
 #include "block_decoder.h"
+#include "index.h"
 
 
 
 
 typedef struct {
 typedef struct {
 	enum {
 	enum {
 		SEQ_STREAM_HEADER,
 		SEQ_STREAM_HEADER,
 		SEQ_BLOCK_HEADER,
 		SEQ_BLOCK_HEADER,
-		SEQ_BLOCK,
+		SEQ_BLOCK_INIT,
+		SEQ_BLOCK_RUN,
 		SEQ_INDEX,
 		SEQ_INDEX,
 		SEQ_STREAM_FOOTER,
 		SEQ_STREAM_FOOTER,
 		SEQ_STREAM_PADDING,
 		SEQ_STREAM_PADDING,
 	} sequence;
 	} sequence;
 
 
-	/// Block or Metadata decoder. This takes little memory and the same
-	/// data structure can be used to decode every Block Header, so it's
-	/// a good idea to have a separate lzma_next_coder structure for it.
+	/// Block decoder
 	lzma_next_coder block_decoder;
 	lzma_next_coder block_decoder;
 
 
 	/// Block options decoded by the Block Header decoder and used by
 	/// Block options decoded by the Block Header decoder and used by
@@ -63,9 +62,9 @@ typedef struct {
 
 
 	/// If true, we will decode concatenated Streams that possibly have
 	/// If true, we will decode concatenated Streams that possibly have
 	/// Stream Padding between or after them. LZMA_STREAM_END is returned
 	/// Stream Padding between or after them. LZMA_STREAM_END is returned
-	/// once the application isn't giving us any new input, and we aren't
-	/// in the middle of a Stream, and possible Stream Padding is a
-	/// multiple of four bytes.
+	/// once the application isn't giving us any new input (LZMA_FINISH),
+	/// and we aren't in the middle of a Stream, and possible
+	/// Stream Padding is a multiple of four bytes.
 	bool concatenated;
 	bool concatenated;
 
 
 	/// When decoding concatenated Streams, this is true as long as we
 	/// When decoding concatenated Streams, this is true as long as we
@@ -165,7 +164,7 @@ stream_decode(void *coder_ptr, const lzma_allocator *allocator,
 
 
 		if (coder->pos == 0) {
 		if (coder->pos == 0) {
 			// Detect if it's Index.
 			// Detect if it's Index.
-			if (in[*in_pos] == 0x00) {
+			if (in[*in_pos] == INDEX_INDICATOR) {
 				coder->sequence = SEQ_INDEX;
 				coder->sequence = SEQ_INDEX;
 				break;
 				break;
 			}
 			}
@@ -187,6 +186,15 @@ stream_decode(void *coder_ptr, const lzma_allocator *allocator,
 			return LZMA_OK;
 			return LZMA_OK;
 
 
 		coder->pos = 0;
 		coder->pos = 0;
+		coder->sequence = SEQ_BLOCK_INIT;
+	}
+
+	// Fall through
+
+	case SEQ_BLOCK_INIT: {
+		// Checking memusage and doing the initialization needs
+		// its own sequence point because we need to be able to
+		// retry if we return LZMA_MEMLIMIT_ERROR.
 
 
 		// Version 1 is needed to support the .ignore_check option.
 		// Version 1 is needed to support the .ignore_check option.
 		coder->block_options.version = 1;
 		coder->block_options.version = 1;
@@ -235,22 +243,20 @@ stream_decode(void *coder_ptr, const lzma_allocator *allocator,
 
 
 		// Free the allocated filter options since they are needed
 		// Free the allocated filter options since they are needed
 		// only to initialize the Block decoder.
 		// only to initialize the Block decoder.
-		for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i)
-			lzma_free(filters[i].options, allocator);
-
+		lzma_filters_free(filters, allocator);
 		coder->block_options.filters = NULL;
 		coder->block_options.filters = NULL;
 
 
-		// Check if memory usage calculation and Block enocoder
+		// Check if memory usage calculation and Block decoder
 		// initialization succeeded.
 		// initialization succeeded.
 		if (ret != LZMA_OK)
 		if (ret != LZMA_OK)
 			return ret;
 			return ret;
 
 
-		coder->sequence = SEQ_BLOCK;
+		coder->sequence = SEQ_BLOCK_RUN;
 	}
 	}
 
 
 	// Fall through
 	// Fall through
 
 
-	case SEQ_BLOCK: {
+	case SEQ_BLOCK_RUN: {
 		const lzma_ret ret = coder->block_decoder.code(
 		const lzma_ret ret = coder->block_decoder.code(
 				coder->block_decoder.coder, allocator,
 				coder->block_decoder.coder, allocator,
 				in, in_pos, in_size, out, out_pos, out_size,
 				in, in_pos, in_size, out, out_pos, out_size,

+ 2 - 3
Utilities/cmliblzma/liblzma/common/stream_decoder.h

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       stream_decoder.h
 /// \file       stream_decoder.h
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #ifndef LZMA_STREAM_DECODER_H
 #ifndef LZMA_STREAM_DECODER_H

+ 2017 - 0
Utilities/cmliblzma/liblzma/common/stream_decoder_mt.c

@@ -0,0 +1,2017 @@
+// SPDX-License-Identifier: 0BSD
+
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_decoder_mt.c
+/// \brief      Multithreaded .xz Stream decoder
+//
+//  Authors:    Sebastian Andrzej Siewior
+//              Lasse Collin
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+#include "block_decoder.h"
+#include "stream_decoder.h"
+#include "index.h"
+#include "outqueue.h"
+
+
+typedef enum {
+	/// Waiting for work.
+	/// Main thread may change this to THR_RUN or THR_EXIT.
+	THR_IDLE,
+
+	/// Decoding is in progress.
+	/// Main thread may change this to THR_STOP or THR_EXIT.
+	/// The worker thread may change this to THR_IDLE.
+	THR_RUN,
+
+	/// The main thread wants the thread to stop whatever it was doing
+	/// but not exit. Main thread may change this to THR_EXIT.
+	/// The worker thread may change this to THR_IDLE.
+	THR_STOP,
+
+	/// The main thread wants the thread to exit.
+	THR_EXIT,
+
+} worker_state;
+
+
+typedef enum {
+	/// Partial updates (storing of worker thread progress
+	/// to lzma_outbuf) are disabled.
+	PARTIAL_DISABLED,
+
+	/// Main thread requests partial updates to be enabled but
+	/// no partial update has been done by the worker thread yet.
+	///
+	/// Changing from PARTIAL_DISABLED to PARTIAL_START requires
+	/// use of the worker-thread mutex. Other transitions don't
+	/// need a mutex.
+	PARTIAL_START,
+
+	/// Partial updates are enabled and the worker thread has done
+	/// at least one partial update.
+	PARTIAL_ENABLED,
+
+} partial_update_mode;
+
+
+struct worker_thread {
+	/// Worker state is protected with our mutex.
+	worker_state state;
+
+	/// Input buffer that will contain the whole Block except Block Header.
+	uint8_t *in;
+
+	/// Amount of memory allocated for "in"
+	size_t in_size;
+
+	/// Number of bytes written to "in" by the main thread
+	size_t in_filled;
+
+	/// Number of bytes consumed from "in" by the worker thread.
+	size_t in_pos;
+
+	/// Amount of uncompressed data that has been decoded. This local
+	/// copy is needed because updating outbuf->pos requires locking
+	/// the main mutex (coder->mutex).
+	size_t out_pos;
+
+	/// Pointer to the main structure is needed to (1) lock the main
+	/// mutex (coder->mutex) when updating outbuf->pos and (2) when
+	/// putting this thread back to the stack of free threads.
+	struct lzma_stream_coder *coder;
+
+	/// The allocator is set by the main thread. Since a copy of the
+	/// pointer is kept here, the application must not change the
+	/// allocator before calling lzma_end().
+	const lzma_allocator *allocator;
+
+	/// Output queue buffer to which the uncompressed data is written.
+	lzma_outbuf *outbuf;
+
+	/// Amount of compressed data that has already been decompressed.
+	/// This is updated from in_pos when our mutex is locked.
+	/// This is size_t, not uint64_t, because per-thread progress
+	/// is limited to sizes of allocated buffers.
+	size_t progress_in;
+
+	/// Like progress_in but for uncompressed data.
+	size_t progress_out;
+
+	/// Updating outbuf->pos requires locking the main mutex
+	/// (coder->mutex). Since the main thread will only read output
+	/// from the oldest outbuf in the queue, only the worker thread
+	/// that is associated with the oldest outbuf needs to update its
+	/// outbuf->pos. This avoids useless mutex contention that would
+	/// happen if all worker threads were frequently locking the main
+	/// mutex to update their outbuf->pos.
+	///
+	/// Only when partial_update is something else than PARTIAL_DISABLED,
+	/// this worker thread will update outbuf->pos after each call to
+	/// the Block decoder.
+	partial_update_mode partial_update;
+
+	/// Block decoder
+	lzma_next_coder block_decoder;
+
+	/// Thread-specific Block options are needed because the Block
+	/// decoder modifies the struct given to it at initialization.
+	lzma_block block_options;
+
+	/// Filter chain memory usage
+	uint64_t mem_filters;
+
+	/// Next structure in the stack of free worker threads.
+	struct worker_thread *next;
+
+	mythread_mutex mutex;
+	mythread_cond cond;
+
+	/// The ID of this thread is used to join the thread
+	/// when it's not needed anymore.
+	mythread thread_id;
+};
+
+
+struct lzma_stream_coder {
+	enum {
+		SEQ_STREAM_HEADER,
+		SEQ_BLOCK_HEADER,
+		SEQ_BLOCK_INIT,
+		SEQ_BLOCK_THR_INIT,
+		SEQ_BLOCK_THR_RUN,
+		SEQ_BLOCK_DIRECT_INIT,
+		SEQ_BLOCK_DIRECT_RUN,
+		SEQ_INDEX_WAIT_OUTPUT,
+		SEQ_INDEX_DECODE,
+		SEQ_STREAM_FOOTER,
+		SEQ_STREAM_PADDING,
+		SEQ_ERROR,
+	} sequence;
+
+	/// Block decoder
+	lzma_next_coder block_decoder;
+
+	/// Every Block Header will be decoded into this structure.
+	/// This is also used to initialize a Block decoder when in
+	/// direct mode. In threaded mode, a thread-specific copy will
+	/// be made for decoder initialization because the Block decoder
+	/// will modify the structure given to it.
+	lzma_block block_options;
+
+	/// Buffer to hold a filter chain for Block Header decoding and
+	/// initialization. These are freed after successful Block decoder
+	/// initialization or at stream_decoder_mt_end(). The thread-specific
+	/// copy of block_options won't hold a pointer to filters[] after
+	/// initialization.
+	lzma_filter filters[LZMA_FILTERS_MAX + 1];
+
+	/// Stream Flags from Stream Header
+	lzma_stream_flags stream_flags;
+
+	/// Index is hashed so that it can be compared to the sizes of Blocks
+	/// with O(1) memory usage.
+	lzma_index_hash *index_hash;
+
+
+	/// Maximum wait time if cannot use all the input and cannot
+	/// fill the output buffer. This is in milliseconds.
+	uint32_t timeout;
+
+
+	/// Error code from a worker thread.
+	///
+	/// \note       Use mutex.
+	lzma_ret thread_error;
+
+	/// Error code to return after pending output has been copied out. If
+	/// set in read_output_and_wait(), this is a mirror of thread_error.
+	/// If set in stream_decode_mt() then it's, for example, error that
+	/// occurred when decoding Block Header.
+	lzma_ret pending_error;
+
+	/// Number of threads that will be created at maximum.
+	uint32_t threads_max;
+
+	/// Number of thread structures that have been initialized from
+	/// "threads", and thus the number of worker threads actually
+	/// created so far.
+	uint32_t threads_initialized;
+
+	/// Array of allocated thread-specific structures. When no threads
+	/// are in use (direct mode) this is NULL. In threaded mode this
+	/// points to an array of threads_max number of worker_thread structs.
+	struct worker_thread *threads;
+
+	/// Stack of free threads. When a thread finishes, it puts itself
+	/// back into this stack. This starts as empty because threads
+	/// are created only when actually needed.
+	///
+	/// \note       Use mutex.
+	struct worker_thread *threads_free;
+
+	/// The most recent worker thread to which the main thread writes
+	/// the new input from the application.
+	struct worker_thread *thr;
+
+	/// Output buffer queue for decompressed data from the worker threads
+	///
+	/// \note       Use mutex with operations that need it.
+	lzma_outq outq;
+
+	mythread_mutex mutex;
+	mythread_cond cond;
+
+
+	/// Memory usage that will not be exceeded in multi-threaded mode.
+	/// Single-threaded mode can exceed this even by a large amount.
+	uint64_t memlimit_threading;
+
+	/// Memory usage limit that should never be exceeded.
+	/// LZMA_MEMLIMIT_ERROR will be returned if decoding isn't possible
+	/// even in single-threaded mode without exceeding this limit.
+	uint64_t memlimit_stop;
+
+	/// Amount of memory in use by the direct mode decoder
+	/// (coder->block_decoder). In threaded mode this is 0.
+	uint64_t mem_direct_mode;
+
+	/// Amount of memory needed by the running worker threads.
+	/// This doesn't include the memory needed by the output buffer.
+	///
+	/// \note       Use mutex.
+	uint64_t mem_in_use;
+
+	/// Amount of memory used by the idle (cached) threads.
+	///
+	/// \note       Use mutex.
+	uint64_t mem_cached;
+
+
+	/// Amount of memory needed for the filter chain of the next Block.
+	uint64_t mem_next_filters;
+
+	/// Amount of memory needed for the thread-specific input buffer
+	/// for the next Block.
+	uint64_t mem_next_in;
+
+	/// Amount of memory actually needed to decode the next Block
+	/// in threaded mode. This is
+	/// mem_next_filters + mem_next_in + memory needed for lzma_outbuf.
+	uint64_t mem_next_block;
+
+
+	/// Amount of compressed data in Stream Header + Blocks that have
+	/// already been finished.
+	///
+	/// \note       Use mutex.
+	uint64_t progress_in;
+
+	/// Amount of uncompressed data in Blocks that have already
+	/// been finished.
+	///
+	/// \note       Use mutex.
+	uint64_t progress_out;
+
+
+	/// If true, LZMA_NO_CHECK is returned if the Stream has
+	/// no integrity check.
+	bool tell_no_check;
+
+	/// If true, LZMA_UNSUPPORTED_CHECK is returned if the Stream has
+	/// an integrity check that isn't supported by this liblzma build.
+	bool tell_unsupported_check;
+
+	/// If true, LZMA_GET_CHECK is returned after decoding Stream Header.
+	bool tell_any_check;
+
+	/// If true, we will tell the Block decoder to skip calculating
+	/// and verifying the integrity check.
+	bool ignore_check;
+
+	/// If true, we will decode concatenated Streams that possibly have
+	/// Stream Padding between or after them. LZMA_STREAM_END is returned
+	/// once the application isn't giving us any new input (LZMA_FINISH),
+	/// and we aren't in the middle of a Stream, and possible
+	/// Stream Padding is a multiple of four bytes.
+	bool concatenated;
+
+	/// If true, we will return any errors immediately instead of first
+	/// producing all output before the location of the error.
+	bool fail_fast;
+
+
+	/// When decoding concatenated Streams, this is true as long as we
+	/// are decoding the first Stream. This is needed to avoid misleading
+	/// LZMA_FORMAT_ERROR in case the later Streams don't have valid magic
+	/// bytes.
+	bool first_stream;
+
+	/// This is used to track if the previous call to stream_decode_mt()
+	/// had output space (*out_pos < out_size) and managed to fill the
+	/// output buffer (*out_pos == out_size). This may be set to true
+	/// in read_output_and_wait(). This is read and then reset to false
+	/// at the beginning of stream_decode_mt().
+	///
+	/// This is needed to support applications that call lzma_code() in
+	/// such a way that more input is provided only when lzma_code()
+	/// didn't fill the output buffer completely. Basically, this makes
+	/// it easier to convert such applications from single-threaded
+	/// decoder to multi-threaded decoder.
+	bool out_was_filled;
+
+	/// Write position in buffer[] and position in Stream Padding
+	size_t pos;
+
+	/// Buffer to hold Stream Header, Block Header, and Stream Footer.
+	/// Block Header has biggest maximum size.
+	uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX];
+};
+
+
+/// Enables updating of outbuf->pos. This is a callback function that is
+/// used with lzma_outq_enable_partial_output().
+static void
+worker_enable_partial_update(void *thr_ptr)
+{
+	struct worker_thread *thr = thr_ptr;
+
+	mythread_sync(thr->mutex) {
+		thr->partial_update = PARTIAL_START;
+		mythread_cond_signal(&thr->cond);
+	}
+}
+
+
+/// Things do to at THR_STOP or when finishing a Block.
+/// This is called with thr->mutex locked.
+static void
+worker_stop(struct worker_thread *thr)
+{
+	// Update memory usage counters.
+	thr->coder->mem_in_use -= thr->in_size;
+	thr->in_size = 0; // thr->in was freed above.
+
+	thr->coder->mem_in_use -= thr->mem_filters;
+	thr->coder->mem_cached += thr->mem_filters;
+
+	// Put this thread to the stack of free threads.
+	thr->next = thr->coder->threads_free;
+	thr->coder->threads_free = thr;
+
+	mythread_cond_signal(&thr->coder->cond);
+	return;
+}
+
+
+static MYTHREAD_RET_TYPE
+worker_decoder(void *thr_ptr)
+{
+	struct worker_thread *thr = thr_ptr;
+	size_t in_filled;
+	partial_update_mode partial_update;
+	lzma_ret ret;
+
+next_loop_lock:
+
+	mythread_mutex_lock(&thr->mutex);
+next_loop_unlocked:
+
+	if (thr->state == THR_IDLE) {
+		mythread_cond_wait(&thr->cond, &thr->mutex);
+		goto next_loop_unlocked;
+	}
+
+	if (thr->state == THR_EXIT) {
+		mythread_mutex_unlock(&thr->mutex);
+
+		lzma_free(thr->in, thr->allocator);
+		lzma_next_end(&thr->block_decoder, thr->allocator);
+
+		mythread_mutex_destroy(&thr->mutex);
+		mythread_cond_destroy(&thr->cond);
+
+		return MYTHREAD_RET_VALUE;
+	}
+
+	if (thr->state == THR_STOP) {
+		thr->state = THR_IDLE;
+		mythread_mutex_unlock(&thr->mutex);
+
+		mythread_sync(thr->coder->mutex) {
+			worker_stop(thr);
+		}
+
+		goto next_loop_lock;
+	}
+
+	assert(thr->state == THR_RUN);
+
+	// Update progress info for get_progress().
+	thr->progress_in = thr->in_pos;
+	thr->progress_out = thr->out_pos;
+
+	// If we don't have any new input, wait for a signal from the main
+	// thread except if partial output has just been enabled. In that
+	// case we will do one normal run so that the partial output info
+	// gets passed to the main thread. The call to block_decoder.code()
+	// is useless but harmless as it can occur only once per Block.
+	in_filled = thr->in_filled;
+	partial_update = thr->partial_update;
+
+	if (in_filled == thr->in_pos && partial_update != PARTIAL_START) {
+		mythread_cond_wait(&thr->cond, &thr->mutex);
+		goto next_loop_unlocked;
+	}
+
+	mythread_mutex_unlock(&thr->mutex);
+
+	// Pass the input in small chunks to the Block decoder.
+	// This way we react reasonably fast if we are told to stop/exit,
+	// and (when partial update is enabled) we tell about our progress
+	// to the main thread frequently enough.
+	const size_t chunk_size = 16384;
+	if ((in_filled - thr->in_pos) > chunk_size)
+		in_filled = thr->in_pos + chunk_size;
+
+	ret = thr->block_decoder.code(
+			thr->block_decoder.coder, thr->allocator,
+			thr->in, &thr->in_pos, in_filled,
+			thr->outbuf->buf, &thr->out_pos,
+			thr->outbuf->allocated, LZMA_RUN);
+
+	if (ret == LZMA_OK) {
+		if (partial_update != PARTIAL_DISABLED) {
+			// The main thread uses thr->mutex to change from
+			// PARTIAL_DISABLED to PARTIAL_START. The main thread
+			// doesn't care about this variable after that so we
+			// can safely change it here to PARTIAL_ENABLED
+			// without a mutex.
+			thr->partial_update = PARTIAL_ENABLED;
+
+			// The main thread is reading decompressed data
+			// from thr->outbuf. Tell the main thread about
+			// our progress.
+			//
+			// NOTE: It's possible that we consumed input without
+			// producing any new output so it's possible that
+			// only in_pos has changed. In case of PARTIAL_START
+			// it is possible that neither in_pos nor out_pos has
+			// changed.
+			mythread_sync(thr->coder->mutex) {
+				thr->outbuf->pos = thr->out_pos;
+				thr->outbuf->decoder_in_pos = thr->in_pos;
+				mythread_cond_signal(&thr->coder->cond);
+			}
+		}
+
+		goto next_loop_lock;
+	}
+
+	// Either we finished successfully (LZMA_STREAM_END) or an error
+	// occurred. Both cases are handled almost identically. The error
+	// case requires updating thr->coder->thread_error.
+	//
+	// The sizes are in the Block Header and the Block decoder
+	// checks that they match, thus we know these:
+	assert(ret != LZMA_STREAM_END || thr->in_pos == thr->in_size);
+	assert(ret != LZMA_STREAM_END
+		|| thr->out_pos == thr->block_options.uncompressed_size);
+
+	// Free the input buffer. Don't update in_size as we need
+	// it later to update thr->coder->mem_in_use.
+	lzma_free(thr->in, thr->allocator);
+	thr->in = NULL;
+
+	mythread_sync(thr->mutex) {
+		if (thr->state != THR_EXIT)
+			thr->state = THR_IDLE;
+	}
+
+	mythread_sync(thr->coder->mutex) {
+		// Move our progress info to the main thread.
+		thr->coder->progress_in += thr->in_pos;
+		thr->coder->progress_out += thr->out_pos;
+		thr->progress_in = 0;
+		thr->progress_out = 0;
+
+		// Mark the outbuf as finished.
+		thr->outbuf->pos = thr->out_pos;
+		thr->outbuf->decoder_in_pos = thr->in_pos;
+		thr->outbuf->finished = true;
+		thr->outbuf->finish_ret = ret;
+		thr->outbuf = NULL;
+
+		// If an error occurred, tell it to the main thread.
+		if (ret != LZMA_STREAM_END
+				&& thr->coder->thread_error == LZMA_OK)
+			thr->coder->thread_error = ret;
+
+		worker_stop(thr);
+	}
+
+	goto next_loop_lock;
+}
+
+
+/// Tells the worker threads to exit and waits for them to terminate.
+static void
+threads_end(struct lzma_stream_coder *coder, const lzma_allocator *allocator)
+{
+	for (uint32_t i = 0; i < coder->threads_initialized; ++i) {
+		mythread_sync(coder->threads[i].mutex) {
+			coder->threads[i].state = THR_EXIT;
+			mythread_cond_signal(&coder->threads[i].cond);
+		}
+	}
+
+	for (uint32_t i = 0; i < coder->threads_initialized; ++i)
+		mythread_join(coder->threads[i].thread_id);
+
+	lzma_free(coder->threads, allocator);
+	coder->threads_initialized = 0;
+	coder->threads = NULL;
+	coder->threads_free = NULL;
+
+	// The threads don't update these when they exit. Do it here.
+	coder->mem_in_use = 0;
+	coder->mem_cached = 0;
+
+	return;
+}
+
+
+static void
+threads_stop(struct lzma_stream_coder *coder)
+{
+	for (uint32_t i = 0; i < coder->threads_initialized; ++i) {
+		mythread_sync(coder->threads[i].mutex) {
+			// The state must be changed conditionally because
+			// THR_IDLE -> THR_STOP is not a valid state change.
+			if (coder->threads[i].state != THR_IDLE) {
+				coder->threads[i].state = THR_STOP;
+				mythread_cond_signal(&coder->threads[i].cond);
+			}
+		}
+	}
+
+	return;
+}
+
+
+/// Initialize a new worker_thread structure and create a new thread.
+static lzma_ret
+initialize_new_thread(struct lzma_stream_coder *coder,
+		const lzma_allocator *allocator)
+{
+	// Allocate the coder->threads array if needed. It's done here instead
+	// of when initializing the decoder because we don't need this if we
+	// use the direct mode (we may even free coder->threads in the middle
+	// of the file if we switch from threaded to direct mode).
+	if (coder->threads == NULL) {
+		coder->threads = lzma_alloc(
+			coder->threads_max * sizeof(struct worker_thread),
+			allocator);
+
+		if (coder->threads == NULL)
+			return LZMA_MEM_ERROR;
+	}
+
+	// Pick a free structure.
+	assert(coder->threads_initialized < coder->threads_max);
+	struct worker_thread *thr
+			= &coder->threads[coder->threads_initialized];
+
+	if (mythread_mutex_init(&thr->mutex))
+		goto error_mutex;
+
+	if (mythread_cond_init(&thr->cond))
+		goto error_cond;
+
+	thr->state = THR_IDLE;
+	thr->in = NULL;
+	thr->in_size = 0;
+	thr->allocator = allocator;
+	thr->coder = coder;
+	thr->outbuf = NULL;
+	thr->block_decoder = LZMA_NEXT_CODER_INIT;
+	thr->mem_filters = 0;
+
+	if (mythread_create(&thr->thread_id, worker_decoder, thr))
+		goto error_thread;
+
+	++coder->threads_initialized;
+	coder->thr = thr;
+
+	return LZMA_OK;
+
+error_thread:
+	mythread_cond_destroy(&thr->cond);
+
+error_cond:
+	mythread_mutex_destroy(&thr->mutex);
+
+error_mutex:
+	return LZMA_MEM_ERROR;
+}
+
+
+static lzma_ret
+get_thread(struct lzma_stream_coder *coder, const lzma_allocator *allocator)
+{
+	// If there is a free structure on the stack, use it.
+	mythread_sync(coder->mutex) {
+		if (coder->threads_free != NULL) {
+			coder->thr = coder->threads_free;
+			coder->threads_free = coder->threads_free->next;
+
+			// The thread is no longer in the cache so subtract
+			// it from the cached memory usage. Don't add it
+			// to mem_in_use though; the caller will handle it
+			// since it knows how much memory it will actually
+			// use (the filter chain might change).
+			coder->mem_cached -= coder->thr->mem_filters;
+		}
+	}
+
+	if (coder->thr == NULL) {
+		assert(coder->threads_initialized < coder->threads_max);
+
+		// Initialize a new thread.
+		return_if_error(initialize_new_thread(coder, allocator));
+	}
+
+	coder->thr->in_filled = 0;
+	coder->thr->in_pos = 0;
+	coder->thr->out_pos = 0;
+
+	coder->thr->progress_in = 0;
+	coder->thr->progress_out = 0;
+
+	coder->thr->partial_update = PARTIAL_DISABLED;
+
+	return LZMA_OK;
+}
+
+
+static lzma_ret
+read_output_and_wait(struct lzma_stream_coder *coder,
+		const lzma_allocator *allocator,
+		uint8_t *restrict out, size_t *restrict out_pos,
+		size_t out_size,
+		bool *input_is_possible,
+		bool waiting_allowed,
+		mythread_condtime *wait_abs, bool *has_blocked)
+{
+	lzma_ret ret = LZMA_OK;
+
+	mythread_sync(coder->mutex) {
+		do {
+			// Get as much output from the queue as is possible
+			// without blocking.
+			const size_t out_start = *out_pos;
+			do {
+				ret = lzma_outq_read(&coder->outq, allocator,
+						out, out_pos, out_size,
+						NULL, NULL);
+
+				// If a Block was finished, tell the worker
+				// thread of the next Block (if it is still
+				// running) to start telling the main thread
+				// when new output is available.
+				if (ret == LZMA_STREAM_END)
+					lzma_outq_enable_partial_output(
+						&coder->outq,
+						&worker_enable_partial_update);
+
+				// Loop until a Block wasn't finished.
+				// It's important to loop around even if
+				// *out_pos == out_size because there could
+				// be an empty Block that will return
+				// LZMA_STREAM_END without needing any
+				// output space.
+			} while (ret == LZMA_STREAM_END);
+
+			// Check if lzma_outq_read reported an error from
+			// the Block decoder.
+			if (ret != LZMA_OK)
+				break;
+
+			// If the output buffer is now full but it wasn't full
+			// when this function was called, set out_was_filled.
+			// This way the next call to stream_decode_mt() knows
+			// that some output was produced and no output space
+			// remained in the previous call to stream_decode_mt().
+			if (*out_pos == out_size && *out_pos != out_start)
+				coder->out_was_filled = true;
+
+			// Check if any thread has indicated an error.
+			if (coder->thread_error != LZMA_OK) {
+				// If LZMA_FAIL_FAST was used, report errors
+				// from worker threads immediately.
+				if (coder->fail_fast) {
+					ret = coder->thread_error;
+					break;
+				}
+
+				// Otherwise set pending_error. The value we
+				// set here will not actually get used other
+				// than working as a flag that an error has
+				// occurred. This is because in SEQ_ERROR
+				// all output before the error will be read
+				// first by calling this function, and once we
+				// reach the location of the (first) error the
+				// error code from the above lzma_outq_read()
+				// will be returned to the application.
+				//
+				// Use LZMA_PROG_ERROR since the value should
+				// never leak to the application. It's
+				// possible that pending_error has already
+				// been set but that doesn't matter: if we get
+				// here, pending_error only works as a flag.
+				coder->pending_error = LZMA_PROG_ERROR;
+			}
+
+			// Check if decoding of the next Block can be started.
+			// The memusage of the active threads must be low
+			// enough, there must be a free buffer slot in the
+			// output queue, and there must be a free thread
+			// (that can be either created or an existing one
+			// reused).
+			//
+			// NOTE: This is checked after reading the output
+			// above because reading the output can free a slot in
+			// the output queue and also reduce active memusage.
+			//
+			// NOTE: If output queue is empty, then input will
+			// always be possible.
+			if (input_is_possible != NULL
+					&& coder->memlimit_threading
+						- coder->mem_in_use
+						- coder->outq.mem_in_use
+						>= coder->mem_next_block
+					&& lzma_outq_has_buf(&coder->outq)
+					&& (coder->threads_initialized
+							< coder->threads_max
+						|| coder->threads_free
+							!= NULL)) {
+				*input_is_possible = true;
+				break;
+			}
+
+			// If the caller doesn't want us to block, return now.
+			if (!waiting_allowed)
+				break;
+
+			// This check is needed only when input_is_possible
+			// is NULL. We must return if we aren't waiting for
+			// input to become possible and there is no more
+			// output coming from the queue.
+			if (lzma_outq_is_empty(&coder->outq)) {
+				assert(input_is_possible == NULL);
+				break;
+			}
+
+			// If there is more data available from the queue,
+			// our out buffer must be full and we need to return
+			// so that the application can provide more output
+			// space.
+			//
+			// NOTE: In general lzma_outq_is_readable() can return
+			// true also when there are no more bytes available.
+			// This can happen when a Block has finished without
+			// providing any new output. We know that this is not
+			// the case because in the beginning of this loop we
+			// tried to read as much as possible even when we had
+			// no output space left and the mutex has been locked
+			// all the time (so worker threads cannot have changed
+			// anything). Thus there must be actual pending output
+			// in the queue.
+			if (lzma_outq_is_readable(&coder->outq)) {
+				assert(*out_pos == out_size);
+				break;
+			}
+
+			// If the application stops providing more input
+			// in the middle of a Block, there will eventually
+			// be one worker thread left that is stuck waiting for
+			// more input (that might never arrive) and a matching
+			// outbuf which the worker thread cannot finish due
+			// to lack of input. We must detect this situation,
+			// otherwise we would end up waiting indefinitely
+			// (if no timeout is in use) or keep returning
+			// LZMA_TIMED_OUT while making no progress. Thus, the
+			// application would never get LZMA_BUF_ERROR from
+			// lzma_code() which would tell the application that
+			// no more progress is possible. No LZMA_BUF_ERROR
+			// means that, for example, truncated .xz files could
+			// cause an infinite loop.
+			//
+			// A worker thread doing partial updates will
+			// store not only the output position in outbuf->pos
+			// but also the matching input position in
+			// outbuf->decoder_in_pos. Here we check if that
+			// input position matches the amount of input that
+			// the worker thread has been given (in_filled).
+			// If so, we must return and not wait as no more
+			// output will be coming without first getting more
+			// input to the worker thread. If the application
+			// keeps calling lzma_code() without providing more
+			// input, it will eventually get LZMA_BUF_ERROR.
+			//
+			// NOTE: We can read partial_update and in_filled
+			// without thr->mutex as only the main thread
+			// modifies these variables. decoder_in_pos requires
+			// coder->mutex which we are already holding.
+			if (coder->thr != NULL && coder->thr->partial_update
+					!= PARTIAL_DISABLED) {
+				// There is exactly one outbuf in the queue.
+				assert(coder->thr->outbuf == coder->outq.head);
+				assert(coder->thr->outbuf == coder->outq.tail);
+
+				if (coder->thr->outbuf->decoder_in_pos
+						== coder->thr->in_filled)
+					break;
+			}
+
+			// Wait for input or output to become possible.
+			if (coder->timeout != 0) {
+				// See the comment in stream_encoder_mt.c
+				// about why mythread_condtime_set() is used
+				// like this.
+				//
+				// FIXME?
+				// In contrast to the encoder, this calls
+				// _condtime_set while the mutex is locked.
+				if (!*has_blocked) {
+					*has_blocked = true;
+					mythread_condtime_set(wait_abs,
+							&coder->cond,
+							coder->timeout);
+				}
+
+				if (mythread_cond_timedwait(&coder->cond,
+						&coder->mutex,
+						wait_abs) != 0) {
+					ret = LZMA_TIMED_OUT;
+					break;
+				}
+			} else {
+				mythread_cond_wait(&coder->cond,
+						&coder->mutex);
+			}
+		} while (ret == LZMA_OK);
+	}
+
+	// If we are returning an error, then the application cannot get
+	// more output from us and thus keeping the threads running is
+	// useless and waste of CPU time.
+	if (ret != LZMA_OK && ret != LZMA_TIMED_OUT)
+		threads_stop(coder);
+
+	return ret;
+}
+
+
+static lzma_ret
+decode_block_header(struct lzma_stream_coder *coder,
+		const lzma_allocator *allocator, const uint8_t *restrict in,
+		size_t *restrict in_pos, size_t in_size)
+{
+	if (*in_pos >= in_size)
+		return LZMA_OK;
+
+	if (coder->pos == 0) {
+		// Detect if it's Index.
+		if (in[*in_pos] == INDEX_INDICATOR)
+			return LZMA_INDEX_DETECTED;
+
+		// Calculate the size of the Block Header. Note that
+		// Block Header decoder wants to see this byte too
+		// so don't advance *in_pos.
+		coder->block_options.header_size
+				= lzma_block_header_size_decode(
+					in[*in_pos]);
+	}
+
+	// Copy the Block Header to the internal buffer.
+	lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
+			coder->block_options.header_size);
+
+	// Return if we didn't get the whole Block Header yet.
+	if (coder->pos < coder->block_options.header_size)
+		return LZMA_OK;
+
+	coder->pos = 0;
+
+	// Version 1 is needed to support the .ignore_check option.
+	coder->block_options.version = 1;
+
+	// Block Header decoder will initialize all members of this array
+	// so we don't need to do it here.
+	coder->block_options.filters = coder->filters;
+
+	// Decode the Block Header.
+	return_if_error(lzma_block_header_decode(&coder->block_options,
+			allocator, coder->buffer));
+
+	// If LZMA_IGNORE_CHECK was used, this flag needs to be set.
+	// It has to be set after lzma_block_header_decode() because
+	// it always resets this to false.
+	coder->block_options.ignore_check = coder->ignore_check;
+
+	// coder->block_options is ready now.
+	return LZMA_STREAM_END;
+}
+
+
+/// Get the size of the Compressed Data + Block Padding + Check.
+static size_t
+comp_blk_size(const struct lzma_stream_coder *coder)
+{
+	return vli_ceil4(coder->block_options.compressed_size)
+			+ lzma_check_size(coder->stream_flags.check);
+}
+
+
+/// Returns true if the size (compressed or uncompressed) is such that
+/// threaded decompression cannot be used. Sizes that are too big compared
+/// to SIZE_MAX must be rejected to avoid integer overflows and truncations
+/// when lzma_vli is assigned to a size_t.
+static bool
+is_direct_mode_needed(lzma_vli size)
+{
+	return size == LZMA_VLI_UNKNOWN || size > SIZE_MAX / 3;
+}
+
+
+static lzma_ret
+stream_decoder_reset(struct lzma_stream_coder *coder,
+		const lzma_allocator *allocator)
+{
+	// Initialize the Index hash used to verify the Index.
+	coder->index_hash = lzma_index_hash_init(coder->index_hash, allocator);
+	if (coder->index_hash == NULL)
+		return LZMA_MEM_ERROR;
+
+	// Reset the rest of the variables.
+	coder->sequence = SEQ_STREAM_HEADER;
+	coder->pos = 0;
+
+	return LZMA_OK;
+}
+
+
+static lzma_ret
+stream_decode_mt(void *coder_ptr, const lzma_allocator *allocator,
+		 const uint8_t *restrict in, size_t *restrict in_pos,
+		 size_t in_size,
+		 uint8_t *restrict out, size_t *restrict out_pos,
+		 size_t out_size, lzma_action action)
+{
+	struct lzma_stream_coder *coder = coder_ptr;
+
+	mythread_condtime wait_abs;
+	bool has_blocked = false;
+
+	// Determine if in SEQ_BLOCK_HEADER and SEQ_BLOCK_THR_RUN we should
+	// tell read_output_and_wait() to wait until it can fill the output
+	// buffer (or a timeout occurs). Two conditions must be met:
+	//
+	// (1) If the caller provided no new input. The reason for this
+	//     can be, for example, the end of the file or that there is
+	//     a pause in the input stream and more input is available
+	//     a little later. In this situation we should wait for output
+	//     because otherwise we would end up in a busy-waiting loop where
+	//     we make no progress and the application just calls us again
+	//     without providing any new input. This would then result in
+	//     LZMA_BUF_ERROR even though more output would be available
+	//     once the worker threads decode more data.
+	//
+	// (2) Even if (1) is true, we will not wait if the previous call to
+	//     this function managed to produce some output and the output
+	//     buffer became full. This is for compatibility with applications
+	//     that call lzma_code() in such a way that new input is provided
+	//     only when the output buffer didn't become full. Without this
+	//     trick such applications would have bad performance (bad
+	//     parallelization due to decoder not getting input fast enough).
+	//
+	//     NOTE: Such loops might require that timeout is disabled (0)
+	//     if they assume that output-not-full implies that all input has
+	//     been consumed. If and only if timeout is enabled, we may return
+	//     when output isn't full *and* not all input has been consumed.
+	//
+	// However, if LZMA_FINISH is used, the above is ignored and we always
+	// wait (timeout can still cause us to return) because we know that
+	// we won't get any more input. This matters if the input file is
+	// truncated and we are doing single-shot decoding, that is,
+	// timeout = 0 and LZMA_FINISH is used on the first call to
+	// lzma_code() and the output buffer is known to be big enough
+	// to hold all uncompressed data:
+	//
+	//   - If LZMA_FINISH wasn't handled specially, we could return
+	//     LZMA_OK before providing all output that is possible with the
+	//     truncated input. The rest would be available if lzma_code() was
+	//     called again but then it's not single-shot decoding anymore.
+	//
+	//   - By handling LZMA_FINISH specially here, the first call will
+	//     produce all the output, matching the behavior of the
+	//     single-threaded decoder.
+	//
+	// So it's a very specific corner case but also easy to avoid. Note
+	// that this special handling of LZMA_FINISH has no effect for
+	// single-shot decoding when the input file is valid (not truncated);
+	// premature LZMA_OK wouldn't be possible as long as timeout = 0.
+	const bool waiting_allowed = action == LZMA_FINISH
+			|| (*in_pos == in_size && !coder->out_was_filled);
+	coder->out_was_filled = false;
+
+	while (true)
+	switch (coder->sequence) {
+	case SEQ_STREAM_HEADER: {
+		// Copy the Stream Header to the internal buffer.
+		const size_t in_old = *in_pos;
+		lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
+				LZMA_STREAM_HEADER_SIZE);
+		coder->progress_in += *in_pos - in_old;
+
+		// Return if we didn't get the whole Stream Header yet.
+		if (coder->pos < LZMA_STREAM_HEADER_SIZE)
+			return LZMA_OK;
+
+		coder->pos = 0;
+
+		// Decode the Stream Header.
+		const lzma_ret ret = lzma_stream_header_decode(
+				&coder->stream_flags, coder->buffer);
+		if (ret != LZMA_OK)
+			return ret == LZMA_FORMAT_ERROR && !coder->first_stream
+					? LZMA_DATA_ERROR : ret;
+
+		// If we are decoding concatenated Streams, and the later
+		// Streams have invalid Header Magic Bytes, we give
+		// LZMA_DATA_ERROR instead of LZMA_FORMAT_ERROR.
+		coder->first_stream = false;
+
+		// Copy the type of the Check so that Block Header and Block
+		// decoders see it.
+		coder->block_options.check = coder->stream_flags.check;
+
+		// Even if we return LZMA_*_CHECK below, we want
+		// to continue from Block Header decoding.
+		coder->sequence = SEQ_BLOCK_HEADER;
+
+		// Detect if there's no integrity check or if it is
+		// unsupported if those were requested by the application.
+		if (coder->tell_no_check && coder->stream_flags.check
+				== LZMA_CHECK_NONE)
+			return LZMA_NO_CHECK;
+
+		if (coder->tell_unsupported_check
+				&& !lzma_check_is_supported(
+					coder->stream_flags.check))
+			return LZMA_UNSUPPORTED_CHECK;
+
+		if (coder->tell_any_check)
+			return LZMA_GET_CHECK;
+	}
+
+	// Fall through
+
+	case SEQ_BLOCK_HEADER: {
+		const size_t in_old = *in_pos;
+		const lzma_ret ret = decode_block_header(coder, allocator,
+				in, in_pos, in_size);
+		coder->progress_in += *in_pos - in_old;
+
+		if (ret == LZMA_OK) {
+			// We didn't decode the whole Block Header yet.
+			//
+			// Read output from the queue before returning. This
+			// is important because it is possible that the
+			// application doesn't have any new input available
+			// immediately. If we didn't try to copy output from
+			// the output queue here, lzma_code() could end up
+			// returning LZMA_BUF_ERROR even though queued output
+			// is available.
+			//
+			// If the lzma_code() call provided at least one input
+			// byte, only copy as much data from the output queue
+			// as is available immediately. This way the
+			// application will be able to provide more input
+			// without a delay.
+			//
+			// On the other hand, if lzma_code() was called with
+			// an empty input buffer(*), treat it specially: try
+			// to fill the output buffer even if it requires
+			// waiting for the worker threads to provide output
+			// (timeout, if specified, can still cause us to
+			// return).
+			//
+			//   - This way the application will be able to get all
+			//     data that can be decoded from the input provided
+			//     so far.
+			//
+			//   - We avoid both premature LZMA_BUF_ERROR and
+			//     busy-waiting where the application repeatedly
+			//     calls lzma_code() which immediately returns
+			//     LZMA_OK without providing new data.
+			//
+			//   - If the queue becomes empty, we won't wait
+			//     anything and will return LZMA_OK immediately
+			//     (coder->timeout is completely ignored).
+			//
+			// (*) See the comment at the beginning of this
+			//     function how waiting_allowed is determined
+			//     and why there is an exception to the rule
+			//     of "called with an empty input buffer".
+			assert(*in_pos == in_size);
+
+			// If LZMA_FINISH was used we know that we won't get
+			// more input, so the file must be truncated if we
+			// get here. If worker threads don't detect any
+			// errors, eventually there will be no more output
+			// while we keep returning LZMA_OK which gets
+			// converted to LZMA_BUF_ERROR in lzma_code().
+			//
+			// If fail-fast is enabled then we will return
+			// immediately using LZMA_DATA_ERROR instead of
+			// LZMA_OK or LZMA_BUF_ERROR. Rationale for the
+			// error code:
+			//
+			//   - Worker threads may have a large amount of
+			//     not-yet-decoded input data and we don't
+			//     know for sure if all data is valid. Bad
+			//     data there would result in LZMA_DATA_ERROR
+			//     when fail-fast isn't used.
+			//
+			//   - Immediate LZMA_BUF_ERROR would be a bit weird
+			//     considering the older liblzma code. lzma_code()
+			//     even has an assertion to prevent coders from
+			//     returning LZMA_BUF_ERROR directly.
+			//
+			// The downside of this is that with fail-fast apps
+			// cannot always distinguish between corrupt and
+			// truncated files.
+			if (action == LZMA_FINISH && coder->fail_fast) {
+				// We won't produce any more output. Stop
+				// the unfinished worker threads so they
+				// won't waste CPU time.
+				threads_stop(coder);
+				return LZMA_DATA_ERROR;
+			}
+
+			// read_output_and_wait() will call threads_stop()
+			// if needed so with that we can use return_if_error.
+			return_if_error(read_output_and_wait(coder, allocator,
+				out, out_pos, out_size,
+				NULL, waiting_allowed,
+				&wait_abs, &has_blocked));
+
+			if (coder->pending_error != LZMA_OK) {
+				coder->sequence = SEQ_ERROR;
+				break;
+			}
+
+			return LZMA_OK;
+		}
+
+		if (ret == LZMA_INDEX_DETECTED) {
+			coder->sequence = SEQ_INDEX_WAIT_OUTPUT;
+			break;
+		}
+
+		// See if an error occurred.
+		if (ret != LZMA_STREAM_END) {
+			// NOTE: Here and in all other places where
+			// pending_error is set, it may overwrite the value
+			// (LZMA_PROG_ERROR) set by read_output_and_wait().
+			// That function might overwrite value set here too.
+			// These are fine because when read_output_and_wait()
+			// sets pending_error, it actually works as a flag
+			// variable only ("some error has occurred") and the
+			// actual value of pending_error is not used in
+			// SEQ_ERROR. In such cases SEQ_ERROR will eventually
+			// get the correct error code from the return value of
+			// a later read_output_and_wait() call.
+			coder->pending_error = ret;
+			coder->sequence = SEQ_ERROR;
+			break;
+		}
+
+		// Calculate the memory usage of the filters / Block decoder.
+		coder->mem_next_filters = lzma_raw_decoder_memusage(
+				coder->filters);
+
+		if (coder->mem_next_filters == UINT64_MAX) {
+			// One or more unknown Filter IDs.
+			coder->pending_error = LZMA_OPTIONS_ERROR;
+			coder->sequence = SEQ_ERROR;
+			break;
+		}
+
+		coder->sequence = SEQ_BLOCK_INIT;
+	}
+
+	// Fall through
+
+	case SEQ_BLOCK_INIT: {
+		// Check if decoding is possible at all with the current
+		// memlimit_stop which we must never exceed.
+		//
+		// This needs to be the first thing in SEQ_BLOCK_INIT
+		// to make it possible to restart decoding after increasing
+		// memlimit_stop with lzma_memlimit_set().
+		if (coder->mem_next_filters > coder->memlimit_stop) {
+			// Flush pending output before returning
+			// LZMA_MEMLIMIT_ERROR. If the application doesn't
+			// want to increase the limit, at least it will get
+			// all the output possible so far.
+			return_if_error(read_output_and_wait(coder, allocator,
+					out, out_pos, out_size,
+					NULL, true, &wait_abs, &has_blocked));
+
+			if (!lzma_outq_is_empty(&coder->outq))
+				return LZMA_OK;
+
+			return LZMA_MEMLIMIT_ERROR;
+		}
+
+		// Check if the size information is available in Block Header.
+		// If it is, check if the sizes are small enough that we don't
+		// need to worry *too* much about integer overflows later in
+		// the code. If these conditions are not met, we must use the
+		// single-threaded direct mode.
+		if (is_direct_mode_needed(coder->block_options.compressed_size)
+				|| is_direct_mode_needed(
+				coder->block_options.uncompressed_size)) {
+			coder->sequence = SEQ_BLOCK_DIRECT_INIT;
+			break;
+		}
+
+		// Calculate the amount of memory needed for the input and
+		// output buffers in threaded mode.
+		//
+		// These cannot overflow because we already checked that
+		// the sizes are small enough using is_direct_mode_needed().
+		coder->mem_next_in = comp_blk_size(coder);
+		const uint64_t mem_buffers = coder->mem_next_in
+				+ lzma_outq_outbuf_memusage(
+				coder->block_options.uncompressed_size);
+
+		// Add the amount needed by the filters.
+		// Avoid integer overflows.
+		if (UINT64_MAX - mem_buffers < coder->mem_next_filters) {
+			// Use direct mode if the memusage would overflow.
+			// This is a theoretical case that shouldn't happen
+			// in practice unless the input file is weird (broken
+			// or malicious).
+			coder->sequence = SEQ_BLOCK_DIRECT_INIT;
+			break;
+		}
+
+		// Amount of memory needed to decode this Block in
+		// threaded mode:
+		coder->mem_next_block = coder->mem_next_filters + mem_buffers;
+
+		// If this alone would exceed memlimit_threading, then we must
+		// use the single-threaded direct mode.
+		if (coder->mem_next_block > coder->memlimit_threading) {
+			coder->sequence = SEQ_BLOCK_DIRECT_INIT;
+			break;
+		}
+
+		// Use the threaded mode. Free the direct mode decoder in
+		// case it has been initialized.
+		lzma_next_end(&coder->block_decoder, allocator);
+		coder->mem_direct_mode = 0;
+
+		// Since we already know what the sizes are supposed to be,
+		// we can already add them to the Index hash. The Block
+		// decoder will verify the values while decoding.
+		const lzma_ret ret = lzma_index_hash_append(coder->index_hash,
+				lzma_block_unpadded_size(
+					&coder->block_options),
+				coder->block_options.uncompressed_size);
+		if (ret != LZMA_OK) {
+			coder->pending_error = ret;
+			coder->sequence = SEQ_ERROR;
+			break;
+		}
+
+		coder->sequence = SEQ_BLOCK_THR_INIT;
+	}
+
+	// Fall through
+
+	case SEQ_BLOCK_THR_INIT: {
+		// We need to wait for a multiple conditions to become true
+		// until we can initialize the Block decoder and let a worker
+		// thread decode it:
+		//
+		//   - Wait for the memory usage of the active threads to drop
+		//     so that starting the decoding of this Block won't make
+		//     us go over memlimit_threading.
+		//
+		//   - Wait for at least one free output queue slot.
+		//
+		//   - Wait for a free worker thread.
+		//
+		// While we wait, we must copy decompressed data to the out
+		// buffer and catch possible decoder errors.
+		//
+		// read_output_and_wait() does all the above.
+		bool block_can_start = false;
+
+		return_if_error(read_output_and_wait(coder, allocator,
+				out, out_pos, out_size,
+				&block_can_start, true,
+				&wait_abs, &has_blocked));
+
+		if (coder->pending_error != LZMA_OK) {
+			coder->sequence = SEQ_ERROR;
+			break;
+		}
+
+		if (!block_can_start) {
+			// It's not a timeout because return_if_error handles
+			// it already. Output queue cannot be empty either
+			// because in that case block_can_start would have
+			// been true. Thus the output buffer must be full and
+			// the queue isn't empty.
+			assert(*out_pos == out_size);
+			assert(!lzma_outq_is_empty(&coder->outq));
+			return LZMA_OK;
+		}
+
+		// We know that we can start decoding this Block without
+		// exceeding memlimit_threading. However, to stay below
+		// memlimit_threading may require freeing some of the
+		// cached memory.
+		//
+		// Get a local copy of variables that require locking the
+		// mutex. It is fine if the worker threads modify the real
+		// values after we read these as those changes can only be
+		// towards more favorable conditions (less memory in use,
+		// more in cache).
+		//
+		// These are initialized to silence warnings.
+		uint64_t mem_in_use = 0;
+		uint64_t mem_cached = 0;
+		struct worker_thread *thr = NULL;
+
+		mythread_sync(coder->mutex) {
+			mem_in_use = coder->mem_in_use;
+			mem_cached = coder->mem_cached;
+			thr = coder->threads_free;
+		}
+
+		// The maximum amount of memory that can be held by other
+		// threads and cached buffers while allowing us to start
+		// decoding the next Block.
+		const uint64_t mem_max = coder->memlimit_threading
+				- coder->mem_next_block;
+
+		// If the existing allocations are so large that starting
+		// to decode this Block might exceed memlimit_threads,
+		// try to free memory from the output queue cache first.
+		//
+		// NOTE: This math assumes the worst case. It's possible
+		// that the limit wouldn't be exceeded if the existing cached
+		// allocations are reused.
+		if (mem_in_use + mem_cached + coder->outq.mem_allocated
+				> mem_max) {
+			// Clear the outq cache except leave one buffer in
+			// the cache if its size is correct. That way we
+			// don't free and almost immediately reallocate
+			// an identical buffer.
+			lzma_outq_clear_cache2(&coder->outq, allocator,
+				coder->block_options.uncompressed_size);
+		}
+
+		// If there is at least one worker_thread in the cache and
+		// the existing allocations are so large that starting to
+		// decode this Block might exceed memlimit_threads, free
+		// memory by freeing cached Block decoders.
+		//
+		// NOTE: The comparison is different here than above.
+		// Here we don't care about cached buffers in outq anymore
+		// and only look at memory actually in use. This is because
+		// if there is something in outq cache, it's a single buffer
+		// that can be used as is. We ensured this in the above
+		// if-block.
+		uint64_t mem_freed = 0;
+		if (thr != NULL && mem_in_use + mem_cached
+				+ coder->outq.mem_in_use > mem_max) {
+			// Don't free the first Block decoder if its memory
+			// usage isn't greater than what this Block will need.
+			// Typically the same filter chain is used for all
+			// Blocks so this way the allocations can be reused
+			// when get_thread() picks the first worker_thread
+			// from the cache.
+			if (thr->mem_filters <= coder->mem_next_filters)
+				thr = thr->next;
+
+			while (thr != NULL) {
+				lzma_next_end(&thr->block_decoder, allocator);
+				mem_freed += thr->mem_filters;
+				thr->mem_filters = 0;
+				thr = thr->next;
+			}
+		}
+
+		// Update the memory usage counters. Note that coder->mem_*
+		// may have changed since we read them so we must subtract
+		// or add the changes.
+		mythread_sync(coder->mutex) {
+			coder->mem_cached -= mem_freed;
+
+			// Memory needed for the filters and the input buffer.
+			// The output queue takes care of its own counter so
+			// we don't touch it here.
+			//
+			// NOTE: After this, coder->mem_in_use +
+			// coder->mem_cached might count the same thing twice.
+			// If so, this will get corrected in get_thread() when
+			// a worker_thread is picked from coder->free_threads
+			// and its memory usage is subtracted from mem_cached.
+			coder->mem_in_use += coder->mem_next_in
+					+ coder->mem_next_filters;
+		}
+
+		// Allocate memory for the output buffer in the output queue.
+		lzma_ret ret = lzma_outq_prealloc_buf(
+				&coder->outq, allocator,
+				coder->block_options.uncompressed_size);
+		if (ret != LZMA_OK) {
+			threads_stop(coder);
+			return ret;
+		}
+
+		// Set up coder->thr.
+		ret = get_thread(coder, allocator);
+		if (ret != LZMA_OK) {
+			threads_stop(coder);
+			return ret;
+		}
+
+		// The new Block decoder memory usage is already counted in
+		// coder->mem_in_use. Store it in the thread too.
+		coder->thr->mem_filters = coder->mem_next_filters;
+
+		// Initialize the Block decoder.
+		coder->thr->block_options = coder->block_options;
+		ret = lzma_block_decoder_init(
+					&coder->thr->block_decoder, allocator,
+					&coder->thr->block_options);
+
+		// Free the allocated filter options since they are needed
+		// only to initialize the Block decoder.
+		lzma_filters_free(coder->filters, allocator);
+		coder->thr->block_options.filters = NULL;
+
+		// Check if memory usage calculation and Block encoder
+		// initialization succeeded.
+		if (ret != LZMA_OK) {
+			coder->pending_error = ret;
+			coder->sequence = SEQ_ERROR;
+			break;
+		}
+
+		// Allocate the input buffer.
+		coder->thr->in_size = coder->mem_next_in;
+		coder->thr->in = lzma_alloc(coder->thr->in_size, allocator);
+		if (coder->thr->in == NULL) {
+			threads_stop(coder);
+			return LZMA_MEM_ERROR;
+		}
+
+		// Get the preallocated output buffer.
+		coder->thr->outbuf = lzma_outq_get_buf(
+				&coder->outq, coder->thr);
+
+		// Start the decoder.
+		mythread_sync(coder->thr->mutex) {
+			assert(coder->thr->state == THR_IDLE);
+			coder->thr->state = THR_RUN;
+			mythread_cond_signal(&coder->thr->cond);
+		}
+
+		// Enable output from the thread that holds the oldest output
+		// buffer in the output queue (if such a thread exists).
+		mythread_sync(coder->mutex) {
+			lzma_outq_enable_partial_output(&coder->outq,
+					&worker_enable_partial_update);
+		}
+
+		coder->sequence = SEQ_BLOCK_THR_RUN;
+	}
+
+	// Fall through
+
+	case SEQ_BLOCK_THR_RUN: {
+		if (action == LZMA_FINISH && coder->fail_fast) {
+			// We know that we won't get more input and that
+			// the caller wants fail-fast behavior. If we see
+			// that we don't have enough input to finish this
+			// Block, return LZMA_DATA_ERROR immediately.
+			// See SEQ_BLOCK_HEADER for the error code rationale.
+			const size_t in_avail = in_size - *in_pos;
+			const size_t in_needed = coder->thr->in_size
+					- coder->thr->in_filled;
+			if (in_avail < in_needed) {
+				threads_stop(coder);
+				return LZMA_DATA_ERROR;
+			}
+		}
+
+		// Copy input to the worker thread.
+		size_t cur_in_filled = coder->thr->in_filled;
+		lzma_bufcpy(in, in_pos, in_size, coder->thr->in,
+				&cur_in_filled, coder->thr->in_size);
+
+		// Tell the thread how much we copied.
+		mythread_sync(coder->thr->mutex) {
+			coder->thr->in_filled = cur_in_filled;
+
+			// NOTE: Most of the time we are copying input faster
+			// than the thread can decode so most of the time
+			// calling mythread_cond_signal() is useless but
+			// we cannot make it conditional because thr->in_pos
+			// is updated without a mutex. And the overhead should
+			// be very much negligible anyway.
+			mythread_cond_signal(&coder->thr->cond);
+		}
+
+		// Read output from the output queue. Just like in
+		// SEQ_BLOCK_HEADER, we wait to fill the output buffer
+		// only if waiting_allowed was set to true in the beginning
+		// of this function (see the comment there).
+		return_if_error(read_output_and_wait(coder, allocator,
+				out, out_pos, out_size,
+				NULL, waiting_allowed,
+				&wait_abs, &has_blocked));
+
+		if (coder->pending_error != LZMA_OK) {
+			coder->sequence = SEQ_ERROR;
+			break;
+		}
+
+		// Return if the input didn't contain the whole Block.
+		if (coder->thr->in_filled < coder->thr->in_size) {
+			assert(*in_pos == in_size);
+			return LZMA_OK;
+		}
+
+		// The whole Block has been copied to the thread-specific
+		// buffer. Continue from the next Block Header or Index.
+		coder->thr = NULL;
+		coder->sequence = SEQ_BLOCK_HEADER;
+		break;
+	}
+
+	case SEQ_BLOCK_DIRECT_INIT: {
+		// Wait for the threads to finish and that all decoded data
+		// has been copied to the output. That is, wait until the
+		// output queue becomes empty.
+		//
+		// NOTE: No need to check for coder->pending_error as
+		// we aren't consuming any input until the queue is empty
+		// and if there is a pending error, read_output_and_wait()
+		// will eventually return it before the queue is empty.
+		return_if_error(read_output_and_wait(coder, allocator,
+				out, out_pos, out_size,
+				NULL, true, &wait_abs, &has_blocked));
+		if (!lzma_outq_is_empty(&coder->outq))
+			return LZMA_OK;
+
+		// Free the cached output buffers.
+		lzma_outq_clear_cache(&coder->outq, allocator);
+
+		// Get rid of the worker threads, including the coder->threads
+		// array.
+		threads_end(coder, allocator);
+
+		// Initialize the Block decoder.
+		const lzma_ret ret = lzma_block_decoder_init(
+				&coder->block_decoder, allocator,
+				&coder->block_options);
+
+		// Free the allocated filter options since they are needed
+		// only to initialize the Block decoder.
+		lzma_filters_free(coder->filters, allocator);
+		coder->block_options.filters = NULL;
+
+		// Check if Block decoder initialization succeeded.
+		if (ret != LZMA_OK)
+			return ret;
+
+		// Make the memory usage visible to _memconfig().
+		coder->mem_direct_mode = coder->mem_next_filters;
+
+		coder->sequence = SEQ_BLOCK_DIRECT_RUN;
+	}
+
+	// Fall through
+
+	case SEQ_BLOCK_DIRECT_RUN: {
+		const size_t in_old = *in_pos;
+		const size_t out_old = *out_pos;
+		const lzma_ret ret = coder->block_decoder.code(
+				coder->block_decoder.coder, allocator,
+				in, in_pos, in_size, out, out_pos, out_size,
+				action);
+		coder->progress_in += *in_pos - in_old;
+		coder->progress_out += *out_pos - out_old;
+
+		if (ret != LZMA_STREAM_END)
+			return ret;
+
+		// Block decoded successfully. Add the new size pair to
+		// the Index hash.
+		return_if_error(lzma_index_hash_append(coder->index_hash,
+				lzma_block_unpadded_size(
+					&coder->block_options),
+				coder->block_options.uncompressed_size));
+
+		coder->sequence = SEQ_BLOCK_HEADER;
+		break;
+	}
+
+	case SEQ_INDEX_WAIT_OUTPUT:
+		// Flush the output from all worker threads so that we can
+		// decode the Index without thinking about threading.
+		return_if_error(read_output_and_wait(coder, allocator,
+				out, out_pos, out_size,
+				NULL, true, &wait_abs, &has_blocked));
+
+		if (!lzma_outq_is_empty(&coder->outq))
+			return LZMA_OK;
+
+		coder->sequence = SEQ_INDEX_DECODE;
+
+	// Fall through
+
+	case SEQ_INDEX_DECODE: {
+		// If we don't have any input, don't call
+		// lzma_index_hash_decode() since it would return
+		// LZMA_BUF_ERROR, which we must not do here.
+		if (*in_pos >= in_size)
+			return LZMA_OK;
+
+		// Decode the Index and compare it to the hash calculated
+		// from the sizes of the Blocks (if any).
+		const size_t in_old = *in_pos;
+		const lzma_ret ret = lzma_index_hash_decode(coder->index_hash,
+				in, in_pos, in_size);
+		coder->progress_in += *in_pos - in_old;
+		if (ret != LZMA_STREAM_END)
+			return ret;
+
+		coder->sequence = SEQ_STREAM_FOOTER;
+	}
+
+	// Fall through
+
+	case SEQ_STREAM_FOOTER: {
+		// Copy the Stream Footer to the internal buffer.
+		const size_t in_old = *in_pos;
+		lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
+				LZMA_STREAM_HEADER_SIZE);
+		coder->progress_in += *in_pos - in_old;
+
+		// Return if we didn't get the whole Stream Footer yet.
+		if (coder->pos < LZMA_STREAM_HEADER_SIZE)
+			return LZMA_OK;
+
+		coder->pos = 0;
+
+		// Decode the Stream Footer. The decoder gives
+		// LZMA_FORMAT_ERROR if the magic bytes don't match,
+		// so convert that return code to LZMA_DATA_ERROR.
+		lzma_stream_flags footer_flags;
+		const lzma_ret ret = lzma_stream_footer_decode(
+				&footer_flags, coder->buffer);
+		if (ret != LZMA_OK)
+			return ret == LZMA_FORMAT_ERROR
+					? LZMA_DATA_ERROR : ret;
+
+		// Check that Index Size stored in the Stream Footer matches
+		// the real size of the Index field.
+		if (lzma_index_hash_size(coder->index_hash)
+				!= footer_flags.backward_size)
+			return LZMA_DATA_ERROR;
+
+		// Compare that the Stream Flags fields are identical in
+		// both Stream Header and Stream Footer.
+		return_if_error(lzma_stream_flags_compare(
+				&coder->stream_flags, &footer_flags));
+
+		if (!coder->concatenated)
+			return LZMA_STREAM_END;
+
+		coder->sequence = SEQ_STREAM_PADDING;
+	}
+
+	// Fall through
+
+	case SEQ_STREAM_PADDING:
+		assert(coder->concatenated);
+
+		// Skip over possible Stream Padding.
+		while (true) {
+			if (*in_pos >= in_size) {
+				// Unless LZMA_FINISH was used, we cannot
+				// know if there's more input coming later.
+				if (action != LZMA_FINISH)
+					return LZMA_OK;
+
+				// Stream Padding must be a multiple of
+				// four bytes.
+				return coder->pos == 0
+						? LZMA_STREAM_END
+						: LZMA_DATA_ERROR;
+			}
+
+			// If the byte is not zero, it probably indicates
+			// beginning of a new Stream (or the file is corrupt).
+			if (in[*in_pos] != 0x00)
+				break;
+
+			++*in_pos;
+			++coder->progress_in;
+			coder->pos = (coder->pos + 1) & 3;
+		}
+
+		// Stream Padding must be a multiple of four bytes (empty
+		// Stream Padding is OK).
+		if (coder->pos != 0) {
+			++*in_pos;
+			++coder->progress_in;
+			return LZMA_DATA_ERROR;
+		}
+
+		// Prepare to decode the next Stream.
+		return_if_error(stream_decoder_reset(coder, allocator));
+		break;
+
+	case SEQ_ERROR:
+		if (!coder->fail_fast) {
+			// Let the application get all data before the point
+			// where the error was detected. This matches the
+			// behavior of single-threaded use.
+			//
+			// FIXME? Some errors (LZMA_MEM_ERROR) don't get here,
+			// they are returned immediately. Thus in rare cases
+			// the output will be less than in the single-threaded
+			// mode. Maybe this doesn't matter much in practice.
+			return_if_error(read_output_and_wait(coder, allocator,
+					out, out_pos, out_size,
+					NULL, true, &wait_abs, &has_blocked));
+
+			// We get here only if the error happened in the main
+			// thread, for example, unsupported Block Header.
+			if (!lzma_outq_is_empty(&coder->outq))
+				return LZMA_OK;
+		}
+
+		// We only get here if no errors were detected by the worker
+		// threads. Errors from worker threads would have already been
+		// returned by the call to read_output_and_wait() above.
+		return coder->pending_error;
+
+	default:
+		assert(0);
+		return LZMA_PROG_ERROR;
+	}
+
+	// Never reached
+}
+
+
+static void
+stream_decoder_mt_end(void *coder_ptr, const lzma_allocator *allocator)
+{
+	struct lzma_stream_coder *coder = coder_ptr;
+
+	threads_end(coder, allocator);
+	lzma_outq_end(&coder->outq, allocator);
+
+	lzma_next_end(&coder->block_decoder, allocator);
+	lzma_filters_free(coder->filters, allocator);
+	lzma_index_hash_end(coder->index_hash, allocator);
+
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+static lzma_check
+stream_decoder_mt_get_check(const void *coder_ptr)
+{
+	const struct lzma_stream_coder *coder = coder_ptr;
+	return coder->stream_flags.check;
+}
+
+
+static lzma_ret
+stream_decoder_mt_memconfig(void *coder_ptr, uint64_t *memusage,
+		uint64_t *old_memlimit, uint64_t new_memlimit)
+{
+	// NOTE: This function gets/sets memlimit_stop. For now,
+	// memlimit_threading cannot be modified after initialization.
+	//
+	// *memusage will include cached memory too. Excluding cached memory
+	// would be misleading and it wouldn't help the applications to
+	// know how much memory is actually needed to decompress the file
+	// because the higher the number of threads and the memlimits are
+	// the more memory the decoder may use.
+	//
+	// Setting a new limit includes the cached memory too and too low
+	// limits will be rejected. Alternative could be to free the cached
+	// memory immediately if that helps to bring the limit down but
+	// the current way is the simplest. It's unlikely that limit needs
+	// to be lowered in the middle of a file anyway; the typical reason
+	// to want a new limit is to increase after LZMA_MEMLIMIT_ERROR
+	// and even such use isn't common.
+	struct lzma_stream_coder *coder = coder_ptr;
+
+	mythread_sync(coder->mutex) {
+		*memusage = coder->mem_direct_mode
+				+ coder->mem_in_use
+				+ coder->mem_cached
+				+ coder->outq.mem_allocated;
+	}
+
+	// If no filter chains are allocated, *memusage may be zero.
+	// Always return at least LZMA_MEMUSAGE_BASE.
+	if (*memusage < LZMA_MEMUSAGE_BASE)
+		*memusage = LZMA_MEMUSAGE_BASE;
+
+	*old_memlimit = coder->memlimit_stop;
+
+	if (new_memlimit != 0) {
+		if (new_memlimit < *memusage)
+			return LZMA_MEMLIMIT_ERROR;
+
+		coder->memlimit_stop = new_memlimit;
+	}
+
+	return LZMA_OK;
+}
+
+
+static void
+stream_decoder_mt_get_progress(void *coder_ptr,
+		uint64_t *progress_in, uint64_t *progress_out)
+{
+	struct lzma_stream_coder *coder = coder_ptr;
+
+	// Lock coder->mutex to prevent finishing threads from moving their
+	// progress info from the worker_thread structure to lzma_stream_coder.
+	mythread_sync(coder->mutex) {
+		*progress_in = coder->progress_in;
+		*progress_out = coder->progress_out;
+
+		for (size_t i = 0; i < coder->threads_initialized; ++i) {
+			mythread_sync(coder->threads[i].mutex) {
+				*progress_in += coder->threads[i].progress_in;
+				*progress_out += coder->threads[i]
+						.progress_out;
+			}
+		}
+	}
+
+	return;
+}
+
+
+static lzma_ret
+stream_decoder_mt_init(lzma_next_coder *next, const lzma_allocator *allocator,
+		       const lzma_mt *options)
+{
+	struct lzma_stream_coder *coder;
+
+	if (options->threads == 0 || options->threads > LZMA_THREADS_MAX)
+		return LZMA_OPTIONS_ERROR;
+
+	if (options->flags & ~LZMA_SUPPORTED_FLAGS)
+		return LZMA_OPTIONS_ERROR;
+
+	lzma_next_coder_init(&stream_decoder_mt_init, next, allocator);
+
+	coder = next->coder;
+	if (!coder) {
+		coder = lzma_alloc(sizeof(struct lzma_stream_coder), allocator);
+		if (coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->coder = coder;
+
+		if (mythread_mutex_init(&coder->mutex)) {
+			lzma_free(coder, allocator);
+			return LZMA_MEM_ERROR;
+		}
+
+		if (mythread_cond_init(&coder->cond)) {
+			mythread_mutex_destroy(&coder->mutex);
+			lzma_free(coder, allocator);
+			return LZMA_MEM_ERROR;
+		}
+
+		next->code = &stream_decode_mt;
+		next->end = &stream_decoder_mt_end;
+		next->get_check = &stream_decoder_mt_get_check;
+		next->memconfig = &stream_decoder_mt_memconfig;
+		next->get_progress = &stream_decoder_mt_get_progress;
+
+		coder->filters[0].id = LZMA_VLI_UNKNOWN;
+		memzero(&coder->outq, sizeof(coder->outq));
+
+		coder->block_decoder = LZMA_NEXT_CODER_INIT;
+		coder->mem_direct_mode = 0;
+
+		coder->index_hash = NULL;
+		coder->threads = NULL;
+		coder->threads_free = NULL;
+		coder->threads_initialized = 0;
+	}
+
+	// Cleanup old filter chain if one remains after unfinished decoding
+	// of a previous Stream.
+	lzma_filters_free(coder->filters, allocator);
+
+	// By allocating threads from scratch we can start memory-usage
+	// accounting from scratch, too. Changes in filter and block sizes may
+	// affect number of threads.
+	//
+	// FIXME? Reusing should be easy but unlike the single-threaded
+	// decoder, with some types of input file combinations reusing
+	// could leave quite a lot of memory allocated but unused (first
+	// file could allocate a lot, the next files could use fewer
+	// threads and some of the allocations from the first file would not
+	// get freed unless memlimit_threading forces us to clear caches).
+	//
+	// NOTE: The direct mode decoder isn't freed here if one exists.
+	// It will be reused or freed as needed in the main loop.
+	threads_end(coder, allocator);
+
+	// All memusage counters start at 0 (including mem_direct_mode).
+	// The little extra that is needed for the structs in this file
+	// get accounted well enough by the filter chain memory usage
+	// which adds LZMA_MEMUSAGE_BASE for each chain. However,
+	// stream_decoder_mt_memconfig() has to handle this specially so that
+	// it will never return less than LZMA_MEMUSAGE_BASE as memory usage.
+	coder->mem_in_use = 0;
+	coder->mem_cached = 0;
+	coder->mem_next_block = 0;
+
+	coder->progress_in = 0;
+	coder->progress_out = 0;
+
+	coder->sequence = SEQ_STREAM_HEADER;
+	coder->thread_error = LZMA_OK;
+	coder->pending_error = LZMA_OK;
+	coder->thr = NULL;
+
+	coder->timeout = options->timeout;
+
+	coder->memlimit_threading = my_max(1, options->memlimit_threading);
+	coder->memlimit_stop = my_max(1, options->memlimit_stop);
+	if (coder->memlimit_threading > coder->memlimit_stop)
+		coder->memlimit_threading = coder->memlimit_stop;
+
+	coder->tell_no_check = (options->flags & LZMA_TELL_NO_CHECK) != 0;
+	coder->tell_unsupported_check
+			= (options->flags & LZMA_TELL_UNSUPPORTED_CHECK) != 0;
+	coder->tell_any_check = (options->flags & LZMA_TELL_ANY_CHECK) != 0;
+	coder->ignore_check = (options->flags & LZMA_IGNORE_CHECK) != 0;
+	coder->concatenated = (options->flags & LZMA_CONCATENATED) != 0;
+	coder->fail_fast = (options->flags & LZMA_FAIL_FAST) != 0;
+
+	coder->first_stream = true;
+	coder->out_was_filled = false;
+	coder->pos = 0;
+
+	coder->threads_max = options->threads;
+
+	return_if_error(lzma_outq_init(&coder->outq, allocator,
+				       coder->threads_max));
+
+	return stream_decoder_reset(coder, allocator);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_decoder_mt(lzma_stream *strm, const lzma_mt *options)
+{
+	lzma_next_strm_init(stream_decoder_mt_init, strm, options);
+
+	strm->internal->supported_actions[LZMA_RUN] = true;
+	strm->internal->supported_actions[LZMA_FINISH] = true;
+
+	return LZMA_OK;
+}

+ 30 - 16
Utilities/cmliblzma/liblzma/common/stream_encoder.c

@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: 0BSD
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 //
 //
 /// \file       stream_encoder.c
 /// \file       stream_encoder.c
@@ -5,9 +7,6 @@
 //
 //
 //  Author:     Lasse Collin
 //  Author:     Lasse Collin
 //
 //
-//  This file has been put into the public domain.
-//  You can do whatever you want with this file.
-//
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "block_encoder.h"
 #include "block_encoder.h"
@@ -219,8 +218,7 @@ stream_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
 	lzma_next_end(&coder->index_encoder, allocator);
 	lzma_next_end(&coder->index_encoder, allocator);
 	lzma_index_end(coder->index, allocator);
 	lzma_index_end(coder->index, allocator);
 
 
-	for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
-		lzma_free(coder->filters[i].options, allocator);
+	lzma_filters_free(coder->filters, allocator);
 
 
 	lzma_free(coder, allocator);
 	lzma_free(coder, allocator);
 	return;
 	return;
@@ -233,6 +231,13 @@ stream_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
 		const lzma_filter *reversed_filters)
 		const lzma_filter *reversed_filters)
 {
 {
 	lzma_stream_coder *coder = coder_ptr;
 	lzma_stream_coder *coder = coder_ptr;
+	lzma_ret ret;
+
+	// Make a copy to a temporary buffer first. This way it is easier
+	// to keep the encoder state unchanged if an error occurs with
+	// lzma_filters_copy().
+	lzma_filter temp[LZMA_FILTERS_MAX + 1];
+	return_if_error(lzma_filters_copy(filters, temp, allocator));
 
 
 	if (coder->sequence <= SEQ_BLOCK_INIT) {
 	if (coder->sequence <= SEQ_BLOCK_INIT) {
 		// There is no incomplete Block waiting to be finished,
 		// There is no incomplete Block waiting to be finished,
@@ -240,31 +245,40 @@ stream_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
 		// trying to initialize the Block encoder with the new
 		// trying to initialize the Block encoder with the new
 		// chain. This way we detect if the chain is valid.
 		// chain. This way we detect if the chain is valid.
 		coder->block_encoder_is_initialized = false;
 		coder->block_encoder_is_initialized = false;
-		coder->block_options.filters = (lzma_filter *)(filters);
-		const lzma_ret ret = block_encoder_init(coder, allocator);
+		coder->block_options.filters = temp;
+		ret = block_encoder_init(coder, allocator);
 		coder->block_options.filters = coder->filters;
 		coder->block_options.filters = coder->filters;
 		if (ret != LZMA_OK)
 		if (ret != LZMA_OK)
-			return ret;
+			goto error;
 
 
 		coder->block_encoder_is_initialized = true;
 		coder->block_encoder_is_initialized = true;
 
 
 	} else if (coder->sequence <= SEQ_BLOCK_ENCODE) {
 	} else if (coder->sequence <= SEQ_BLOCK_ENCODE) {
 		// We are in the middle of a Block. Try to update only
 		// We are in the middle of a Block. Try to update only
 		// the filter-specific options.
 		// the filter-specific options.
-		return_if_error(coder->block_encoder.update(
+		ret = coder->block_encoder.update(
 				coder->block_encoder.coder, allocator,
 				coder->block_encoder.coder, allocator,
-				filters, reversed_filters));
+				filters, reversed_filters);
+		if (ret != LZMA_OK)
+			goto error;
 	} else {
 	} else {
 		// Trying to update the filter chain when we are already
 		// Trying to update the filter chain when we are already
 		// encoding Index or Stream Footer.
 		// encoding Index or Stream Footer.
-		return LZMA_PROG_ERROR;
+		ret = LZMA_PROG_ERROR;
+		goto error;
 	}
 	}
 
 
-	// Free the copy of the old chain and make a copy of the new chain.
-	for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
-		lzma_free(coder->filters[i].options, allocator);
+	// Free the options of the old chain.
+	lzma_filters_free(coder->filters, allocator);
+
+	// Copy the new filter chain in place.
+	memcpy(coder->filters, temp, sizeof(temp));
+
+	return LZMA_OK;
 
 
-	return lzma_filters_copy(filters, coder->filters, allocator);
+error:
+	lzma_filters_free(temp, allocator);
+	return ret;
 }
 }
 
 
 
 
@@ -319,7 +333,7 @@ stream_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
 
 
 	// Initialize the Block encoder. This way we detect unsupported
 	// Initialize the Block encoder. This way we detect unsupported
 	// filter chains when initializing the Stream encoder instead of
 	// filter chains when initializing the Stream encoder instead of
-	// giving an error after Stream Header has already written out.
+	// giving an error after Stream Header has already been written out.
 	return stream_encoder_update(coder, allocator, filters, NULL);
 	return stream_encoder_update(coder, allocator, filters, NULL);
 }
 }
 
 

部分文件因文件數量過多而無法顯示