From e644c556c5d37c42937a8a657857da04ddf98d07 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Tue, 2 May 2017 18:59:01 +0200 Subject: [PATCH] Fix bad bit writer initialization. When re-initializing a bit writer, we could set invalid values because the bit writer was not big enough. Change-Id: Id25ab6712603245a5a12d5f4a86fe35a9a799a5d --- src/enc/vp8l_enc.c | 20 ++++++++++---------- src/utils/bit_writer_utils.c | 14 ++++++++++++++ src/utils/bit_writer_utils.h | 3 +++ 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/enc/vp8l_enc.c b/src/enc/vp8l_enc.c index 86407318..bd6bb077 100644 --- a/src/enc/vp8l_enc.c +++ b/src/enc/vp8l_enc.c @@ -1507,12 +1507,12 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, int use_delta_palette = 0; int entropy_idx[kNumEntropyIx]; int num_entropy_idx = 0; - int i; + int idx; int red_and_blue_always_zero = 0; size_t best_size = 0; VP8LBitWriter bw_init = *bw, bw_best; - if (enc == NULL || !VP8LBitWriterInit(&bw_best, 0)) { + if (enc == NULL || !VP8LBitWriterClone(bw, &bw_best)) { err = VP8_ENC_ERROR_OUT_OF_MEMORY; goto Error; } @@ -1526,12 +1526,12 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, goto Error; } - for (i = 0; i < num_entropy_idx; ++i) { - enc->use_palette_ = (entropy_idx[i] == kPalette); - enc->use_subtract_green_ = (entropy_idx[i] == kSubGreen) || - (entropy_idx[i] == kSpatialSubGreen); - enc->use_predict_ = (entropy_idx[i] == kSpatial) || - (entropy_idx[i] == kSpatialSubGreen); + for (idx = 0; idx < num_entropy_idx; ++idx) { + enc->use_palette_ = (entropy_idx[idx] == kPalette); + enc->use_subtract_green_ = (entropy_idx[idx] == kSubGreen) || + (entropy_idx[idx] == kSpatialSubGreen); + enc->use_predict_ = (entropy_idx[idx] == kSpatial) || + (entropy_idx[idx] == kSpatialSubGreen); if (low_effort) { enc->use_cross_color_ = 0; } else { @@ -1632,7 +1632,7 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, if (err != VP8_ENC_OK) goto Error; // If we are better than what we already have. - if (best_size == 0 || VP8LBitWriterNumBytes(bw) < best_size) { + if (idx == 0 || VP8LBitWriterNumBytes(bw) < best_size) { best_size = VP8LBitWriterNumBytes(bw); // Store the BitWriter. VP8LBitWriterSwap(bw, &bw_best); @@ -1648,7 +1648,7 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, stats->transform_bits = enc->transform_bits_; stats->cache_bits = enc->cache_bits_; stats->palette_size = enc->palette_size_; - stats->lossless_size = (int)(VP8LBitWriterNumBytes(bw) - byte_position); + stats->lossless_size = (int)(best_size - byte_position); stats->lossless_hdr_size = hdr_size; stats->lossless_data_size = data_size; } diff --git a/src/utils/bit_writer_utils.c b/src/utils/bit_writer_utils.c index e394462c..afa1c10a 100644 --- a/src/utils/bit_writer_utils.c +++ b/src/utils/bit_writer_utils.c @@ -239,6 +239,19 @@ int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size) { return VP8LBitWriterResize(bw, expected_size); } +int VP8LBitWriterClone(const VP8LBitWriter* const src, + VP8LBitWriter* const dst) { + const size_t current_size = src->cur_ - src->buf_; + assert(src->cur_ >= src->buf_ && src->cur_ <= src->end_); + memset(dst, 0, sizeof(*dst)); + if (!VP8LBitWriterResize(dst, current_size)) return 0; + memcpy(dst->buf_, src->buf_, current_size); + dst->bits_ = src->bits_; + dst->used_ = src->used_; + dst->error_ = src->error_; + return 1; +} + void VP8LBitWriterWipeOut(VP8LBitWriter* const bw) { if (bw != NULL) { WebPSafeFree(bw->buf_); @@ -251,6 +264,7 @@ void VP8LBitWriterReset(const VP8LBitWriter* const bw_init, bw->bits_ = bw_init->bits_; bw->used_ = bw_init->used_; bw->cur_ = bw->buf_ + (bw_init->cur_ - bw_init->buf_); + assert(bw->cur_ <= bw->end_); bw->error_ = bw_init->error_; } diff --git a/src/utils/bit_writer_utils.h b/src/utils/bit_writer_utils.h index 59ae5144..479d3afe 100644 --- a/src/utils/bit_writer_utils.h +++ b/src/utils/bit_writer_utils.h @@ -106,6 +106,9 @@ static WEBP_INLINE size_t VP8LBitWriterNumBytes(VP8LBitWriter* const bw) { // Returns false in case of memory allocation error. int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size); +// Returns false in case of memory allocation error. +int VP8LBitWriterClone(const VP8LBitWriter* const src, + VP8LBitWriter* const dst); // Finalize the bitstream coding. Returns a pointer to the internal buffer. uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw); // Release any pending memory and zeroes the object.