Bug 1840202 - Update libwebp to v1.3.1-rc2 r=aosmond

Differential Revision: https://phabricator.services.mozilla.com/D181923
This commit is contained in:
Updatebot 2023-06-27 13:55:07 +00:00
Родитель df6c6cbbd9
Коммит 541b2ef29d
13 изменённых файлов: 98 добавлений и 61 удалений

Просмотреть файл

@ -1,12 +1,15 @@
- 6/1/2023: version 1.3.1
- 6/23/2023: version 1.3.1
This is a binary compatible release.
* security fix for lossless encoder (#603, chromium: #1420107, CVE-2023-1999)
* security fixes for lossless encoder (#603, chromium: #1420107, #1455619,
CVE-2023-1999)
* improve error reporting through WebPPicture error codes
* fix upsampling for RGB565 and RGBA4444 in NEON builds
* img2webp: add -sharp_yuv & -near_lossless
* Windows builds:
- fix compatibility with clang-cl (#607)
- improve Arm64 performance with cl.exe
- add Arm64EC support
* fix webp_js with emcc >= 3.1.27 (stack size change, #614)
* CMake fixes (#592, #610, #612)
* further updates to the container and lossless bitstream docs (#581, #611)

Просмотреть файл

@ -11,7 +11,7 @@ origin:
url: "https://chromium.googlesource.com/webm/libwebp"
license: BSD-3-Clause
release: v1.3.1-rc1 (2023-06-01T17:26:20-07:00).
release: v1.3.1-rc2 (2023-06-23T11:52:38-07:00).
revision: "v1.3.0"

Просмотреть файл

@ -658,19 +658,26 @@ uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size,
uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size,
int* width, int* height, uint8_t** u, uint8_t** v,
int* stride, int* uv_stride) {
WebPDecBuffer output; // only to preserve the side-infos
uint8_t* const out = Decode(MODE_YUV, data, data_size,
width, height, &output);
if (out != NULL) {
const WebPYUVABuffer* const buf = &output.u.YUVA;
*u = buf->u;
*v = buf->v;
*stride = buf->y_stride;
*uv_stride = buf->u_stride;
assert(buf->u_stride == buf->v_stride);
// data, width and height are checked by Decode().
if (u == NULL || v == NULL || stride == NULL || uv_stride == NULL) {
return NULL;
}
{
WebPDecBuffer output; // only to preserve the side-infos
uint8_t* const out = Decode(MODE_YUV, data, data_size,
width, height, &output);
if (out != NULL) {
const WebPYUVABuffer* const buf = &output.u.YUVA;
*u = buf->u;
*v = buf->v;
*stride = buf->y_stride;
*uv_stride = buf->u_stride;
assert(buf->u_stride == buf->v_stride);
}
return out;
}
return out;
}
static void DefaultFeatures(WebPBitstreamFeatures* const features) {

Просмотреть файл

@ -141,6 +141,11 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height,
!reduce_levels, &tmp_bw, &result->stats);
if (ok) {
output = VP8LBitWriterFinish(&tmp_bw);
if (tmp_bw.error_) {
VP8LBitWriterWipeOut(&tmp_bw);
memset(&result->bw, 0, sizeof(result->bw));
return 0;
}
output_size = VP8LBitWriterNumBytes(&tmp_bw);
if (output_size > data_size) {
// compressed size is larger than source! Revert to uncompressed mode.
@ -314,11 +319,11 @@ static int EncodeAlpha(VP8Encoder* const enc,
assert(filter >= WEBP_FILTER_NONE && filter <= WEBP_FILTER_FAST);
if (quality < 0 || quality > 100) {
return 0;
return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION);
}
if (method < ALPHA_NO_COMPRESSION || method > ALPHA_LOSSLESS_COMPRESSION) {
return 0;
return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION);
}
if (method == ALPHA_NO_COMPRESSION) {
@ -328,7 +333,7 @@ static int EncodeAlpha(VP8Encoder* const enc,
quant_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size);
if (quant_alpha == NULL) {
return 0;
return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
// Extract alpha data (width x height) from raw_data (stride x height).
@ -348,6 +353,9 @@ static int EncodeAlpha(VP8Encoder* const enc,
ok = ApplyFiltersAndEncode(quant_alpha, width, height, data_size, method,
filter, reduce_levels, effort_level, output,
output_size, pic->stats);
if (!ok) {
WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY); // imprecise
}
#if !defined(WEBP_DISABLE_STATS)
if (pic->stats != NULL) { // need stats?
pic->stats->coded_size += (int)(*output_size);
@ -407,7 +415,7 @@ int VP8EncStartAlpha(VP8Encoder* const enc) {
WebPWorker* const worker = &enc->alpha_worker_;
// Makes sure worker is good to go.
if (!WebPGetWorkerInterface()->Reset(worker)) {
return 0;
return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
WebPGetWorkerInterface()->Launch(worker);
return 1;

Просмотреть файл

@ -474,6 +474,10 @@ int VP8EncAnalyze(VP8Encoder* const enc) {
} else { // Use only one default segment.
ResetAllMBInfo(enc);
}
if (!ok) {
return WebPEncodingSetError(enc->pic_,
VP8_ENC_ERROR_OUT_OF_MEMORY); // imprecise
}
return ok;
}

Просмотреть файл

@ -283,8 +283,7 @@ int VP8LHashChainFill(VP8LHashChain* const p, int quality,
hash_to_first_index =
(int32_t*)WebPSafeMalloc(HASH_SIZE, sizeof(*hash_to_first_index));
if (hash_to_first_index == NULL) {
WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
return 0;
return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
percent_range = remaining_percent / 2;
@ -1050,8 +1049,7 @@ int VP8LGetBackwardReferences(
refs_best = GetBackwardReferencesLowEffort(
width, height, argb, cache_bits_best, hash_chain, refs);
if (refs_best == NULL) {
WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
return 0;
return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
// Set it in first position.
BackwardRefsSwap(refs_best, &refs[0]);
@ -1059,8 +1057,7 @@ int VP8LGetBackwardReferences(
if (!GetBackwardReferences(width, height, argb, quality, lz77_types_to_try,
cache_bits_max, do_no_cache, hash_chain, refs,
cache_bits_best)) {
WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
return 0;
return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
}

Просмотреть файл

@ -689,7 +689,7 @@ static int PreLoopInitialize(VP8Encoder* const enc) {
}
if (!ok) {
VP8EncFreeBitWriters(enc); // malloc error occurred
WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
return ok;
}
@ -719,6 +719,7 @@ static int PostLoopFinalize(VP8EncIterator* const it, int ok) {
} else {
// Something bad happened -> need to do some memory cleanup.
VP8EncFreeBitWriters(enc);
return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
return ok;
}
@ -754,6 +755,11 @@ int VP8EncLoop(VP8Encoder* const enc) {
// *then* decide how to code the skip decision if there's one.
if (!VP8Decimate(&it, &info, rd_opt) || dont_use_skip) {
CodeResiduals(it.bw_, &it, &info);
if (it.bw_->error_) {
// enc->pic_->error_code is set in PostLoopFinalize().
ok = 0;
break;
}
} else { // reset predictors after a skip
ResetAfterSkip(&it);
}

Просмотреть файл

@ -535,7 +535,9 @@ static int ImportYUVAFromRGBA(const uint8_t* r_ptr,
WebPInitConvertARGBToYUV();
InitGammaTables();
if (tmp_rgb == NULL) return 0; // malloc error
if (tmp_rgb == NULL) {
return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
// Downsample Y/U/V planes, two rows at a time
for (y = 0; y < (height >> 1); ++y) {

Просмотреть файл

@ -137,7 +137,9 @@ int WebPPictureCrop(WebPPicture* pic,
PictureGrabSpecs(pic, &tmp);
tmp.width = width;
tmp.height = height;
if (!WebPPictureAlloc(&tmp)) return 0;
if (!WebPPictureAlloc(&tmp)) {
return WebPEncodingSetError(pic, tmp.error_code);
}
if (!pic->use_argb) {
const int y_offset = top * pic->y_stride + left;
@ -212,26 +214,28 @@ int WebPPictureRescale(WebPPicture* picture, int width, int height) {
prev_height = picture->height;
if (!WebPRescalerGetScaledDimensions(
prev_width, prev_height, &width, &height)) {
return 0;
return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
}
PictureGrabSpecs(picture, &tmp);
tmp.width = width;
tmp.height = height;
if (!WebPPictureAlloc(&tmp)) return 0;
if (!WebPPictureAlloc(&tmp)) {
return WebPEncodingSetError(picture, tmp.error_code);
}
if (!picture->use_argb) {
work = (rescaler_t*)WebPSafeMalloc(2ULL * width, sizeof(*work));
if (work == NULL) {
WebPPictureFree(&tmp);
return 0;
return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
// If present, we need to rescale alpha first (for AlphaMultiplyY).
if (picture->a != NULL) {
WebPInitAlphaProcessing();
if (!RescalePlane(picture->a, prev_width, prev_height, picture->a_stride,
tmp.a, width, height, tmp.a_stride, work, 1)) {
return 0;
return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
}
}
@ -246,14 +250,14 @@ int WebPPictureRescale(WebPPicture* picture, int width, int height) {
!RescalePlane(picture->v, HALVE(prev_width), HALVE(prev_height),
picture->uv_stride, tmp.v, HALVE(width), HALVE(height),
tmp.uv_stride, work, 1)) {
return 0;
return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
}
AlphaMultiplyY(&tmp, 1);
} else {
work = (rescaler_t*)WebPSafeMalloc(2ULL * width * 4, sizeof(*work));
if (work == NULL) {
WebPPictureFree(&tmp);
return 0;
return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
// In order to correctly interpolate colors, we need to apply the alpha
// weighting first (black-matting), scale the RGB values, and remove
@ -263,7 +267,7 @@ int WebPPictureRescale(WebPPicture* picture, int width, int height) {
if (!RescalePlane((const uint8_t*)picture->argb, prev_width, prev_height,
picture->argb_stride * 4, (uint8_t*)tmp.argb, width,
height, tmp.argb_stride * 4, work, 4)) {
return 0;
return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
}
AlphaMultiplyARGB(&tmp, 1);
}

Просмотреть файл

@ -258,7 +258,10 @@ static int EmitPartitionsSize(const VP8Encoder* const enc,
buf[3 * p + 1] = (part_size >> 8) & 0xff;
buf[3 * p + 2] = (part_size >> 16) & 0xff;
}
return p ? pic->writer(buf, 3 * p, pic) : 1;
if (p && !pic->writer(buf, 3 * p, pic)) {
return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE);
}
return 1;
}
//------------------------------------------------------------------------------
@ -381,6 +384,7 @@ int VP8EncWrite(VP8Encoder* const enc) {
enc->coded_size_ = (int)(CHUNK_HEADER_SIZE + riff_size);
ok = ok && WebPReportProgress(pic, final_percent, &enc->percent_);
if (!ok) WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE);
return ok;
}

Просмотреть файл

@ -196,8 +196,7 @@ static int CoOccurrenceBuild(const WebPPicture* const pic,
uint32_t palette_sorted[MAX_PALETTE_SIZE];
lines = (uint32_t*)WebPSafeMalloc(2 * pic->width, sizeof(*lines));
if (lines == NULL) {
WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
return 0;
return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
line_top = &lines[0];
line_current = &lines[pic->width];
@ -255,8 +254,7 @@ static int PaletteSortModifiedZeng(
cooccurrence =
(uint32_t*)WebPSafeCalloc(num_colors * num_colors, sizeof(*cooccurrence));
if (cooccurrence == NULL) {
WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
return 0;
return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
if (!CoOccurrenceBuild(pic, palette_sorted, num_colors, cooccurrence)) {
WebPSafeFree(cooccurrence);
@ -1013,8 +1011,7 @@ static int StoreImageToBitMask(
VP8LRefsCursorNext(&c);
}
if (bw->error_) {
WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
return 0;
return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
return 1;
}
@ -1298,7 +1295,10 @@ static int EncodeImageInternal(
}
}
tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens));
if (tokens == NULL) goto Error;
if (tokens == NULL) {
WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
goto Error;
}
for (i = 0; i < 5 * histogram_image_size; ++i) {
HuffmanTreeCode* const codes = &huffman_codes[i];
StoreHuffmanCode(bw, huff_tree, tokens, codes);
@ -1449,18 +1449,21 @@ static int WriteImage(const WebPPicture* const pic, VP8LBitWriter* const bw,
const size_t vp8l_size = VP8L_SIGNATURE_SIZE + webpll_size;
const size_t pad = vp8l_size & 1;
const size_t riff_size = TAG_SIZE + CHUNK_HEADER_SIZE + vp8l_size + pad;
*coded_size = 0;
if (bw->error_) {
return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
if (!WriteRiffHeader(pic, riff_size, vp8l_size) ||
!pic->writer(webpll_data, webpll_size, pic)) {
WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE);
return 0;
return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE);
}
if (pad) {
const uint8_t pad_byte[1] = { 0 };
if (!pic->writer(pad_byte, 1, pic)) {
WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE);
return 0;
return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_WRITE);
}
}
*coded_size = CHUNK_HEADER_SIZE + riff_size;
@ -1505,8 +1508,7 @@ static int AllocateTransformBuffer(VP8LEncoder* const enc, int width,
ClearTransformBuffer(enc);
mem = (uint32_t*)WebPSafeMalloc(mem_size, sizeof(*mem));
if (mem == NULL) {
WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
return 0;
return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
enc->transform_mem_ = mem;
enc->transform_mem_size_ = (size_t)mem_size;
@ -1614,8 +1616,7 @@ static int ApplyPalette(const uint32_t* src, uint32_t src_stride, uint32_t* dst,
int x, y;
if (tmp_row == NULL) {
WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
return 0;
return WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
if (palette_size < APPLY_PALETTE_GREEDY_MAX) {
@ -1969,9 +1970,8 @@ int VP8LEncodeStream(const WebPConfig* const config,
int ok_main;
if (enc_main == NULL || !VP8LBitWriterInit(&bw_side, 0)) {
WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
VP8LEncoderDelete(enc_main);
return 0;
return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
}
// Avoid "garbage value" error from Clang's static analysis tool.
@ -2118,8 +2118,7 @@ int VP8LEncodeImage(const WebPConfig* const config,
if (picture == NULL) return 0;
if (config == NULL || picture->argb == NULL) {
WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
return 0;
return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
}
width = picture->width;

Просмотреть файл

@ -307,7 +307,10 @@ int WebPEncodingSetError(const WebPPicture* const pic,
WebPEncodingError error) {
assert((int)error < VP8_ENC_ERROR_LAST);
assert((int)error >= VP8_ENC_OK);
((WebPPicture*)pic)->error_code = error;
// The oldest error reported takes precedence over the new one.
if (pic->error_code == VP8_ENC_OK) {
((WebPPicture*)pic)->error_code = error;
}
return 0;
}
@ -317,8 +320,7 @@ int WebPReportProgress(const WebPPicture* const pic,
*percent_store = percent;
if (pic->progress_hook && !pic->progress_hook(percent, pic)) {
// user abort requested
WebPEncodingSetError(pic, VP8_ENC_ERROR_USER_ABORT);
return 0;
return WebPEncodingSetError(pic, VP8_ENC_ERROR_USER_ABORT);
}
}
return 1; // ok
@ -329,7 +331,7 @@ int WebPEncode(const WebPConfig* config, WebPPicture* pic) {
int ok = 0;
if (pic == NULL) return 0;
WebPEncodingSetError(pic, VP8_ENC_OK); // all ok so far
pic->error_code = VP8_ENC_OK; // all ok so far
if (config == NULL) { // bad params
return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
}

Просмотреть файл

@ -81,10 +81,11 @@ WEBP_EXTERN uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size,
// returned is the Y samples buffer. Upon return, *u and *v will point to
// the U and V chroma data. These U and V buffers need NOT be passed to
// WebPFree(), unlike the returned Y luma one. The dimension of the U and V
// planes are both (*width + 1) / 2 and (*height + 1)/ 2.
// planes are both (*width + 1) / 2 and (*height + 1) / 2.
// Upon return, the Y buffer has a stride returned as '*stride', while U and V
// have a common stride returned as '*uv_stride'.
// Return NULL in case of error.
// 'width' and 'height' may be NULL, the other pointers must not be.
// Returns NULL in case of error.
// (*) Also named Y'CbCr. See: https://en.wikipedia.org/wiki/YCbCr
WEBP_EXTERN uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size,
int* width, int* height,