diff options
Diffstat (limited to 'src/3rdparty/libwebp/src/mux/muxedit.c')
-rw-r--r-- | src/3rdparty/libwebp/src/mux/muxedit.c | 104 |
1 files changed, 76 insertions, 28 deletions
diff --git a/src/3rdparty/libwebp/src/mux/muxedit.c b/src/3rdparty/libwebp/src/mux/muxedit.c index 25770b3..24ca471 100644 --- a/src/3rdparty/libwebp/src/mux/muxedit.c +++ b/src/3rdparty/libwebp/src/mux/muxedit.c @@ -20,17 +20,18 @@ // Life of a mux object. static void MuxInit(WebPMux* const mux) { - if (mux == NULL) return; + assert(mux != NULL); memset(mux, 0, sizeof(*mux)); + mux->canvas_width_ = 0; // just to be explicit + mux->canvas_height_ = 0; } WebPMux* WebPNewInternal(int version) { if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_MUX_ABI_VERSION)) { return NULL; } else { - WebPMux* const mux = (WebPMux*)malloc(sizeof(WebPMux)); - // If mux is NULL MuxInit is a noop. - MuxInit(mux); + WebPMux* const mux = (WebPMux*)WebPSafeMalloc(1ULL, sizeof(WebPMux)); + if (mux != NULL) MuxInit(mux); return mux; } } @@ -43,7 +44,7 @@ static void DeleteAllImages(WebPMuxImage** const wpi_list) { } static void MuxRelease(WebPMux* const mux) { - if (mux == NULL) return; + assert(mux != NULL); DeleteAllImages(&mux->images_); ChunkListDelete(&mux->vp8x_); ChunkListDelete(&mux->iccp_); @@ -54,9 +55,10 @@ static void MuxRelease(WebPMux* const mux) { } void WebPMuxDelete(WebPMux* mux) { - // If mux is NULL MuxRelease is a noop. - MuxRelease(mux); - free(mux); + if (mux != NULL) { + MuxRelease(mux); + WebPSafeFree(mux); + } } //------------------------------------------------------------------------------ @@ -102,7 +104,7 @@ static WebPMuxError CreateFrameFragmentData( assert(info->dispose_method == (info->dispose_method & 1)); // Note: assertion on upper bounds is done in PutLE24(). - frame_frgm_bytes = (uint8_t*)malloc(frame_frgm_size); + frame_frgm_bytes = (uint8_t*)WebPSafeMalloc(1ULL, frame_frgm_size); if (frame_frgm_bytes == NULL) return WEBP_MUX_MEMORY_ERROR; PutLE24(frame_frgm_bytes + 0, info->x_offset / 2); @@ -360,6 +362,34 @@ WebPMuxError WebPMuxSetAnimationParams(WebPMux* mux, return MuxSet(mux, kChunks[IDX_ANIM].tag, 1, &anim, 1); } +#if WEBP_MUX_ABI_VERSION > 0x0101 +WebPMuxError WebPMuxSetCanvasSize(WebPMux* mux, + int width, int height) { + WebPMuxError err; + if (mux == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + if (width < 0 || height < 0 || + width > MAX_CANVAS_SIZE || height > MAX_CANVAS_SIZE) { + return WEBP_MUX_INVALID_ARGUMENT; + } + if (width * (uint64_t)height >= MAX_IMAGE_AREA) { + return WEBP_MUX_INVALID_ARGUMENT; + } + if ((width * height) == 0 && (width | height) != 0) { + // one of width / height is zero, but not both -> invalid! + return WEBP_MUX_INVALID_ARGUMENT; + } + // If we already assembled a VP8X chunk, invalidate it. + err = MuxDeleteAllNamedData(mux, kChunks[IDX_VP8X].tag); + if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err; + + mux->canvas_width_ = width; + mux->canvas_height_ = height; + return WEBP_MUX_OK; +} +#endif + //------------------------------------------------------------------------------ // Delete API(s). @@ -413,9 +443,10 @@ static WebPMuxError GetImageInfo(const WebPMuxImage* const wpi, return WEBP_MUX_OK; } -static WebPMuxError GetImageCanvasWidthHeight( - const WebPMux* const mux, uint32_t flags, - int* const width, int* const height) { +// Returns the tightest dimension for the canvas considering the image list. +static WebPMuxError GetAdjustedCanvasSize(const WebPMux* const mux, + uint32_t flags, + int* const width, int* const height) { WebPMuxImage* wpi = NULL; assert(mux != NULL); assert(width != NULL && height != NULL); @@ -513,12 +544,7 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) { flags |= ALPHA_FLAG; // Some images have an alpha channel. } - if (flags == 0) { - // For Simple Image, VP8X chunk should not be added. - return WEBP_MUX_OK; - } - - err = GetImageCanvasWidthHeight(mux, flags, &width, &height); + err = GetAdjustedCanvasSize(mux, flags, &width, &height); if (err != WEBP_MUX_OK) return err; if (width <= 0 || height <= 0) { @@ -528,6 +554,19 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) { return WEBP_MUX_INVALID_ARGUMENT; } + if (mux->canvas_width_ != 0 || mux->canvas_height_ != 0) { + if (width > mux->canvas_width_ || height > mux->canvas_height_) { + return WEBP_MUX_INVALID_ARGUMENT; + } + width = mux->canvas_width_; + height = mux->canvas_height_; + } + + if (flags == 0) { + // For Simple Image, VP8X chunk should not be added. + return WEBP_MUX_OK; + } + if (MuxHasAlpha(images)) { // This means some frames explicitly/implicitly contain alpha. // Note: This 'flags' update must NOT be done for a lossless image @@ -548,9 +587,9 @@ static WebPMuxError MuxCleanup(WebPMux* const mux) { int num_fragments; int num_anim_chunks; - // If we have an image with single fragment or frame, convert it to a - // non-animated non-fragmented image (to avoid writing FRGM/ANMF chunk - // unnecessarily). + // If we have an image with a single fragment or frame, and its rectangle + // covers the whole canvas, convert it to a non-animated non-fragmented image + // (to avoid writing FRGM/ANMF chunk unnecessarily). WebPMuxError err = WebPMuxNumChunks(mux, kChunks[IDX_ANMF].id, &num_frames); if (err != WEBP_MUX_OK) return err; err = WebPMuxNumChunks(mux, kChunks[IDX_FRGM].id, &num_fragments); @@ -559,14 +598,18 @@ static WebPMuxError MuxCleanup(WebPMux* const mux) { WebPMuxImage* frame_frag; err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, &frame_frag); assert(err == WEBP_MUX_OK); // We know that one frame/fragment does exist. - if (frame_frag->header_ != NULL) { + assert(frame_frag != NULL); + if (frame_frag->header_ != NULL && + ((mux->canvas_width_ == 0 && mux->canvas_height_ == 0) || + (frame_frag->width_ == mux->canvas_width_ && + frame_frag->height_ == mux->canvas_height_))) { assert(frame_frag->header_->tag_ == kChunks[IDX_ANMF].tag || frame_frag->header_->tag_ == kChunks[IDX_FRGM].tag); ChunkDelete(frame_frag->header_); // Removes ANMF/FRGM chunk. frame_frag->header_ = NULL; + num_frames = 0; + num_fragments = 0; } - num_frames = 0; - num_fragments = 0; } // Remove ANIM chunk if this is a non-animated image. err = WebPMuxNumChunks(mux, kChunks[IDX_ANIM].id, &num_anim_chunks); @@ -603,7 +646,13 @@ WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) { uint8_t* dst = NULL; WebPMuxError err; - if (mux == NULL || assembled_data == NULL) { + if (assembled_data == NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + // Clean up returned data, in case something goes wrong. + memset(assembled_data, 0, sizeof(*assembled_data)); + + if (mux == NULL) { return WEBP_MUX_INVALID_ARGUMENT; } @@ -619,7 +668,7 @@ WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) { + ChunkListDiskSize(mux->exif_) + ChunkListDiskSize(mux->xmp_) + ChunkListDiskSize(mux->unknown_) + RIFF_HEADER_SIZE; - data = (uint8_t*)malloc(size); + data = (uint8_t*)WebPSafeMalloc(1ULL, size); if (data == NULL) return WEBP_MUX_MEMORY_ERROR; // Emit header & chunks. @@ -636,7 +685,7 @@ WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) { // Validate mux. err = MuxValidate(mux); if (err != WEBP_MUX_OK) { - free(data); + WebPSafeFree(data); data = NULL; size = 0; } @@ -649,4 +698,3 @@ WebPMuxError WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data) { } //------------------------------------------------------------------------------ - |