aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2015-02-06 15:09:54 +0100
committerMichael Niedermayer <michaelni@gmx.at>2015-02-17 19:43:18 +0100
commit0c9d465e98c72a527ff5c6a2f78d537c03810112 (patch)
treea4848532c44b55c11b778693cffae1876f1ca2c9 /libavcodec
parenta3dca10470ec4a219974ceb53f2f9a40b87f9267 (diff)
downloadffmpeg-0c9d465e98c72a527ff5c6a2f78d537c03810112.tar.gz
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 6fafc62b0bd0e206deb77a7aabbf3a370ad80789) Conflicts: libavcodec/h264_slice.c
Diffstat (limited to 'libavcodec')
-rw-r--r--libavcodec/h264.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index c1fa344db7..08010c70e3 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -3506,6 +3506,8 @@ static int decode_slice_header(H264Context *h, H264Context *h0)
int must_reinit;
int needs_reinit = 0;
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_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);
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,
"non-existing SPS %u referenced\n",
h->pps.sps_id);
return AVERROR_INVALIDDATA;
}
+ if (first_slice)
+ h->pps = *h0->pps_buffers[pps_id];
+
+ if (pps->sps_id != h->sps.sps_id ||
+ pps->sps_id != h->current_sps_id ||
+ h0->sps_buffers[pps->sps_id]->new) {
- if (h->pps.sps_id != h->sps.sps_id ||
- h->pps.sps_id != h->current_sps_id ||
- h0->sps_buffers[h->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];