avcodec/h264: Be more strict on rejecting pps/sps changes

Fixes race condition
Fixes: signal_sigsegv_1472ac3_468_cov_2915641226_CABACI3_Sony_B.jsv

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
(cherry picked from commit 6fafc62b0b)

Conflicts:

	libavcodec/h264_slice.c
This commit is contained in:
Michael Niedermayer
2015-02-06 15:09:54 +01:00
parent a3dca10470
commit 0c9d465e98

View File

@@ -3506,6 +3506,8 @@ static int decode_slice_header(H264Context *h, H264Context *h0)
int must_reinit; int must_reinit;
int needs_reinit = 0; int needs_reinit = 0;
int field_pic_flag, bottom_field_flag; int field_pic_flag, bottom_field_flag;
int first_slice = h == h0 && !h0->current_slice;
PPS *pps;
h->me.qpel_put = h->h264qpel.put_h264_qpel_pixels_tab; h->me.qpel_put = h->h264qpel.put_h264_qpel_pixels_tab;
h->me.qpel_avg = h->h264qpel.avg_h264_qpel_pixels_tab; h->me.qpel_avg = h->h264qpel.avg_h264_qpel_pixels_tab;
@@ -3570,18 +3572,27 @@ static int decode_slice_header(H264Context *h, H264Context *h0)
h0->au_pps_id, pps_id); h0->au_pps_id, pps_id);
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
h->pps = *h0->pps_buffers[pps_id];
if (!h0->sps_buffers[h->pps.sps_id]) { pps = h0->pps_buffers[pps_id];
if (!h0->sps_buffers[pps->sps_id]) {
av_log(h->avctx, AV_LOG_ERROR, av_log(h->avctx, AV_LOG_ERROR,
"non-existing SPS %u referenced\n", "non-existing SPS %u referenced\n",
h->pps.sps_id); h->pps.sps_id);
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
if (first_slice)
h->pps = *h0->pps_buffers[pps_id];
if (h->pps.sps_id != h->sps.sps_id || if (pps->sps_id != h->sps.sps_id ||
h->pps.sps_id != h->current_sps_id || pps->sps_id != h->current_sps_id ||
h0->sps_buffers[h->pps.sps_id]->new) { h0->sps_buffers[pps->sps_id]->new) {
if (!first_slice) {
av_log(h->avctx, AV_LOG_ERROR,
"SPS changed in the middle of the frame\n");
return AVERROR_INVALIDDATA;
}
h->sps = *h0->sps_buffers[h->pps.sps_id]; h->sps = *h0->sps_buffers[h->pps.sps_id];