Fixes: Timeout (14sec -> 133ms) Fixes: 14843/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_NUV_fuzzer-5661969614372864
Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer <mich...@niedermayer.cc> --- libavcodec/nuv.c | 35 ++++++++++++++++++++++++++++++++--- tests/ref/fate/nuv-rtjpeg | 1 - 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/libavcodec/nuv.c b/libavcodec/nuv.c index 75b14bce5b..043b299080 100644 --- a/libavcodec/nuv.c +++ b/libavcodec/nuv.c @@ -42,6 +42,8 @@ typedef struct NuvContext { unsigned char *decomp_buf; uint32_t lq[64], cq[64]; RTJpegContext rtj; + int need_flush; + AVPacket flush_pkt; } NuvContext; static const uint8_t fallback_lquant[] = { @@ -66,6 +68,12 @@ static const uint8_t fallback_cquant[] = { 99, 99, 99, 99, 99, 99, 99, 99 }; +static void decode_flush(AVCodecContext *avctx){ + NuvContext *s = avctx->priv_data; + + s->need_flush = 0; +} + /** * @brief copy frame data from buffer to AVFrame, handling stride. * @param f destination AVFrame @@ -172,6 +180,25 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, NUV_COPY_LAST = 'L' } comptype; + if (!avpkt->data) { + if (c->need_flush) { + c->need_flush = 0; + if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) + return ret; + c->pic->pkt_pos = c->flush_pkt.pos; + c->pic->pkt_duration = c->flush_pkt.duration; + c->pic->pkt_dts = c->flush_pkt.dts; + c->pic->pkt_pts = + c->pic->pts = c->flush_pkt.pts; + if ((ret = av_frame_ref(data, c->pic)) < 0) + return ret; + *got_frame = 1; + } + return 0; + } + c->flush_pkt = *avpkt; + + if (buf_size < 12) { av_log(avctx, AV_LOG_ERROR, "coded frame too small\n"); return AVERROR_INVALIDDATA; @@ -204,8 +231,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } break; case NUV_COPY_LAST: - keyframe = 0; - break; + c->need_flush = 1; + return buf_size; default: keyframe = 1; break; @@ -313,6 +340,7 @@ retry: if ((result = av_frame_ref(picture, c->pic)) < 0) return result; + c->need_flush = 0; *got_frame = 1; return orig_size; } @@ -364,6 +392,7 @@ AVCodec ff_nuv_decoder = { .init = decode_init, .close = decode_end, .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .flush = decode_flush, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/tests/ref/fate/nuv-rtjpeg b/tests/ref/fate/nuv-rtjpeg index b6f3b080dc..0914b985ec 100644 --- a/tests/ref/fate/nuv-rtjpeg +++ b/tests/ref/fate/nuv-rtjpeg @@ -6,7 +6,6 @@ 0, 118, 118, 0, 460800, 0x54aedafe 0, 152, 152, 0, 460800, 0xb7aa8b56 0, 177, 177, 0, 460800, 0x283ea3b5 -0, 202, 202, 0, 460800, 0x283ea3b5 0, 235, 235, 0, 460800, 0x10e577de 0, 269, 269, 0, 460800, 0x4e091ee2 0, 302, 302, 0, 460800, 0x2ea88828 -- 2.21.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".