Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

XZ: Fix incorrect XZ_BUF_ERROR

xz_dec_run() could incorrectly return XZ_BUF_ERROR if all of the
following was true:

- The caller knows how many bytes of output to expect and only provides
that much output space.

- When the last output bytes are decoded, the caller-provided input
buffer ends right before the LZMA2 end of payload marker. So LZMA2
won't provide more output anymore, but it won't know it yet and thus
won't return XZ_STREAM_END yet.

- A BCJ filter is in use and it hasn't left any unfiltered bytes in the
temp buffer. This can happen with any BCJ filter, but in practice
it's more likely with filters other than the x86 BCJ.

This fixes <https://bugzilla.redhat.com/show_bug.cgi?id=735408> where
Squashfs thinks that a valid file system is corrupt.

This also fixes a similar bug in single-call mode where the uncompressed
size of a block using BCJ + LZMA2 was 0 bytes and caller provided no
output space. Many empty .xz files don't contain any blocks and thus
don't trigger this bug.

This also tweaks a closely related detail: xz_dec_bcj_run() could call
xz_dec_lzma2_run() to decode into temp buffer when it was known to be
useless. This was harmless although it wasted a minuscule number of CPU
cycles.

Signed-off-by: Lasse Collin <lasse.collin@tukaani.org>
Cc: stable <stable@kernel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Lasse Collin and committed by
Linus Torvalds
9c1f8594 e5b26a88

+20 -7
+20 -7
lib/xz/xz_dec_bcj.c
··· 441 441 * next filter in the chain. Apply the BCJ filter on the new data 442 442 * in the output buffer. If everything cannot be filtered, copy it 443 443 * to temp and rewind the output buffer position accordingly. 444 + * 445 + * This needs to be always run when temp.size == 0 to handle a special 446 + * case where the output buffer is full and the next filter has no 447 + * more output coming but hasn't returned XZ_STREAM_END yet. 444 448 */ 445 - if (s->temp.size < b->out_size - b->out_pos) { 449 + if (s->temp.size < b->out_size - b->out_pos || s->temp.size == 0) { 446 450 out_start = b->out_pos; 447 451 memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size); 448 452 b->out_pos += s->temp.size; ··· 469 465 s->temp.size = b->out_pos - out_start; 470 466 b->out_pos -= s->temp.size; 471 467 memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size); 468 + 469 + /* 470 + * If there wasn't enough input to the next filter to fill 471 + * the output buffer with unfiltered data, there's no point 472 + * to try decoding more data to temp. 473 + */ 474 + if (b->out_pos + s->temp.size < b->out_size) 475 + return XZ_OK; 472 476 } 473 477 474 478 /* 475 - * If we have unfiltered data in temp, try to fill by decoding more 476 - * data from the next filter. Apply the BCJ filter on temp. Then we 477 - * hopefully can fill the actual output buffer by copying filtered 478 - * data from temp. A mix of filtered and unfiltered data may be left 479 - * in temp; it will be taken care on the next call to this function. 479 + * We have unfiltered data in temp. If the output buffer isn't full 480 + * yet, try to fill the temp buffer by decoding more data from the 481 + * next filter. Apply the BCJ filter on temp. Then we hopefully can 482 + * fill the actual output buffer by copying filtered data from temp. 483 + * A mix of filtered and unfiltered data may be left in temp; it will 484 + * be taken care on the next call to this function. 480 485 */ 481 - if (s->temp.size > 0) { 486 + if (b->out_pos < b->out_size) { 482 487 /* Make b->out{,_pos,_size} temporarily point to s->temp. */ 483 488 s->out = b->out; 484 489 s->out_pos = b->out_pos;