From 4dd4d535313016cf934a187ba8f46e51b583cfb9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Reimar=20D=C3=B6ffinger?= Date: Fri, 26 Feb 2016 18:38:19 +0100 Subject: [PATCH] Document and validate AVFrame plane pointers. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Check that the required plane pointers and only those are set up. Currently does not enforce anything for the palette pointer of pseudopal formats as I am unsure about the requirements. Signed-off-by: Reimar Döffinger --- doc/APIchanges | 6 ++++++ libavcodec/utils.c | 26 ++++++++++++++++++++++++++ libavcodec/version.h | 2 +- libavutil/frame.h | 3 +++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index a808e9e794..a75f3468f1 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,12 @@ libavutil: 2015-08-28 API changes, most recent first: +2016-02-28 - xxxxxxx - lavc 57.27.101 + Validate AVFrame returned by get_buffer2 to have required + planes not NULL and unused planes set to NULL as crashes + and buffer overflow are possible with certain streams if + that is not the case. + 2016-xx-xx - xxxxxxx - lavc 57.27.100 - avcodec.h "flags2" decoding option now allows the flag "ass_ro_flush_noop" preventing the reset of the ASS ReadOrder field on flush. This affects the content of diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 5791ffaef6..b1ba51e797 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -853,6 +853,30 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) return ff_init_buffer_info(avctx, frame); } +static void validate_avframe_allocation(AVCodecContext *avctx, AVFrame *frame) +{ + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { + int i; + int num_planes = av_pix_fmt_count_planes(frame->format); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); + int flags = desc ? desc->flags : 0; + if (num_planes == 1 && (flags & AV_PIX_FMT_FLAG_PAL)) + num_planes = 2; + for (i = 0; i < num_planes; i++) { + av_assert0(frame->data[i]); + } + // For now do not enforce anything for palette of pseudopal formats + if (num_planes == 1 && (flags & AV_PIX_FMT_FLAG_PSEUDOPAL)) + num_planes = 2; + // For formats without data like hwaccel allow unused pointers to be non-NULL. + for (i = num_planes; num_planes > 0 && i < FF_ARRAY_ELEMS(frame->data); i++) { + if (frame->data[i]) + av_log(avctx, AV_LOG_ERROR, "Buffer returned by get_buffer2() did not zero unused plane pointers\n"); + frame->data[i] = NULL; + } + } +} + static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags) { const AVHWAccel *hwaccel = avctx->hwaccel; @@ -889,6 +913,8 @@ static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags) avctx->sw_pix_fmt = avctx->pix_fmt; ret = avctx->get_buffer2(avctx, frame, flags); + if (ret >= 0) + validate_avframe_allocation(avctx, frame); end: if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions) { diff --git a/libavcodec/version.h b/libavcodec/version.h index 10a10a7e56..95f4551992 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 57 #define LIBAVCODEC_VERSION_MINOR 27 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavutil/frame.h b/libavutil/frame.h index 56001a8798..76a8123dcb 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -187,6 +187,9 @@ typedef struct AVFrame { * see avcodec_align_dimensions2(). Some filters and swscale can read * up to 16 bytes beyond the planes, if these filters are to be used, * then 16 extra bytes must be allocated. + * + * NOTE: Except for hwaccel formats, pointers not needed by the format + * MUST be set to NULL. */ uint8_t *data[AV_NUM_DATA_POINTERS]; -- 2.11.0