diff options
Diffstat (limited to 'lib/xz')
| -rw-r--r-- | lib/xz/Kconfig | 10 | ||||
| -rw-r--r-- | lib/xz/xz_dec_bcj.c | 27 | ||||
| -rw-r--r-- | lib/xz/xz_dec_lzma2.c | 10 | ||||
| -rw-r--r-- | lib/xz/xz_private.h | 2 |
4 files changed, 32 insertions, 17 deletions
diff --git a/lib/xz/Kconfig b/lib/xz/Kconfig index 60a6088d0e5..12d2d777f36 100644 --- a/lib/xz/Kconfig +++ b/lib/xz/Kconfig @@ -6,42 +6,40 @@ config XZ_DEC the .xz file format as the container. For integrity checking, CRC32 is supported. See Documentation/xz.txt for more information. +if XZ_DEC + config XZ_DEC_X86 bool "x86 BCJ filter decoder" if EXPERT default y - depends on XZ_DEC select XZ_DEC_BCJ config XZ_DEC_POWERPC bool "PowerPC BCJ filter decoder" if EXPERT default y - depends on XZ_DEC select XZ_DEC_BCJ config XZ_DEC_IA64 bool "IA-64 BCJ filter decoder" if EXPERT default y - depends on XZ_DEC select XZ_DEC_BCJ config XZ_DEC_ARM bool "ARM BCJ filter decoder" if EXPERT default y - depends on XZ_DEC select XZ_DEC_BCJ config XZ_DEC_ARMTHUMB bool "ARM-Thumb BCJ filter decoder" if EXPERT default y - depends on XZ_DEC select XZ_DEC_BCJ config XZ_DEC_SPARC bool "SPARC BCJ filter decoder" if EXPERT default y - depends on XZ_DEC select XZ_DEC_BCJ +endif + config XZ_DEC_BCJ bool default n diff --git a/lib/xz/xz_dec_bcj.c b/lib/xz/xz_dec_bcj.c index e51e2558ca9..a768e6d28bb 100644 --- a/lib/xz/xz_dec_bcj.c +++ b/lib/xz/xz_dec_bcj.c @@ -441,8 +441,12 @@ XZ_EXTERN enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, * next filter in the chain. Apply the BCJ filter on the new data * in the output buffer. If everything cannot be filtered, copy it * to temp and rewind the output buffer position accordingly. + * + * This needs to be always run when temp.size == 0 to handle a special + * case where the output buffer is full and the next filter has no + * more output coming but hasn't returned XZ_STREAM_END yet. */ - if (s->temp.size < b->out_size - b->out_pos) { + if (s->temp.size < b->out_size - b->out_pos || s->temp.size == 0) { out_start = b->out_pos; memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size); b->out_pos += s->temp.size; @@ -465,16 +469,25 @@ XZ_EXTERN enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, s->temp.size = b->out_pos - out_start; b->out_pos -= s->temp.size; memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size); + + /* + * If there wasn't enough input to the next filter to fill + * the output buffer with unfiltered data, there's no point + * to try decoding more data to temp. + */ + if (b->out_pos + s->temp.size < b->out_size) + return XZ_OK; } /* - * If we have unfiltered data in temp, try to fill by decoding more - * data from the next filter. Apply the BCJ filter on temp. Then we - * hopefully can fill the actual output buffer by copying filtered - * data from temp. A mix of filtered and unfiltered data may be left - * in temp; it will be taken care on the next call to this function. + * We have unfiltered data in temp. If the output buffer isn't full + * yet, try to fill the temp buffer by decoding more data from the + * next filter. Apply the BCJ filter on temp. Then we hopefully can + * fill the actual output buffer by copying filtered data from temp. + * A mix of filtered and unfiltered data may be left in temp; it will + * be taken care on the next call to this function. */ - if (s->temp.size > 0) { + if (b->out_pos < b->out_size) { /* Make b->out{,_pos,_size} temporarily point to s->temp. */ s->out = b->out; s->out_pos = b->out_pos; diff --git a/lib/xz/xz_dec_lzma2.c b/lib/xz/xz_dec_lzma2.c index ea5fa4fe9d6..08c3c804999 100644 --- a/lib/xz/xz_dec_lzma2.c +++ b/lib/xz/xz_dec_lzma2.c @@ -969,6 +969,9 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, */ tmp = b->in[b->in_pos++]; + if (tmp == 0x00) + return XZ_STREAM_END; + if (tmp >= 0xE0 || tmp == 0x01) { s->lzma2.need_props = true; s->lzma2.need_dict_reset = false; @@ -1001,9 +1004,6 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, lzma_reset(s); } } else { - if (tmp == 0x00) - return XZ_STREAM_END; - if (tmp > 0x02) return XZ_DATA_ERROR; @@ -1043,6 +1043,8 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, s->lzma2.sequence = SEQ_LZMA_PREPARE; + /* Fall through */ + case SEQ_LZMA_PREPARE: if (s->lzma2.compressed < RC_INIT_BYTES) return XZ_DATA_ERROR; @@ -1053,6 +1055,8 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, s->lzma2.compressed -= RC_INIT_BYTES; s->lzma2.sequence = SEQ_LZMA_RUN; + /* Fall through */ + case SEQ_LZMA_RUN: /* * Set dictionary limit to indicate how much we want diff --git a/lib/xz/xz_private.h b/lib/xz/xz_private.h index a65633e0696..482b90f363f 100644 --- a/lib/xz/xz_private.h +++ b/lib/xz/xz_private.h @@ -12,7 +12,7 @@ #ifdef __KERNEL__ # include <linux/xz.h> -# include <asm/byteorder.h> +# include <linux/kernel.h> # include <asm/unaligned.h> /* XZ_PREBOOT may be defined only via decompress_unxz.c. */ # ifndef XZ_PREBOOT |
