1
0
Fork 0
forked from len0rd/rockbox

ImageViewer: Fix FS#13329 (GIF File handle/memory leaks)

Change-Id: Ib3ef22716c8ba35c7bb78231ca4f5c7155f16018
This commit is contained in:
Christian Soffke 2021-12-20 00:33:34 +01:00 committed by Aidan MacDonald
parent f379e1dbb3
commit 8f063d49c2
3 changed files with 40 additions and 16 deletions

View file

@ -132,6 +132,8 @@ static int load_image(char *filename, struct image_info *info,
time = *rb->current_tick - time; time = *rb->current_tick - time;
} }
gif_decoder_destroy_memory_pool(p_decoder);
if (!iv->running_slideshow && !p_decoder->error) if (!iv->running_slideshow && !p_decoder->error)
{ {
rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ); rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
@ -142,6 +144,9 @@ static int load_image(char *filename, struct image_info *info,
if (p_decoder->error) if (p_decoder->error)
{ {
if (p_decoder->error == D_GIF_ERR_NOT_ENOUGH_MEM)
return PLUGIN_OUTOFMEM;
rb->splashf(HZ, "%s", GifErrorString(p_decoder->error)); rb->splashf(HZ, "%s", GifErrorString(p_decoder->error));
return PLUGIN_ERROR; return PLUGIN_ERROR;
} }
@ -157,12 +162,9 @@ static int load_image(char *filename, struct image_info *info,
img_size = (p_decoder->native_img_size*p_decoder->frames_count + 3) & ~3; img_size = (p_decoder->native_img_size*p_decoder->frames_count + 3) & ~3;
disp_size = (sizeof(unsigned char *)*p_decoder->frames_count*4 + 3) & ~3; disp_size = (sizeof(unsigned char *)*p_decoder->frames_count*4 + 3) & ~3;
/* No memory to allocate disp matrix */
if (memory_size < img_size + disp_size) if (memory_size < img_size + disp_size)
{ return PLUGIN_OUTOFMEM;
/* No memory to allocate disp matrix */
rb->splashf(HZ, "%s", GifErrorString(D_GIF_ERR_NOT_ENOUGH_MEM));
return PLUGIN_ERROR;
}
disp = (unsigned char **)(p_decoder->mem + img_size); disp = (unsigned char **)(p_decoder->mem + img_size);
disp_buf = (unsigned char *)disp + disp_size; disp_buf = (unsigned char *)disp + disp_size;

View file

@ -115,6 +115,11 @@ void gif_decoder_init(struct gif_decoder *d, void *mem, size_t size)
init_memory_pool(d->mem_size, d->mem); init_memory_pool(d->mem_size, d->mem);
} }
void gif_decoder_destroy_memory_pool(struct gif_decoder *d)
{
destroy_memory_pool(d->mem);
}
void gif_open(char *filename, struct gif_decoder *d) void gif_open(char *filename, struct gif_decoder *d)
{ {
if ((GifFile = DGifOpenFileName(filename, &d->error)) == NULL) if ((GifFile = DGifOpenFileName(filename, &d->error)) == NULL)
@ -181,6 +186,7 @@ void gif_decode(struct gif_decoder *d,
{ {
/* error allocating temp space */ /* error allocating temp space */
d->error = D_GIF_ERR_NOT_ENOUGH_MEM; d->error = D_GIF_ERR_NOT_ENOUGH_MEM;
DGifCloseFile(GifFile);
return; return;
} }
@ -196,7 +202,7 @@ void gif_decode(struct gif_decoder *d,
if (pixels_buffer[0] == NULL) if (pixels_buffer[0] == NULL)
{ {
d->error = D_GIF_ERR_NOT_ENOUGH_MEM; d->error = D_GIF_ERR_NOT_ENOUGH_MEM;
return; goto free_and_return;
} }
/* Global background color */ /* Global background color */
@ -215,7 +221,7 @@ void gif_decode(struct gif_decoder *d,
if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
{ {
d->error = GifFile->Error; d->error = GifFile->Error;
return; goto free_and_return;
} }
switch (RecordType) switch (RecordType)
@ -225,7 +231,7 @@ void gif_decode(struct gif_decoder *d,
if (DGifGetImageDesc(GifFile) == GIF_ERROR) if (DGifGetImageDesc(GifFile) == GIF_ERROR)
{ {
d->error = GifFile->Error; d->error = GifFile->Error;
return; goto free_and_return;
} }
/* Image Position relative to canvas */ /* Image Position relative to canvas */
@ -239,7 +245,7 @@ void gif_decode(struct gif_decoder *d,
GifFile->SColorMap == NULL) GifFile->SColorMap == NULL)
{ {
d->error = D_GIF_ERR_NO_COLOR_MAP; d->error = D_GIF_ERR_NO_COLOR_MAP;
return; goto free_and_return;
} }
/* sanity check */ /* sanity check */
@ -247,7 +253,7 @@ void gif_decode(struct gif_decoder *d,
GifFile->Image.Top+GifFile->Image.Height>GifFile->SHeight) GifFile->Image.Top+GifFile->Image.Height>GifFile->SHeight)
{ {
d->error = D_GIF_ERR_DATA_TOO_BIG; d->error = D_GIF_ERR_DATA_TOO_BIG;
return; goto free_and_return;
} }
if (GifFile->Image.GCB && if (GifFile->Image.GCB &&
@ -275,7 +281,7 @@ void gif_decode(struct gif_decoder *d,
if (DGifGetLine(GifFile, Line, Width) == GIF_ERROR) if (DGifGetLine(GifFile, Line, Width) == GIF_ERROR)
{ {
d->error = GifFile->Error; d->error = GifFile->Error;
return; goto free_and_return;
} }
gif2pixels(Line, pixels_buffer[buf_idx], gif2pixels(Line, pixels_buffer[buf_idx],
@ -294,7 +300,7 @@ void gif_decode(struct gif_decoder *d,
if (DGifGetLine(GifFile, Line, Width) == GIF_ERROR) if (DGifGetLine(GifFile, Line, Width) == GIF_ERROR)
{ {
d->error = GifFile->Error; d->error = GifFile->Error;
return; goto free_and_return;
} }
gif2pixels(Line, pixels_buffer[buf_idx], gif2pixels(Line, pixels_buffer[buf_idx],
@ -310,7 +316,7 @@ void gif_decode(struct gif_decoder *d,
if (out == NULL) if (out == NULL)
{ {
d->error = D_GIF_ERR_NOT_ENOUGH_MEM; d->error = D_GIF_ERR_NOT_ENOUGH_MEM;
return; goto free_and_return;
} }
bm.data = out + d->native_img_size*d->frames_count; bm.data = out + d->native_img_size*d->frames_count;
@ -350,7 +356,7 @@ void gif_decode(struct gif_decoder *d,
GIF_ERROR) GIF_ERROR)
{ {
d->error = GifFile->Error; d->error = GifFile->Error;
return; goto free_and_return;
} }
if (ExtCode == GRAPHICS_EXT_FUNC_CODE) if (ExtCode == GRAPHICS_EXT_FUNC_CODE)
@ -364,7 +370,7 @@ void gif_decode(struct gif_decoder *d,
GifFile->Image.GCB) == GIF_ERROR) GifFile->Image.GCB) == GIF_ERROR)
{ {
d->error = GifFile->Error; d->error = GifFile->Error;
return; goto free_and_return;
} }
d->delay = GifFile->Image.GCB->DelayTime; d->delay = GifFile->Image.GCB->DelayTime;
} }
@ -375,7 +381,7 @@ void gif_decode(struct gif_decoder *d,
if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR)
{ {
d->error = GifFile->Error; d->error = GifFile->Error;
return; goto free_and_return;
} }
} }
break; break;
@ -391,6 +397,10 @@ void gif_decode(struct gif_decoder *d,
if (DGifCloseFile(GifFile) == GIF_ERROR) if (DGifCloseFile(GifFile) == GIF_ERROR)
{ {
d->error = GifFile->Error; d->error = GifFile->Error;
free(pixels_buffer[0]);
if (pixels_buffer[1])
free(pixels_buffer[1]);
free(Line);
return; return;
} }
@ -472,4 +482,15 @@ void gif_decode(struct gif_decoder *d,
} }
} }
#endif #endif
return;
free_and_return:
if (Line)
free(Line);
if (pixels_buffer[0])
free(pixels_buffer[0]);
if (pixels_buffer[1])
free(pixels_buffer[1]);
DGifCloseFile(GifFile);
return;
} }

View file

@ -30,6 +30,7 @@ struct gif_decoder {
}; };
void gif_decoder_init(struct gif_decoder *decoder, void *mem, size_t size); void gif_decoder_init(struct gif_decoder *decoder, void *mem, size_t size);
void gif_decoder_destroy_memory_pool(struct gif_decoder *d);
void gif_open(char *filename, struct gif_decoder *d); void gif_open(char *filename, struct gif_decoder *d);
void gif_decode(struct gif_decoder *d, void (*pf_progress)(int current, int total)); void gif_decode(struct gif_decoder *d, void (*pf_progress)(int current, int total));