aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archival/libarchive/unxz/xz_dec_bcj.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/archival/libarchive/unxz/xz_dec_bcj.c b/archival/libarchive/unxz/xz_dec_bcj.c
index a01a4cdcf..e0f913a94 100644
--- a/archival/libarchive/unxz/xz_dec_bcj.c
+++ b/archival/libarchive/unxz/xz_dec_bcj.c
@@ -446,8 +446,12 @@ XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_bcj_run(struct xz_dec_bcj *s,
446 * next filter in the chain. Apply the BCJ filter on the new data 446 * next filter in the chain. Apply the BCJ filter on the new data
447 * in the output buffer. If everything cannot be filtered, copy it 447 * in the output buffer. If everything cannot be filtered, copy it
448 * to temp and rewind the output buffer position accordingly. 448 * to temp and rewind the output buffer position accordingly.
449 *
450 * This needs to be always run when temp.size == 0 to handle a special
451 * case where the output buffer is full and the next filter has no
452 * more output coming but hasn't returned XZ_STREAM_END yet.
449 */ 453 */
450 if (s->temp.size < b->out_size - b->out_pos) { 454 if (s->temp.size < b->out_size - b->out_pos || s->temp.size == 0) {
451 out_start = b->out_pos; 455 out_start = b->out_pos;
452 memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size); 456 memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size);
453 b->out_pos += s->temp.size; 457 b->out_pos += s->temp.size;
@@ -470,16 +474,25 @@ XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_bcj_run(struct xz_dec_bcj *s,
470 s->temp.size = b->out_pos - out_start; 474 s->temp.size = b->out_pos - out_start;
471 b->out_pos -= s->temp.size; 475 b->out_pos -= s->temp.size;
472 memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size); 476 memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size);
477
478 /*
479 * If there wasn't enough input to the next filter to fill
480 * the output buffer with unfiltered data, there's no point
481 * to try decoding more data to temp.
482 */
483 if (b->out_pos + s->temp.size < b->out_size)
484 return XZ_OK;
473 } 485 }
474 486
475 /* 487 /*
476 * If we have unfiltered data in temp, try to fill by decoding more 488 * We have unfiltered data in temp. If the output buffer isn't full
477 * data from the next filter. Apply the BCJ filter on temp. Then we 489 * yet, try to fill the temp buffer by decoding more data from the
478 * hopefully can fill the actual output buffer by copying filtered 490 * next filter. Apply the BCJ filter on temp. Then we hopefully can
479 * data from temp. A mix of filtered and unfiltered data may be left 491 * fill the actual output buffer by copying filtered data from temp.
480 * in temp; it will be taken care on the next call to this function. 492 * A mix of filtered and unfiltered data may be left in temp; it will
493 * be taken care on the next call to this function.
481 */ 494 */
482 if (s->temp.size > 0) { 495 if (b->out_pos < b->out_size) {
483 /* Make b->out{,_pos,_size} temporarily point to s->temp. */ 496 /* Make b->out{,_pos,_size} temporarily point to s->temp. */
484 s->out = b->out; 497 s->out = b->out;
485 s->out_pos = b->out_pos; 498 s->out_pos = b->out_pos;