h264: prevent decoding of slice NALs in extradata
It is not posible to call get_buffer during frame-mt codec initialization. Libavformat might pass huge amounts of data as extradata after parsing broken files. The 'extradata' for the fuzzed sample sample_varPAR_s5374_r001-02.avi is 2.8M large and contains multiple slices.
This commit is contained in:
@ -954,7 +954,8 @@ fail:
|
|||||||
return -1; // free_tables will clean up for us
|
return -1; // free_tables will clean up for us
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size);
|
static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
|
||||||
|
int parse_extradata);
|
||||||
|
|
||||||
static av_cold void common_init(H264Context *h)
|
static av_cold void common_init(H264Context *h)
|
||||||
{
|
{
|
||||||
@ -1001,7 +1002,7 @@ int ff_h264_decode_extradata(H264Context *h)
|
|||||||
nalsize = AV_RB16(p) + 2;
|
nalsize = AV_RB16(p) + 2;
|
||||||
if (p - avctx->extradata + nalsize > avctx->extradata_size)
|
if (p - avctx->extradata + nalsize > avctx->extradata_size)
|
||||||
return -1;
|
return -1;
|
||||||
if (decode_nal_units(h, p, nalsize) < 0) {
|
if (decode_nal_units(h, p, nalsize, 1) < 0) {
|
||||||
av_log(avctx, AV_LOG_ERROR,
|
av_log(avctx, AV_LOG_ERROR,
|
||||||
"Decoding sps %d from avcC failed\n", i);
|
"Decoding sps %d from avcC failed\n", i);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1014,7 +1015,7 @@ int ff_h264_decode_extradata(H264Context *h)
|
|||||||
nalsize = AV_RB16(p) + 2;
|
nalsize = AV_RB16(p) + 2;
|
||||||
if (p - avctx->extradata + nalsize > avctx->extradata_size)
|
if (p - avctx->extradata + nalsize > avctx->extradata_size)
|
||||||
return -1;
|
return -1;
|
||||||
if (decode_nal_units(h, p, nalsize) < 0) {
|
if (decode_nal_units(h, p, nalsize, 1) < 0) {
|
||||||
av_log(avctx, AV_LOG_ERROR,
|
av_log(avctx, AV_LOG_ERROR,
|
||||||
"Decoding pps %d from avcC failed\n", i);
|
"Decoding pps %d from avcC failed\n", i);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1025,7 +1026,7 @@ int ff_h264_decode_extradata(H264Context *h)
|
|||||||
h->nal_length_size = (avctx->extradata[4] & 0x03) + 1;
|
h->nal_length_size = (avctx->extradata[4] & 0x03) + 1;
|
||||||
} else {
|
} else {
|
||||||
h->is_avc = 0;
|
h->is_avc = 0;
|
||||||
if (decode_nal_units(h, avctx->extradata, avctx->extradata_size) < 0)
|
if (decode_nal_units(h, avctx->extradata, avctx->extradata_size, 1) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -3708,7 +3709,8 @@ static int execute_decode_slices(H264Context *h, int context_count)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
|
static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
|
||||||
|
int parse_extradata)
|
||||||
{
|
{
|
||||||
MpegEncContext *const s = &h->s;
|
MpegEncContext *const s = &h->s;
|
||||||
AVCodecContext *const avctx = s->avctx;
|
AVCodecContext *const avctx = s->avctx;
|
||||||
@ -3831,6 +3833,17 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
again:
|
again:
|
||||||
|
/* Ignore every NAL unit type except PPS and SPS during extradata
|
||||||
|
* parsing. Decoding slices is not possible in codec init
|
||||||
|
* with frame-mt */
|
||||||
|
if (parse_extradata && HAVE_THREADS &&
|
||||||
|
(s->avctx->active_thread_type & FF_THREAD_FRAME) &&
|
||||||
|
(hx->nal_unit_type != NAL_PPS &&
|
||||||
|
hx->nal_unit_type != NAL_SPS)) {
|
||||||
|
av_log(avctx, AV_LOG_INFO, "Ignoring NAL unit %d during "
|
||||||
|
"extradata parsing\n", hx->nal_unit_type);
|
||||||
|
hx->nal_unit_type = NAL_FF_IGNORE;
|
||||||
|
}
|
||||||
err = 0;
|
err = 0;
|
||||||
switch (hx->nal_unit_type) {
|
switch (hx->nal_unit_type) {
|
||||||
case NAL_IDR_SLICE:
|
case NAL_IDR_SLICE:
|
||||||
@ -3953,6 +3966,8 @@ again:
|
|||||||
case NAL_SPS_EXT:
|
case NAL_SPS_EXT:
|
||||||
case NAL_AUXILIARY_SLICE:
|
case NAL_AUXILIARY_SLICE:
|
||||||
break;
|
break;
|
||||||
|
case NAL_FF_IGNORE:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
av_log(avctx, AV_LOG_DEBUG, "Unknown NAL code: %d (%d bits)\n",
|
av_log(avctx, AV_LOG_DEBUG, "Unknown NAL code: %d (%d bits)\n",
|
||||||
hx->nal_unit_type, bit_length);
|
hx->nal_unit_type, bit_length);
|
||||||
@ -4049,7 +4064,7 @@ out:
|
|||||||
return buf_index;
|
return buf_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf_index = decode_nal_units(h, buf, buf_size);
|
buf_index = decode_nal_units(h, buf, buf_size, 0);
|
||||||
if (buf_index < 0)
|
if (buf_index < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -112,7 +112,8 @@ enum {
|
|||||||
NAL_END_STREAM,
|
NAL_END_STREAM,
|
||||||
NAL_FILLER_DATA,
|
NAL_FILLER_DATA,
|
||||||
NAL_SPS_EXT,
|
NAL_SPS_EXT,
|
||||||
NAL_AUXILIARY_SLICE = 19
|
NAL_AUXILIARY_SLICE = 19,
|
||||||
|
NAL_FF_IGNORE = 0xff0f001,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user