diff --git a/examples/anim_util.c b/examples/anim_util.c index 5c593df3..464c4c38 100644 --- a/examples/anim_util.c +++ b/examples/anim_util.c @@ -39,13 +39,24 @@ static int IsFullFrame(int width, int height, return (width == canvas_width && height == canvas_height); } +static int CheckSizeForOverflow(uint64_t size) { + return (size == (size_t)size); +} + static int AllocateFrames(AnimatedImage* const image, uint32_t num_frames) { uint32_t i; - const size_t rgba_size = - image->canvas_width * kNumChannels * image->canvas_height; - uint8_t* const mem = (uint8_t*)malloc(num_frames * rgba_size * sizeof(*mem)); - DecodedFrame* const frames = - (DecodedFrame*)malloc(num_frames * sizeof(*frames)); + uint8_t* mem = NULL; + DecodedFrame* frames = NULL; + const uint64_t rgba_size = + (uint64_t)image->canvas_width * kNumChannels * image->canvas_height; + const uint64_t total_size = (uint64_t)num_frames * rgba_size * sizeof(*mem); + const uint64_t total_frame_size = (uint64_t)num_frames * sizeof(*frames); + if (!CheckSizeForOverflow(total_size) || + !CheckSizeForOverflow(total_frame_size)) { + return 0; + } + mem = (uint8_t*)malloc(total_size); + frames = (DecodedFrame*)malloc(total_frame_size); if (mem == NULL || frames == NULL) { free(mem); diff --git a/src/demux/anim_decode.c b/src/demux/anim_decode.c index 1989eb4a..0a468adf 100644 --- a/src/demux/anim_decode.c +++ b/src/demux/anim_decode.c @@ -112,18 +112,15 @@ WebPAnimDecoder* WebPAnimDecoderNewInternal( dec->info_.bgcolor = WebPDemuxGetI(dec->demux_, WEBP_FF_BACKGROUND_COLOR); dec->info_.frame_count = WebPDemuxGetI(dec->demux_, WEBP_FF_FRAME_COUNT); - { - const int canvas_bytes = - dec->info_.canvas_width * NUM_CHANNELS * dec->info_.canvas_height; - // Note: calloc() because we fill frame with zeroes as well. - dec->curr_frame_ = WebPSafeCalloc(1ULL, canvas_bytes); - if (dec->curr_frame_ == NULL) goto Error; - dec->prev_frame_disposed_ = WebPSafeCalloc(1ULL, canvas_bytes); - if (dec->prev_frame_disposed_ == NULL) goto Error; - } + // Note: calloc() because we fill frame with zeroes as well. + dec->curr_frame_ = WebPSafeCalloc( + dec->info_.canvas_width * NUM_CHANNELS, dec->info_.canvas_height); + if (dec->curr_frame_ == NULL) goto Error; + dec->prev_frame_disposed_ = WebPSafeCalloc( + dec->info_.canvas_width * NUM_CHANNELS, dec->info_.canvas_height); + if (dec->prev_frame_disposed_ == NULL) goto Error; WebPAnimDecoderReset(dec); - return dec; Error: @@ -144,9 +141,13 @@ static int IsFullFrame(int width, int height, int canvas_width, } // Clear the canvas to transparent. -static void ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width, - uint32_t canvas_height) { - memset(buf, 0, canvas_width * NUM_CHANNELS * canvas_height); +static int ZeroFillCanvas(uint8_t* buf, uint32_t canvas_width, + uint32_t canvas_height) { + const uint64_t size = + (uint64_t)canvas_width * canvas_height * NUM_CHANNELS * sizeof(*buf); + if (size != (size_t)size) return 0; + memset(buf, 0, (size_t)size); + return 1; } // Clear given frame rectangle to transparent. @@ -162,10 +163,13 @@ static void ZeroFillFrameRect(uint8_t* buf, int buf_stride, int x_offset, } // Copy width * height pixels from 'src' to 'dst'. -static void CopyCanvas(const uint8_t* src, uint8_t* dst, - uint32_t width, uint32_t height) { +static int CopyCanvas(const uint8_t* src, uint8_t* dst, + uint32_t width, uint32_t height) { + const uint64_t size = (uint64_t)width * height * NUM_CHANNELS; + if (size != (size_t)size) return 0; assert(src != NULL && dst != NULL); - memcpy(dst, src, width * NUM_CHANNELS * height); + memcpy(dst, src, (size_t)size); + return 1; } // Returns true if the current frame is a key-frame. @@ -328,9 +332,14 @@ int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, is_key_frame = IsKeyFrame(&iter, &dec->prev_iter_, dec->prev_frame_was_keyframe_, width, height); if (is_key_frame) { - ZeroFillCanvas(dec->curr_frame_, width, height); + if (!ZeroFillCanvas(dec->curr_frame_, width, height)) { + goto Error; + } } else { - CopyCanvas(dec->prev_frame_disposed_, dec->curr_frame_, width, height); + if (!CopyCanvas(dec->prev_frame_disposed_, dec->curr_frame_, + width, height)) { + goto Error; + } } // Decode.