mux: plug some memory leaks on error

Make sure chunk->data and wpi are not leaked by
MuxAddFrameTileInternal() in case of MEMORY_ERROR in ChunkSetNth().

Change-Id: Ie20e84b92f4bdcb7c3b94520f36b20dd2e730545
This commit is contained in:
Urvang Joshi 2012-01-17 05:41:56 +00:00 committed by James Zern
parent 241ddd38e2
commit b0d2fecf25
3 changed files with 28 additions and 12 deletions

View File

@ -355,52 +355,63 @@ static WebPMuxError MuxAddFrameTileInternal(WebPMux* const mux, uint32_t nth,
err = GetImageData(data, size, &vp8_data, &vp8_size, NULL, NULL); err = GetImageData(data, size, &vp8_data, &vp8_size, NULL, NULL);
if (err != WEBP_MUX_OK) return err; if (err != WEBP_MUX_OK) return err;
ChunkInit(&chunk);
MuxImageInit(&wpi); MuxImageInit(&wpi);
if (has_alpha) { if (has_alpha) {
// Add alpha chunk. // Add alpha chunk.
ChunkInit(&chunk);
err = ChunkAssignDataImageInfo(&chunk, alpha_data, alpha_size, NULL, err = ChunkAssignDataImageInfo(&chunk, alpha_data, alpha_size, NULL,
copy_data, kChunks[ALPHA_ID].chunkTag); copy_data, kChunks[ALPHA_ID].chunkTag);
if (err != WEBP_MUX_OK) return err; if (err != WEBP_MUX_OK) return err;
err = ChunkSetNth(&chunk, &wpi.alpha_, 1); err = ChunkSetNth(&chunk, &wpi.alpha_, 1);
if (err != WEBP_MUX_OK) return err; if (err != WEBP_MUX_OK) return err;
ChunkInit(&chunk); // chunk owned by wpi.alpha_ now.
} }
// Create image_info object. // Create image_info object.
image_info = CreateImageInfo(x_offset, y_offset, duration, vp8_data, image_info = CreateImageInfo(x_offset, y_offset, duration, vp8_data,
vp8_size); vp8_size);
if (image_info == NULL) return WEBP_MUX_MEMORY_ERROR; if (image_info == NULL) {
MuxImageRelease(&wpi);
return WEBP_MUX_MEMORY_ERROR;
}
// Add image chunk. // Add image chunk.
ChunkInit(&chunk);
err = ChunkAssignDataImageInfo(&chunk, vp8_data, vp8_size, image_info, err = ChunkAssignDataImageInfo(&chunk, vp8_data, vp8_size, image_info,
copy_data, kChunks[IMAGE_ID].chunkTag); copy_data, kChunks[IMAGE_ID].chunkTag);
if (err != WEBP_MUX_OK) goto Err; if (err != WEBP_MUX_OK) goto Err;
image_info = NULL; // Owned by 'chunk' now.
err = ChunkSetNth(&chunk, &wpi.vp8_, 1); err = ChunkSetNth(&chunk, &wpi.vp8_, 1);
if (err != WEBP_MUX_OK) goto Err; if (err != WEBP_MUX_OK) goto Err;
ChunkInit(&chunk); // chunk owned by wpi.vp8_ now.
// Create frame/tile data from image_info. // Create frame/tile data from image_info.
err = CreateDataFromImageInfo(image_info, is_frame, &frame_tile_data, err = CreateDataFromImageInfo(wpi.vp8_->image_info_, is_frame,
&frame_tile_data_size); &frame_tile_data, &frame_tile_data_size);
if (err != WEBP_MUX_OK) goto Err; if (err != WEBP_MUX_OK) goto Err;
// Add frame/tile chunk (with copy_data = 1). // Add frame/tile chunk (with copy_data = 1).
ChunkInit(&chunk);
err = ChunkAssignDataImageInfo(&chunk, frame_tile_data, frame_tile_data_size, err = ChunkAssignDataImageInfo(&chunk, frame_tile_data, frame_tile_data_size,
NULL, 1, tag); NULL, 1, tag);
if (err != WEBP_MUX_OK) goto Err; if (err != WEBP_MUX_OK) goto Err;
free(frame_tile_data);
frame_tile_data = NULL;
err = ChunkSetNth(&chunk, &wpi.header_, 1); err = ChunkSetNth(&chunk, &wpi.header_, 1);
if (err != WEBP_MUX_OK) goto Err; if (err != WEBP_MUX_OK) goto Err;
ChunkInit(&chunk); // chunk owned by wpi.header_ now.
free(frame_tile_data);
// Add this WebPMuxImage to mux. // Add this WebPMuxImage to mux.
return MuxImageSetNth(&wpi, &mux->images_, nth); err = MuxImageSetNth(&wpi, &mux->images_, nth);
if (err != WEBP_MUX_OK) goto Err;
// All is well.
return WEBP_MUX_OK;
Err: // Something bad happened. Err: // Something bad happened.
free(image_info); free(image_info);
free(frame_tile_data); free(frame_tile_data);
ChunkRelease(&chunk);
MuxImageRelease(&wpi);
return err; return err;
} }

View File

@ -153,6 +153,9 @@ WebPMuxError ChunkAssignDataImageInfo(WebPChunk* chunk, const uint8_t* data,
WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list, WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list,
uint32_t nth); uint32_t nth);
// Releases chunk and returns chunk->next_.
WebPChunk* ChunkRelease(WebPChunk* const chunk);
// Deletes given chunk & returns chunk->next_. // Deletes given chunk & returns chunk->next_.
WebPChunk* ChunkDelete(WebPChunk* const chunk); WebPChunk* ChunkDelete(WebPChunk* const chunk);
@ -174,6 +177,9 @@ uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst);
// Initialize. // Initialize.
void MuxImageInit(WebPMuxImage* const wpi); void MuxImageInit(WebPMuxImage* const wpi);
// Releases image 'wpi' and returns wpi->next.
WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi);
// Delete image 'wpi' and return the next image in the list or NULL. // Delete image 'wpi' and return the next image in the list or NULL.
// 'wpi' can be NULL. // 'wpi' can be NULL.
WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi); WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi);

View File

@ -47,8 +47,7 @@ void ChunkInit(WebPChunk* const chunk) {
chunk->next_ = NULL; chunk->next_ = NULL;
} }
// Releases chunk and returns chunk->next_. WebPChunk* ChunkRelease(WebPChunk* const chunk) {
static WebPChunk* ChunkRelease(WebPChunk* const chunk) {
WebPChunk* next; WebPChunk* next;
if (chunk == NULL) return NULL; if (chunk == NULL) return NULL;
free(chunk->image_info_); free(chunk->image_info_);
@ -239,7 +238,7 @@ void MuxImageInit(WebPMuxImage* const wpi) {
wpi->next_ = NULL; wpi->next_ = NULL;
} }
static WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) { WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) {
WebPMuxImage* next; WebPMuxImage* next;
if (wpi == NULL) return NULL; if (wpi == NULL) return NULL;
ChunkDelete(wpi->header_); ChunkDelete(wpi->header_);