diff options
| -rw-r--r-- | lib/xz/xz_dec_bcj.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/lib/xz/xz_dec_bcj.c b/lib/xz/xz_dec_bcj.c index e51e2558ca9d..a768e6d28bbb 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, | |||
| 441 | * next filter in the chain. Apply the BCJ filter on the new data | 441 | * next filter in the chain. Apply the BCJ filter on the new data |
| 442 | * in the output buffer. If everything cannot be filtered, copy it | 442 | * in the output buffer. If everything cannot be filtered, copy it |
| 443 | * to temp and rewind the output buffer position accordingly. | 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 | out_start = b->out_pos; | 450 | out_start = b->out_pos; |
| 447 | memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size); | 451 | memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size); |
| 448 | b->out_pos += s->temp.size; | 452 | b->out_pos += s->temp.size; |
| @@ -465,16 +469,25 @@ XZ_EXTERN enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, | |||
| 465 | s->temp.size = b->out_pos - out_start; | 469 | s->temp.size = b->out_pos - out_start; |
| 466 | b->out_pos -= s->temp.size; | 470 | b->out_pos -= s->temp.size; |
| 467 | memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size); | 471 | memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size); |
| 472 | |||
| 473 | /* | ||
| 474 | * If there wasn't enough input to the next filter to fill | ||
| 475 | * the output buffer with unfiltered data, there's no point | ||
| 476 | * to try decoding more data to temp. | ||
| 477 | */ | ||
| 478 | if (b->out_pos + s->temp.size < b->out_size) | ||
| 479 | return XZ_OK; | ||
| 468 | } | 480 | } |
| 469 | 481 | ||
| 470 | /* | 482 | /* |
| 471 | * If we have unfiltered data in temp, try to fill by decoding more | 483 | * We have unfiltered data in temp. If the output buffer isn't full |
| 472 | * data from the next filter. Apply the BCJ filter on temp. Then we | 484 | * yet, try to fill the temp buffer by decoding more data from the |
| 473 | * hopefully can fill the actual output buffer by copying filtered | 485 | * next filter. Apply the BCJ filter on temp. Then we hopefully can |
| 474 | * data from temp. A mix of filtered and unfiltered data may be left | 486 | * fill the actual output buffer by copying filtered data from temp. |
| 475 | * in temp; it will be taken care on the next call to this function. | 487 | * A mix of filtered and unfiltered data may be left in temp; it will |
| 488 | * be taken care on the next call to this function. | ||
| 476 | */ | 489 | */ |
| 477 | if (s->temp.size > 0) { | 490 | if (b->out_pos < b->out_size) { |
| 478 | /* Make b->out{,_pos,_size} temporarily point to s->temp. */ | 491 | /* Make b->out{,_pos,_size} temporarily point to s->temp. */ |
| 479 | s->out = b->out; | 492 | s->out = b->out; |
| 480 | s->out_pos = b->out_pos; | 493 | s->out_pos = b->out_pos; |
