packages feed

xz-clib 5.6.4 → 5.8.0

raw patch · 57 files changed

+2008/−681 lines, 57 files

Files

Changelog.md view
@@ -1,3 +1,7 @@+## 5.8.0++* Update to 5.8.0 upstream sources+ ## 5.6.3  * Update to 5.6.3 upstream sources
+ cbits/common/my_landlock.h view
@@ -0,0 +1,141 @@+// SPDX-License-Identifier: 0BSD++///////////////////////////////////////////////////////////////////////////////+//+/// \file       my_landlock.h+/// \brief      Linux Landlock sandbox helper functions+//+//  Author:     Lasse Collin+//+///////////////////////////////////////////////////////////////////////////////++#ifndef MY_LANDLOCK_H+#define MY_LANDLOCK_H++#include "sysdefs.h"++#include <linux/landlock.h>+#include <sys/syscall.h>+#include <sys/prctl.h>+++/// \brief      Initialize Landlock ruleset attributes to forbid everything+///+/// The supported Landlock ABI is checked at runtime and only the supported+/// actions are forbidden in the attributes. Thus, if the attributes are+/// used with my_landlock_create_ruleset(), it shouldn't fail.+///+/// \return     On success, the Landlock ABI version is returned (a positive+///             integer). If Landlock isn't supported, -1 is returned.+static int+my_landlock_ruleset_attr_forbid_all(struct landlock_ruleset_attr *attr)+{+	memzero(attr, sizeof(*attr));++	const int abi_version = syscall(SYS_landlock_create_ruleset,+			(void *)NULL, 0, LANDLOCK_CREATE_RULESET_VERSION);+	if (abi_version <= 0)+		return -1;++	// ABI 1 except the few at the end+	attr->handled_access_fs+			= LANDLOCK_ACCESS_FS_EXECUTE+			| LANDLOCK_ACCESS_FS_WRITE_FILE+			| LANDLOCK_ACCESS_FS_READ_FILE+			| LANDLOCK_ACCESS_FS_READ_DIR+			| LANDLOCK_ACCESS_FS_REMOVE_DIR+			| LANDLOCK_ACCESS_FS_REMOVE_FILE+			| LANDLOCK_ACCESS_FS_MAKE_CHAR+			| LANDLOCK_ACCESS_FS_MAKE_DIR+			| LANDLOCK_ACCESS_FS_MAKE_REG+			| LANDLOCK_ACCESS_FS_MAKE_SOCK+			| LANDLOCK_ACCESS_FS_MAKE_FIFO+			| LANDLOCK_ACCESS_FS_MAKE_BLOCK+			| LANDLOCK_ACCESS_FS_MAKE_SYM+#ifdef LANDLOCK_ACCESS_FS_REFER+			| LANDLOCK_ACCESS_FS_REFER // ABI 2+#endif+#ifdef LANDLOCK_ACCESS_FS_TRUNCATE+			| LANDLOCK_ACCESS_FS_TRUNCATE // ABI 3+#endif+#ifdef LANDLOCK_ACCESS_FS_IOCTL_DEV+			| LANDLOCK_ACCESS_FS_IOCTL_DEV // ABI 5+#endif+			;++#ifdef LANDLOCK_ACCESS_NET_BIND_TCP+	// ABI 4+	attr->handled_access_net+			= LANDLOCK_ACCESS_NET_BIND_TCP+			| LANDLOCK_ACCESS_NET_CONNECT_TCP;+#endif++#ifdef LANDLOCK_SCOPE_SIGNAL+	 // ABI 6+	 attr->scoped+			 = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET+			 | LANDLOCK_SCOPE_SIGNAL;+#endif++	// Disable flags that require a new ABI version.+	switch (abi_version) {+	case 1:+#ifdef LANDLOCK_ACCESS_FS_REFER+		attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_REFER;+#endif+		FALLTHROUGH;++	case 2:+#ifdef LANDLOCK_ACCESS_FS_TRUNCATE+		attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_TRUNCATE;+#endif+		FALLTHROUGH;++	case 3:+#ifdef LANDLOCK_ACCESS_NET_BIND_TCP+		attr->handled_access_net = 0;+#endif+		FALLTHROUGH;++	case 4:+#ifdef LANDLOCK_ACCESS_FS_IOCTL_DEV+		attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_IOCTL_DEV;+#endif+		FALLTHROUGH;++	case 5:+#ifdef LANDLOCK_SCOPE_SIGNAL+		attr->scoped = 0;+#endif+		FALLTHROUGH;++	default:+		// We only know about the features of the ABIs 1-6.+		break;+	}++	return abi_version;+}+++/// \brief      Wrapper for the landlock_create_ruleset(2) syscall+///+/// Syscall wrappers provide argument type checking.+///+/// \note       Remember to call `prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)` too!+static inline int+my_landlock_create_ruleset(const struct landlock_ruleset_attr *attr,+		size_t size, uint32_t flags)+{+	return syscall(SYS_landlock_create_ruleset, attr, size, flags);+}+++/// \brief      Wrapper for the landlock_restrict_self(2) syscall+static inline int+my_landlock_restrict_self(int ruleset_fd, uint32_t flags)+{+	return syscall(SYS_landlock_restrict_self, ruleset_fd, flags);+}++#endif
cbits/common/sysdefs.h view
@@ -168,17 +168,24 @@ #	define __bool_true_false_are_defined 1 #endif +// We may need alignas from C11/C17/C23.+#if __STDC_VERSION__ >= 202311+	// alignas is a keyword in C23. Do nothing.+#elif __STDC_VERSION__ >= 201112+#	include <stdalign.h>+#elif defined(__GNUC__) || defined(__clang__)+#	define alignas(n) __attribute__((__aligned__(n)))+#else+#	define alignas(n)+#endif+ #include <string.h> -// Visual Studio 2013 update 2 supports only __inline, not inline.-// MSVC v19.0 / VS 2015 and newer support both.+// MSVC v19.00 (VS 2015 version 14.0) and later should work. // // 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-#	endif #	if _MSC_VER < 1927 && !defined(restrict) #		define restrict __restrict #	endif@@ -206,6 +213,15 @@ #	define lzma_attr_alloc_size(x) __attribute__((__alloc_size__(x))) #else #	define lzma_attr_alloc_size(x)+#endif++#if __STDC_VERSION__ >= 202311+#	define FALLTHROUGH [[__fallthrough__]]+#elif (defined(__GNUC__) && __GNUC__ >= 7) \+		|| (defined(__clang_major__) && __clang_major__ >= 10)+#	define FALLTHROUGH __attribute__((__fallthrough__))+#else+#	define FALLTHROUGH ((void)0) #endif  #endif
cbits/common/tuklib_common.h view
@@ -56,6 +56,13 @@ #	define TUKLIB_GNUC_REQ(major, minor) 0 #endif +#if defined(__GNUC__) || defined(__clang__)+#	define tuklib_attr_format_printf(fmt_index, args_index) \+		__attribute__((__format__(__printf__, fmt_index, args_index)))+#else+#	define tuklib_attr_format_printf(fmt_index, args_index)+#endif+ // 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]] ]].@@ -68,9 +75,7 @@ //     __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+#if   defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311 #	define tuklib_attr_noreturn [[noreturn]] #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112 #	define tuklib_attr_noreturn _Noreturn
cbits/common/tuklib_gettext.h view
@@ -40,4 +40,15 @@ #endif #define N_(msgid) msgid +// Optional: Strings that are word wrapped using tuklib_mbstr_wrap may be+// marked with W_("foo) in the source code. xgettext can then add a comment+// to all such strings to inform translators. The following option needs to+// be added to XGETTEXT_OPTIONS in po/Makevars or in an equivalent place:+//+// '--keyword=W_:1,"This is word wrapped at spaces. The Unicode character U+00A0 works as a non-breaking space. Tab (\t) is interpret as a zero-width space (the tab itself is not displayed); U+200B is NOT supported. Manual word wrapping with \n is supported but requires care."'+//+// NOTE: The double-quotes in the --keyword argument above must be passed to+// xgettext as is, thus one needs the single-quotes in Makevars.+#define W_(msgid) _(msgid)+ #endif
cbits/common/tuklib_mbstr.h view
@@ -27,10 +27,7 @@ /// /// This is somewhat similar to wcswidth() but works on multibyte strings. ///-/// \param      str         String whose width is to be calculated. If the-///                         current locale uses a multibyte character set-///                         that has shift states, the string must begin-///                         and end in the initial shift state.+/// \param      str         String whose width is to be calculated. /// \param      bytes       If this is not NULL, *bytes is set to the ///                         value returned by strlen(str) (even if an ///                         error occurs when calculating the width).@@ -38,8 +35,24 @@ /// \return     On success, the number of columns needed to display the ///             string e.g. in a terminal emulator is returned. On error, ///             (size_t)-1 is returned. Possible errors include invalid,-///             partial, or non-printable multibyte character in str, or-///             that str doesn't end in the initial shift state.+///             partial, or non-printable multibyte character in str.++#define tuklib_mbstr_width_mem TUKLIB_SYMBOL(tuklib_mbstr_width_mem)+extern size_t tuklib_mbstr_width_mem(const char *str, size_t len);+///<+/// \brief      Get the number of columns needed for the multibyte buffer+///+/// This is like tuklib_mbstr_width() except that this takes the buffer+/// length in bytes as the second argument. This allows using the function+/// for buffers that aren't terminated with '\0'.+///+/// \param      str         String whose width is to be calculated.+/// \param      len         Number of bytes to read from str.+///+/// \return     On success, the number of columns needed to display the+///             string e.g. in a terminal emulator is returned. On error,+///             (size_t)-1 is returned. Possible errors include invalid,+///             partial, or non-printable multibyte character in str.  #define tuklib_mbstr_fw TUKLIB_SYMBOL(tuklib_mbstr_fw) extern int tuklib_mbstr_fw(const char *str, int columns_min);
+ cbits/common/tuklib_mbstr_nonprint.c view
@@ -0,0 +1,162 @@+// SPDX-License-Identifier: 0BSD++///////////////////////////////////////////////////////////////////////////////+//+/// \file       tuklib_mbstr_nonprint.c+/// \brief      Find and replace non-printable characters with question marks+//+//  Author:     Lasse Collin+//+///////////////////////////////////////////////////////////////////////////////++#include "tuklib_mbstr_nonprint.h"+#include <stdlib.h>+#include <string.h>+#include <errno.h>++#ifdef HAVE_MBRTOWC+#	include <wchar.h>+#	include <wctype.h>+#else+#	include <ctype.h>+#endif+++static bool+is_next_printable(const char *str, size_t len, size_t *next_len)+{+#ifdef HAVE_MBRTOWC+	// This assumes that character sets with locking shift states aren't+	// used, and thus mbsinit() is never needed.+	mbstate_t ps;+	memset(&ps, 0, sizeof(ps));++	wchar_t wc;+	*next_len = mbrtowc(&wc, str, len, &ps);++	if (*next_len == (size_t)-2) {+		// Incomplete multibyte sequence: Treat the whole sequence+		// as a single non-printable multibyte character that ends+		// the string.+		*next_len = len;+		return false;+	}++	// Check more broadly than just ret == (size_t)-1 to be safe+	// in case mbrtowc() returns something weird. This check+	// covers (size_t)-1 (that is, SIZE_MAX) too because len is from+	// strlen() and the terminating '\0' isn't part of the length.+	if (*next_len < 1 || *next_len > len) {+		// Invalid multibyte sequence: Treat the first byte as+		// a non-printable single-byte character. Decoding will+		// be restarted from the next byte on the next call to+		// this function.+		*next_len = 1;+		return false;+	}++#	if defined(_WIN32) && !defined(__CYGWIN__)+	// On Windows, wchar_t stores UTF-16 code units, thus characters+	// outside the Basic Multilingual Plane (BMP) don't fit into+	// a single wchar_t. In an UTF-8 locale, UCRT's mbrtowc() returns+	// successfully when the input is a non-BMP character but the+	// output is the replacement character U+FFFD.+	//+	// iswprint() returns 0 for U+FFFD on Windows for some reason. Treat+	// U+FFFD as printable and thus also all non-BMP chars as printable.+	if (wc == 0xFFFD)+		return true;+#	endif++	return iswprint((wint_t)wc) != 0;+#else+	(void)len;+	*next_len = 1;+	return isprint((unsigned char)str[0]) != 0;+#endif+}+++static bool+has_nonprint(const char *str, size_t len)+{+	for (size_t i = 0; i < len; ) {+		size_t next_len;+		if (!is_next_printable(str + i, len - i, &next_len))+			return true;++		i += next_len;+	}++	return false;+}+++extern bool+tuklib_has_nonprint(const char *str)+{+	const int saved_errno = errno;+	const bool ret = has_nonprint(str, strlen(str));+	errno = saved_errno;+	return ret;+}+++extern const char *+tuklib_mask_nonprint_r(const char *str, char **mem)+{+	const int saved_errno = errno;++	// Free the old string, if any.+	free(*mem);+	*mem = NULL;++	// If the whole input string contains only printable characters,+	// return the input string.+	const size_t len = strlen(str);+	if (!has_nonprint(str, len)) {+		errno = saved_errno;+		return str;+	}++	// Allocate memory for the masked string. Since we use the single-byte+	// character '?' to mask non-printable characters, it's possible that+	// a few bytes less memory would be needed in reality if multibyte+	// characters are masked.+	//+	// If allocation fails, return "???" because it should be safer than+	// returning the unmasked string.+	*mem = malloc(len + 1);+	if (*mem == NULL) {+		errno = saved_errno;+		return "???";+	}++	// Replace all non-printable characters with '?'.+	char *dest = *mem;++	for (size_t i = 0; i < len; ) {+		size_t next_len;+		if (is_next_printable(str + i, len - i, &next_len)) {+			memcpy(dest, str + i, next_len);+			dest += next_len;+		} else {+			*dest++ = '?';+		}++		i += next_len;+	}++	*dest = '\0';++	errno = saved_errno;+	return *mem;+}+++extern const char *+tuklib_mask_nonprint(const char *str)+{+	static char *mem = NULL;+	return tuklib_mask_nonprint_r(str, &mem);+}
+ cbits/common/tuklib_mbstr_nonprint.h view
@@ -0,0 +1,71 @@+// SPDX-License-Identifier: 0BSD++///////////////////////////////////////////////////////////////////////////////+//+/// \file       tuklib_mbstr_nonprint.h+/// \brief      Find and replace non-printable characters with question marks+///+/// If mbrtowc(3) is available, it and iswprint(3) is used to check if all+/// characters are printable. Otherwise single-byte character set is assumed+/// and isprint(3) is used.+//+//  Author:     Lasse Collin+//+///////////////////////////////////////////////////////////////////////////////++#ifndef TUKLIB_MBSTR_NONPRINT_H+#define TUKLIB_MBSTR_NONPRINT_H++#include "tuklib_common.h"+TUKLIB_DECLS_BEGIN++#define tuklib_has_nonprint TUKLIB_SYMBOL(tuklib_has_nonprint)+extern bool tuklib_has_nonprint(const char *str);+///<+/// \brief      Check if a string contains any non-printable characters+///+/// \return     false if str contains only valid multibyte characters and+///             iswprint(3) returns non-zero for all of them; true otherwise.+///             The value of errno is preserved.+///+/// \note       In case mbrtowc(3) isn't available, single-byte character set+///             is assumed and isprint(3) is used instead of iswprint(3).++#define tuklib_mask_nonprint_r TUKLIB_SYMBOL(tuklib_mask_nonprint_r)+extern const char *tuklib_mask_nonprint_r(const char *str, char **mem);+///<+/// \brief      Replace non-printable characters with question marks+///+/// \param      str     Untrusted string, for example, a filename+/// \param      mem     This function always calls free(*mem) to free the old+///                     allocation and then sets *mem = NULL. Before the first+///                     call, *mem should be initialized to NULL. If this+///                     function needs to allocate memory for a modified+///                     string, a pointer to the allocated memory will be+///                     stored to *mem. Otherwise *mem will remain NULL.+///+/// \return     If tuklib_has_nonprint(str) returns false, this function+///             returns str. Otherwise memory is allocated to hold a modified+///             string and a pointer to that is returned. The pointer to the+///             allocated memory is also stored to *mem. A modified string+///             has the problematic characters replaced by '?'. If memory+///             allocation fails, "???" is returned and *mem is NULL.+///             The value of errno is preserved.++#define tuklib_mask_nonprint TUKLIB_SYMBOL(tuklib_mask_nonprint)+extern const char *tuklib_mask_nonprint(const char *str);+///<+/// \brief      Replace non-printable characters with question marks+///+/// This is a convenience function for single-threaded use. This calls+/// tuklib_mask_nonprint_r() using an internal static variable to hold+/// the possible allocation.+///+/// \param      str     Untrusted string, for example, a filename+///+/// \return     See tuklib_mask_nonprint_r().+///+/// \note       This function is not thread safe!++TUKLIB_DECLS_END+#endif
cbits/common/tuklib_mbstr_width.c view
@@ -24,9 +24,17 @@ 	if (bytes != NULL) 		*bytes = len; +	return tuklib_mbstr_width_mem(str, len);+}+++extern size_t+tuklib_mbstr_width_mem(const char *str, size_t len)+{ #ifndef HAVE_MBRTOWC 	// In single-byte mode, the width of the string is the same 	// as its length.+	(void)str; 	return len;  #else@@ -41,7 +49,7 @@ 	while (i < len) { 		wchar_t wc; 		const size_t ret = mbrtowc(&wc, str + i, len - i, &state);-		if (ret < 1 || ret > len)+		if (ret < 1 || ret > len - i) 			return (size_t)-1;  		i += ret;@@ -62,9 +70,14 @@ #endif 	} -	// Require that the string ends in the initial shift state.-	// This way the caller can be combine the string with other-	// strings without needing to worry about the shift states.+	// It's good to check that the string ended in the initial state.+	// However, in practice this is redundant:+	//+	//   - No one will use this code with character sets that have+	//     locking shift states.+	//+	//   - We already checked that mbrtowc() didn't return (size_t)-2+	//     which would indicate a partial multibyte character. 	if (!mbsinit(&state)) 		return (size_t)-1; 
+ cbits/common/tuklib_mbstr_wrap.c view
@@ -0,0 +1,294 @@+// SPDX-License-Identifier: 0BSD++///////////////////////////////////////////////////////////////////////////////+//+/// \file       tuklib_mbstr_wrap.c+/// \brief      Word wraps a string and prints it to a FILE stream+///+/// This depends on tuklib_mbstr_width.c.+//+//  Author:     Lasse Collin+//+///////////////////////////////////////////////////////////////////////////////++#include "tuklib_mbstr.h"+#include "tuklib_mbstr_wrap.h"+#include <stdarg.h>+#include <stdlib.h>+#include <stdio.h>+#include <string.h>+++extern int+tuklib_wraps(FILE *outfile, const struct tuklib_wrap_opt *opt, const char *str)+{+	// left_cont may be less than left_margin. In that case, if the first+	// word is extremely long, it will stay on the first line even if+	// the line then gets overlong.+	//+	// On the other hand, left2_cont < left2_margin isn't allowed because+	// it could result in inconsistent behavior when a very long word+	// comes right after a \v.+	//+	// It is fine to have left2_margin < left_margin although it would be+	// an odd use case.+	if (!(opt->left_margin < opt->right_margin+			&& opt->left_cont < opt->right_margin+			&& opt->left2_margin <= opt->left2_cont+			&& opt->left2_cont < opt->right_margin))+		return TUKLIB_WRAP_ERR_OPT;++	// This is set to TUKLIB_WRAP_WARN_OVERLONG if one or more+	// output lines extend past opt->right_margin columns.+	int warn_overlong = 0;++	// Indentation of the first output line after \n or \r.+	// \v sets this to opt->left2_margin.+	// \r resets this back to the original value.+	size_t first_indent = opt->left_margin;++	// Indentation of the output lines that occur due to word wrapping.+	// \v sets this to opt->left2_cont and \r back to the original value.+	size_t cont_indent = opt->left_cont;++	// If word wrapping occurs, the newline isn't printed unless more+	// text would be put on the continuation line. This is also used+	// when \v needs to start on a new line.+	bool pending_newline = false;++	// Spaces are printed only when there is something else to put+	// after the spaces on the line. This avoids unwanted empty lines+	// in the output and makes it possible to ignore possible spaces+	// before a \v character.+	size_t pending_spaces = first_indent;++	// Current output column. When cur_col == pending_spaces, nothing+	// has been actually printed to the current output line.+	size_t cur_col = pending_spaces;++	while (true) {+		// Number of bytes until the *next* line-break opportunity.+		size_t len = 0;++		// Number of columns until the *next* line-break opportunity.+		size_t width = 0;++		// Text between a pair of \b characters is treated as+		// an unbreakable block even if it contains spaces.+		// It must not contain any control characters before+		// the closing \b.+		bool unbreakable = false;++		while (true) {+			// Find the next character that we handle specially.+			// In an unbreakable block, search only for the+			// closing \b; if missing, the unbreakable block+			// extends to the end of the string.+			const size_t n = strcspn(str + len,+					unbreakable ? "\b" : " \t\n\r\v\b");++			// Calculate how many columns the characters need.+			const size_t w = tuklib_mbstr_width_mem(str + len, n);+			if (w == (size_t)-1)+				return TUKLIB_WRAP_ERR_STR;++			width += w;+			len += n;++			// \b isn't a line-break opportunity so it has to+			// be handled here. For simplicity, empty blocks+			// are treated as zero-width characters.+			if (str[len] == '\b') {+				++len;+				unbreakable = !unbreakable;+				continue;+			}++			break;+		}++		// Determine if adding this chunk of text would make the+		// current output line exceed opt->right_margin columns.+		const bool too_long = cur_col + width > opt->right_margin;++		// Wrap the line if needed. However:+		//+		//   - Don't wrap if the current column is less than where+		//     the continuation line would begin. In that case+		//     the chunk wouldn't fit on the next line either so+		//     we just have to produce an overlong line.+		//+		//   - Don't wrap if so far the line only contains spaces.+		//     Wrapping in that case would leave a weird empty line.+		//     NOTE: This "only contains spaces" condition is the+		//     reason why left2_margin > left2_cont isn't allowed.+		if (too_long && cur_col > cont_indent+				&& cur_col > pending_spaces) {+			// There might be trailing spaces or zero-width spaces+			// which need to be ignored to keep the output pretty.+			//+			// Spaces need to be ignored because in some+			// writing styles there are two spaces after+			// a full stop. Example string:+			//+			//     "Foo bar.  Abc def."+			//              ^+			// If the first space after the first full stop+			// triggers word wrapping, both spaces must be+			// ignored. Otherwise the next line would be+			// indented too much.+			//+			// Zero-width spaces are ignored the same way+			// because they are meaningless if an adjacent+			// character is a space.+			while (*str == ' ' || *str == '\t')+				++str;++			// Don't print the newline here; only mark it as+			// pending. This avoids an unwanted empty line if+			// there is a \n or \r or \0 after the spaces have+			// been ignored.+			pending_newline = true;+			pending_spaces = cont_indent;+			cur_col = pending_spaces;++			// Since str may have been incremented due to the+			// ignored spaces, the loop needs to be restarted.+			continue;+		}++		// Print the current chunk of text before the next+		// line-break opportunity. If the chunk was empty,+		// don't print anything so that the pending newline+		// and pending spaces aren't printed on their own.+		if (len > 0) {+			if (pending_newline) {+				pending_newline = false;+				if (putc('\n', outfile) == EOF)+					return TUKLIB_WRAP_ERR_IO;+			}++			while (pending_spaces > 0) {+				if (putc(' ', outfile) == EOF)+					return TUKLIB_WRAP_ERR_IO;++				--pending_spaces;+			}++			for (size_t i = 0; i < len; ++i) {+				// Ignore unbreakable block characters (\b).+				const int c = (unsigned char)str[i];+				if (c != '\b' && putc(c, outfile) == EOF)+					return TUKLIB_WRAP_ERR_IO;+			}++			str += len;+			cur_col += width;++			// Remember if the line got overlong. If no other+			// errors occur, we return warn_overlong. It might+			// help in catching problematic strings.+			if (too_long)+				warn_overlong = TUKLIB_WRAP_WARN_OVERLONG;+		}++		// Handle the special character after the chunk of text.+		switch (*str) {+		case ' ':+			// Regular space.+			++cur_col;+			++pending_spaces;+			break;++		case '\v':+			// Set the alternative indentation settings.+			first_indent = opt->left2_margin;+			cont_indent = opt->left2_cont;++			if (first_indent > cur_col) {+				// Add one or more spaces to reach+				// the column specified in first_indent.+				pending_spaces += first_indent - cur_col;+			} else {+				// There is no room to add even one space+				// before reaching the column first_indent.+				pending_newline = true;+				pending_spaces = first_indent;+			}++			cur_col = first_indent;+			break;++		case '\0': // Implicit newline at the end of the string.+		case '\r': // Newline that also resets the effect of \v.+		case '\n': // Newline without resetting the indentation mode.+			if (putc('\n', outfile) == EOF)+				return TUKLIB_WRAP_ERR_IO;++			if (*str == '\0')+				return warn_overlong;++			if (*str == '\r') {+				first_indent = opt->left_margin;+				cont_indent = opt->left_cont;+			}++			pending_newline = false;+			pending_spaces = first_indent;+			cur_col = first_indent;+			break;+		}++		// Skip the specially-handled character.+		++str;+	}+}+++extern int+tuklib_wrapf(FILE *stream, const struct tuklib_wrap_opt *opt,+		const char *fmt, ...)+{+	va_list ap;+	char *buf;++#ifdef HAVE_VASPRINTF+	va_start(ap, fmt);++#ifdef __clang__+#	pragma GCC diagnostic push+#	pragma GCC diagnostic ignored "-Wformat-nonliteral"+#endif+	const int n = vasprintf(&buf, fmt, ap);+#ifdef __clang__+#	pragma GCC diagnostic pop+#endif++	va_end(ap);+	if (n == -1)+		return TUKLIB_WRAP_ERR_FORMAT;+#else+	// Fixed buffer size is dumb but in practice one shouldn't need+	// huge strings for *formatted* output. This simple method is safe+	// with pre-C99 vsnprintf() implementations too which don't return+	// the required buffer size (they return -1 or buf_size - 1) or+	// which might not null-terminate the buffer in case it's too small.+	const size_t buf_size = 128 * 1024;+	buf = malloc(buf_size);+	if (buf == NULL)+		return TUKLIB_WRAP_ERR_FORMAT;++	va_start(ap, fmt);+	const int n = vsnprintf(buf, buf_size, fmt, ap);+	va_end(ap);++	if (n <= 0 || n >= (int)(buf_size - 1)) {+		free(buf);+		return TUKLIB_WRAP_ERR_FORMAT;+	}+#endif++	const int ret = tuklib_wraps(stream, opt, buf);+	free(buf);+	return ret;+}
+ cbits/common/tuklib_mbstr_wrap.h view
@@ -0,0 +1,204 @@+// SPDX-License-Identifier: 0BSD++///////////////////////////////////////////////////////////////////////////////+//+/// \file       tuklib_mbstr_wrap.h+/// \brief      Word wrapping for multibyte strings+///+/// The word wrapping functions are intended to be usable, for example,+/// for printing --help text in command line tools. While manually-wrapped+/// --help text allows precise formatting, such freedom requires translators+/// to count spaces and determine where line breaks should occur. It's+/// tedious and error prone, and experience has shown that only some+/// translators do it well. Automatic word wrapping is less flexible but+/// results in polished-enough look with less effort from everyone.+/// Right-to-left languages and languages that don't use spaces between+/// words will still need extra effort though.+//+//  Author:     Lasse Collin+//+///////////////////////////////////////////////////////////////////////////////++#ifndef TUKLIB_MBSTR_WRAP_H+#define TUKLIB_MBSTR_WRAP_H++#include "tuklib_common.h"+#include <stdio.h>++TUKLIB_DECLS_BEGIN++/// One or more output lines exceeded right_margin.+/// This only a warning; everything was still printed successfully.+#define TUKLIB_WRAP_WARN_OVERLONG   0x01++/// Error writing to to the output FILE. The error flag in the FILE+/// should have been set as well.+#define TUKLIB_WRAP_ERR_IO          0x02++/// Invalid options in struct tuklib_wrap_opt.+/// Nothing was printed.+#define TUKLIB_WRAP_ERR_OPT         0x04++/// Invalid or unsupported multibyte character in the input string:+/// either mbrtowc() failed or wcwidth() returned a negative value.+#define TUKLIB_WRAP_ERR_STR         0x08++/// Only tuklib_wrapf(): Error in converting the format string.+/// It's either a memory allocation failure or something bad with the+/// format string or arguments.+#define TUKLIB_WRAP_ERR_FORMAT      0x10++/// Options for tuklib_wraps() and tuklib_wrapf()+struct tuklib_wrap_opt {+	/// Indentation of the first output line after `\n` or `\r`.+	/// This can be anything less than right_margin.+	unsigned short left_margin;++	/// Column where word-wrapped continuation lines start.+	/// This can be anything less than right_margin.+	unsigned short left_cont;++	/// Column where the text after `\v` will start, either on the current+	/// line (when there is room to add at least one space) or on a new+	/// empty line.+	unsigned short left2_margin;++	/// Like left_cont but for text after a `\v`. However, this must+	/// be greater than or equal to left2_margin in addition to being+	/// less than right_margin.+	unsigned short left2_cont;++	/// For 80-column terminals, it is recommended to use 79 here for+	/// maximum portability. 80 will work most of the time but it will+	/// result in unwanted empty lines in the rare case where a terminal+	/// moves the cursor to the beginning of the next line immediately+	/// when the last column has been used.+	unsigned short right_margin;+};++#define tuklib_wraps TUKLIB_SYMBOL(tuklib_wraps)+extern int tuklib_wraps(FILE *stream, const struct tuklib_wrap_opt *opt,+		const char *str);+///<+/// \brief      Word wrap a multibyte string and write it to a FILE+///+/// Word wrapping is done only at spaces and at the special control characters+/// described below. Multiple consecutive spaces are handled properly: strings+/// that have two (or more) spaces after a full sentence will look good even+/// when the spaces occur at a word wrapping boundary. Trailing spaces are+/// ignored at the end of a line or at the end of a string.+///+/// The following control characters have been repurposed:+///+///   - `\t` = Zero-width space allows a line break without producing any+///            output by itself. This can be useful after hard hyphens as+///            hyphens aren't otherwise used for line breaking. This can also+///            be useful in languages that don't use spaces between words.+///            (The Unicode character U+200B isn't supported.)+///   - `\b` = Text between a pair of `\b` characters is treated as an+///            unbreakable block (not wrapped even if there are spaces).+///            For example, a non-breaking space can be done like+///            in `"123\b \bMiB"`. Control characters (like `\n` or `\t`)+///            aren't allowed before the closing `\b`. If closing `\b` is+///            missing, the block extends to the end of the string. Empty+///            blocks are treated as zero-width characters. If line breaks+///            are possible around an empty block (like in `"foo \b\b bar"`+///            or `"foo \b"`), it can result in weird output.+///   - `\v` = Change to alternative indentation (left2_margin).+///   - `\r` = Reset back to the initial indentation and add a newline.+///            The next line will be indented by left_margin.+///   - `\n` = Add a newline without resetting the effect of `\v`. The+///            next line will be indented by left_margin or left2_margin+///            (not left_cont or left2_cont).+///+/// Only `\n` should appear in translatable strings. `\t` works too but+/// even that might confuse some translators even if there is a TRANSLATORS+/// comment explaining its meaning.+///+/// To use the other control characters in messages, one should use+/// tuklib_wrapf() with appropriate printf format string to combine+/// translatable strings with non-translatable portions. For example:+///+/// \code{.c}+/// static const struct tuklib_wrap_opt wrap2 = { 2,  2, 22, 22, 79 };+/// int e = 0;+/// ...+/// e |= tuklib_wrapf(stdout, &wrap2,+///                   "-h, --help\v%s\r"+///                   "    --version\v%s",+///                   W_("display this help and exit"),+///                   W_("display version information and exit"));+/// ...+/// if (e != 0) {+///     // Handle warning or error.+///     ...+/// }+/// \endcode+///+/// Control characters other than `\n` and `\t` are unusable in+/// translatable strings:+///+///   - Gettext tools show annoying warnings if C escape sequences other+///     than `\n` or `\t` are seen. (Otherwise they still work perfectly+///     fine though.)+///+///   - While at least Poedit and Lokalize support all escapes, some+///     editors only support `\n` and `\t`.+///+///   - They could confuse some translators, resulting in broken+///     translations.+///+/// Using non-control characters would solve some issues but it wouldn't+/// help with the unfortunate real-world issue that some translators would+/// likely have trouble understanding a new syntax. The Gettext manual+/// specifically warns about this, see the subheading "No unusual markup"+/// in `info (gettext)Preparing Strings`. (While using `\t` for zero-width+/// space is such custom markup, most translators will never need it.)+///+/// Translators can use the Unicode character U+00A0 (or U+202F) if they+/// need a non-breaking space. For example, in French a non-breaking space+/// may be needed before colons and question marks (U+00A0 is common in+/// real-world French PO files).+///+/// Using a non-ASCII char in a string in the C code (like `"123\u00A0MiB"`)+/// can work if one tells xgettext that input encoding is UTF-8, one+/// ensures that the C compiler uses UTF-8 as the input charset, and one+/// is certain that the program is *always* run under an UTF-8 locale.+/// Unfortunately a portable program cannot make this kind of assumptions,+/// which means that there is no pretty way to have a non-breaking space in+/// a translatable string.+///+/// Optional: To tell translators which strings are automatically word+/// wrapped, see the macro `W_` in tuklib_gettext.h.+///+/// \param      stream      Output FILE stream. For decent performance, it+///                         should be in buffered mode because this function+///                         writes the output one byte at a time with fputc().+/// \param      opt         Word wrapping options.+/// \param      str         Null-terminated multibyte string that is in+///                         the encoding used by the current locale.+///+/// \return     Returns 0 on success. If an error or warning occurs, one of+///             TUKLIB_WRAP_* codes is returned. Those codes are powers+///             of two. When warning/error detection can be delayed, the+///             return values can be accumulated from multiple calls using+///             bitwise-or into a single variable which can be checked after+///             all strings have (hopefully) been printed.++#define tuklib_wrapf TUKLIB_SYMBOL(tuklib_wrapf)+tuklib_attr_format_printf(3, 4)+extern int tuklib_wrapf(FILE *stream, const struct tuklib_wrap_opt *opt,+		const char *fmt, ...);+///<+/// \brief      Format and word-wrap a multibyte string and write it to a FILE+///+/// This is like tuklib_wraps() except that this takes a printf+/// format string.+///+/// \note       On platforms that lack vasprintf(), the intermediate+///             result from vsnprintf() must fit into a 128 KiB buffer.+///             TUKLIB_WRAP_ERR_FORMAT is returned if it doesn't but+///             only on platforms that lack vasprintf().++TUKLIB_DECLS_END+#endif
cbits/common/tuklib_physmem.c view
@@ -91,18 +91,11 @@ 		// supports reporting values greater than 4 GiB. To keep the 		// code working also on older Windows versions, use 		// GlobalMemoryStatusEx() conditionally.-		HMODULE kernel32 = GetModuleHandle(TEXT("kernel32.dll"));+		HMODULE kernel32 = GetModuleHandleA("kernel32.dll"); 		if (kernel32 != NULL) { 			typedef BOOL (WINAPI *gmse_type)(LPMEMORYSTATUSEX);-#ifdef CAN_DISABLE_WCAST_FUNCTION_TYPE-#	pragma GCC diagnostic push-#	pragma GCC diagnostic ignored "-Wcast-function-type"-#endif 			gmse_type gmse = (gmse_type)GetProcAddress( 					kernel32, "GlobalMemoryStatusEx");-#ifdef CAN_DISABLE_WCAST_FUNCTION_TYPE-#	pragma GCC diagnostic pop-#endif 			if (gmse != NULL) { 				MEMORYSTATUSEX meminfo; 				meminfo.dwLength = sizeof(meminfo);@@ -155,7 +148,7 @@ 			ret += entries[i].end - entries[i].start + 1;  #elif defined(TUKLIB_PHYSMEM_AIX)-	ret = _system_configuration.physmem;+	ret = (uint64_t)_system_configuration.physmem;  #elif defined(TUKLIB_PHYSMEM_SYSCONF) 	const long pagesize = sysconf(_SC_PAGESIZE);
cbits/config.h.in view
@@ -330,6 +330,9 @@ /* Define to 1 if you have the 'utimes' function. */ #undef HAVE_UTIMES +/* Define to 1 if you have the 'vasprintf' function. */+#undef HAVE_VASPRINTF+ /* Define to 1 or 0, depending whether the compiler supports simple visibility    declarations. */ #undef HAVE_VISIBILITY
cbits/liblzma/api/lzma/bcj.h view
@@ -96,3 +96,100 @@ 	uint32_t start_offset;  } lzma_options_bcj;+++/**+ * \brief       Raw ARM64 BCJ encoder+ *+ * This is for special use cases only.+ *+ * \param       start_offset  The lowest 32 bits of the offset in the+ *                            executable being filtered. For the ARM64+ *                            filter, this must be a multiple of four.+ *                            For the very best results, this should also+ *                            be in sync with 4096-byte page boundaries+ *                            in the executable due to how ARM64's ADRP+ *                            instruction works.+ * \param       buf           Buffer to be filtered in place+ * \param       size          Size of the buffer+ *+ * \return      Number of bytes that were processed in `buf`. This is at most+ *              `size`. With the ARM64 filter, the return value is always+ *              a multiple of 4, and at most 3 bytes are left unfiltered.+ *+ * \since       5.7.1alpha+ */+extern LZMA_API(size_t) lzma_bcj_arm64_encode(+		uint32_t start_offset, uint8_t *buf, size_t size) lzma_nothrow;++/**+ * \brief       Raw ARM64 BCJ decoder+ *+ * See lzma_bcj_arm64_encode().+ *+ * \since       5.7.1alpha+ */+extern LZMA_API(size_t) lzma_bcj_arm64_decode(+		uint32_t start_offset, uint8_t *buf, size_t size) lzma_nothrow;+++/**+ * \brief       Raw RISC-V BCJ encoder+ *+ * This is for special use cases only.+ *+ * \param       start_offset  The lowest 32 bits of the offset in the+ *                            executable being filtered. For the RISC-V+ *                            filter, this must be a multiple of 2.+ * \param       buf           Buffer to be filtered in place+ * \param       size          Size of the buffer+ *+ * \return      Number of bytes that were processed in `buf`. This is at most+ *              `size`. With the RISC-V filter, the return value is always+ *              a multiple of 2, and at most 7 bytes are left unfiltered.+ *+ * \since       5.7.1alpha+ */+extern LZMA_API(size_t) lzma_bcj_riscv_encode(+		uint32_t start_offset, uint8_t *buf, size_t size) lzma_nothrow;++/**+ * \brief       Raw RISC-V BCJ decoder+ *+ * See lzma_bcj_riscv_encode().+ *+ * \since       5.7.1alpha+ */+extern LZMA_API(size_t) lzma_bcj_riscv_decode(+		uint32_t start_offset, uint8_t *buf, size_t size) lzma_nothrow;+++/**+ * \brief       Raw x86 BCJ encoder+ *+ * This is for special use cases only.+ *+ * \param       start_offset  The lowest 32 bits of the offset in the+ *                            executable being filtered. For the x86+ *                            filter, all values are valid.+ * \param       buf           Buffer to be filtered in place+ * \param       size          Size of the buffer+ *+ * \return      Number of bytes that were processed in `buf`. This is at most+ *              `size`. For the x86 filter, the return value is always+ *              a multiple of 1, and at most 4 bytes are left unfiltered.+ *+ * \since       5.7.1alpha+ */+extern LZMA_API(size_t) lzma_bcj_x86_encode(+		uint32_t start_offset, uint8_t *buf, size_t size) lzma_nothrow;++/**+ * \brief       Raw x86 BCJ decoder+ *+ * See lzma_bcj_x86_encode().+ *+ * \since       5.7.1alpha+ */+extern LZMA_API(size_t) lzma_bcj_x86_decode(+		uint32_t start_offset, uint8_t *buf, size_t size) lzma_nothrow;
cbits/liblzma/api/lzma/container.h view
@@ -573,7 +573,7 @@  * 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+ * function and lzma_code() is that memory allocations can be reused for  * better performance.  *  * lzma_code() will try to encode as much input as is possible to fit into
cbits/liblzma/api/lzma/version.h view
@@ -19,10 +19,10 @@ #define LZMA_VERSION_MAJOR 5  /** \brief Minor version number of the liblzma release. */-#define LZMA_VERSION_MINOR 6+#define LZMA_VERSION_MINOR 8  /** \brief Patch version number of the liblzma release. */-#define LZMA_VERSION_PATCH 4+#define LZMA_VERSION_PATCH 0  /**  * \brief Version stability marker
cbits/liblzma/check/check.h view
@@ -95,24 +95,6 @@ } lzma_check_state;  -/// lzma_crc32_table[0] is needed by LZ encoder so we need to keep-/// the array two-dimensional.-#ifdef HAVE_SMALL-lzma_attr_visibility_hidden-extern uint32_t lzma_crc32_table[1][256];--extern void lzma_crc32_init(void);--#else--lzma_attr_visibility_hidden-extern const uint32_t lzma_crc32_table[8][256];--lzma_attr_visibility_hidden-extern const uint64_t lzma_crc64_table[4][256];-#endif-- /// \brief      Initialize *check depending on type extern void lzma_check_init(lzma_check_state *check, lzma_check type); 
cbits/liblzma/check/crc32_arm64.h view
@@ -7,7 +7,7 @@ // //  Authors:    Chenxi Mao //              Jia Tan-//              Hans Jansen+//              Lasse Collin // /////////////////////////////////////////////////////////////////////////////// @@ -49,25 +49,50 @@ { 	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);+	if (size >= 8) {+		// Align the input buffer because this was shown to be+		// significantly faster than unaligned accesses.+		const size_t align = (0 - (uintptr_t)buf) & 7; -	for (const uint8_t *limit = buf + align_amount; buf < limit; ++buf)-		crc = __crc32b(crc, *buf);+		if (align & 1)+			crc = __crc32b(crc, *buf++); -	size -= align_amount;+		if (align & 2) {+			crc = __crc32h(crc, aligned_read16le(buf));+			buf += 2;+		} -	// 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));+		if (align & 4) {+			crc = __crc32w(crc, aligned_read32le(buf));+			buf += 4;+		} +		size -= align;++		// 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));++		size &= 7;+	}+ 	// Process the remaining bytes that are not 8 byte aligned.-	for (const uint8_t *limit = buf + (size & 7); buf < limit; ++buf)+	if (size & 4) {+		crc = __crc32w(crc, aligned_read32le(buf));+		buf += 4;+	}++	if (size & 2) {+		crc = __crc32h(crc, aligned_read16le(buf));+		buf += 2;+	}++	if (size & 1) 		crc = __crc32b(crc, *buf);  	return ~crc;
cbits/liblzma/check/crc32_fast.c view
@@ -7,7 +7,6 @@ // //  Authors:    Lasse Collin //              Ilya Kurdyukov-//              Hans Jansen // /////////////////////////////////////////////////////////////////////////////// @@ -15,10 +14,12 @@ #include "crc_common.h"  #if defined(CRC_X86_CLMUL)-#	define BUILDING_CRC32_CLMUL+#	define BUILDING_CRC_CLMUL 32 #	include "crc_x86_clmul.h" #elif defined(CRC32_ARM64) #	include "crc32_arm64.h"+#elif defined(CRC32_LOONGARCH)+#	include "crc32_loongarch.h" #endif  @@ -28,8 +29,19 @@ // Generic CRC32 // /////////////////// +#ifdef WORDS_BIGENDIAN+#	include "crc32_table_be.h"+#else+#	include "crc32_table_le.h"+#endif+++#ifdef HAVE_CRC_X86_ASM+extern uint32_t lzma_crc32_generic(+		const uint8_t *buf, size_t size, uint32_t crc);+#else static uint32_t-crc32_generic(const uint8_t *buf, size_t size, uint32_t crc)+lzma_crc32_generic(const uint8_t *buf, size_t size, uint32_t crc) { 	crc = ~crc; @@ -85,7 +97,8 @@  	return ~crc; }-#endif+#endif // HAVE_CRC_X86_ASM+#endif // CRC32_GENERIC   #if defined(CRC32_GENERIC) && defined(CRC32_ARCH_OPTIMIZED)@@ -119,7 +132,7 @@ crc32_resolve(void) { 	return is_arch_extension_supported()-			? &crc32_arch_optimized : &crc32_generic;+			? &crc32_arch_optimized : &lzma_crc32_generic; }  @@ -164,27 +177,6 @@ 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@@ -199,6 +191,6 @@ 	return crc32_arch_optimized(buf, size, crc);  #else-	return crc32_generic(buf, size, crc);+	return lzma_crc32_generic(buf, size, crc); #endif }
+ cbits/liblzma/check/crc32_loongarch.h view
@@ -0,0 +1,65 @@+// SPDX-License-Identifier: 0BSD++///////////////////////////////////////////////////////////////////////////////+//+/// \file       crc32_loongarch.h+/// \brief      CRC32 calculation with LoongArch optimization+//+//  Authors:    Xi Ruoyao+//              Lasse Collin+//+///////////////////////////////////////////////////////////////////////////////++#ifndef LZMA_CRC32_LOONGARCH_H+#define LZMA_CRC32_LOONGARCH_H++#include <larchintrin.h>+++static uint32_t+crc32_arch_optimized(const uint8_t *buf, size_t size, uint32_t crc_unsigned)+{+	int32_t crc = (int32_t)~crc_unsigned;++	if (size >= 8) {+		const size_t align = (0 - (uintptr_t)buf) & 7;++		if (align & 1)+			crc = __crc_w_b_w((int8_t)*buf++, crc);++		if (align & 2) {+			crc = __crc_w_h_w((int16_t)aligned_read16le(buf), crc);+			buf += 2;+		}++		if (align & 4) {+			crc = __crc_w_w_w((int32_t)aligned_read32le(buf), crc);+			buf += 4;+		}++		size -= align;++		for (const uint8_t *limit = buf + (size & ~(size_t)7);+				buf < limit; buf += 8)+			crc = __crc_w_d_w((int64_t)aligned_read64le(buf), crc);++		size &= 7;+	}++	if (size & 4) {+		crc = __crc_w_w_w((int32_t)aligned_read32le(buf), crc);+		buf += 4;+	}++	if (size & 2) {+		crc = __crc_w_h_w((int16_t)aligned_read16le(buf), crc);+		buf += 2;+	}++	if (size & 1)+		crc = __crc_w_b_w((int8_t)*buf, crc);++	return (uint32_t)~crc;+}++#endif // LZMA_CRC32_LOONGARCH_H
cbits/liblzma/check/crc32_small.c view
@@ -10,8 +10,11 @@ ///////////////////////////////////////////////////////////////////////////////  #include "check.h"+#include "crc_common.h"  +// The table is used by the LZ encoder too, thus it's not static like+// in crc64_small.c. uint32_t lzma_crc32_table[1][256];  
− cbits/liblzma/check/crc32_table.c
@@ -1,42 +0,0 @@-// SPDX-License-Identifier: 0BSD--///////////////////////////////////////////////////////////////////////////////-//-/// \file       crc32_table.c-/// \brief      Precalculated CRC32 table with correct endianness-//-//  Author:     Lasse Collin-//-///////////////////////////////////////////////////////////////////////////////--#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.-extern const uint32_t lzma_crc32_table[8][256];--#	ifdef WORDS_BIGENDIAN-#		include "crc32_table_be.h"-#	else-#		include "crc32_table_le.h"-#	endif-#endif
cbits/liblzma/check/crc64_fast.c view
@@ -14,7 +14,7 @@ #include "crc_common.h"  #if defined(CRC_X86_CLMUL)-#	define BUILDING_CRC64_CLMUL+#	define BUILDING_CRC_CLMUL 64 #	include "crc_x86_clmul.h" #endif @@ -25,6 +25,18 @@ // Generic slice-by-four CRC64 // ///////////////////////////////// +#if defined(WORDS_BIGENDIAN)+#	include "crc64_table_be.h"+#else+#	include "crc64_table_le.h"+#endif+++#ifdef HAVE_CRC_X86_ASM+extern uint64_t lzma_crc64_generic(+		const uint8_t *buf, size_t size, uint64_t crc);+#else+ #ifdef WORDS_BIGENDIAN #	define A1(x) ((x) >> 56) #else@@ -34,7 +46,7 @@  // See the comments in crc32_fast.c. They aren't duplicated here. static uint64_t-crc64_generic(const uint8_t *buf, size_t size, uint64_t crc)+lzma_crc64_generic(const uint8_t *buf, size_t size, uint64_t crc) { 	crc = ~crc; @@ -78,7 +90,8 @@  	return ~crc; }-#endif+#endif // HAVE_CRC_X86_ASM+#endif // CRC64_GENERIC   #if defined(CRC64_GENERIC) && defined(CRC64_ARCH_OPTIMIZED)@@ -97,7 +110,7 @@ crc64_resolve(void) { 	return is_arch_extension_supported()-			? &crc64_arch_optimized : &crc64_generic;+			? &crc64_arch_optimized : &lzma_crc64_generic; }  #ifdef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR@@ -133,24 +146,24 @@ 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);+#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__) \+		&& defined(_M_IX86) && defined(CRC64_ARCH_OPTIMIZED)+	// VS2015-2022 might corrupt the ebx register on 32-bit x86 when+	// the CLMUL code is enabled. This hack forces MSVC to store and+	// restore ebx. This is only needed here, not in lzma_crc32().+	__asm  mov ebx, ebx #endif++#if defined(CRC64_GENERIC) && defined(CRC64_ARCH_OPTIMIZED) 	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);+	return lzma_crc64_generic(buf, size, crc); #endif }
− cbits/liblzma/check/crc64_table.c
@@ -1,37 +0,0 @@-// SPDX-License-Identifier: 0BSD--///////////////////////////////////////////////////////////////////////////////-//-/// \file       crc64_table.c-/// \brief      Precalculated CRC64 table with correct endianness-//-//  Author:     Lasse Collin-//-///////////////////////////////////////////////////////////////////////////////--#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.-extern const uint64_t lzma_crc64_table[4][256];--#	if defined(WORDS_BIGENDIAN)-#		include "crc64_table_be.h"-#	else-#		include "crc64_table_le.h"-#	endif-#endif
+ cbits/liblzma/check/crc_clmul_consts_gen.c view
@@ -0,0 +1,160 @@+// SPDX-License-Identifier: 0BSD++///////////////////////////////////////////////////////////////////////////////+//+/// \file       crc_clmul_consts_gen.c+/// \brief      Generate constants for CLMUL CRC code+///+/// Compiling: gcc -std=c99 -o crc_clmul_consts_gen crc_clmul_consts_gen.c+///+/// This is for CRCs that use reversed bit order (bit reflection).+/// The same CLMUL CRC code can be used with CRC64 and smaller ones like+/// CRC32 apart from one special case: CRC64 needs an extra step in the+/// Barrett reduction to handle the 65th bit; the smaller ones don't.+/// Otherwise it's enough to just change the polynomial and the derived+/// constants and use the same code.+///+/// See the Intel white paper "Fast CRC Computation for Generic Polynomials+/// Using PCLMULQDQ Instruction" from 2009.+//+//  Author:     Lasse Collin+//+///////////////////////////////////////////////////////////////////////////////++#include <inttypes.h>+#include <stdio.h>+++/// CRC32 (Ethernet) polynomial in reversed representation+static const uint64_t p32 = 0xedb88320;++// CRC64 (ECMA-182) polynomial in reversed representation+static const uint64_t p64 = 0xc96c5795d7870f42;+++/// Calculates floor(x^128 / p) where p is a CRC64 polynomial in+/// reversed representation. The result is in reversed representation too.+static uint64_t+calc_cldiv(uint64_t p)+{+	// Quotient+	uint64_t q = 0;++	// Align the x^64 term with the x^128 (the implied high bits of the+	// divisor and the dividend) and do the first step of polynomial long+	// division, calculating the first remainder. The variable q remains+	// zero because the highest bit of the quotient is an implied bit 1+	// (we kind of set q = 1 << -1).+	uint64_t r = p;++	// Then process the remaining 64 terms. Note that r has no implied+	// high bit, only q and p do. (And remember that a high bit in the+	// polynomial is stored at a low bit in the variable due to the+	// reversed bit order.)+	for (unsigned i = 0; i < 64; ++i) {+		q |= (r & 1) << i;+		r = (r >> 1) ^ (r & 1 ? p : 0);+	}++	return q;+}+++/// Calculate the remainder of carryless division:+///+///     x^(bits + n - 1) % p, where n=64 (for CRC64)+///+/// p must be in reversed representation which omits the bit of+/// the highest term of the polynomial. Instead, it is an implied bit+/// at kind of like "1 << -1" position, as if it had just been shifted out.+///+/// The return value is in the reversed bit order. (There are no implied bits.)+static uint64_t+calc_clrem(uint64_t p, unsigned bits)+{+	// Do the first step of polynomial long division.+	uint64_t r = p;++	// Then process the remaining terms. Start with i = 1 instead of i = 0+	// to account for the -1 in x^(bits + n - 1). This -1 is convenient+	// with the reversed bit order. See the "Bit-Reflection" section in+	// the Intel white paper.+	for (unsigned i = 1; i < bits; ++i)+		r = (r >> 1) ^ (r & 1 ? p : 0);++	return r;+}+++extern int+main(void)+{+	puts("// CRC64");++	// The order of the two 64-bit constants in a vector don't matter.+	// It feels logical to put them in this order as it matches the+	// order in which the input bytes are read.+	printf("const __m128i fold512 = _mm_set_epi64x("+		"0x%016" PRIx64 ", 0x%016" PRIx64 ");\n",+		calc_clrem(p64, 4 * 128 - 64),+		calc_clrem(p64, 4 * 128));++	printf("const __m128i fold128 = _mm_set_epi64x("+		"0x%016" PRIx64 ", 0x%016" PRIx64 ");\n",+		calc_clrem(p64, 128 - 64),+		calc_clrem(p64, 128));++	// When we multiply by mu, we care about the high bits of the result+	// (in reversed bit order!). It doesn't matter that the low bit gets+	// shifted out because the affected output bits will be ignored.+	// Below we add the implied high bit with "| 1" after the shifting+	// so that the high bits of the multiplication will be correct.+	//+	// p64 is shifted left by one so that the final multiplication+	// in Barrett reduction won't be misaligned by one bit. We could+	// use "(p64 << 1) | 1" instead of "p64 << 1" too but it makes+	// no difference as that bit won't affect the relevant output bits+	// (we only care about the lowest 64 bits of the result, that is,+	// lowest in the reversed bit order).+	//+	// NOTE: The 65rd bit of p64 gets shifted out. It needs to be+	// compensated with 64-bit shift and xor in the CRC64 code.+	printf("const __m128i mu_p = _mm_set_epi64x("+		"0x%016" PRIx64 ", 0x%016" PRIx64 ");\n",+		(calc_cldiv(p64) << 1) | 1,+		p64 << 1);++	puts("");++	puts("// CRC32");++	printf("const __m128i fold512 = _mm_set_epi64x("+		"0x%08" PRIx64 ", 0x%08" PRIx64 ");\n",+		calc_clrem(p32, 4 * 128 - 64),+		calc_clrem(p32, 4 * 128));++	printf("const __m128i fold128 = _mm_set_epi64x("+		"0x%08" PRIx64 ", 0x%08" PRIx64 ");\n",+		calc_clrem(p32, 128 - 64),+		calc_clrem(p32, 128));++	// CRC32 calculation is done by modulus scaling it to a CRC64.+	// Since the CRC is in reversed representation, only the mu+	// constant changes with the modulus scaling. This method avoids+	// one additional constant and one additional clmul in the final+	// reduction steps, making the code both simpler and faster.+	//+	// p32 is shifted left by one so that the final multiplication+	// in Barrett reduction won't be misaligned by one bit. We could+	// use "(p32 << 1) | 1" instead of "p32 << 1" too but it makes+	// no difference as that bit won't affect the relevant output bits.+	//+	// NOTE: The 33-bit value fits in 64 bits so, unlike with CRC64,+	// there is no need to compensate for any missing bits in the code.+	printf("const __m128i mu_p = _mm_set_epi64x("+		"0x%016" PRIx64 ", 0x%" PRIx64 ");\n",+		(calc_cldiv(p32) << 1) | 1,+		p32 << 1);++	return 0;+}
cbits/liblzma/check/crc_common.h view
@@ -3,11 +3,10 @@ /////////////////////////////////////////////////////////////////////////////// // /// \file       crc_common.h-/// \brief      Some functions and macros for CRC32 and CRC64+/// \brief      Macros and declarations for CRC32 and CRC64 // //  Authors:    Lasse Collin //              Ilya Kurdyukov-//              Hans Jansen //              Jia Tan // ///////////////////////////////////////////////////////////////////////////////@@ -18,6 +17,10 @@ #include "common.h"  +/////////////+// Generic //+/////////////+ #ifdef WORDS_BIGENDIAN #	define A(x) ((x) >> 24) #	define B(x) (((x) >> 16) & 0xFF)@@ -38,43 +41,63 @@ #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__))+/// lzma_crc32_table[0] is needed by LZ encoder so we need to keep+/// the array two-dimensional.+#ifdef HAVE_SMALL+lzma_attr_visibility_hidden+extern uint32_t lzma_crc32_table[1][256];++extern void lzma_crc32_init(void);+ #else-#	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+lzma_attr_visibility_hidden+extern const uint32_t lzma_crc32_table[8][256];++lzma_attr_visibility_hidden+extern const uint64_t lzma_crc64_table[4][256]; #endif  +///////////////////+// Configuration //+///////////////////++// NOTE: This config isn't used if HAVE_SMALL is defined!++// These are defined if the generic slicing-by-n implementations and their+// lookup tables are built. #undef CRC32_GENERIC #undef CRC64_GENERIC +// These are defined if an arch-specific version is built. If both this+// and matching _GENERIC is defined then runtime detection must be used. #undef CRC32_ARCH_OPTIMIZED #undef CRC64_ARCH_OPTIMIZED  // The x86 CLMUL is used for both CRC32 and CRC64. #undef CRC_X86_CLMUL +// Many ARM64 processor have CRC32 instructions.+// CRC64 could be done with CLMUL but it's not implemented yet. #undef CRC32_ARM64-#undef CRC64_ARM64_CLMUL -#undef CRC_USE_GENERIC_FOR_SMALL_INPUTS+// 64-bit LoongArch has CRC32 instructions.+#undef CRC32_LOONGARCH ++// ARM64+//+// 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 CRC_ARM64_RUNTIME_DETECTION 1+#endif+ // 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@@ -82,21 +105,40 @@ #	if defined(__ARM_FEATURE_CRC32) #		define CRC32_ARCH_OPTIMIZED 1 #		define CRC32_ARM64 1-#	elif defined(ARM64_RUNTIME_DETECTION)+#	elif defined(CRC_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.++// LoongArch //-// 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__)) \+// Only 64-bit LoongArch is supported for now. No runtime detection+// is needed because the LoongArch specification says that the CRC32+// instructions are a part of the Basic Integer Instructions and+// they shall be implemented by 64-bit LoongArch implementations.+#ifdef HAVE_LOONGARCH_CRC32+#	define CRC32_ARCH_OPTIMIZED 1+#	define CRC32_LOONGARCH 1+#endif+++// x86 and E2K+#if defined(HAVE_USABLE_CLMUL)+	// If CLMUL is allowed unconditionally in the compiler options then+	// the generic version and the tables can be omitted. Exceptions:+	//+	//   - If 32-bit x86 assembly files are enabled then those are always+	//     built and runtime detection is used even if compiler flags+	//     were set to allow CLMUL unconditionally.+	//+	//   - This doesn't work with MSVC as I don't know how to detect+	//     the features here.+	//+#	if (defined(__SSSE3__) && defined(__SSE4_1__) && defined(__PCLMUL__) \+			&& !defined(HAVE_CRC_X86_ASM)) \ 		|| (defined(__e2k__) && __iset__ >= 6) #		define CRC32_ARCH_OPTIMIZED 1 #		define CRC64_ARCH_OPTIMIZED 1@@ -107,21 +149,12 @@ #		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 ++// Fallback configuration+// // For CRC32 use the generic slice-by-eight implementation if no optimized // version is available. #if !defined(CRC32_ARCH_OPTIMIZED) && !defined(CRC32_GENERIC)
cbits/liblzma/check/crc_x86_clmul.h view
@@ -8,26 +8,20 @@ /// 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+/// See the Intel white paper "Fast CRC Computation for Generic Polynomials+/// Using PCLMULQDQ Instruction" from 2009. The original file seems to be+/// gone from Intel's website but a version is available here: /// 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).+/// (The link was checked on 2024-06-11.) /// /// 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.+/// can be built at a time. The version to build is selected by defining+/// BUILDING_CRC_CLMUL to 32 or 64 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.+/// NOTE: The x86 CLMUL CRC implementation was rewritten for XZ Utils 5.8.0. //-//  Authors:    Ilya Kurdyukov-//              Hans Jansen-//              Lasse Collin-//              Jia Tan+//  Authors:    Lasse Collin+//              Ilya Kurdyukov // /////////////////////////////////////////////////////////////////////////////// @@ -37,6 +31,10 @@ #endif #define LZMA_CRC_X86_CLMUL_H +#if BUILDING_CRC_CLMUL != 32 && BUILDING_CRC_CLMUL != 64+#	error BUILDING_CRC_CLMUL is undefined or has an invalid value+#endif+ #include <immintrin.h>  #if defined(_MSC_VER)@@ -59,330 +57,277 @@ #endif  -#define MASK_L(in, mask, r) r = _mm_shuffle_epi8(in, mask)+// GCC and Clang would produce good code with _mm_set_epi64x+// but MSVC needs _mm_cvtsi64_si128 on x86-64.+#if defined(__i386__) || defined(_M_IX86)+#	define my_set_low64(a) _mm_set_epi64x(0, (a))+#else+#	define my_set_low64(a) _mm_cvtsi64_si128(a)+#endif -#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)+// Align it so that the whole array is within the same cache line.+// More than one unaligned load can be done from this during the+// same CRC function call.+//+// The bytes [0] to [31] are used with AND to clear the low bytes. (With ANDN+// those could be used to clear the high bytes too but it's not needed here.)+//+// The bytes [16] to [47] are for left shifts.+// The bytes [32] to [63] are for right shifts.+alignas(64)+static uint8_t vmasks[64] = {+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,+	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,+};  +// *Unaligned* 128-bit load 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)+static inline __m128i+my_load128(const uint8_t *p) {-	// 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);+	return _mm_loadu_si128((const __m128i *)p);+} -	// 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);+// Keep the highest "count" bytes as is and clear the remaining low bytes.+crc_attr_target+static inline __m128i+keep_high_bytes(__m128i v, size_t count)+{+	return _mm_and_si128(my_load128((vmasks + count)), v);+} -	// 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));+// Shift the 128-bit value left by "amount" bytes (not bits).+crc_attr_target+static inline __m128i+shift_left(__m128i v, size_t amount)+{+	return _mm_shuffle_epi8(v, my_load128((vmasks + 32 - amount)));+} -	// 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);-	}+// Shift the 128-bit value right by "amount" bytes (not bits).+crc_attr_target+static inline __m128i+shift_right(__m128i v, size_t amount)+{+	return _mm_shuffle_epi8(v, my_load128((vmasks + 32 + amount))); }  -/////////////////////-// 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)+crc_attr_target+static inline __m128i+fold(__m128i v, __m128i k) {-	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;+	__m128i a = _mm_clmulepi64_si128(v, k, 0x00);+	__m128i b = _mm_clmulepi64_si128(v, k, 0x11);+	return _mm_xor_si128(a, b); } -// same as ~crc(&a, sizeof(a), ~0)-static uint64_t-calc_hi(uint64_t p, uint64_t a, int n)++crc_attr_target+static inline __m128i+fold_xor(__m128i v, __m128i k, const uint8_t *buf) {-	int i;-	for (i = 0; i < n; i++)-		a = (a >> 1) ^ ((0 - (a & 1)) & p);-	return a;+	return _mm_xor_si128(my_load128(buf), fold(v, k)); }-*/ -#ifdef BUILDING_CRC32_CLMUL +#if BUILDING_CRC_CLMUL == 32 crc_attr_target-crc_attr_no_sanitize_address static uint32_t crc32_arch_optimized(const uint8_t *buf, size_t size, uint32_t crc)+#else+crc_attr_target+static uint64_t+crc64_arch_optimized(const uint8_t *buf, size_t size, uint64_t crc)+#endif {-#ifndef CRC_USE_GENERIC_FOR_SMALL_INPUTS-	// The code assumes that there is at least one byte of input.+	// We will assume 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+	// See crc_clmul_consts_gen.c.+#if BUILDING_CRC_CLMUL == 32+	const __m128i fold512 = _mm_set_epi64x(0x1d9513d7, 0x8f352d95);+	const __m128i fold128 = _mm_set_epi64x(0xccaa009e, 0xae689191);+	const __m128i mu_p = _mm_set_epi64x(+		(int64_t)0xb4e5b025f7011641, 0x1db710640);+#else+	const __m128i fold512 = _mm_set_epi64x(+		(int64_t)0x081f6054a7842df4, (int64_t)0x6ae3efbb9dd441f3); -	const __m128i vfold4 = _mm_set_epi64x(mu, p);-	const __m128i vfold8 = _mm_set_epi64x(0, k5);-	const __m128i vfold16 = _mm_set_epi64x(k4, k3);+	const __m128i fold128 = _mm_set_epi64x(+		(int64_t)0xdabe95afc7875f40, (int64_t)0xe05dd497ca393ae4); -	__m128i v0, v1, v2;+	const __m128i mu_p = _mm_set_epi64x(+		(int64_t)0x9c3e466c172963d5, (int64_t)0x92d8af2baf0e1e84);+#endif -	crc_simd_body(buf, size, &v0, &v1, vfold16,-			_mm_cvtsi32_si128((int32_t)~crc));+	__m128i v0, v1, v2, v3; -	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+	crc = ~crc; +	if (size < 8) {+		uint64_t x = crc;+		size_t i = 0; -/////////////////////-// x86 CLMUL CRC64 //-/////////////////////+		// Checking the bit instead of comparing the size means+		// that we don't need to update the size between the steps.+		if (size & 4) {+			x ^= read32le(buf);+			buf += 4;+			i = 32;+		} -/*-// 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;+		if (size & 2) {+			x ^= (uint64_t)read16le(buf) << i;+			buf += 2;+			i += 16;+		} -	for (unsigned i = 0; i < 64; ++i) {-		b = (b >> 1) | (a << 63);-		a = (a >> 1) ^ (a & 1 ? poly : 0);-	}+		if (size & 1)+			x ^= (uint64_t)*buf << i; -	return b;-}+		v0 = my_set_low64((int64_t)x);+		v0 = shift_left(v0, 8 - size); -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);+	} else if (size < 16) {+		v0 = my_set_low64((int64_t)(crc ^ read64le(buf))); -	return a;-}-*/+		// NOTE: buf is intentionally left 8 bytes behind so that+		// we can read the last 1-7 bytes with read64le(buf + size).+		size -= 8; -#ifdef BUILDING_CRC64_CLMUL+		// Handling 8-byte input specially is a speed optimization+		// as the clmul can be skipped. A branch is also needed to+		// avoid a too high shift amount.+		if (size > 0) {+			const size_t padding = 8 - size;+			uint64_t high = read64le(buf + size) >> (padding * 8); -// 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)+#if defined(__i386__) || defined(_M_IX86)+			// Simple but likely not the best code for 32-bit x86.+			v0 = _mm_insert_epi32(v0, (int32_t)high, 2);+			v0 = _mm_insert_epi32(v0, (int32_t)(high >> 32), 3);+#else+			v0 = _mm_insert_epi64(v0, (int64_t)high, 1); #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+			v0 = shift_left(v0, padding); -	// 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)+			v1 = _mm_srli_si128(v0, 8);+			v0 = _mm_clmulepi64_si128(v0, fold128, 0x10);+			v0 = _mm_xor_si128(v0, v1);+		}+	} else {+		v0 = my_set_low64((int64_t)crc); -	const __m128i vfold8 = _mm_set_epi64x((int64_t)p, (int64_t)mu);-	const __m128i vfold16 = _mm_set_epi64x((int64_t)k2, (int64_t)k1);+		// To align or not to align the buf pointer? If the end of+		// the buffer isn't aligned, aligning the pointer here would+		// make us do an extra folding step with the associated byte+		// shuffling overhead. The cost of that would need to be+		// lower than the benefit of aligned reads. Testing on an old+		// Intel Ivy Bridge processor suggested that aligning isn't+		// worth the cost but it likely depends on the processor and+		// buffer size. Unaligned loads (MOVDQU) should be fast on+		// x86 processors that support PCLMULQDQ, so we don't align+		// the buf pointer here. -	__m128i v0, v1, v2;+		// Read the first (and possibly the only) full 16 bytes.+		v0 = _mm_xor_si128(v0, my_load128(buf));+		buf += 16;+		size -= 16; -#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+		if (size >= 48) {+			v1 = my_load128(buf);+			v2 = my_load128(buf + 16);+			v3 = my_load128(buf + 32);+			buf += 48;+			size -= 48; -	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);+			while (size >= 64) {+				v0 = fold_xor(v0, fold512, buf);+				v1 = fold_xor(v1, fold512, buf + 16);+				v2 = fold_xor(v2, fold512, buf + 32);+				v3 = fold_xor(v3, fold512, buf + 48);+				buf += 64;+				size -= 64;+			} +			v0 = _mm_xor_si128(v1, fold(v0, fold128));+			v0 = _mm_xor_si128(v2, fold(v0, fold128));+			v0 = _mm_xor_si128(v3, fold(v0, fold128));+		}++		while (size >= 16) {+			v0 = fold_xor(v0, fold128, buf);+			buf += 16;+			size -= 16;+		}++		if (size > 0) {+			// We want the last "size" number of input bytes to+			// be at the high bits of v1. First do a full 16-byte+			// load and then mask the low bytes to zeros.+			v1 = my_load128(buf + size - 16);+			v1 = keep_high_bytes(v1, size);++			// Shift high bytes from v0 to the low bytes of v1.+			//+			// Alternatively we could replace the combination+			// keep_high_bytes + shift_right + _mm_or_si128 with+			// _mm_shuffle_epi8 + _mm_blendv_epi8 but that would+			// require larger tables for the masks. Now there are+			// three loads (instead of two) from the mask tables+			// but they all are from the same cache line.+			v1 = _mm_or_si128(v1, shift_right(v0, size));++			// Shift high bytes of v0 away, padding the+			// low bytes with zeros.+			v0 = shift_left(v0, 16 - size);++			v0 = _mm_xor_si128(v1, fold(v0, fold128));+		}++		v1 = _mm_srli_si128(v0, 8);+		v0 = _mm_clmulepi64_si128(v0, fold128, 0x10);+		v0 = _mm_xor_si128(v0, v1);+	}++	// Barrett reduction++#if BUILDING_CRC_CLMUL == 32+	v1 = _mm_clmulepi64_si128(v0, mu_p, 0x10); // v0 * mu+	v1 = _mm_clmulepi64_si128(v1, mu_p, 0x00); // v1 * p+	v0 = _mm_xor_si128(v0, v1);+	return ~(uint32_t)_mm_extract_epi32(v0, 2);+#else+	// Because p is 65 bits but one bit doesn't fit into the 64-bit+	// half of __m128i, finish the second clmul by shifting v1 left+	// by 64 bits and xorring it to the final result.+	v1 = _mm_clmulepi64_si128(v0, mu_p, 0x10); // v0 * mu+	v2 = _mm_slli_si128(v1, 8);+	v1 = _mm_clmulepi64_si128(v1, mu_p, 0x00); // v1 * p+	v0 = _mm_xor_si128(v0, v2);+	v0 = _mm_xor_si128(v0, v1); #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.
cbits/liblzma/common/alone_decoder.c view
@@ -134,8 +134,7 @@  		coder->pos = 0; 		coder->sequence = SEQ_CODER_INIT;--	// Fall through+		FALLTHROUGH;  	case SEQ_CODER_INIT: { 		if (coder->memusage > coder->memlimit)
cbits/liblzma/common/auto_decoder.c view
@@ -79,7 +79,7 @@ 				return LZMA_GET_CHECK; 		} -	// Fall through+		FALLTHROUGH;  	case SEQ_CODE: { 		const lzma_ret ret = coder->next.code(@@ -91,9 +91,8 @@ 			return ret;  		coder->sequence = SEQ_FINISH;+		FALLTHROUGH; 	}--	// Fall through  	case SEQ_FINISH: 		// When LZMA_CONCATENATED was used and we were decoding
cbits/liblzma/common/block_decoder.c view
@@ -146,10 +146,9 @@ 		coder->block->uncompressed_size = coder->uncompressed_size;  		coder->sequence = SEQ_PADDING;+		FALLTHROUGH; 	} -	// Fall through- 	case SEQ_PADDING: 		// Compressed Data is padded to a multiple of four bytes. 		while (coder->compressed_size & 3) {@@ -173,8 +172,7 @@ 			lzma_check_finish(&coder->check, coder->block->check);  		coder->sequence = SEQ_CHECK;--	// Fall through+		FALLTHROUGH;  	case SEQ_CHECK: { 		const size_t check_size = lzma_check_size(coder->block->check);
cbits/liblzma/common/block_encoder.c view
@@ -94,10 +94,9 @@ 		coder->block->uncompressed_size = coder->uncompressed_size;  		coder->sequence = SEQ_PADDING;+		FALLTHROUGH; 	} -	// Fall through- 	case SEQ_PADDING: 		// Pad Compressed Data to a multiple of four bytes. We can 		// use coder->compressed_size for this since we don't need@@ -117,8 +116,7 @@ 		lzma_check_finish(&coder->check, coder->block->check);  		coder->sequence = SEQ_CHECK;--	// Fall through+		FALLTHROUGH;  	case SEQ_CHECK: { 		const size_t check_size = lzma_check_size(coder->block->check);
cbits/liblzma/common/common.c view
@@ -348,7 +348,7 @@ 		else 			strm->internal->sequence = ISEQ_END; -	// Fall through+		FALLTHROUGH;  	case LZMA_NO_CHECK: 	case LZMA_UNSUPPORTED_CHECK:
cbits/liblzma/common/file_info.c view
@@ -298,15 +298,13 @@ 		// Start looking for Stream Padding and Stream Footer 		// at the end of the file. 		coder->file_target_pos = coder->file_size;--	// Fall through+		FALLTHROUGH;  	case SEQ_PADDING_SEEK: 		coder->sequence = SEQ_PADDING_DECODE; 		return_if_error(reverse_seek( 				coder, in_start, in_pos, in_size));--	// Fall through+		FALLTHROUGH;  	case SEQ_PADDING_DECODE: { 		// Copy to coder->temp first. This keeps the code simpler if@@ -356,9 +354,9 @@ 		if (coder->temp_size < LZMA_STREAM_HEADER_SIZE) 			return_if_error(reverse_seek( 					coder, in_start, in_pos, in_size));-	} -	// Fall through+		FALLTHROUGH;+	}  	case SEQ_FOOTER: 		// Copy the Stream Footer field into coder->temp.@@ -414,7 +412,7 @@ 				return LZMA_SEEK_NEEDED; 		} -	// Fall through+		FALLTHROUGH;  	case SEQ_INDEX_INIT: { 		// Calculate the amount of memory already used by the earlier@@ -444,10 +442,9 @@  		coder->index_remaining = coder->footer_flags.backward_size; 		coder->sequence = SEQ_INDEX_DECODE;+		FALLTHROUGH; 	} -	// 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@@ -574,9 +571,9 @@ 			return_if_error(reverse_seek(coder, 					in_start, in_pos, in_size)); 		}-	} -	// Fall through+		FALLTHROUGH;+	}  	case SEQ_HEADER_DECODE: 		// Copy the Stream Header field into coder->temp.@@ -596,8 +593,7 @@ 				coder->temp + coder->temp_size)));  		coder->sequence = SEQ_HEADER_COMPARE;--	// Fall through+		FALLTHROUGH;  	case SEQ_HEADER_COMPARE: 		// Compare Stream Header against Stream Footer. They must
cbits/liblzma/common/index_decoder.c view
@@ -93,8 +93,7 @@  		coder->pos = 0; 		coder->sequence = SEQ_MEMUSAGE;--	// Fall through+		FALLTHROUGH;  	case SEQ_MEMUSAGE: 		if (lzma_index_memusage(1, coder->count) > coder->memlimit) {@@ -153,8 +152,7 @@ 	case SEQ_PADDING_INIT: 		coder->pos = lzma_index_padding_size(coder->index); 		coder->sequence = SEQ_PADDING;--	// Fall through+		FALLTHROUGH;  	case SEQ_PADDING: 		if (coder->pos > 0) {@@ -170,8 +168,7 @@ 				*in_pos - in_start, coder->crc32);  		coder->sequence = SEQ_CRC32;--	// Fall through+		FALLTHROUGH;  	case SEQ_CRC32: 		do {
cbits/liblzma/common/index_encoder.c view
@@ -93,8 +93,7 @@ 		}  		coder->sequence = SEQ_UNPADDED;--	// Fall through+		FALLTHROUGH;  	case SEQ_UNPADDED: 	case SEQ_UNCOMPRESSED: {@@ -127,8 +126,7 @@ 				*out_pos - out_start, coder->crc32);  		coder->sequence = SEQ_CRC32;--	// Fall through+		FALLTHROUGH;  	case SEQ_CRC32: 		// We don't use the main loop, because we don't want
cbits/liblzma/common/index_hash.c view
@@ -267,9 +267,9 @@ 		index_hash->pos = (LZMA_VLI_C(4) - index_size_unpadded( 				index_hash->records.count, 				index_hash->records.index_list_size)) & 3;-		index_hash->sequence = SEQ_PADDING; -	// Fall through+		index_hash->sequence = SEQ_PADDING;+		FALLTHROUGH;  	case SEQ_PADDING: 		if (index_hash->pos > 0) {@@ -302,8 +302,7 @@ 				*in_pos - in_start, index_hash->crc32);  		index_hash->sequence = SEQ_CRC32;--	// Fall through+		FALLTHROUGH;  	case SEQ_CRC32: 		do {
cbits/liblzma/common/lzip_decoder.c view
@@ -150,10 +150,9 @@ 		coder->member_size = sizeof(lzip_id_string);  		coder->sequence = SEQ_VERSION;+		FALLTHROUGH; 	} -	// Fall through- 	case SEQ_VERSION: 		if (*in_pos >= in_size) 			return LZMA_OK;@@ -173,7 +172,7 @@ 		if (coder->tell_any_check) 			return LZMA_GET_CHECK; -	// Fall through+		FALLTHROUGH;  	case SEQ_DICT_SIZE: { 		if (*in_pos >= in_size)@@ -220,10 +219,9 @@ 		// LZMA_MEMLIMIT_ERROR we need to be able to restart after 		// the memlimit has been increased. 		coder->sequence = SEQ_CODER_INIT;+		FALLTHROUGH; 	} -	// Fall through- 	case SEQ_CODER_INIT: { 		if (coder->memusage > coder->memlimit) 			return LZMA_MEMLIMIT_ERROR;@@ -243,10 +241,9 @@  		coder->crc32 = 0; 		coder->sequence = SEQ_LZMA_STREAM;+		FALLTHROUGH; 	} -	// Fall through- 	case SEQ_LZMA_STREAM: { 		const size_t in_start = *in_pos; 		const size_t out_start = *out_pos;@@ -273,9 +270,8 @@ 			return ret;  		coder->sequence = SEQ_MEMBER_FOOTER;+		FALLTHROUGH; 	}--	// Fall through  	case SEQ_MEMBER_FOOTER: { 		// The footer of .lz version 0 lacks the Member size field.
cbits/liblzma/common/memcmplen.h view
@@ -58,8 +58,7 @@  #if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \ 		&& (((TUKLIB_GNUC_REQ(3, 4) || defined(__clang__)) \-				&& (defined(__x86_64__) \-					|| defined(__aarch64__))) \+				&& SIZE_MAX == UINT64_MAX) \ 			|| (defined(__INTEL_COMPILER) && defined(__x86_64__)) \ 			|| (defined(__INTEL_COMPILER) && defined(_M_X64)) \ 			|| (defined(_MSC_VER) && (defined(_M_X64) \
cbits/liblzma/common/stream_decoder.c view
@@ -154,9 +154,9 @@  		if (coder->tell_any_check) 			return LZMA_GET_CHECK;-	} -	// Fall through+		FALLTHROUGH;+	}  	case SEQ_BLOCK_HEADER: { 		if (*in_pos >= in_size)@@ -187,10 +187,9 @@  		coder->pos = 0; 		coder->sequence = SEQ_BLOCK_INIT;+		FALLTHROUGH; 	} -	// Fall through- 	case SEQ_BLOCK_INIT: { 		// Checking memusage and doing the initialization needs 		// its own sequence point because we need to be able to@@ -252,10 +251,9 @@ 			return ret;  		coder->sequence = SEQ_BLOCK_RUN;+		FALLTHROUGH; 	} -	// Fall through- 	case SEQ_BLOCK_RUN: { 		const lzma_ret ret = coder->block_decoder.code( 				coder->block_decoder.coder, allocator,@@ -291,10 +289,9 @@ 			return ret;  		coder->sequence = SEQ_STREAM_FOOTER;+		FALLTHROUGH; 	} -	// Fall through- 	case SEQ_STREAM_FOOTER: { 		// Copy the Stream Footer to the internal buffer. 		lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,@@ -331,9 +328,8 @@ 			return LZMA_STREAM_END;  		coder->sequence = SEQ_STREAM_PADDING;+		FALLTHROUGH; 	}--	// Fall through  	case SEQ_STREAM_PADDING: 		assert(coder->concatenated);
cbits/liblzma/common/stream_decoder_mt.c view
@@ -1077,9 +1077,9 @@  		if (coder->tell_any_check) 			return LZMA_GET_CHECK;-	} -	// Fall through+		FALLTHROUGH;+	}  	case SEQ_BLOCK_HEADER: { 		const size_t in_old = *in_pos;@@ -1214,10 +1214,9 @@ 		}  		coder->sequence = SEQ_BLOCK_INIT;+		FALLTHROUGH; 	} -	// Fall through- 	case SEQ_BLOCK_INIT: { 		// Check if decoding is possible at all with the current 		// memlimit_stop which we must never exceed.@@ -1303,10 +1302,9 @@ 		}  		coder->sequence = SEQ_BLOCK_THR_INIT;+		FALLTHROUGH; 	} -	// 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@@ -1508,10 +1506,9 @@ 		}  		coder->sequence = SEQ_BLOCK_THR_RUN;+		FALLTHROUGH; 	} -	// 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@@ -1613,10 +1610,9 @@ 		coder->mem_direct_mode = coder->mem_next_filters;  		coder->sequence = SEQ_BLOCK_DIRECT_RUN;+		FALLTHROUGH; 	} -	// Fall through- 	case SEQ_BLOCK_DIRECT_RUN: { 		const size_t in_old = *in_pos; 		const size_t out_old = *out_pos;@@ -1652,8 +1648,7 @@ 			return LZMA_OK;  		coder->sequence = SEQ_INDEX_DECODE;--	// Fall through+		FALLTHROUGH;  	case SEQ_INDEX_DECODE: { 		// If we don't have any input, don't call@@ -1672,10 +1667,9 @@ 			return ret;  		coder->sequence = SEQ_STREAM_FOOTER;+		FALLTHROUGH; 	} -	// Fall through- 	case SEQ_STREAM_FOOTER: { 		// Copy the Stream Footer to the internal buffer. 		const size_t in_old = *in_pos;@@ -1714,9 +1708,8 @@ 			return LZMA_STREAM_END;  		coder->sequence = SEQ_STREAM_PADDING;+		FALLTHROUGH; 	}--	// Fall through  	case SEQ_STREAM_PADDING: 		assert(coder->concatenated);
cbits/liblzma/common/stream_encoder_mt.c view
@@ -731,8 +731,7 @@  		coder->header_pos = 0; 		coder->sequence = SEQ_BLOCK;--	// Fall through+		FALLTHROUGH;  	case SEQ_BLOCK: { 		// Initialized to silence warnings.@@ -851,9 +850,9 @@ 		// to be ready to be copied out. 		coder->progress_out += lzma_index_size(coder->index) 				+ LZMA_STREAM_HEADER_SIZE;-	} -	// Fall through+		FALLTHROUGH;+	}  	case SEQ_INDEX: { 		// Call the Index encoder. It doesn't take any input, so@@ -873,9 +872,8 @@ 			return LZMA_PROG_ERROR;  		coder->sequence = SEQ_STREAM_FOOTER;+		FALLTHROUGH; 	}--	// Fall through  	case SEQ_STREAM_FOOTER: 		lzma_bufcpy(coder->header, &coder->header_pos,
cbits/liblzma/common/string_conversion.c view
@@ -12,6 +12,11 @@ #include "filter_common.h"  +// liblzma itself doesn't use gettext to translate messages.+// Mark the strings still so that xz can translate them.+#define N_(msgid) msgid++ ///////////////////// // String building // /////////////////////@@ -319,7 +324,7 @@ 	assert(*str < str_end);  	if (!(**str >= '0' && **str <= '9'))-		return "Unsupported preset";+		return N_("Unsupported preset");  	*preset = (uint32_t)(**str - '0'); @@ -331,7 +336,7 @@ 			break;  		default:-			return "Unsupported preset flag";+			return N_("Unsupported flag in the preset"); 		} 	} @@ -350,7 +355,7 @@  	lzma_options_lzma *opts = filter_options; 	if (lzma_lzma_preset(opts, preset))-		return "Unsupported preset";+		return N_("Unsupported preset");  	return NULL; }@@ -442,7 +447,7 @@ 		return errmsg;  	if (opts->lc + opts->lp > LZMA_LCLP_MAX)-		return "The sum of lc and lp must not exceed 4";+		return N_("The sum of lc and lp must not exceed 4");  	return NULL; }@@ -578,21 +583,21 @@ 		// Fail if the '=' wasn't found or the option name is missing 		// (the first char is '='). 		if (equals_sign == NULL || **str == '=')-			return "Options must be 'name=value' pairs separated "-					"with commas";+			return N_("Options must be 'name=value' pairs "+					"separated with commas");  		// Reject a too long option name so that the memcmp() 		// in the loop below won't read past the end of the 		// string in optmap[i].name. 		const size_t name_len = (size_t)(equals_sign - *str); 		if (name_len > NAME_LEN_MAX)-			return "Unknown option name";+			return N_("Unknown option name");  		// Find the option name from optmap[]. 		size_t i = 0; 		while (true) { 			if (i == optmap_size)-				return "Unknown option name";+				return N_("Unknown option name");  			if (memcmp(*str, optmap[i].name, name_len) == 0 					&& optmap[i].name[name_len] == '\0')@@ -609,7 +614,7 @@ 		// string so check it here. 		const size_t value_len = (size_t)(name_eq_value_end - *str); 		if (value_len == 0)-			return "Option value cannot be empty";+			return N_("Option value cannot be empty");  		// LZMA1/2 preset has its own parsing function. 		if (optmap[i].type == OPTMAP_TYPE_LZMA_PRESET) {@@ -630,14 +635,14 @@ 			// in the loop below won't read past the end of the 			// string in optmap[i].u.map[j].name. 			if (value_len > NAME_LEN_MAX)-				return "Invalid option value";+				return N_("Invalid option value");  			const name_value_map *map = optmap[i].u.map; 			size_t j = 0; 			while (true) { 				// The array is terminated with an empty name. 				if (map[j].name[0] == '\0')-					return "Invalid option value";+					return N_("Invalid option value");  				if (memcmp(*str, map[j].name, value_len) == 0 						&& map[j].name[value_len]@@ -651,7 +656,8 @@ 		} else if (**str < '0' || **str > '9') { 			// Note that "max" isn't supported while it is 			// supported in xz. It's not useful here.-			return "Value is not a non-negative decimal integer";+			return N_("Value is not a non-negative "+					"decimal integer"); 		} else { 			// strtoul() has locale-specific behavior so it cannot 			// be relied on to get reproducible results since we@@ -665,13 +671,13 @@ 			v = 0; 			do { 				if (v > UINT32_MAX / 10)-					return "Value out of range";+					return N_("Value out of range");  				v *= 10;  				const uint32_t add = (uint32_t)(*p - '0'); 				if (UINT32_MAX - add < v)-					return "Value out of range";+					return N_("Value out of range");  				v += add; 				++p;@@ -696,8 +702,9 @@ 				if ((optmap[i].flags & OPTMAP_USE_BYTE_SUFFIX) 						== 0) { 					*str = multiplier_start;-					return "This option does not support "-						"any integer suffixes";+					return N_("This option does not "+						"support any multiplier "+						"suffixes"); 				}  				uint32_t shift;@@ -720,8 +727,13 @@  				default: 					*str = multiplier_start;-					return "Invalid multiplier suffix "-							"(KiB, MiB, or GiB)";++					// TRANSLATORS: Don't translate the+					// suffixes "KiB", "MiB", or "GiB"+					// because a user can only specify+					// untranslated suffixes.+					return N_("Invalid multiplier suffix "+							"(KiB, MiB, or GiB)"); 				}  				++p;@@ -740,19 +752,19 @@ 				// Now we must have no chars remaining. 				if (p < name_eq_value_end) { 					*str = multiplier_start;-					return "Invalid multiplier suffix "-							"(KiB, MiB, or GiB)";+					return N_("Invalid multiplier suffix "+							"(KiB, MiB, or GiB)"); 				}  				if (v > (UINT32_MAX >> shift))-					return "Value out of range";+					return N_("Value out of range");  				v <<= shift; 			}  			if (v < optmap[i].u.range.min 					|| v > optmap[i].u.range.max)-				return "Value out of range";+				return N_("Value out of range"); 		}  		// Set the value in filter_options. Enums are handled@@ -814,15 +826,15 @@ 	// string in filter_name_map[i].name. 	const size_t name_len = (size_t)(name_end - *str); 	if (name_len > NAME_LEN_MAX)-		return "Unknown filter name";+		return N_("Unknown filter name");  	for (size_t i = 0; i < ARRAY_SIZE(filter_name_map); ++i) { 		if (memcmp(*str, filter_name_map[i].name, name_len) == 0 				&& filter_name_map[i].name[name_len] == '\0') { 			if (only_xz && filter_name_map[i].id 					>= LZMA_FILTER_RESERVED_START)-				return "This filter cannot be used in "-						"the .xz format";+				return N_("This filter cannot be used in "+						"the .xz format");  			// Allocate the filter-specific options and 			// initialize the memory with zeros.@@ -830,7 +842,7 @@ 					filter_name_map[i].opts_size, 					allocator); 			if (options == NULL)-				return "Memory allocation failed";+				return N_("Memory allocation failed");  			// Filter name was found so the input string is good 			// at least this far.@@ -850,7 +862,7 @@ 		} 	} -	return "Unknown filter name";+	return N_("Unknown filter name"); }  @@ -869,8 +881,8 @@ 		++*str;  	if (**str == '\0')-		return "Empty string is not allowed, "-				"try \"6\" if a default value is needed";+		return N_("Empty string is not allowed, "+				"try '6' if a default value is needed");  	// Detect the type of the string. 	//@@ -893,7 +905,7 @@ 			// there are no chars other than spaces. 			for (size_t i = 1; str_end[i] != '\0'; ++i) 				if (str_end[i] != ' ')-					return "Unsupported preset";+					return N_("Unsupported preset"); 		} else { 			// There are no trailing spaces. Use the whole string. 			str_end = *str + str_len;@@ -906,11 +918,11 @@  		lzma_options_lzma *opts = lzma_alloc(sizeof(*opts), allocator); 		if (opts == NULL)-			return "Memory allocation failed";+			return N_("Memory allocation failed");  		if (lzma_lzma_preset(opts, preset)) { 			lzma_free(opts, allocator);-			return "Unsupported preset";+			return N_("Unsupported preset"); 		}  		filters[0].id = LZMA_FILTER_LZMA2;@@ -934,7 +946,7 @@ 	size_t i = 0; 	do { 		if (i == LZMA_FILTERS_MAX) {-			errmsg = "The maximum number of filters is four";+			errmsg = N_("The maximum number of filters is four"); 			goto error; 		} @@ -956,7 +968,7 @@ 		// Inputs that have "--" at the end or "-- " in the middle 		// will result in an empty filter name. 		if (filter_end == *str) {-			errmsg = "Filter name is missing";+			errmsg = N_("Filter name is missing"); 			goto error; 		} @@ -983,8 +995,8 @@ 		const lzma_ret ret = lzma_validate_chain(temp_filters, &dummy); 		assert(ret == LZMA_OK || ret == LZMA_OPTIONS_ERROR); 		if (ret != LZMA_OK) {-			errmsg = "Invalid filter chain "-					"('lzma2' missing at the end?)";+			errmsg = N_("Invalid filter chain "+					"('lzma2' missing at the end?)"); 			goto error; 		} 	}@@ -1012,17 +1024,26 @@ 	if (error_pos != NULL) 		*error_pos = 0; -	if (str == NULL || filters == NULL)+	if (str == NULL || filters == NULL) {+		// Don't translate this because it's only shown in case of+		// a programming error. 		return "Unexpected NULL pointer argument(s) " 				"to lzma_str_to_filters()";+	}  	// Validate the flags. 	const uint32_t supported_flags 			= LZMA_STR_ALL_FILTERS 			| LZMA_STR_NO_VALIDATION; -	if (flags & ~supported_flags)+	if (flags & ~supported_flags) {+		// This message is possible only if the caller uses flags+		// that are only supported in a newer liblzma version (or+		// the flags are simply buggy). Don't translate this at least+		// when liblzma itself doesn't use gettext; xz and liblzma+		// are usually upgraded at the same time. 		return "Unsupported flags to lzma_str_to_filters()";+	}  	const char *used = str; 	const char *errmsg = str_to_filters(&used, filters, flags, allocator);
cbits/liblzma/lz/lz_decoder.c view
@@ -53,9 +53,9 @@ static void lz_decoder_reset(lzma_coder *coder) {-	coder->dict.pos = 2 * LZ_DICT_REPEAT_MAX;+	coder->dict.pos = LZ_DICT_INIT_POS; 	coder->dict.full = 0;-	coder->dict.buf[2 * LZ_DICT_REPEAT_MAX - 1] = '\0';+	coder->dict.buf[LZ_DICT_INIT_POS - 1] = '\0'; 	coder->dict.has_wrapped = false; 	coder->dict.need_reset = false; 	return;@@ -261,10 +261,12 @@ 	// recommended to give aligned buffers to liblzma. 	// 	// Reserve 2 * LZ_DICT_REPEAT_MAX bytes of extra space which is-	// needed for alloc_size.+	// needed for alloc_size. Reserve also LZ_DICT_EXTRA bytes of extra+	// space which is *not* counted in alloc_size or coder->dict.size. 	// 	// Avoid integer overflow.-	if (lz_options.dict_size > SIZE_MAX - 15 - 2 * LZ_DICT_REPEAT_MAX)+	if (lz_options.dict_size > SIZE_MAX - 15 - 2 * LZ_DICT_REPEAT_MAX+			- LZ_DICT_EXTRA) 		return LZMA_MEM_ERROR;  	lz_options.dict_size = (lz_options.dict_size + 15) & ~((size_t)(15));@@ -277,7 +279,13 @@ 	// Allocate and initialize the dictionary. 	if (coder->dict.size != alloc_size) { 		lzma_free(coder->dict.buf, allocator);-		coder->dict.buf = lzma_alloc(alloc_size, allocator);++		// The LZ_DICT_EXTRA bytes at the end of the buffer aren't+		// included in alloc_size. These extra bytes allow+		// dict_repeat() to read and write more data than requested.+		// Otherwise this extra space is ignored.+		coder->dict.buf = lzma_alloc(alloc_size + LZ_DICT_EXTRA,+				allocator); 		if (coder->dict.buf == NULL) 			return LZMA_MEM_ERROR; @@ -320,5 +328,6 @@ extern uint64_t lzma_lz_decoder_memusage(size_t dictionary_size) {-	return sizeof(lzma_coder) + (uint64_t)(dictionary_size);+	return sizeof(lzma_coder) + (uint64_t)(dictionary_size)+			+ 2 * LZ_DICT_REPEAT_MAX + LZ_DICT_EXTRA; }
cbits/liblzma/lz/lz_decoder.h view
@@ -15,11 +15,41 @@  #include "common.h" +#ifdef HAVE_IMMINTRIN_H+#	include <immintrin.h>+#endif -/// Maximum length of a match rounded up to a nice power of 2 which is-/// a good size for aligned memcpy(). The allocated dictionary buffer will-/// be 2 * LZ_DICT_REPEAT_MAX bytes larger than the actual dictionary size:++// dict_repeat() implementation variant:+// 0 = Byte-by-byte copying only.+// 1 = Use memcpy() for non-overlapping copies.+// 2 = Use x86 SSE2 for non-overlapping copies.+#ifndef LZMA_LZ_DECODER_CONFIG+#	if defined(TUKLIB_FAST_UNALIGNED_ACCESS) \+		&& defined(HAVE_IMMINTRIN_H) \+		&& (defined(__SSE2__) || defined(_M_X64) \+			|| (defined(_M_IX86_FP) && _M_IX86_FP >= 2))+#		define LZMA_LZ_DECODER_CONFIG 2+#	else+#		define LZMA_LZ_DECODER_CONFIG 1+#	endif+#endif++/// Byte-by-byte and memcpy() copy exactly the amount needed. Other methods+/// can copy up to LZ_DICT_EXTRA bytes more than requested, and this amount+/// of extra space is needed at the end of the allocated dictionary buffer. ///+/// NOTE: If this is increased, update LZMA_DICT_REPEAT_MAX too.+#if LZMA_LZ_DECODER_CONFIG >= 2+#	define LZ_DICT_EXTRA 32+#else+#	define LZ_DICT_EXTRA 0+#endif++/// Maximum number of bytes that dict_repeat() may copy. The allocated+/// dictionary buffer will be 2 * LZ_DICT_REPEAT_MAX + LZMA_DICT_EXTRA bytes+/// larger than the actual dictionary size:+/// /// (1) Every time the decoder reaches the end of the dictionary buffer, ///     the last LZ_DICT_REPEAT_MAX bytes will be copied to the beginning. ///     This way dict_repeat() will only need to copy from one place,@@ -27,15 +57,27 @@ /// /// (2) The other LZ_DICT_REPEAT_MAX bytes is kept as a buffer between ///     the oldest byte still in the dictionary and the current write-///     position. This way dict_repeat(dict, dict->size - 1, &len)+///     position. This way dict_repeat() with the maximum valid distance ///     won't need memmove() as the copying cannot overlap. ///+/// (3) LZ_DICT_EXTRA bytes are required at the end of the dictionary buffer+///     so that extra copying done by dict_repeat() won't write or read past+///     the end of the allocated buffer. This amount is *not* counted as part+///     of lzma_dict.size.+/// /// Note that memcpy() still cannot be used if distance < len. ///-/// LZMA's longest match length is 273 so pick a multiple of 16 above that.+/// LZMA's longest match length is 273 bytes. The LZMA decoder looks at+/// the lowest four bits of the dictionary position, thus 273 must be+/// rounded up to the next multiple of 16 (288). In addition, optimized+/// dict_repeat() copies 32 bytes at a time, thus this must also be+/// a multiple of 32. #define LZ_DICT_REPEAT_MAX 288 +/// Initial position in lzma_dict.buf when the dictionary is empty.+#define LZ_DICT_INIT_POS (2 * LZ_DICT_REPEAT_MAX) + typedef struct { 	/// Pointer to the dictionary buffer. 	uint8_t *buf;@@ -158,7 +200,8 @@  /// Repeat *len bytes at distance. static inline bool-dict_repeat(lzma_dict *dict, uint32_t distance, uint32_t *len)+dict_repeat(lzma_dict *restrict dict,+		uint32_t distance, uint32_t *restrict len) { 	// Don't write past the end of the dictionary. 	const size_t dict_avail = dict->limit - dict->pos;@@ -169,9 +212,17 @@ 	if (distance >= dict->pos) 		back += dict->size - LZ_DICT_REPEAT_MAX; -	// Repeat a block of data from the history. Because memcpy() is faster-	// than copying byte by byte in a loop, the copying process gets split-	// into two cases.+#if LZMA_LZ_DECODER_CONFIG == 0+	// Minimal byte-by-byte method. This might be the least bad choice+	// if memcpy() isn't fast and there's no replacement for it below.+	while (left-- > 0) {+		dict->buf[dict->pos++] = dict->buf[back++];+	}++#else+	// Because memcpy() or a similar method can be faster than copying+	// byte by byte in a loop, the copying process is split into+	// two cases. 	if (distance < left) { 		// Source and target areas overlap, thus we can't use 		// memcpy() nor even memmove() safely.@@ -179,32 +230,56 @@ 			dict->buf[dict->pos++] = dict->buf[back++]; 		} while (--left > 0); 	} else {+#	if LZMA_LZ_DECODER_CONFIG == 1 		memcpy(dict->buf + dict->pos, dict->buf + back, left); 		dict->pos += left;++#	elif LZMA_LZ_DECODER_CONFIG == 2+		// This can copy up to 32 bytes more than required.+		// (If left == 0, we still copy 32 bytes.)+		size_t pos = dict->pos;+		dict->pos += left;+		do {+			const __m128i x0 = _mm_loadu_si128(+					(__m128i *)(dict->buf + back));+			const __m128i x1 = _mm_loadu_si128(+					(__m128i *)(dict->buf + back + 16));+			back += 32;+			_mm_storeu_si128(+					(__m128i *)(dict->buf + pos), x0);+			_mm_storeu_si128(+					(__m128i *)(dict->buf + pos + 16), x1);+			pos += 32;+		} while (pos < dict->pos);++#	else+#		error "Invalid LZMA_LZ_DECODER_CONFIG value"+#	endif 	}+#endif  	// Update how full the dictionary is. 	if (!dict->has_wrapped)-		dict->full = dict->pos - 2 * LZ_DICT_REPEAT_MAX;+		dict->full = dict->pos - LZ_DICT_INIT_POS;  	return *len != 0; }   static inline void-dict_put(lzma_dict *dict, uint8_t byte)+dict_put(lzma_dict *restrict dict, uint8_t byte) { 	dict->buf[dict->pos++] = byte;  	if (!dict->has_wrapped)-		dict->full = dict->pos - 2 * LZ_DICT_REPEAT_MAX;+		dict->full = dict->pos - LZ_DICT_INIT_POS; }   /// Puts one byte into the dictionary. Returns true if the dictionary was /// already full and the byte couldn't be added. static inline bool-dict_put_safe(lzma_dict *dict, uint8_t byte)+dict_put_safe(lzma_dict *restrict dict, uint8_t byte) { 	if (unlikely(dict->pos == dict->limit)) 		return true;@@ -234,7 +309,7 @@ 			dict->buf, &dict->pos, dict->limit);  	if (!dict->has_wrapped)-		dict->full = dict->pos - 2 * LZ_DICT_REPEAT_MAX;+		dict->full = dict->pos - LZ_DICT_INIT_POS;  	return; }
cbits/liblzma/lz/lz_encoder.c view
@@ -15,7 +15,7 @@  // See lz_encoder_hash.h. This is a bit hackish but avoids making // endianness a conditional in makefiles.-#if defined(WORDS_BIGENDIAN) && !defined(HAVE_SMALL)+#ifdef LZMA_LZ_HASH_TABLE_IS_NEEDED #	include "lz_encoder_hash_table.h" #endif 
cbits/liblzma/lz/lz_encoder_hash.h view
@@ -5,23 +5,37 @@ /// \file       lz_encoder_hash.h /// \brief      Hash macros for match finders //-//  Author:     Igor Pavlov+//  Authors:    Igor Pavlov+//              Lasse Collin // ///////////////////////////////////////////////////////////////////////////////  #ifndef LZMA_LZ_ENCODER_HASH_H #define LZMA_LZ_ENCODER_HASH_H -#if defined(WORDS_BIGENDIAN) && !defined(HAVE_SMALL)-	// This is to make liblzma produce the same output on big endian-	// systems that it does on little endian systems. lz_encoder.c-	// takes care of including the actual table.+// We need to know if CRC32_GENERIC is defined and we may need the declaration+// of lzma_crc32_table[][].+#include "crc_common.h"++// If HAVE_SMALL is defined, then lzma_crc32_table[][] exists and+// it's little endian even on big endian systems.+//+// If HAVE_SMALL isn't defined, lzma_crc32_table[][] is in native endian+// but we want a little endian one so that the compressed output won't+// depend on the processor endianness. Big endian systems are less common+// so those get the burden of an extra 1 KiB table.+//+// If HAVE_SMALL isn't defined and CRC32_GENERIC isn't defined either,+// then lzma_crc32_table[][] doesn't exist.+#if defined(HAVE_SMALL) \+		|| (defined(CRC32_GENERIC) && !defined(WORDS_BIGENDIAN))+#	define hash_table lzma_crc32_table[0]+#else+	// lz_encoder.c takes care of including the actual table. 	lzma_attr_visibility_hidden 	extern const uint32_t lzma_lz_hash_table[256]; #	define hash_table lzma_lz_hash_table-#else-#	include "check.h"-#	define hash_table lzma_crc32_table[0]+#	define LZMA_LZ_HASH_TABLE_IS_NEEDED 1 #endif  #define HASH_2_SIZE (UINT32_C(1) << 10)
cbits/liblzma/lzma/lzma2_encoder.c view
@@ -159,8 +159,7 @@ 		coder->uncompressed_size = 0; 		coder->compressed_size = 0; 		coder->sequence = SEQ_LZMA_ENCODE;--	// Fall through+		FALLTHROUGH;  	case SEQ_LZMA_ENCODE: { 		// Calculate how much more uncompressed data this chunk@@ -219,10 +218,9 @@ 		lzma2_header_lzma(coder);  		coder->sequence = SEQ_LZMA_COPY;+		FALLTHROUGH; 	} -	// Fall through- 	case SEQ_LZMA_COPY: 		// Copy the compressed chunk along its headers to the 		// output buffer.@@ -244,8 +242,7 @@ 			return LZMA_OK;  		coder->sequence = SEQ_UNCOMPRESSED_COPY;--	// Fall through+		FALLTHROUGH;  	case SEQ_UNCOMPRESSED_COPY: 		// Copy the uncompressed data as is from the dictionary
cbits/liblzma/simple/arm.c view
@@ -18,8 +18,10 @@ 		uint32_t now_pos, bool is_encoder, 		uint8_t *buffer, size_t size) {+	size &= ~(size_t)3;+ 	size_t i;-	for (i = 0; i + 4 <= size; i += 4) {+	for (i = 0; i < size; i += 4) { 		if (buffer[i + 3] == 0xEB) { 			uint32_t src = ((uint32_t)(buffer[i + 2]) << 16) 					| ((uint32_t)(buffer[i + 1]) << 8)
cbits/liblzma/simple/arm64.c view
@@ -28,6 +28,8 @@ 		uint32_t now_pos, bool is_encoder, 		uint8_t *buffer, size_t size) {+	size &= ~(size_t)3;+ 	size_t i;  	// Clang 14.0.6 on x86-64 makes this four times bigger and 40 % slower@@ -37,7 +39,7 @@ #ifdef __clang__ #	pragma clang loop vectorize(disable) #endif-	for (i = 0; i + 4 <= size; i += 4) {+	for (i = 0; i < size; i += 4) { 		uint32_t pc = (uint32_t)(now_pos + i); 		uint32_t instr = read32le(buffer + i); @@ -122,6 +124,15 @@ { 	return arm64_coder_init(next, allocator, filters, true); }+++extern LZMA_API(size_t)+lzma_bcj_arm64_encode(uint32_t start_offset, uint8_t *buf, size_t size)+{+	// start_offset must be a multiple of four.+	start_offset &= ~UINT32_C(3);+	return arm64_code(NULL, start_offset, true, buf, size);+} #endif  @@ -132,5 +143,14 @@ 		const lzma_filter_info *filters) { 	return arm64_coder_init(next, allocator, filters, false);+}+++extern LZMA_API(size_t)+lzma_bcj_arm64_decode(uint32_t start_offset, uint8_t *buf, size_t size)+{+	// start_offset must be a multiple of four.+	start_offset &= ~UINT32_C(3);+	return arm64_code(NULL, start_offset, false, buf, size); } #endif
cbits/liblzma/simple/armthumb.c view
@@ -18,8 +18,13 @@ 		uint32_t now_pos, bool is_encoder, 		uint8_t *buffer, size_t size) {+	if (size < 4)+		return 0;++	size -= 4;+ 	size_t i;-	for (i = 0; i + 4 <= size; i += 2) {+	for (i = 0; i <= size; i += 2) { 		if ((buffer[i + 1] & 0xF8) == 0xF0 				&& (buffer[i + 3] & 0xF8) == 0xF8) { 			uint32_t src = (((uint32_t)(buffer[i + 1]) & 7) << 19)
cbits/liblzma/simple/ia64.c view
@@ -25,8 +25,10 @@ 		4, 4, 0, 0, 4, 4, 0, 0 	}; +	size &= ~(size_t)15;+ 	size_t i;-	for (i = 0; i + 16 <= size; i += 16) {+	for (i = 0; i < size; i += 16) { 		const uint32_t instr_template = buffer[i] & 0x1F; 		const uint32_t mask = BRANCH_TABLE[instr_template]; 		uint32_t bit_pos = 5;
cbits/liblzma/simple/powerpc.c view
@@ -18,8 +18,10 @@ 		uint32_t now_pos, bool is_encoder, 		uint8_t *buffer, size_t size) {+	size &= ~(size_t)3;+ 	size_t i;-	for (i = 0; i + 4 <= size; i += 4) {+	for (i = 0; i < size; i += 4) { 		// PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link) 		if ((buffer[i] >> 2) == 0x12 				&& ((buffer[i + 3] & 3) == 1)) {
cbits/liblzma/simple/riscv.c view
@@ -617,6 +617,15 @@ 	return lzma_simple_coder_init(next, allocator, filters, 			&riscv_encode, 0, 8, 2, true); }+++extern LZMA_API(size_t)+lzma_bcj_riscv_encode(uint32_t start_offset, uint8_t *buf, size_t size)+{+	// start_offset must be a multiple of two.+	start_offset &= ~UINT32_C(1);+	return riscv_encode(NULL, start_offset, true, buf, size);+} #endif  @@ -751,5 +760,14 @@ { 	return lzma_simple_coder_init(next, allocator, filters, 			&riscv_decode, 0, 8, 2, false);+}+++extern LZMA_API(size_t)+lzma_bcj_riscv_decode(uint32_t start_offset, uint8_t *buf, size_t size)+{+	// start_offset must be a multiple of two.+	start_offset &= ~UINT32_C(1);+	return riscv_decode(NULL, start_offset, false, buf, size); } #endif
cbits/liblzma/simple/sparc.c view
@@ -18,9 +18,10 @@ 		uint32_t now_pos, bool is_encoder, 		uint8_t *buffer, size_t size) {-	size_t i;-	for (i = 0; i + 4 <= size; i += 4) {+	size &= ~(size_t)3; +	size_t i;+	for (i = 0; i < size; i += 4) { 		if ((buffer[i] == 0x40 && (buffer[i + 1] & 0xC0) == 0x00) 				|| (buffer[i] == 0x7F 				&& (buffer[i + 1] & 0xC0) == 0xC0)) {
cbits/liblzma/simple/x86.c view
@@ -143,6 +143,18 @@ { 	return x86_coder_init(next, allocator, filters, true); }+++extern LZMA_API(size_t)+lzma_bcj_x86_encode(uint32_t start_offset, uint8_t *buf, size_t size)+{+	lzma_simple_x86 simple = {+		.prev_mask = 0,+		.prev_pos = (uint32_t)(-5),+	};++	return x86_code(&simple, start_offset, true, buf, size);+} #endif  @@ -153,5 +165,17 @@ 		const lzma_filter_info *filters) { 	return x86_coder_init(next, allocator, filters, false);+}+++extern LZMA_API(size_t)+lzma_bcj_x86_decode(uint32_t start_offset, uint8_t *buf, size_t size)+{+	lzma_simple_x86 simple = {+		.prev_mask = 0,+		.prev_pos = (uint32_t)(-5),+	};++	return x86_code(&simple, start_offset, false, buf, size); } #endif
configure view
@@ -4903,22 +4903,22 @@ else case e in #(   e) gl_test_posix_shell_script='        func_return () {-	 (exit $1)+         (exit $1)        }        func_success () {-	 func_return 0+         func_return 0        }        func_failure () {-	 func_return 1+         func_return 1        }        func_ret_success () {-	 return 0+         return 0        }        func_ret_failure () {-	 return 1+         return 1        }        subshell_umask_sanity () {-	 (umask 22; (umask 0); test $(umask) -eq 22)+         (umask 22; (umask 0); test $(umask) -eq 22)        }        test "$(echo foo)" = foo &&        func_success &&@@ -4929,11 +4929,11 @@        subshell_umask_sanity      '      for gl_cv_posix_shell in \-	 "$CONFIG_SHELL" "$SHELL" /bin/sh /bin/bash /bin/ksh /bin/sh5 no; do+         "$CONFIG_SHELL" "$SHELL" /bin/sh /bin/bash /bin/ksh /bin/sh5 no; do        case $gl_cv_posix_shell in          /*)-	   "$gl_cv_posix_shell" -c "$gl_test_posix_shell_script" 2>/dev/null \-	     && break;;+           "$gl_cv_posix_shell" -c "$gl_test_posix_shell_script" 2>/dev/null \+             && break;;        esac      done ;; esac@@ -20052,8 +20052,6 @@ esac  -  gl_replace_getopt=-   if test -z "$gl_replace_getopt"; then            for ac_header in getopt.h do :@@ -21117,6 +21115,12 @@ if test "x$ac_cv_func_wcwidth" = xyes then :   printf "%s\n" "#define HAVE_WCWIDTH 1" >>confdefs.h++fi+ac_fn_c_check_func "$LINENO" "vasprintf" "ac_cv_func_vasprintf"+if test "x$ac_cv_func_vasprintf" = xyes+then :+  printf "%s\n" "#define HAVE_VASPRINTF 1" >>confdefs.h  fi 
xz-clib.cabal view
@@ -1,6 +1,6 @@ cabal-version:       2.2 name:                xz-clib-version:             5.6.4+version:             5.8.0  synopsis:            LZMA/XZ clibs description:         C source code for the LZMA/XZ compression and decompression library@@ -54,12 +54,13 @@   default-language:    Haskell2010   c-sources:     cbits/common/tuklib_cpucores.c+    cbits/common/tuklib_mbstr_nonprint.c+    cbits/common/tuklib_mbstr_wrap.c     cbits/common/tuklib_physmem.c     cbits/liblzma/check/check.c     cbits/liblzma/check/crc32_fast.c-    cbits/liblzma/check/crc32_table.c     cbits/liblzma/check/crc64_fast.c-    cbits/liblzma/check/crc64_table.c+    cbits/liblzma/check/crc_clmul_consts_gen.c     cbits/liblzma/check/sha256.c     cbits/liblzma/common/alone_decoder.c     cbits/liblzma/common/alone_encoder.c