[FFmpeg-devel] [PATCH] avcodec: validate codec parameters in avcodec_parameters_to_context

Andreas Cadhalpun andreas.cadhalpun at googlemail.com
Tue Oct 25 02:50:47 EEST 2016


This should reduce the impact of a demuxer (or API user) setting bogus
codec parameters.

Suggested-by: wm4
Signed-off-by: Andreas Cadhalpun <Andreas.Cadhalpun at googlemail.com>
---
 libavcodec/utils.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 81 insertions(+), 1 deletion(-)

diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 87de15f..9977ffd 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -4227,8 +4227,20 @@ int avcodec_parameters_to_context(AVCodecContext *codec,
     codec->codec_id   = par->codec_id;
     codec->codec_tag  = par->codec_tag;
 
+    if (par->bit_rate < 0) {
+        av_log(codec, AV_LOG_ERROR, "Invalid bit rate %"PRId64"\n", par->bit_rate);
+        return AVERROR(EINVAL);
+    }
     codec->bit_rate              = par->bit_rate;
+    if (par->bits_per_coded_sample < 0) {
+        av_log(codec, AV_LOG_ERROR, "Invalid bits per coded sample %d\n", par->bits_per_coded_sample);
+        return AVERROR(EINVAL);
+    }
     codec->bits_per_coded_sample = par->bits_per_coded_sample;
+    if (par->bits_per_raw_sample < 0) {
+        av_log(codec, AV_LOG_ERROR, "Invalid bits per raw sample %d\n", par->bits_per_raw_sample);
+        return AVERROR(EINVAL);
+    }
     codec->bits_per_raw_sample   = par->bits_per_raw_sample;
     codec->profile               = par->profile;
     codec->level                 = par->level;
@@ -4236,42 +4248,110 @@ int avcodec_parameters_to_context(AVCodecContext *codec,
     switch (par->codec_type) {
     case AVMEDIA_TYPE_VIDEO:
         codec->pix_fmt                = par->format;
+        if ( (par->width || par->height) && av_image_check_size(par->width, par->height, 0, codec) < 0)
+            return AVERROR(EINVAL);
         codec->width                  = par->width;
         codec->height                 = par->height;
         codec->field_order            = par->field_order;
+        if (par->color_range < 0 || par->color_range > AVCOL_RANGE_NB) {
+            av_log(codec, AV_LOG_ERROR, "Invalid color range %d\n", par->color_range);
+            return AVERROR(EINVAL);
+        }
         codec->color_range            = par->color_range;
+        if (par->color_primaries < 0 || par->color_primaries > AVCOL_PRI_NB) {
+            av_log(codec, AV_LOG_ERROR, "Invalid color primaries %d\n", par->color_primaries);
+            return AVERROR(EINVAL);
+        }
         codec->color_primaries        = par->color_primaries;
+        if (par->color_trc < 0 || par->color_trc > AVCOL_TRC_NB) {
+            av_log(codec, AV_LOG_ERROR, "Invalid color transfer characteristics %d\n", par->color_trc);
+            return AVERROR(EINVAL);
+        }
         codec->color_trc              = par->color_trc;
+        if (par->color_space < 0 || par->color_space > AVCOL_SPC_NB) {
+            av_log(codec, AV_LOG_ERROR, "Invalid color space %d\n", par->color_space);
+            return AVERROR(EINVAL);
+        }
         codec->colorspace             = par->color_space;
+        if (par->chroma_location < 0 || par->chroma_location > AVCHROMA_LOC_NB) {
+            av_log(codec, AV_LOG_ERROR, "Invalid chroma location %d\n", par->chroma_location);
+            return AVERROR(EINVAL);
+        }
         codec->chroma_sample_location = par->chroma_location;
+        if (par->sample_aspect_ratio.num < 0 || par->sample_aspect_ratio.den < 0) {
+            av_log(codec, AV_LOG_ERROR, "Invalid sample aspect ratio %d/%d\n",
+                   par->sample_aspect_ratio.num, par->sample_aspect_ratio.den);
+            return AVERROR(EINVAL);
+        }
         codec->sample_aspect_ratio    = par->sample_aspect_ratio;
+        if (par->video_delay < 0) {
+            av_log(codec, AV_LOG_ERROR, "Invalid video delay %d\n", par->video_delay);
+            return AVERROR(EINVAL);
+        }
         codec->has_b_frames           = par->video_delay;
         break;
     case AVMEDIA_TYPE_AUDIO:
+        if (par->format < -1 || par->format > AV_SAMPLE_FMT_NB) {
+            av_log(codec, AV_LOG_ERROR, "Invalid sample format %d\n", par->format);
+            return AVERROR(EINVAL);
+        }
         codec->sample_fmt       = par->format;
         codec->channel_layout   = par->channel_layout;
+        if (par->channels < 0) {
+            av_log(codec, AV_LOG_ERROR, "Invalid number of channels %d\n", par->channels);
+            return AVERROR(EINVAL);
+        }
         codec->channels         = par->channels;
+        if (par->sample_rate < 0) {
+            av_log(codec, AV_LOG_ERROR, "Invalid sample rate %d\n", par->sample_rate);
+            return AVERROR(EINVAL);
+        }
         codec->sample_rate      = par->sample_rate;
+        if (par->block_align < 0) {
+            av_log(codec, AV_LOG_ERROR, "Invalid block align %d\n", par->block_align);
+            return AVERROR(EINVAL);
+        }
         codec->block_align      = par->block_align;
+        if (par->frame_size < 0) {
+            av_log(codec, AV_LOG_ERROR, "Invalid frame size %d\n", par->frame_size);
+            return AVERROR(EINVAL);
+        }
         codec->frame_size       = par->frame_size;
+        if (par->initial_padding < 0) {
+            av_log(codec, AV_LOG_ERROR, "Invalid initial padding %d\n", par->initial_padding);
+            return AVERROR(EINVAL);
+        }
         codec->delay            =
         codec->initial_padding  = par->initial_padding;
+        if (par->trailing_padding < 0) {
+            av_log(codec, AV_LOG_ERROR, "Invalid trailing padding %d\n", par->trailing_padding);
+            return AVERROR(EINVAL);
+        }
         codec->trailing_padding = par->trailing_padding;
+        if (par->seek_preroll < 0) {
+            av_log(codec, AV_LOG_ERROR, "Invalid seek preroll %d\n", par->seek_preroll);
+            return AVERROR(EINVAL);
+        }
         codec->seek_preroll     = par->seek_preroll;
         break;
     case AVMEDIA_TYPE_SUBTITLE:
+        if ((par->width || par->height) && av_image_check_size(par->width, par->height, 0, codec) < 0)
+            return AVERROR(EINVAL);
         codec->width  = par->width;
         codec->height = par->height;
         break;
     }
 
-    if (par->extradata) {
+    if (par->extradata_size > 0) {
         av_freep(&codec->extradata);
         codec->extradata = av_mallocz(par->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
         if (!codec->extradata)
             return AVERROR(ENOMEM);
         memcpy(codec->extradata, par->extradata, par->extradata_size);
         codec->extradata_size = par->extradata_size;
+    } else if (par->extradata_size < 0) {
+        av_log(codec, AV_LOG_ERROR, "Invalid extradata size %d", par->extradata_size);
+        return AVERROR(EINVAL);
     }
 
     return 0;
-- 
2.9.3


More information about the ffmpeg-devel mailing list