http://git.tukaani.org/?p=xz-embedded.git;a=commitdiff;h=4cec51e1be4797a4bd8b266a1d34cabd7fdb79fd --- busybox-1.20.2.org/archival/libarchive/unxz/xz_dec_lzma2.c +++ busybox-1.20.2/archival/libarchive/unxz/xz_dec_lzma2.c @@ -972,6 +972,9 @@ */ 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; @@ -1004,9 +1007,6 @@ lzma_reset(s); } } else { - if (tmp == 0x00) - return XZ_STREAM_END; - if (tmp > 0x02) return XZ_DATA_ERROR; http://git.tukaani.org/?p=xz-embedded.git;a=commitdiff;h=9690fe69dc97eb2e7fe2804e4448a5278cde5411 --- busybox-1.20.2.org/archival/libarchive/unxz/xz_dec_bcj.c +++ busybox-1.20.2/archival/libarchive/unxz/xz_dec_bcj.c @@ -443,8 +443,12 @@ * 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; @@ -467,16 +471,25 @@ 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; http://lists.busybox.net/pipermail/busybox/2013-February/078927.html --- busybox-1.20.2.org/archival/libarchive/decompress_unxz.c +++ busybox-1.20.2/archival/libarchive/decompress_unxz.c @@ -86,8 +86,40 @@ IF_DESKTOP(total += iobuf.out_pos;) iobuf.out_pos = 0; } - if (r == XZ_STREAM_END) { - break; + while (r == XZ_STREAM_END) { + /* Handle concatenated .xz Streams including possible + * Stream Padding. + */ + if (iobuf.in_pos == iobuf.in_size) { + int rd = safe_read(src_fd, membuf, BUFSIZ); + if (rd < 0) { + bb_error_msg(bb_msg_read_error); + total = -1; + goto out; + } + if (rd == 0) + goto out; + + iobuf.in_size = rd; + iobuf.in_pos = 0; + } + + /* Stream Padding must always be a multiple of four + * bytes to preserve four-byte alignment. To keep the + * code slightly smaller, we aren't as strict here as + * the .xz spec requires. We just skip all zero-bytes + * without checking the alignment and thus can accept + * files that aren't valid, e.g. the XZ Utils test + * files bad-0pad-empty.xz and bad-0catpad-empty.xz. + */ + while (iobuf.in_pos < iobuf.in_size) { + if (membuf[iobuf.in_pos] != 0) { + xz_dec_reset(state); + r = XZ_OK; + break; + } + ++iobuf.in_pos; + } } if (r != XZ_OK && r != XZ_UNSUPPORTED_CHECK) { bb_error_msg("corrupted data"); @@ -95,6 +127,8 @@ break; } } + +out: xz_dec_end(state); free(membuf);