| Index: third_party/libwebp/dec/buffer.c
|
| diff --git a/third_party/libwebp/dec/buffer.c b/third_party/libwebp/dec/buffer.c
|
| index caaf2f00081753cebc83fe31839ee0b71dc13d03..c159f6f24893bd9c91b6fa2837bb880751506ac5 100644
|
| --- a/third_party/libwebp/dec/buffer.c
|
| +++ b/third_party/libwebp/dec/buffer.c
|
| @@ -1,4 +1,4 @@
|
| -// Copyright 2011 Google Inc.
|
| +// Copyright 2011 Google Inc. All Rights Reserved.
|
| //
|
| // This code is licensed under the same terms as WebM:
|
| // Software License Agreement: http://www.webmproject.org/license/software/
|
| @@ -10,8 +10,10 @@
|
| // Author: Skal (pascal.massimino@gmail.com)
|
|
|
| #include <stdlib.h>
|
| -#include "vp8i.h"
|
| -#include "webpi.h"
|
| +
|
| +#include "./vp8i.h"
|
| +#include "./webpi.h"
|
| +#include "../utils/utils.h"
|
|
|
| #if defined(__cplusplus) || defined(c_plusplus)
|
| extern "C" {
|
| @@ -21,14 +23,26 @@ extern "C" {
|
| // WebPDecBuffer
|
|
|
| // Number of bytes per pixel for the different color-spaces.
|
| -static const int kModeBpp[MODE_LAST] = { 3, 4, 3, 4, 4, 2, 2, 1, 1 };
|
| +static const int kModeBpp[MODE_LAST] = {
|
| + 3, 4, 3, 4, 4, 2, 2,
|
| + 4, 4, 4, 2, // pre-multiplied modes
|
| + 1, 1 };
|
| +
|
| +// Check that webp_csp_mode is within the bounds of WEBP_CSP_MODE.
|
| +// Convert to an integer to handle both the unsigned/signed enum cases
|
| +// without the need for casting to remove type limit warnings.
|
| +static int IsValidColorspace(int webp_csp_mode) {
|
| + return (webp_csp_mode >= MODE_RGB && webp_csp_mode < MODE_LAST);
|
| +}
|
|
|
| static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) {
|
| int ok = 1;
|
| - WEBP_CSP_MODE mode = buffer->colorspace;
|
| + const WEBP_CSP_MODE mode = buffer->colorspace;
|
| const int width = buffer->width;
|
| const int height = buffer->height;
|
| - if (mode >= MODE_YUV) { // YUV checks
|
| + if (!IsValidColorspace(mode)) {
|
| + ok = 0;
|
| + } else if (!WebPIsRGBMode(mode)) { // YUV checks
|
| const WebPYUVABuffer* const buf = &buffer->u.YUVA;
|
| const uint64_t y_size = (uint64_t)buf->y_stride * height;
|
| const uint64_t u_size = (uint64_t)buf->u_stride * ((height + 1) / 2);
|
| @@ -37,18 +51,23 @@ static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) {
|
| ok &= (y_size <= buf->y_size);
|
| ok &= (u_size <= buf->u_size);
|
| ok &= (v_size <= buf->v_size);
|
| - ok &= (a_size <= buf->a_size);
|
| ok &= (buf->y_stride >= width);
|
| ok &= (buf->u_stride >= (width + 1) / 2);
|
| ok &= (buf->v_stride >= (width + 1) / 2);
|
| - if (buf->a) {
|
| + ok &= (buf->y != NULL);
|
| + ok &= (buf->u != NULL);
|
| + ok &= (buf->v != NULL);
|
| + if (mode == MODE_YUVA) {
|
| ok &= (buf->a_stride >= width);
|
| + ok &= (a_size <= buf->a_size);
|
| + ok &= (buf->a != NULL);
|
| }
|
| } else { // RGB checks
|
| const WebPRGBABuffer* const buf = &buffer->u.RGBA;
|
| const uint64_t size = (uint64_t)buf->stride * height;
|
| ok &= (size <= buf->size);
|
| ok &= (buf->stride >= width * kModeBpp[mode]);
|
| + ok &= (buf->rgba != NULL);
|
| }
|
| return ok ? VP8_STATUS_OK : VP8_STATUS_INVALID_PARAM;
|
| }
|
| @@ -56,23 +75,22 @@ static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) {
|
| static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) {
|
| const int w = buffer->width;
|
| const int h = buffer->height;
|
| + const WEBP_CSP_MODE mode = buffer->colorspace;
|
|
|
| - if (w <= 0 || h <= 0) {
|
| + if (w <= 0 || h <= 0 || !IsValidColorspace(mode)) {
|
| return VP8_STATUS_INVALID_PARAM;
|
| }
|
|
|
| if (!buffer->is_external_memory && buffer->private_memory == NULL) {
|
| uint8_t* output;
|
| - WEBP_CSP_MODE mode = buffer->colorspace;
|
| - int stride;
|
| int uv_stride = 0, a_stride = 0;
|
| - uint64_t size, uv_size = 0, a_size = 0, total_size;
|
| + uint64_t uv_size = 0, a_size = 0, total_size;
|
| // We need memory and it hasn't been allocated yet.
|
| // => initialize output buffer, now that dimensions are known.
|
| - stride = w * kModeBpp[mode];
|
| - size = (uint64_t)stride * h;
|
| + const int stride = w * kModeBpp[mode];
|
| + const uint64_t size = (uint64_t)stride * h;
|
|
|
| - if (mode >= MODE_YUV) {
|
| + if (!WebPIsRGBMode(mode)) {
|
| uv_stride = (w + 1) / 2;
|
| uv_size = (uint64_t)uv_stride * ((h + 1) / 2);
|
| if (mode == MODE_YUVA) {
|
| @@ -83,16 +101,13 @@ static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) {
|
| total_size = size + 2 * uv_size + a_size;
|
|
|
| // Security/sanity checks
|
| - if (((size_t)total_size != total_size) || (total_size >= (1ULL << 40))) {
|
| - return VP8_STATUS_INVALID_PARAM;
|
| - }
|
| -
|
| - buffer->private_memory = output = (uint8_t*)malloc((size_t)total_size);
|
| + output = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*output));
|
| if (output == NULL) {
|
| return VP8_STATUS_OUT_OF_MEMORY;
|
| }
|
| + buffer->private_memory = output;
|
|
|
| - if (mode >= MODE_YUV) { // YUVA initialization
|
| + if (!WebPIsRGBMode(mode)) { // YUVA initialization
|
| WebPYUVABuffer* const buf = &buffer->u.YUVA;
|
| buf->y = output;
|
| buf->y_stride = stride;
|
| @@ -140,7 +155,7 @@ VP8StatusCode WebPAllocateDecBuffer(int w, int h,
|
| if (options->scaled_width <= 0 || options->scaled_height <= 0) {
|
| return VP8_STATUS_INVALID_PARAM;
|
| }
|
| - w = options->scaled_width;
|
| + w = options->scaled_width;
|
| h = options->scaled_height;
|
| }
|
| }
|
| @@ -154,15 +169,17 @@ VP8StatusCode WebPAllocateDecBuffer(int w, int h,
|
| //------------------------------------------------------------------------------
|
| // constructors / destructors
|
|
|
| -int WebPInitDecBufferInternal(WebPDecBuffer* const buffer, int version) {
|
| - if (version != WEBP_DECODER_ABI_VERSION) return 0; // version mismatch
|
| - if (!buffer) return 0;
|
| +int WebPInitDecBufferInternal(WebPDecBuffer* buffer, int version) {
|
| + if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) {
|
| + return 0; // version mismatch
|
| + }
|
| + if (buffer == NULL) return 0;
|
| memset(buffer, 0, sizeof(*buffer));
|
| return 1;
|
| }
|
|
|
| -void WebPFreeDecBuffer(WebPDecBuffer* const buffer) {
|
| - if (buffer) {
|
| +void WebPFreeDecBuffer(WebPDecBuffer* buffer) {
|
| + if (buffer != NULL) {
|
| if (!buffer->is_external_memory)
|
| free(buffer->private_memory);
|
| buffer->private_memory = NULL;
|
| @@ -171,9 +188,9 @@ void WebPFreeDecBuffer(WebPDecBuffer* const buffer) {
|
|
|
| void WebPCopyDecBuffer(const WebPDecBuffer* const src,
|
| WebPDecBuffer* const dst) {
|
| - if (src && dst) {
|
| + if (src != NULL && dst != NULL) {
|
| *dst = *src;
|
| - if (src->private_memory) {
|
| + if (src->private_memory != NULL) {
|
| dst->is_external_memory = 1; // dst buffer doesn't own the memory.
|
| dst->private_memory = NULL;
|
| }
|
| @@ -182,9 +199,9 @@ void WebPCopyDecBuffer(const WebPDecBuffer* const src,
|
|
|
| // Copy and transfer ownership from src to dst (beware of parameter order!)
|
| void WebPGrabDecBuffer(WebPDecBuffer* const src, WebPDecBuffer* const dst) {
|
| - if (src && dst) {
|
| + if (src != NULL && dst != NULL) {
|
| *dst = *src;
|
| - if (src->private_memory) {
|
| + if (src->private_memory != NULL) {
|
| src->is_external_memory = 1; // src relinquishes ownership
|
| src->private_memory = NULL;
|
| }
|
|
|