summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReimar Döffinger <Reimar.Doeffinger@gmx.de>2016-02-26 18:38:19 +0100
committerReimar Döffinger <Reimar.Doeffinger@gmx.de>2016-02-28 13:33:14 +0100
commit4dd4d535313016cf934a187ba8f46e51b583cfb9 (patch)
tree9cc4cf77a540f13782400a73b0020637a54e72ba
parent45fa03b1f9b0475df666f7592f250c37763b7d64 (diff)
Document and validate AVFrame plane pointers.
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>
-rw-r--r--doc/APIchanges6
-rw-r--r--libavcodec/utils.c26
-rw-r--r--libavcodec/version.h2
-rw-r--r--libavutil/frame.h3
4 files changed, 36 insertions, 1 deletions
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];