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 <Reimar.Doeffinger@gmx.de>tags/n3.1
@@ -15,6 +15,12 @@ libavutil: 2015-08-28 | |||||
API changes, most recent first: | 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 | 2016-xx-xx - xxxxxxx - lavc 57.27.100 - avcodec.h | ||||
"flags2" decoding option now allows the flag "ass_ro_flush_noop" preventing | "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 | the reset of the ASS ReadOrder field on flush. This affects the content of | ||||
@@ -853,6 +853,30 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) | |||||
return ff_init_buffer_info(avctx, 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) | static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags) | ||||
{ | { | ||||
const AVHWAccel *hwaccel = avctx->hwaccel; | 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; | avctx->sw_pix_fmt = avctx->pix_fmt; | ||||
ret = avctx->get_buffer2(avctx, frame, flags); | ret = avctx->get_buffer2(avctx, frame, flags); | ||||
if (ret >= 0) | |||||
validate_avframe_allocation(avctx, frame); | |||||
end: | end: | ||||
if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions) { | if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions) { | ||||
@@ -29,7 +29,7 @@ | |||||
#define LIBAVCODEC_VERSION_MAJOR 57 | #define LIBAVCODEC_VERSION_MAJOR 57 | ||||
#define LIBAVCODEC_VERSION_MINOR 27 | #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, \ | #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | ||||
LIBAVCODEC_VERSION_MINOR, \ | LIBAVCODEC_VERSION_MINOR, \ | ||||
@@ -187,6 +187,9 @@ typedef struct AVFrame { | |||||
* see avcodec_align_dimensions2(). Some filters and swscale can read | * see avcodec_align_dimensions2(). Some filters and swscale can read | ||||
* up to 16 bytes beyond the planes, if these filters are to be used, | * up to 16 bytes beyond the planes, if these filters are to be used, | ||||
* then 16 extra bytes must be allocated. | * 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]; | uint8_t *data[AV_NUM_DATA_POINTERS]; | ||||