From 2ac6eedac5e576bb98c9ba6573cfcd4782b175b0 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 2 Feb 2017 21:48:05 +0100 Subject: avcodec/pngdec: Store metadata directly into AVFrame Fixes memleak Fixes: 500/clusterfuzz-testcase-6315221727576064 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/targets/ffmpeg Signed-off-by: Michael Niedermayer --- libavcodec/pngdec.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 601b8db0aa..5b0d3cff77 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -1098,7 +1098,7 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s, static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s, AVFrame *p, AVPacket *avpkt) { - AVDictionary *metadata = NULL; + AVDictionary **metadatap = NULL; uint32_t tag, length; int decode_next_dat = 0; int ret; @@ -1109,7 +1109,6 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s, if (avctx->codec_id == AV_CODEC_ID_PNG && avctx->skip_frame == AVDISCARD_ALL) { - av_frame_set_metadata(p, metadata); return 0; } @@ -1155,6 +1154,7 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s, } } + metadatap = avpriv_frame_get_metadatap(p); switch (tag) { case MKTAG('I', 'H', 'D', 'R'): if ((ret = decode_ihdr_chunk(avctx, s, length)) < 0) @@ -1196,12 +1196,12 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s, goto skip_tag; break; case MKTAG('t', 'E', 'X', 't'): - if (decode_text_chunk(s, length, 0, &metadata) < 0) + if (decode_text_chunk(s, length, 0, metadatap) < 0) av_log(avctx, AV_LOG_WARNING, "Broken tEXt chunk\n"); bytestream2_skip(&s->gb, length + 4); break; case MKTAG('z', 'T', 'X', 't'): - if (decode_text_chunk(s, length, 1, &metadata) < 0) + if (decode_text_chunk(s, length, 1, metadatap) < 0) av_log(avctx, AV_LOG_WARNING, "Broken zTXt chunk\n"); bytestream2_skip(&s->gb, length + 4); break; @@ -1238,9 +1238,9 @@ skip_tag: } } exit_loop: + if (avctx->codec_id == AV_CODEC_ID_PNG && avctx->skip_frame == AVDISCARD_ALL) { - av_frame_set_metadata(p, metadata); return 0; } @@ -1290,12 +1290,9 @@ exit_loop: ff_thread_report_progress(&s->picture, INT_MAX, 0); ff_thread_report_progress(&s->previous_picture, INT_MAX, 0); - av_frame_set_metadata(p, metadata); - metadata = NULL; return 0; fail: - av_dict_free(&metadata); ff_thread_report_progress(&s->picture, INT_MAX, 0); ff_thread_report_progress(&s->previous_picture, INT_MAX, 0); return ret; -- cgit v1.2.3