fix invalid-write bug for alpha-decoding

On the non-fast path (use_8b_decode_=0) for decoding the alpha-mask,
we could end up requesting ApplyInverseTransform() with more rows
to process than NUM_ARGB_CACHE_ROWS. This could only happen on the
very last bottom rows of the image.

* ProcessRows() doesn't need to be fixed, since we never request more
  than NUM_ARGB_CACHE_ROWS rows. Added an assert for that.

* the use_8b_decode_=1 case doesn't use argb_cache_, but rather does
  the palette-decoding call directly. So, no problem here too.

Only the generic (and rather rare) case of calling ExtractAlphaRows()
was affected.

Change-Id: I58e28d590dcc08c24d237429b79614abcef1db7c
This commit is contained in:
Pascal Massimino 2016-06-15 14:49:42 +02:00
parent f66512db94
commit 9a583c66f9

View File

@ -721,6 +721,9 @@ static void ProcessRows(VP8LDecoder* const dec, int row) {
const int num_rows = row - dec->last_row_;
assert(row <= dec->io_->crop_bottom);
// We can't process more than NUM_ARGB_CACHE_ROWS at a time (that's the size
// of argb_cache_), but we currently don't need more than that.
assert(num_rows <= NUM_ARGB_CACHE_ROWS);
if (num_rows > 0) { // Emit output.
VP8Io* const io = dec->io_;
uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
@ -1464,23 +1467,31 @@ static int AllocateInternalBuffers8b(VP8LDecoder* const dec) {
// Special row-processing that only stores the alpha data.
static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {
const int num_rows = last_row - dec->last_row_;
const uint32_t* const in = dec->pixels_ + dec->width_ * dec->last_row_;
int cur_row = dec->last_row_;
int num_rows = last_row - cur_row;
const uint32_t* in = dec->pixels_ + dec->width_ * cur_row;
assert(last_row <= dec->io_->crop_bottom);
if (num_rows > 0) {
while (num_rows > 0) {
const int num_rows_to_process =
(num_rows > NUM_ARGB_CACHE_ROWS) ? NUM_ARGB_CACHE_ROWS : num_rows;
// Extract alpha (which is stored in the green plane).
ALPHDecoder* const alph_dec = (ALPHDecoder*)dec->io_->opaque;
uint8_t* const output = alph_dec->output_;
const int width = dec->io_->width; // the final width (!= dec->width_)
const int cache_pixs = width * num_rows;
uint8_t* dst = output + width * dec->last_row_;
const int cache_pixs = width * num_rows_to_process;
uint8_t* const dst = output + width * cur_row;
const uint32_t* const src = dec->argb_cache_;
int i;
ApplyInverseTransforms(dec, num_rows, in);
ApplyInverseTransforms(dec, num_rows_to_process, in);
for (i = 0; i < cache_pixs; ++i) dst[i] = (src[i] >> 8) & 0xff;
AlphaApplyFilter(alph_dec, dec->last_row_, last_row, dst, width);
AlphaApplyFilter(alph_dec,
cur_row, cur_row + num_rows_to_process, dst, width);
num_rows -= num_rows_to_process;
in += num_rows_to_process * dec->width_;
cur_row += num_rows_to_process;
}
assert(cur_row == last_row);
dec->last_row_ = dec->last_out_row_ = last_row;
}