From e72590b57929619d29728f43d8e718665078ea66 Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Sun, 20 Oct 2019 23:48:36 +0300 Subject: userspace/Makefile: Add bytetest.o to "make clean". Thanks to DU HUANPENG. --- userspace/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/userspace/Makefile b/userspace/Makefile index 5bd6b28..8bfb98b 100644 --- a/userspace/Makefile +++ b/userspace/Makefile @@ -44,5 +44,5 @@ boottest: $(BOOTTEST_OBJS) $(COMMON_SRCS) .PHONY: clean clean: - -$(RM) $(COMMON_OBJS) $(XZMINIDEC_OBJS) $(BUFTEST_OBJS) \ - $(BOOTTEST_OBJS) $(PROGRAMS) + -$(RM) $(COMMON_OBJS) $(XZMINIDEC_OBJS) $(BYTETEST_OBJS) \ + $(BUFTEST_OBJS) $(BOOTTEST_OBJS) $(PROGRAMS) -- cgit v1.2.3 From 525549dce62c134ebe26255deab0eb795d92599d Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Wed, 30 Oct 2019 18:15:25 +0200 Subject: Add bytetest to .gitignore. Thanks to DU HUANPENG. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 056aaef..357fc0b 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ modules.order xzminidec buftest boottest +bytetest -- cgit v1.2.3 From 40d291b609d0cc6344f3e26ed34b4fd755e403da Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Wed, 30 Oct 2019 18:26:56 +0200 Subject: Fix XZ_DYN_ALLOC to avoid useless memory reallocations. s->dict.allocated was initialized to 0 but never set after a successful allocation, thus the code always thought that the dictionary buffer has to be reallocated. Thanks to Yu Sun from Cisco Systems for reporting this bug. --- linux/lib/xz/xz_dec_lzma2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/lib/xz/xz_dec_lzma2.c b/linux/lib/xz/xz_dec_lzma2.c index 08c3c80..156f26f 100644 --- a/linux/lib/xz/xz_dec_lzma2.c +++ b/linux/lib/xz/xz_dec_lzma2.c @@ -1146,6 +1146,7 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s, uint8_t props) if (DEC_IS_DYNALLOC(s->dict.mode)) { if (s->dict.allocated < s->dict.size) { + s->dict.allocated = s->dict.size; vfree(s->dict.buf); s->dict.buf = vmalloc(s->dict.size); if (s->dict.buf == NULL) { -- cgit v1.2.3 From cfc1499e9fc23d8caa6dfdf1cc3ccf60d6fcd947 Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Mon, 3 Feb 2020 00:18:32 +0200 Subject: Avoid overlapping memcpy() with invalid input with in-place decompression. With valid files, the safety margin described in lib/decompress_unxz.c ensures that these buffers cannot overlap. But if the uncompressed size of the input is larger than the caller thought, which is possible when the input file is invalid/corrupt, the buffers can overlap. Obviously the result will then be garbage (and usually the decoder will return an error too) but no other harm will happen when such an over-run occurs. This change only affects uncompressed LZMA2 chunks and so this should have no effect on performance. --- linux/lib/decompress_unxz.c | 2 +- linux/lib/xz/xz_dec_lzma2.c | 21 +++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/linux/lib/decompress_unxz.c b/linux/lib/decompress_unxz.c index 9f34eb5..3033b20 100644 --- a/linux/lib/decompress_unxz.c +++ b/linux/lib/decompress_unxz.c @@ -167,7 +167,7 @@ * memeq and memzero are not used much and any remotely sane implementation * is fast enough. memcpy/memmove speed matters in multi-call mode, but * the kernel image is decompressed in single-call mode, in which only - * memcpy speed can matter and only if there is a lot of uncompressible data + * memmove speed can matter and only if there is a lot of uncompressible data * (LZMA2 stores uncompressible chunks in uncompressed form). Thus, the * functions below should just be kept small; it's probably not worth * optimizing for speed. diff --git a/linux/lib/xz/xz_dec_lzma2.c b/linux/lib/xz/xz_dec_lzma2.c index 156f26f..dd80989 100644 --- a/linux/lib/xz/xz_dec_lzma2.c +++ b/linux/lib/xz/xz_dec_lzma2.c @@ -387,7 +387,14 @@ static void dict_uncompressed(struct dictionary *dict, struct xz_buf *b, *left -= copy_size; - memcpy(dict->buf + dict->pos, b->in + b->in_pos, copy_size); + /* + * If doing in-place decompression in single-call mode and the + * uncompressed size of the file is larger than the caller + * thought (i.e. it is invalid input!), the buffers below may + * overlap and cause undefined behavior with memcpy(). + * With valid inputs memcpy() would be fine here. + */ + memmove(dict->buf + dict->pos, b->in + b->in_pos, copy_size); dict->pos += copy_size; if (dict->full < dict->pos) @@ -397,7 +404,11 @@ static void dict_uncompressed(struct dictionary *dict, struct xz_buf *b, if (dict->pos == dict->end) dict->pos = 0; - memcpy(b->out + b->out_pos, b->in + b->in_pos, + /* + * Like above but for multi-call mode: use memmove() + * to avoid undefined behavior with invalid input. + */ + memmove(b->out + b->out_pos, b->in + b->in_pos, copy_size); } @@ -421,6 +432,12 @@ static uint32_t dict_flush(struct dictionary *dict, struct xz_buf *b) if (dict->pos == dict->end) dict->pos = 0; + /* + * These buffers cannot overlap even if doing in-place + * decompression because in multi-call mode dict->buf + * has been allocated by us in this file; it's not + * provided by the caller like in single-call mode. + */ memcpy(b->out + b->out_pos, dict->buf + dict->start, copy_size); } -- cgit v1.2.3 From 49443879b6ae9e54aabfb3e89274969cd8d8a12e Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Mon, 2 Nov 2020 17:04:21 +0200 Subject: Drop a duplicated word in a comment in xz.h. Thanks to Randy Dunlap. --- linux/include/linux/xz.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/include/linux/xz.h b/linux/include/linux/xz.h index 0a4b38d..a0eeeca 100644 --- a/linux/include/linux/xz.h +++ b/linux/include/linux/xz.h @@ -32,7 +32,7 @@ extern "C" { * enum xz_mode - Operation mode * * @XZ_SINGLE: Single-call mode. This uses less RAM than - * than multi-call modes, because the LZMA2 + * multi-call modes, because the LZMA2 * dictionary doesn't need to be allocated as * part of the decoder state. All required data * structures are allocated at initialization, -- cgit v1.2.3 From 090e6a054d6283b144d20f5783852b95eade90ee Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Mon, 2 Nov 2020 18:33:36 +0200 Subject: Convert HTTP links to HTTPS links. Thanks to Alexander A. Klimov. --- linux/Documentation/xz.txt | 6 +++--- linux/include/linux/xz.h | 2 +- linux/lib/xz/xz_crc32.c | 2 +- linux/lib/xz/xz_crc64.c | 2 +- linux/lib/xz/xz_dec_bcj.c | 2 +- linux/lib/xz/xz_dec_lzma2.c | 2 +- linux/lib/xz/xz_lzma2.h | 2 +- linux/lib/xz/xz_stream.h | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/linux/Documentation/xz.txt b/linux/Documentation/xz.txt index 68329ac..1e1a915 100644 --- a/linux/Documentation/xz.txt +++ b/linux/Documentation/xz.txt @@ -13,13 +13,13 @@ Introduction The XZ decompressor in Linux is called XZ Embedded. It supports the LZMA2 filter and optionally also BCJ filters. CRC32 is supported for integrity checking. The home page of XZ Embedded is at - , where you can find the + , where you can find the latest version and also information about using the code outside the Linux kernel. For userspace, XZ Utils provide a zlib-like compression library and a gzip-like command line tool. XZ Utils can be downloaded from - . + . XZ related components in the kernel @@ -107,7 +107,7 @@ Conformance to the .xz file format specification Reporting bugs Before reporting a bug, please check that it's not fixed already - at upstream. See to get the + at upstream. See to get the latest code. Report bugs to or visit #tukaani on diff --git a/linux/include/linux/xz.h b/linux/include/linux/xz.h index a0eeeca..d24b94a 100644 --- a/linux/include/linux/xz.h +++ b/linux/include/linux/xz.h @@ -2,7 +2,7 @@ * XZ decompressor * * Authors: Lasse Collin - * Igor Pavlov + * Igor Pavlov * * This file has been put into the public domain. * You can do whatever you want with this file. diff --git a/linux/lib/xz/xz_crc32.c b/linux/lib/xz/xz_crc32.c index 34532d1..5627b00 100644 --- a/linux/lib/xz/xz_crc32.c +++ b/linux/lib/xz/xz_crc32.c @@ -2,7 +2,7 @@ * CRC32 using the polynomial from IEEE-802.3 * * Authors: Lasse Collin - * Igor Pavlov + * Igor Pavlov * * This file has been put into the public domain. * You can do whatever you want with this file. diff --git a/linux/lib/xz/xz_crc64.c b/linux/lib/xz/xz_crc64.c index ca1caee..215e04d 100644 --- a/linux/lib/xz/xz_crc64.c +++ b/linux/lib/xz/xz_crc64.c @@ -4,7 +4,7 @@ * This file is similar to xz_crc32.c. See the comments there. * * Authors: Lasse Collin - * Igor Pavlov + * Igor Pavlov * * This file has been put into the public domain. * You can do whatever you want with this file. diff --git a/linux/lib/xz/xz_dec_bcj.c b/linux/lib/xz/xz_dec_bcj.c index a768e6d..72ddac6 100644 --- a/linux/lib/xz/xz_dec_bcj.c +++ b/linux/lib/xz/xz_dec_bcj.c @@ -2,7 +2,7 @@ * Branch/Call/Jump (BCJ) filter decoders * * Authors: Lasse Collin - * Igor Pavlov + * Igor Pavlov * * This file has been put into the public domain. * You can do whatever you want with this file. diff --git a/linux/lib/xz/xz_dec_lzma2.c b/linux/lib/xz/xz_dec_lzma2.c index dd80989..2deb544 100644 --- a/linux/lib/xz/xz_dec_lzma2.c +++ b/linux/lib/xz/xz_dec_lzma2.c @@ -2,7 +2,7 @@ * LZMA2 decoder * * Authors: Lasse Collin - * Igor Pavlov + * Igor Pavlov * * This file has been put into the public domain. * You can do whatever you want with this file. diff --git a/linux/lib/xz/xz_lzma2.h b/linux/lib/xz/xz_lzma2.h index 071d67b..92d852d 100644 --- a/linux/lib/xz/xz_lzma2.h +++ b/linux/lib/xz/xz_lzma2.h @@ -2,7 +2,7 @@ * LZMA2 definitions * * Authors: Lasse Collin - * Igor Pavlov + * Igor Pavlov * * This file has been put into the public domain. * You can do whatever you want with this file. diff --git a/linux/lib/xz/xz_stream.h b/linux/lib/xz/xz_stream.h index 66cb5a7..430bb3a 100644 --- a/linux/lib/xz/xz_stream.h +++ b/linux/lib/xz/xz_stream.h @@ -19,7 +19,7 @@ /* * See the .xz file format specification at - * http://tukaani.org/xz/xz-file-format.txt + * https://tukaani.org/xz/xz-file-format.txt * to understand the container format. */ -- cgit v1.2.3 From 82078b6109122ede1f76b76e75e54dcea7fc8d25 Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Mon, 15 Feb 2021 18:08:05 +0200 Subject: xzminidec: Detect read errors from stdin. --- userspace/xzminidec.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/userspace/xzminidec.c b/userspace/xzminidec.c index ba07413..753bbc9 100644 --- a/userspace/xzminidec.c +++ b/userspace/xzminidec.c @@ -61,6 +61,12 @@ int main(int argc, char **argv) while (true) { if (b.in_pos == b.in_size) { b.in_size = fread(in, 1, sizeof(in), stdin); + + if (ferror(stdin)) { + msg = "Read error\n"; + goto error; + } + b.in_pos = 0; } -- cgit v1.2.3 From ef038b9db55bba73e2574ae451d62e16ce9c0ef9 Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Mon, 15 Feb 2021 19:10:05 +0200 Subject: Make xz_crc64.c compatible with -std=gnu89 on 32-bit platforms. When "unsigned long" is 32 bits and GCC or Clang is in gnu89 mode, the 64-bit constant doesn't become "unsigned long long" like it would in C99. This is because in gnu89 mode "unsigned long long" is a GNU extension to C89 and isn't considered when selecting the type of the integer constant. The CRC64 support was added in 2013 and the code has been broken on 32-bit platforms unless one modified the Makefile to set C99 or a newer C standard. I didn't want to omit -std=gnu89 because Linux still uses it and xz_crc64.c (which isn't in Linux) was the only place that wasn't compatible with -std=gnu89. Thanks to bzt for reporting the problem. --- linux/lib/xz/xz_crc64.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/linux/lib/xz/xz_crc64.c b/linux/lib/xz/xz_crc64.c index 215e04d..60c40f6 100644 --- a/linux/lib/xz/xz_crc64.c +++ b/linux/lib/xz/xz_crc64.c @@ -20,7 +20,11 @@ STATIC_RW_DATA uint64_t xz_crc64_table[256]; XZ_EXTERN void xz_crc64_init(void) { - const uint64_t poly = 0xC96C5795D7870F42; + /* + * The ULL suffix is needed for -std=gnu89 compatibility + * on 32-bit platforms. + */ + const uint64_t poly = 0xC96C5795D7870F42ULL; uint32_t i; uint32_t j; -- cgit v1.2.3 From d8a12bc0c61282b38439ee76b05dbde0200002e1 Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Mon, 15 Feb 2021 19:45:13 +0200 Subject: userspace/Makefile: Add a comment about -std=gnu89 and add -Wno-long-long. gcc -std=gnu89 -pedantic warns about the ULL integer constant suffix in xz_crc64.c so silence it with -Wno-long-long. clang -std=gnu89 -pedantic is noisy about C99 features and language extensions. Omitting either option silences all these warnings, so mention this in a comment. --- userspace/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/userspace/Makefile b/userspace/Makefile index 8bfb98b..d39d041 100644 --- a/userspace/Makefile +++ b/userspace/Makefile @@ -7,11 +7,14 @@ # You can do whatever you want with this file. # +# gcc -std=gnu89 is used because Linux uses it. It is fine to omit it as +# the code is also C99/C11 compatible. With clang you may wish to omit +# either -std=gnu89 or -pedantic as having both gives quite a few warnings. CC = gcc -std=gnu89 BCJ_CPPFLAGS = -DXZ_DEC_X86 -DXZ_DEC_POWERPC -DXZ_DEC_IA64 \ -DXZ_DEC_ARM -DXZ_DEC_ARMTHUMB -DXZ_DEC_SPARC CPPFLAGS = -DXZ_USE_CRC64 -DXZ_DEC_ANY_CHECK -CFLAGS = -ggdb3 -O2 -pedantic -Wall -Wextra +CFLAGS = -ggdb3 -O2 -pedantic -Wall -Wextra -Wno-long-long RM = rm -f VPATH = ../linux/include/linux ../linux/lib/xz COMMON_SRCS = xz_crc32.c xz_crc64.c xz_dec_stream.c xz_dec_lzma2.c xz_dec_bcj.c -- cgit v1.2.3 From 6f0e0c41e3682254c2e0be245f275f77df821ffe Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Thu, 6 May 2021 20:18:46 +0300 Subject: Add xz_dec_catrun() to support concatenated .xz files. --- README | 15 +++++++++ linux/include/linux/xz.h | 44 +++++++++++++++++++++++- linux/lib/xz/xz_dec_stream.c | 80 +++++++++++++++++++++++++++++++++++++++++++- userspace/Makefile | 2 +- userspace/xz_config.h | 3 ++ userspace/xzminidec.c | 8 ++++- 6 files changed, 148 insertions(+), 4 deletions(-) diff --git a/README b/README index 566d604..c8ca09c 100644 --- a/README +++ b/README @@ -84,6 +84,21 @@ Embedding into userspace applications environment. Probably you should at least skim through it even if the default file works as is. +Supporting concatenated .xz files + + Regular .xz files can be concatenated as is and the xz command line + tool will decompress all streams from a concatenated file (a few + other popular formats and tools support this too). This kind of .xz + files aren't as uncommon as one might think because pxz, an early + threaded XZ compressor, created this kind of .xz files. + + The xz_dec_run() function will stop after decompressing one stream. + This is good when XZ data is stored inside some other file format. + However, if one is decompressing regular standalone .xz files, one + will want to decompress all streams in the file. This is easy with + xz_dec_catrun(). To include support for xz_dec_catrun(), you need + to #define XZ_DEC_CONCATENATED in xz_config.h or in compiler flags. + Integrity check support XZ Embedded always supports the integrity check types None and diff --git a/linux/include/linux/xz.h b/linux/include/linux/xz.h index d24b94a..8c25dd5 100644 --- a/linux/include/linux/xz.h +++ b/linux/include/linux/xz.h @@ -198,7 +198,7 @@ struct xz_dec; XZ_EXTERN struct xz_dec *xz_dec_init(enum xz_mode mode, uint32_t dict_max); /** - * xz_dec_run() - Run the XZ decoder + * xz_dec_run() - Run the XZ decoder for a single XZ stream * @s: Decoder state allocated using xz_dec_init() * @b: Input and output buffers * @@ -214,9 +214,51 @@ XZ_EXTERN struct xz_dec *xz_dec_init(enum xz_mode mode, uint32_t dict_max); * cannot give the single-call decoder a too small buffer and then expect to * get that amount valid data from the beginning of the stream. You must use * the multi-call decoder if you don't want to uncompress the whole stream. + * + * Use xz_dec_run() when XZ data is stored inside some other file format. + * The decoding will stop after one XZ stream has been decompresed. To + * decompress regular .xz files which might have multiple concatenated + * streams, use xz_dec_catrun() instead. */ XZ_EXTERN enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b); +/** + * xz_dec_catrun() - Run the XZ decoder with support for concatenated streams + * @s: Decoder state allocated using xz_dec_init() + * @b: Input and output buffers + * @finish: This is an int instead of bool to avoid requiring stdbool.h. + * As long as more input might be coming, finish must be false. + * When the caller knows that it has provided all the input to + * the decoder (some possibly still in b->in), it must set finish + * to true. Only when finish is true can this function return + * XZ_STREAM_END to indicate successful decompression of the + * file. In single-call mode (XZ_SINGLE) finish is assumed to + * always be true; the caller-provided value is ignored. + * + * This is like xz_dec_run() except that this makes it easy to decode .xz + * files with multiple streams (multiple .xz files concatenated as is). + * The rarely-used Stream Padding feature is supported too, that is, there + * can be null bytes after or between the streams. The number of null bytes + * must be a multiple of four. + * + * When finish is false and b->in_pos == b->in_size, it is possible that + * XZ_BUF_ERROR isn't returned even when no progress is possible (XZ_OK is + * returned instead). This shouldn't matter because in this situation a + * reasonable caller will attempt to provide more input or set finish to + * true for the next xz_dec_catrun() call anyway. + * + * For any struct xz_dec that has been initialized for multi-call mode: + * Once decoding has been started with xz_dec_run() or xz_dec_catrun(), + * the same function must be used until xz_dec_reset() or xz_dec_end(). + * Switching between the two decoding functions without resetting results + * in undefined behavior. + * + * xz_dec_catrun() is only available if XZ_DEC_CONCATENATED was defined + * at compile time. + */ +XZ_EXTERN enum xz_ret xz_dec_catrun(struct xz_dec *s, struct xz_buf *b, + int finish); + /** * xz_dec_reset() - Reset an already allocated decoder state * @s: Decoder state allocated using xz_dec_init() diff --git a/linux/lib/xz/xz_dec_stream.c b/linux/lib/xz/xz_dec_stream.c index f69581b..e4aab73 100644 --- a/linux/lib/xz/xz_dec_stream.c +++ b/linux/lib/xz/xz_dec_stream.c @@ -35,7 +35,8 @@ struct xz_dec { SEQ_INDEX, SEQ_INDEX_PADDING, SEQ_INDEX_CRC32, - SEQ_STREAM_FOOTER + SEQ_STREAM_FOOTER, + SEQ_STREAM_PADDING } sequence; /* Position in variable-length integers and Check fields */ @@ -742,6 +743,10 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) return XZ_OK; return dec_stream_footer(s); + + case SEQ_STREAM_PADDING: + /* Never reached, only silencing a warning */ + break; } } @@ -809,6 +814,79 @@ XZ_EXTERN enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b) return ret; } +#ifdef XZ_DEC_CONCATENATED +XZ_EXTERN enum xz_ret xz_dec_catrun(struct xz_dec *s, struct xz_buf *b, + int finish) +{ + enum xz_ret ret; + + if (DEC_IS_SINGLE(s->mode)) { + xz_dec_reset(s); + finish = true; + } + + while (true) { + if (s->sequence == SEQ_STREAM_PADDING) { + /* + * Skip Stream Padding. Its size must be a multiple + * of four bytes which is tracked with s->pos. + */ + while (true) { + if (b->in_pos == b->in_size) { + /* + * Note that if we are repeatedly + * given no input and finish is false, + * we will keep returning XZ_OK even + * though no progress is being made. + * The lack of XZ_BUF_ERROR support + * isn't a problem here because a + * reasonable caller will eventually + * provide more input or set finish + * to true. + */ + if (!finish) + return XZ_OK; + + if (s->pos != 0) + return XZ_DATA_ERROR; + + return XZ_STREAM_END; + } + + if (b->in[b->in_pos] != 0x00) { + if (s->pos != 0) + return XZ_DATA_ERROR; + + break; + } + + ++b->in_pos; + s->pos = (s->pos + 1) & 3; + } + + /* + * More input remains. It should be a new Stream. + * + * In single-call mode xz_dec_run() will always call + * xz_dec_reset(). Thus, we need to do it here only + * in multi-call mode. + */ + if (DEC_IS_MULTI(s->mode)) + xz_dec_reset(s); + } + + ret = xz_dec_run(s, b); + + if (ret != XZ_STREAM_END) + break; + + s->sequence = SEQ_STREAM_PADDING; + } + + return ret; +} +#endif + XZ_EXTERN struct xz_dec *xz_dec_init(enum xz_mode mode, uint32_t dict_max) { struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL); diff --git a/userspace/Makefile b/userspace/Makefile index d39d041..1acacf0 100644 --- a/userspace/Makefile +++ b/userspace/Makefile @@ -13,7 +13,7 @@ CC = gcc -std=gnu89 BCJ_CPPFLAGS = -DXZ_DEC_X86 -DXZ_DEC_POWERPC -DXZ_DEC_IA64 \ -DXZ_DEC_ARM -DXZ_DEC_ARMTHUMB -DXZ_DEC_SPARC -CPPFLAGS = -DXZ_USE_CRC64 -DXZ_DEC_ANY_CHECK +CPPFLAGS = -DXZ_USE_CRC64 -DXZ_DEC_ANY_CHECK -DXZ_DEC_CONCATENATED CFLAGS = -ggdb3 -O2 -pedantic -Wall -Wextra -Wno-long-long RM = rm -f VPATH = ../linux/include/linux ../linux/lib/xz diff --git a/userspace/xz_config.h b/userspace/xz_config.h index eb9dac1..ee590d7 100644 --- a/userspace/xz_config.h +++ b/userspace/xz_config.h @@ -10,6 +10,9 @@ #ifndef XZ_CONFIG_H #define XZ_CONFIG_H +/* Uncomment to enable building of xz_dec_catrun(). */ +/* #define XZ_DEC_CONCATENATED */ + /* Uncomment to enable CRC64 support. */ /* #define XZ_USE_CRC64 */ diff --git a/userspace/xzminidec.c b/userspace/xzminidec.c index 753bbc9..b542109 100644 --- a/userspace/xzminidec.c +++ b/userspace/xzminidec.c @@ -70,7 +70,13 @@ int main(int argc, char **argv) b.in_pos = 0; } - ret = xz_dec_run(s, &b); + /* + * There are a few ways to set the "finish" (the third) + * argument. We could use feof(stdin) but testing in_size + * is fine too and may also work in applications that don't + * use FILEs. + */ + ret = xz_dec_catrun(s, &b, b.in_size == 0); if (b.out_pos == sizeof(out)) { if (fwrite(out, 1, b.out_pos, stdout) != b.out_pos) { -- cgit v1.2.3 From 41e657bfaa84cde5907020b7032d58f9245fc26b Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Sun, 20 Jun 2021 21:17:27 +0300 Subject: Fix a typo in a comment. --- linux/lib/xz/xz_dec_lzma2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/lib/xz/xz_dec_lzma2.c b/linux/lib/xz/xz_dec_lzma2.c index 2deb544..42a55f5 100644 --- a/linux/lib/xz/xz_dec_lzma2.c +++ b/linux/lib/xz/xz_dec_lzma2.c @@ -778,7 +778,7 @@ static bool lzma_main(struct xz_dec_lzma2 *s) } /* - * Reset the LZMA decoder and range decoder state. Dictionary is nore reset + * Reset the LZMA decoder and range decoder state. Dictionary is not reset * here, because LZMA state may be reset without resetting the dictionary. */ static void lzma_reset(struct xz_dec_lzma2 *s) -- cgit v1.2.3 From 8122033d26644f970ca192466487218c06a1011e Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Sun, 20 Jun 2021 21:38:40 +0300 Subject: Move s->lzma.len = 0 initialization to lzma_reset(). It's a more logical place even if the resetting needs to be done only once per LZMA2 stream (if lzma_reset() called in the middle of an LZMA2 stream, .len will already be 0). --- linux/lib/xz/xz_dec_lzma2.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/linux/lib/xz/xz_dec_lzma2.c b/linux/lib/xz/xz_dec_lzma2.c index 42a55f5..05cb845 100644 --- a/linux/lib/xz/xz_dec_lzma2.c +++ b/linux/lib/xz/xz_dec_lzma2.c @@ -791,6 +791,7 @@ static void lzma_reset(struct xz_dec_lzma2 *s) s->lzma.rep1 = 0; s->lzma.rep2 = 0; s->lzma.rep3 = 0; + s->lzma.len = 0; /* * All probabilities are initialized to the same value. This hack @@ -1174,8 +1175,6 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s, uint8_t props) } } - s->lzma.len = 0; - s->lzma2.sequence = SEQ_CONTROL; s->lzma2.need_dict_reset = true; -- cgit v1.2.3 From 03d0415b7a4a3616e820e08f39f5309d6d32047b Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Fri, 2 Jul 2021 19:32:08 +0300 Subject: Validate the value before, not after, assigning it to an enum variable. This might matter, for example, if the underlying type of enum xz_check was a signed char. In such a case the validation wouldn't catch an unsupported header. With most compilers it already worked correctly but it's better to change it for portability and conformance. This may increase the code size by a few bytes though. An alternative would be to use an unsigned int instead of enum xz_check but using an enumeration looks cleaner. --- linux/lib/xz/xz_dec_stream.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux/lib/xz/xz_dec_stream.c b/linux/lib/xz/xz_dec_stream.c index e4aab73..2c41f5f 100644 --- a/linux/lib/xz/xz_dec_stream.c +++ b/linux/lib/xz/xz_dec_stream.c @@ -424,12 +424,12 @@ static enum xz_ret dec_stream_header(struct xz_dec *s) * check types too, but then the check won't be verified and * a warning (XZ_UNSUPPORTED_CHECK) will be given. */ + if (s->temp.buf[HEADER_MAGIC_SIZE + 1] > XZ_CHECK_MAX) + return XZ_OPTIONS_ERROR; + s->check_type = s->temp.buf[HEADER_MAGIC_SIZE + 1]; #ifdef XZ_DEC_ANY_CHECK - if (s->check_type > XZ_CHECK_MAX) - return XZ_OPTIONS_ERROR; - if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type)) return XZ_UNSUPPORTED_CHECK; #else -- cgit v1.2.3 From 8f3ed8b1759abe53ff21f6d9eee1b341e8540e8e Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Sun, 19 Sep 2021 21:33:42 +0300 Subject: Add MicroLZMA decoder. MicroLZMA is a yet another header format variant where the first byte of a raw LZMA stream (without the end of stream marker) has been replaced with a bitwise-negation of the lc/lp/pb properties byte. MicroLZMA was created to be used in EROFS but can be used by other things too where wasting minimal amount of space for headers is important. This is implemented using most of the LZMA2 code as is so the amount of new code is small. The API has a few extra features compared to the XZ decoder. On the other hand, the API lacks XZ_BUF_ERROR support which is important to take into account when using this API. MicroLZMA doesn't support BCJ filters. In theory they could be added later as there are many unused/reserved values for the first byte of the compressed stream but in practice it is somewhat unlikely to happen due to a few implementation reasons. Thanks to Gao Xiang (EROFS developer) for testing and feedback. --- linux/include/linux/xz.h | 106 ++++++++++++++++++++++++++++++ linux/lib/xz/Kconfig | 13 ++++ linux/lib/xz/xz_dec_lzma2.c | 156 +++++++++++++++++++++++++++++++++++++++++++- linux/lib/xz/xz_dec_syms.c | 9 ++- linux/lib/xz/xz_private.h | 3 + 5 files changed, 284 insertions(+), 3 deletions(-) diff --git a/linux/include/linux/xz.h b/linux/include/linux/xz.h index 8c25dd5..f3801eb 100644 --- a/linux/include/linux/xz.h +++ b/linux/include/linux/xz.h @@ -279,6 +279,112 @@ XZ_EXTERN void xz_dec_reset(struct xz_dec *s); */ XZ_EXTERN void xz_dec_end(struct xz_dec *s); +/* + * Decompressor for MicroLZMA, an LZMA variant with a very minimal header. + * See xz_dec_microlzma_alloc() below for details. + * + * These functions aren't used or available in preboot code and thus aren't + * marked with XZ_EXTERN. This avoids warnings about static functions that + * are never defined. + */ +/** + * struct xz_dec_microlzma - Opaque type to hold the MicroLZMA decoder state + */ +struct xz_dec_microlzma; + +/** + * xz_dec_microlzma_alloc() - Allocate memory for the MicroLZMA decoder + * @mode XZ_SINGLE or XZ_PREALLOC + * @dict_size LZMA dictionary size. This must be at least 4 KiB and + * at most 3 GiB. + * + * In contrast to xz_dec_init(), this function only allocates the memory + * and remembers the dictionary size. xz_dec_microlzma_reset() must be used + * before calling xz_dec_microlzma_run(). + * + * The amount of allocated memory is a little less than 30 KiB with XZ_SINGLE. + * With XZ_PREALLOC also a dictionary buffer of dict_size bytes is allocated. + * + * On success, xz_dec_microlzma_alloc() returns a pointer to + * struct xz_dec_microlzma. If memory allocation fails or + * dict_size is invalid, NULL is returned. + * + * The compressed format supported by this decoder is a raw LZMA stream + * whose first byte (always 0x00) has been replaced with bitwise-negation + * of the LZMA properties (lc/lp/pb) byte. For example, if lc/lp/pb is + * 3/0/2, the first byte is 0xA2. This way the first byte can never be 0x00. + * Just like with LZMA2, lc + lp <= 4 must be true. The LZMA end-of-stream + * marker must not be used. The unused values are reserved for future use. + * This MicroLZMA header format was created for use in EROFS but may be used + * by others too. + */ +extern struct xz_dec_microlzma *xz_dec_microlzma_alloc(enum xz_mode mode, + uint32_t dict_size); + +/** + * xz_dec_microlzma_reset() - Reset the MicroLZMA decoder state + * @s Decoder state allocated using xz_dec_microlzma_alloc() + * @comp_size Compressed size of the input stream + * @uncomp_size Uncompressed size of the input stream. A value smaller + * than the real uncompressed size of the input stream can + * be specified if uncomp_size_is_exact is set to false. + * uncomp_size can never be set to a value larger than the + * expected real uncompressed size because it would eventually + * result in XZ_DATA_ERROR. + * @uncomp_size_is_exact This is an int instead of bool to avoid + * requiring stdbool.h. This should normally be set to true. + * When this is set to false, error detection is weaker. + */ +extern void xz_dec_microlzma_reset(struct xz_dec_microlzma *s, + uint32_t comp_size, uint32_t uncomp_size, + int uncomp_size_is_exact); + +/** + * xz_dec_microlzma_run() - Run the MicroLZMA decoder + * @s Decoder state initialized using xz_dec_microlzma_reset() + * @b: Input and output buffers + * + * This works similarly to xz_dec_run() with a few important differences. + * Only the differences are documented here. + * + * The only possible return values are XZ_OK, XZ_STREAM_END, and + * XZ_DATA_ERROR. This function cannot return XZ_BUF_ERROR: if no progress + * is possible due to lack of input data or output space, this function will + * keep returning XZ_OK. Thus, the calling code must be written so that it + * will eventually provide input and output space matching (or exceeding) + * comp_size and uncomp_size arguments given to xz_dec_microlzma_reset(). + * If the caller cannot do this (for example, if the input file is truncated + * or otherwise corrupt), the caller must detect this error by itself to + * avoid an infinite loop. + * + * If the compressed data seems to be corrupt, XZ_DATA_ERROR is returned. + * This can happen also when incorrect dictionary, uncompressed, or + * compressed sizes have been specified. + * + * With XZ_PREALLOC only: As an extra feature, b->out may be NULL to skip over + * uncompressed data. This way the caller doesn't need to provide a temporary + * output buffer for the bytes that will be ignored. + * + * With XZ_SINGLE only: In contrast to xz_dec_run(), the return value XZ_OK + * is also possible and thus XZ_SINGLE is actually a limited multi-call mode. + * After XZ_OK the bytes decoded so far may be read from the output buffer. + * It is possible to continue decoding but the variables b->out and b->out_pos + * MUST NOT be changed by the caller. Increasing the value of b->out_size is + * allowed to make more output space available; one doesn't need to provide + * space for the whole uncompressed data on the first call. The input buffer + * may be changed normally like with XZ_PREALLOC. This way input data can be + * provided from non-contiguous memory. + */ +extern enum xz_ret xz_dec_microlzma_run(struct xz_dec_microlzma *s, + struct xz_buf *b); + +/** + * xz_dec_microlzma_end() - Free the memory allocated for the decoder state + * @s: Decoder state allocated using xz_dec_microlzma_alloc(). + * If s is NULL, this function does nothing. + */ +extern void xz_dec_microlzma_end(struct xz_dec_microlzma *s); + /* * Standalone build (userspace build or in-kernel build for boot time use) * needs a CRC32 implementation. For normal in-kernel use, kernel's own diff --git a/linux/lib/xz/Kconfig b/linux/lib/xz/Kconfig index 08837db..3e58caf 100644 --- a/linux/lib/xz/Kconfig +++ b/linux/lib/xz/Kconfig @@ -38,6 +38,19 @@ config XZ_DEC_SPARC default y if SPARC select XZ_DEC_BCJ +config XZ_DEC_MICROLZMA + bool "MicroLZMA decoder" + default n + help + MicroLZMA is a header format variant where the first byte + of a raw LZMA stream (without the end of stream marker) has + been replaced with a bitwise-negation of the lc/lp/pb + properties byte. MicroLZMA was created to be used in EROFS + but can be used by other things too where wasting minimal + amount of space for headers is important. + + Unless you know that you need this, say N. + endif config XZ_DEC_BCJ diff --git a/linux/lib/xz/xz_dec_lzma2.c b/linux/lib/xz/xz_dec_lzma2.c index 05cb845..cf40a2a 100644 --- a/linux/lib/xz/xz_dec_lzma2.c +++ b/linux/lib/xz/xz_dec_lzma2.c @@ -248,6 +248,10 @@ struct lzma2_dec { * before the first LZMA chunk. */ bool need_props; + +#ifdef XZ_DEC_MICROLZMA + bool pedantic_microlzma; +#endif }; struct xz_dec_lzma2 { @@ -419,6 +423,12 @@ static void dict_uncompressed(struct dictionary *dict, struct xz_buf *b, } } +#ifdef XZ_DEC_MICROLZMA +# define DICT_FLUSH_SUPPORTS_SKIPPING true +#else +# define DICT_FLUSH_SUPPORTS_SKIPPING false +#endif + /* * Flush pending data from dictionary to b->out. It is assumed that there is * enough space in b->out. This is guaranteed because caller uses dict_limit() @@ -437,9 +447,14 @@ static uint32_t dict_flush(struct dictionary *dict, struct xz_buf *b) * decompression because in multi-call mode dict->buf * has been allocated by us in this file; it's not * provided by the caller like in single-call mode. + * + * With MicroLZMA, b->out can be NULL to skip bytes that + * the caller doesn't need. This cannot be done with XZ + * because it would break BCJ filters. */ - memcpy(b->out + b->out_pos, dict->buf + dict->start, - copy_size); + if (!DICT_FLUSH_SUPPORTS_SKIPPING || b->out != NULL) + memcpy(b->out + b->out_pos, dict->buf + dict->start, + copy_size); } dict->start = dict->pos; @@ -1190,3 +1205,140 @@ XZ_EXTERN void xz_dec_lzma2_end(struct xz_dec_lzma2 *s) kfree(s); } + +#ifdef XZ_DEC_MICROLZMA +/* This is a wrapper struct to have a nice struct name in the public API. */ +struct xz_dec_microlzma { + struct xz_dec_lzma2 s; +}; + +enum xz_ret xz_dec_microlzma_run(struct xz_dec_microlzma *s_ptr, + struct xz_buf *b) +{ + struct xz_dec_lzma2 *s = &s_ptr->s; + + /* + * sequence is SEQ_PROPERTIES before the first input byte, + * SEQ_LZMA_PREPARE until a total of five bytes have been read, + * and SEQ_LZMA_RUN for the rest of the input stream. + */ + if (s->lzma2.sequence != SEQ_LZMA_RUN) { + if (s->lzma2.sequence == SEQ_PROPERTIES) { + /* One byte is needed for the props. */ + if (b->in_pos >= b->in_size) + return XZ_OK; + + /* + * Don't increment b->in_pos here. The same byte is + * also passed to rc_read_init() which will ignore it. + */ + if (!lzma_props(s, ~b->in[b->in_pos])) + return XZ_DATA_ERROR; + + s->lzma2.sequence = SEQ_LZMA_PREPARE; + } + + /* + * xz_dec_microlzma_reset() doesn't validate the compressed + * size so we do it here. We have to limit the maximum size + * to avoid integer overflows in lzma2_lzma(). 3 GiB is a nice + * round number and much more than users of this code should + * ever need. + */ + if (s->lzma2.compressed < RC_INIT_BYTES + || s->lzma2.compressed > (3U << 30)) + return XZ_DATA_ERROR; + + if (!rc_read_init(&s->rc, b)) + return XZ_OK; + + s->lzma2.compressed -= RC_INIT_BYTES; + s->lzma2.sequence = SEQ_LZMA_RUN; + + dict_reset(&s->dict, b); + } + + /* This is to allow increasing b->out_size between calls. */ + if (DEC_IS_SINGLE(s->dict.mode)) + s->dict.end = b->out_size - b->out_pos; + + while (true) { + dict_limit(&s->dict, min_t(size_t, b->out_size - b->out_pos, + s->lzma2.uncompressed)); + + if (!lzma2_lzma(s, b)) + return XZ_DATA_ERROR; + + s->lzma2.uncompressed -= dict_flush(&s->dict, b); + + if (s->lzma2.uncompressed == 0) { + if (s->lzma2.pedantic_microlzma) { + if (s->lzma2.compressed > 0 || s->lzma.len > 0 + || !rc_is_finished(&s->rc)) + return XZ_DATA_ERROR; + } + + return XZ_STREAM_END; + } + + if (b->out_pos == b->out_size) + return XZ_OK; + + if (b->in_pos == b->in_size + && s->temp.size < s->lzma2.compressed) + return XZ_OK; + } +} + +struct xz_dec_microlzma *xz_dec_microlzma_alloc(enum xz_mode mode, + uint32_t dict_size) +{ + struct xz_dec_microlzma *s; + + /* Restrict dict_size to the same range as in the LZMA2 code. */ + if (dict_size < 4096 || dict_size > (3U << 30)) + return NULL; + + s = kmalloc(sizeof(*s), GFP_KERNEL); + if (s == NULL) + return NULL; + + s->s.dict.mode = mode; + s->s.dict.size = dict_size; + + if (DEC_IS_MULTI(mode)) { + s->s.dict.end = dict_size; + + s->s.dict.buf = vmalloc(dict_size); + if (s->s.dict.buf == NULL) { + kfree(s); + return NULL; + } + } + + return s; +} + +void xz_dec_microlzma_reset(struct xz_dec_microlzma *s, uint32_t comp_size, + uint32_t uncomp_size, int uncomp_size_is_exact) +{ + /* + * comp_size is validated in xz_dec_microlzma_run(). + * uncomp_size can safely be anything. + */ + s->s.lzma2.compressed = comp_size; + s->s.lzma2.uncompressed = uncomp_size; + s->s.lzma2.pedantic_microlzma = uncomp_size_is_exact; + + s->s.lzma2.sequence = SEQ_PROPERTIES; + s->s.temp.size = 0; +} + +void xz_dec_microlzma_end(struct xz_dec_microlzma *s) +{ + if (DEC_IS_MULTI(s->s.dict.mode)) + vfree(s->s.dict.buf); + + kfree(s); +} +#endif diff --git a/linux/lib/xz/xz_dec_syms.c b/linux/lib/xz/xz_dec_syms.c index 32eb3c0..61098c6 100644 --- a/linux/lib/xz/xz_dec_syms.c +++ b/linux/lib/xz/xz_dec_syms.c @@ -15,8 +15,15 @@ EXPORT_SYMBOL(xz_dec_reset); EXPORT_SYMBOL(xz_dec_run); EXPORT_SYMBOL(xz_dec_end); +#ifdef CONFIG_XZ_DEC_MICROLZMA +EXPORT_SYMBOL(xz_dec_microlzma_alloc); +EXPORT_SYMBOL(xz_dec_microlzma_reset); +EXPORT_SYMBOL(xz_dec_microlzma_run); +EXPORT_SYMBOL(xz_dec_microlzma_end); +#endif + MODULE_DESCRIPTION("XZ decompressor"); -MODULE_VERSION("1.0"); +MODULE_VERSION("1.1"); MODULE_AUTHOR("Lasse Collin and Igor Pavlov"); /* diff --git a/linux/lib/xz/xz_private.h b/linux/lib/xz/xz_private.h index 482b90f..d9fd49b 100644 --- a/linux/lib/xz/xz_private.h +++ b/linux/lib/xz/xz_private.h @@ -37,6 +37,9 @@ # ifdef CONFIG_XZ_DEC_SPARC # define XZ_DEC_SPARC # endif +# ifdef CONFIG_XZ_DEC_MICROLZMA +# define XZ_DEC_MICROLZMA +# endif # define memeq(a, b, size) (memcmp(a, b, size) == 0) # define memzero(buf, size) memset(buf, 0, size) # endif -- cgit v1.2.3 From c61e095215ead4506c7ce775110baf9854d481a3 Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Sun, 19 Sep 2021 22:59:11 +0300 Subject: Fix typos in comments. I happened to find these from the Linux source tree. --- linux/lib/decompress_unxz.c | 2 +- linux/lib/xz/xz_dec_bcj.c | 2 +- linux/lib/xz/xz_dec_lzma2.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/linux/lib/decompress_unxz.c b/linux/lib/decompress_unxz.c index 3033b20..e2ec23a 100644 --- a/linux/lib/decompress_unxz.c +++ b/linux/lib/decompress_unxz.c @@ -23,7 +23,7 @@ * uncompressible. Thus, we must look for worst-case expansion when the * compressor is encoding uncompressible data. * - * The structure of the .xz file in case of a compresed kernel is as follows. + * The structure of the .xz file in case of a compressed kernel is as follows. * Sizes (as bytes) of the fields are in parenthesis. * * Stream Header (12) diff --git a/linux/lib/xz/xz_dec_bcj.c b/linux/lib/xz/xz_dec_bcj.c index 72ddac6..ef449e9 100644 --- a/linux/lib/xz/xz_dec_bcj.c +++ b/linux/lib/xz/xz_dec_bcj.c @@ -422,7 +422,7 @@ XZ_EXTERN enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, /* * Flush pending already filtered data to the output buffer. Return - * immediatelly if we couldn't flush everything, or if the next + * immediately if we couldn't flush everything, or if the next * filter in the chain had already returned XZ_STREAM_END. */ if (s->temp.filtered > 0) { diff --git a/linux/lib/xz/xz_dec_lzma2.c b/linux/lib/xz/xz_dec_lzma2.c index cf40a2a..c3098c0 100644 --- a/linux/lib/xz/xz_dec_lzma2.c +++ b/linux/lib/xz/xz_dec_lzma2.c @@ -147,8 +147,8 @@ struct lzma_dec { /* * LZMA properties or related bit masks (number of literal - * context bits, a mask dervied from the number of literal - * position bits, and a mask dervied from the number + * context bits, a mask derived from the number of literal + * position bits, and a mask derived from the number * position bits) */ uint32_t lc; @@ -516,7 +516,7 @@ static __always_inline void rc_normalize(struct rc_dec *rc) } /* - * Decode one bit. In some versions, this function has been splitted in three + * Decode one bit. In some versions, this function has been split in three * functions so that the compiler is supposed to be able to more easily avoid * an extra branch. In this particular version of the LZMA decoder, this * doesn't seem to be a good idea (tested with GCC 3.3.6, 3.4.6, and 4.3.3 -- cgit v1.2.3 From 3f438e15109229bb14ab45f285f4bff5412a9542 Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Sun, 19 Sep 2021 23:12:57 +0300 Subject: Fix spelling in comments. non-splitted -> non-split uncompressible -> incompressible --- linux/lib/decompress_unxz.c | 10 +++++----- linux/lib/xz/xz_dec_lzma2.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/linux/lib/decompress_unxz.c b/linux/lib/decompress_unxz.c index e2ec23a..7dfdde7 100644 --- a/linux/lib/decompress_unxz.c +++ b/linux/lib/decompress_unxz.c @@ -20,8 +20,8 @@ * * The worst case for in-place decompression is that the beginning of * the file is compressed extremely well, and the rest of the file is - * uncompressible. Thus, we must look for worst-case expansion when the - * compressor is encoding uncompressible data. + * incompressible. Thus, we must look for worst-case expansion when the + * compressor is encoding incompressible data. * * The structure of the .xz file in case of a compressed kernel is as follows. * Sizes (as bytes) of the fields are in parenthesis. @@ -58,7 +58,7 @@ * uncompressed size of the payload is in practice never less than the * payload size itself. The LZMA2 format would allow uncompressed size * to be less than the payload size, but no sane compressor creates such - * files. LZMA2 supports storing uncompressible data in uncompressed form, + * files. LZMA2 supports storing incompressible data in uncompressed form, * so there's never a need to create payloads whose uncompressed size is * smaller than the compressed size. * @@ -167,8 +167,8 @@ * memeq and memzero are not used much and any remotely sane implementation * is fast enough. memcpy/memmove speed matters in multi-call mode, but * the kernel image is decompressed in single-call mode, in which only - * memmove speed can matter and only if there is a lot of uncompressible data - * (LZMA2 stores uncompressible chunks in uncompressed form). Thus, the + * memmove speed can matter and only if there is a lot of incompressible data + * (LZMA2 stores incompressible chunks in uncompressed form). Thus, the * functions below should just be kept small; it's probably not worth * optimizing for speed. */ diff --git a/linux/lib/xz/xz_dec_lzma2.c b/linux/lib/xz/xz_dec_lzma2.c index c3098c0..c929f1c 100644 --- a/linux/lib/xz/xz_dec_lzma2.c +++ b/linux/lib/xz/xz_dec_lzma2.c @@ -520,7 +520,7 @@ static __always_inline void rc_normalize(struct rc_dec *rc) * functions so that the compiler is supposed to be able to more easily avoid * an extra branch. In this particular version of the LZMA decoder, this * doesn't seem to be a good idea (tested with GCC 3.3.6, 3.4.6, and 4.3.3 - * on x86). Using a non-splitted version results in nicer looking code too. + * on x86). Using a non-split version results in nicer looking code too. * * NOTE: This must return an int. Do not make it return a bool or the speed * of the code generated by GCC 3.x decreases 10-15 %. (GCC 4.3 doesn't care, -- cgit v1.2.3 From f387aad3a11dcce7fcee2ca3e2d465416d0f920a Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 4 Oct 2021 16:27:22 -0700 Subject: Add METADATA. Bug: http://b/184301514 Test: N/A Change-Id: Ia1d1ef3a97cd72be5190a9283574017c241dfcbe --- METADATA | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/METADATA b/METADATA index 313792c..a2a2f4d 100644 --- a/METADATA +++ b/METADATA @@ -1,3 +1,15 @@ +name: "xz-embedded" +description: "XZ Embedded" third_party { + url { + type: GIT + value: "https://git.tukaani.org/?p=xz-embedded.git" + } + version: "79b68de5657beecfad575578a7181cf6fca869cb" license_type: UNENCUMBERED + last_upgrade_date { + year: 2017 + month: 4 + day: 7 + } } -- cgit v1.2.3