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);