Home / exploitsPDF  

FFmpeg buffer overflow vulnerability

Posted on 17 September 2013

The H.264 specification includes two types of parameter sets: sequence parameter set and picture parameter set. An active sequence parameter set remains unchanged throughout a coded video sequence, and an active picture parameter set remains unchanged within a coded picture. The sequence and picture parameter set structures contain information such as picture size, optional coding modes employed, and macroblock to slice group map. To be able to change picture parameters (such as the picture size) without having to transmit parameter set updates synchronously to the slice packet stream, the encoder and decoder can maintain a list of more than one sequence and picture parameter set. Each slice header contains a codeword that indicates the sequence and picture parameter set to be used. libavcodec/h264.c libavcodec/h264.h libavcodec/h264_ps.c diff --git a/libavcodec/h264.c b/libavcodec/h264.c index 6e62c0d..059d65b 100644 (file) --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -2847,6 +2847,53 @@ int ff_h264_get_profile(SPS *sps) return profile; } +static int h264_set_parameter_from_sps(H264Context *h) +{ + MpegEncContext *s = &h->s; + + if (s->flags & CODEC_FLAG_LOW_DELAY || + (h->sps.bitstream_restriction_flag && + !h->sps.num_reorder_frames)) { + if (s->avctx->has_b_frames > 1 || h->delayed_pic[0]) + av_log(h->s.avctx, AV_LOG_WARNING, "Delayed frames seen. " + "Reenabling low delay requires a codec flush. "); + else + s->low_delay = 1; + } + + if (s->avctx->has_b_frames < 2) + s->avctx->has_b_frames = !s->low_delay; + + if (s->avctx->bits_per_raw_sample != h->sps.bit_depth_luma || + h->cur_chroma_format_idc != h->sps.chroma_format_idc) { + if (s->avctx->codec && + s->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU && + (h->sps.bit_depth_luma != 8 || h->sps.chroma_format_idc > 1)) { + av_log(s->avctx, AV_LOG_ERROR, + "VDPAU decoding does not support video colorspace. "); + return AVERROR_INVALIDDATA; + } + if (h->sps.bit_depth_luma >= 8 && h->sps.bit_depth_luma <= 10 && + (h->sps.bit_depth_luma != 9 || !CHROMA422)) { + s->avctx->bits_per_raw_sample = h->sps.bit_depth_luma; + h->cur_chroma_format_idc = h->sps.chroma_format_idc; + h->pixel_shift = h->sps.bit_depth_luma > 8; + + ff_h264dsp_init(&h->h264dsp, h->sps.bit_depth_luma, + h->sps.chroma_format_idc); + ff_h264_pred_init(&h->hpc, s->codec_id, h->sps.bit_depth_luma, + h->sps.chroma_format_idc); + s->dsp.dct_bits = h->sps.bit_depth_luma > 8 ? 32 : 16; + ff_dsputil_init(&s->dsp, s->avctx); + } else { + av_log(s->avctx, AV_LOG_ERROR, "Unsupported bit depth: %d ", + h->sps.bit_depth_luma); + return AVERROR_INVALIDDATA; + } + } + return 0; +} + /** * Decode a slice header. * This will also call ff_MPV_common_init() and frame_start() as needed. @@ -2863,7 +2910,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0) MpegEncContext *const s0 = &h0->s; unsigned int first_mb_in_slice; unsigned int pps_id; - int num_ref_idx_active_override_flag; + int num_ref_idx_active_override_flag, ret; unsigned int slice_type, tmp, i, j; int default_ref_list_done = 0; int last_pic_structure, last_pic_dropable; @@ -2940,7 +2987,14 @@ static int decode_slice_header(H264Context *h, H264Context *h0) h->pps.sps_id); return -1; } - h->sps = *h0->sps_buffers[h->pps.sps_id]; + + if (h->pps.sps_id != h->current_sps_id || + h0->sps_buffers[h->pps.sps_id]->new) { + h0->sps_buffers[h->pps.sps_id]->new = 0; + + h->current_sps_id = h->pps.sps_id; + h->sps = *h0->sps_buffers[h->pps.sps_id]; + } s->avctx->profile = ff_h264_get_profile(&h->sps); s->avctx->level = h->sps.level_idc; @@ -2989,24 +3043,8 @@ static int decode_slice_header(H264Context *h, H264Context *h0) s->avctx->sample_aspect_ratio = h->sps.sar; av_assert0(s->avctx->sample_aspect_ratio.den); - if (s->avctx->bits_per_raw_sample != h->sps.bit_depth_luma || - h->cur_chroma_format_idc != h->sps.chroma_format_idc) { - if (h->sps.bit_depth_luma >= 8 && h->sps.bit_depth_luma <= 10 && - (h->sps.bit_depth_luma != 9 || !CHROMA422)) { - s->avctx->bits_per_raw_sample = h->sps.bit_depth_luma; - h->cur_chroma_format_idc = h->sps.chroma_format_idc; - h->pixel_shift = h->sps.bit_depth_luma > 8; - - ff_h264dsp_init(&h->h264dsp, h->sps.bit_depth_luma, h->sps.chroma_format_idc); - ff_h264_pred_init(&h->hpc, s->codec_id, h->sps.bit_depth_luma, h->sps.chroma_format_idc); - s->dsp.dct_bits = h->sps.bit_depth_luma > 8 ? 32 : 16; - ff_dsputil_init(&s->dsp, s->avctx); - } else { - av_log(s->avctx, AV_LOG_ERROR, "Unsupported bit depth: %d chroma_idc: %d ", - h->sps.bit_depth_luma, h->sps.chroma_format_idc); - return -1; - } - } + if ((ret = h264_set_parameter_from_sps(h)) < 0) + return ret; if (h->sps.video_signal_type_present_flag) { s->avctx->color_range = h->sps.full_range>0 ? AVCOL_RANGE_JPEG @@ -4435,6 +4473,7 @@ again: ff_h264_decode_seq_parameter_set(h); } + if (s->flags & CODEC_FLAG_LOW_DELAY || (h->sps.bitstream_restriction_flag && !h->sps.num_reorder_frames)) diff --git a/libavcodec/h264.h b/libavcodec/h264.h index a27f82f..22f8100 100644 (file) --- a/libavcodec/h264.h +++ b/libavcodec/h264.h @@ -206,6 +206,7 @@ typedef struct SPS { int bit_depth_chroma; ///< bit_depth_chroma_minus8 + 8 int residual_color_transform_flag; ///< residual_colour_transform_flag int constraint_set_flags; ///< constraint_set[0-3]_flag + int new; ///< flag to keep track if the decoder context needs re-init due to changed SPS } SPS; /** @@ -332,6 +333,7 @@ typedef struct H264Context { int emu_edge_width; int emu_edge_height; + unsigned current_sps_id; ///< id of the current SPS SPS sps; ///< current sps /** diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c index 261e2d2..bf07cbb 100644 (file) --- a/libavcodec/h264_ps.c +++ b/libavcodec/h264_ps.c @@ -478,10 +478,13 @@ int ff_h264_decode_seq_parameter_set(H264Context *h){ sps->bit_depth_luma ); } + sps->new = 1; av_free(h->sps_buffers[sps_id]); - h->sps_buffers[sps_id]= sps; - h->sps = *sps; + h->sps_buffers[sps_id] = sps; + h->sps = *sps; + h->current_sps_id = sps_id; + return 0; fail: av_free(sps);

 

TOP