[FFmpeg-devel] [PATCH v2 11/11] libavformat/asfdec: fix variable types and add checks for unsupported values
softworkz
ffmpegagent at gmail.com
Sat May 7 12:36:44 EEST 2022
From: softworkz <softworkz at hotmail.com>
Signed-off-by: softworkz <softworkz at hotmail.com>
---
libavformat/asfdec_f.c | 168 ++++++++++++++++++++++++++---------------
1 file changed, 108 insertions(+), 60 deletions(-)
diff --git a/libavformat/asfdec_f.c b/libavformat/asfdec_f.c
index b8140a6d57..c7141f6da1 100644
--- a/libavformat/asfdec_f.c
+++ b/libavformat/asfdec_f.c
@@ -332,9 +332,9 @@ static int asf_read_stream_properties(AVFormatContext *s, uint64_t size)
ASFStream *asf_st;
ff_asf_guid g;
enum AVMediaType type;
- int type_specific_size, sizeX;
- unsigned int tag1;
- int64_t pos1, pos2, start_time;
+ unsigned int tag1, type_specific_size, sizeX;
+ int64_t pos1, pos2;
+ uint32_t start_time;
int test_for_ext_stream_audio, is_dvr_ms_audio = 0;
if (s->nb_streams == ASF_MAX_STREAMS) {
@@ -403,7 +403,14 @@ static int asf_read_stream_properties(AVFormatContext *s, uint64_t size)
st->codecpar->codec_type = type;
if (type == AVMEDIA_TYPE_AUDIO) {
- int ret = ff_get_wav_header(s, pb, st->codecpar, type_specific_size, 0);
+ int ret;
+
+ if (type_specific_size > INT32_MAX) {
+ av_log(s, AV_LOG_DEBUG, "Unsupported WAV header size (> INT32_MAX)\n");
+ return AVERROR(ENOTSUP);
+ }
+
+ ret = ff_get_wav_header(s, pb, st->codecpar, (int)type_specific_size, 0);
if (ret < 0)
return ret;
if (is_dvr_ms_audio) {
@@ -433,21 +440,32 @@ static int asf_read_stream_properties(AVFormatContext *s, uint64_t size)
}
} else if (type == AVMEDIA_TYPE_VIDEO &&
size - (avio_tell(pb) - pos1 + 24) >= 51) {
+ unsigned int width, height;
avio_rl32(pb);
avio_rl32(pb);
avio_r8(pb);
avio_rl16(pb); /* size */
- sizeX = avio_rl32(pb); /* size */
- st->codecpar->width = avio_rl32(pb);
- st->codecpar->height = avio_rl32(pb);
+ sizeX = avio_rl32(pb); /* size */
+ width = avio_rl32(pb);
+ height = avio_rl32(pb);
+
+ if (width > INT32_MAX || height > INT32_MAX) {
+ av_log(s, AV_LOG_DEBUG, "Unsupported video size %dx%d\n", width, height);
+ return AVERROR(ENOTSUP);
+ }
+
+ st->codecpar->width = (int)width;
+ st->codecpar->height = (int)height;
/* not available for asf */
avio_rl16(pb); /* panes */
st->codecpar->bits_per_coded_sample = avio_rl16(pb); /* depth */
tag1 = avio_rl32(pb);
avio_skip(pb, 20);
if (sizeX > 40) {
- if (size < sizeX - 40 || sizeX - 40 > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
- return AVERROR_INVALIDDATA;
+ if (size < sizeX - 40 || sizeX - 40 > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
+ av_log(s, AV_LOG_DEBUG, "Unsupported extradata size\n");
+ return AVERROR(ENOTSUP);
+ }
st->codecpar->extradata_size = ffio_limit(pb, sizeX - 40);
st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size +
AV_INPUT_BUFFER_PADDING_SIZE);
@@ -499,9 +517,9 @@ static int asf_read_ext_stream_properties(AVFormatContext *s)
ASFContext *asf = s->priv_data;
AVIOContext *pb = s->pb;
ff_asf_guid g;
- int ext_len, payload_ext_ct, stream_ct, i;
- uint32_t leak_rate, stream_num;
- unsigned int stream_languageid_index;
+ uint16_t payload_ext_ct, stream_ct, i;
+ uint32_t leak_rate, ext_len;
+ uint16_t stream_languageid_index, stream_num;
avio_rl64(pb); // starttime
avio_rl64(pb); // endtime
@@ -513,15 +531,15 @@ static int asf_read_ext_stream_properties(AVFormatContext *s)
avio_rl32(pb); // alt-init-bucket-fullness
avio_rl32(pb); // max-object-size
avio_rl32(pb); // flags (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits reserved)
- stream_num = avio_rl16(pb); // stream-num
+ stream_num = (uint16_t)avio_rl16(pb); // stream-num
- stream_languageid_index = avio_rl16(pb); // stream-language-id-index
+ stream_languageid_index = (uint16_t)avio_rl16(pb); // stream-language-id-index
if (stream_num < 128)
asf->streams[stream_num].stream_language_index = stream_languageid_index;
avio_rl64(pb); // avg frametime in 100ns units
- stream_ct = avio_rl16(pb); // stream-name-count
- payload_ext_ct = avio_rl16(pb); // payload-extension-system-count
+ stream_ct = (uint16_t)avio_rl16(pb); // stream-name-count
+ payload_ext_ct = (uint16_t)avio_rl16(pb); // payload-extension-system-count
if (stream_num < 128) {
asf->stream_bitrates[stream_num] = leak_rate;
@@ -535,12 +553,10 @@ static int asf_read_ext_stream_properties(AVFormatContext *s)
}
for (i = 0; i < payload_ext_ct; i++) {
- int size;
+ uint16_t size;
ff_get_guid(pb, &g);
- size = avio_rl16(pb);
+ size = (uint16_t)avio_rl16(pb);
ext_len = avio_rl32(pb);
- if (ext_len < 0)
- return AVERROR_INVALIDDATA;
avio_skip(pb, ext_len);
if (stream_num < 128 && i < FF_ARRAY_ELEMS(asf->streams[stream_num].payload)) {
ASFPayload *p = &asf->streams[stream_num].payload[i];
@@ -577,20 +593,21 @@ static int asf_read_ext_content_desc(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
ASFContext *asf = s->priv_data;
- int desc_count, i, ret;
+ uint16_t desc_count, i;
+ int ret;
- desc_count = avio_rl16(pb);
+ desc_count = (uint16_t)avio_rl16(pb);
for (i = 0; i < desc_count; i++) {
- int name_len, value_type, value_len;
+ uint16_t name_len, value_type, value_len;
char name[1024];
- name_len = avio_rl16(pb);
+ name_len = (uint16_t)avio_rl16(pb);
if (name_len % 2) // must be even, broken lavf versions wrote len-1
name_len += 1;
if ((ret = avio_get_str16le(pb, name_len, name, sizeof(name))) < name_len)
avio_skip(pb, name_len - ret);
- value_type = avio_rl16(pb);
- value_len = avio_rl16(pb);
+ value_type = (uint16_t)avio_rl16(pb);
+ value_len = (uint16_t)avio_rl16(pb);
if (!value_type && value_len % 2)
value_len += 1;
/* My sample has that stream set to 0 maybe that mean the container.
@@ -623,14 +640,16 @@ static int asf_read_language_list(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
ASFContext *asf = s->priv_data;
- int j, ret;
- int stream_count = avio_rl16(pb);
+ int ret;
+ uint16_t j;
+ const uint16_t stream_count = (uint16_t)avio_rl16(pb);
+
for (j = 0; j < stream_count; j++) {
char lang[6];
- unsigned int lang_len = avio_r8(pb);
+ const uint8_t lang_len = (uint8_t)avio_r8(pb);
if ((ret = avio_get_str16le(pb, lang_len, lang,
sizeof(lang))) < lang_len)
- avio_skip(pb, lang_len - ret);
+ avio_skip(pb, (int)lang_len - ret);
if (j < 128)
av_strlcpy(asf->stream_languages[j], lang,
sizeof(*asf->stream_languages));
@@ -643,14 +662,14 @@ static int asf_read_metadata(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
ASFContext *asf = s->priv_data;
- int n, name_len_utf8;
- uint16_t stream_num, name_len_utf16, value_type;
+ int name_len_utf8;
+ uint16_t stream_num, name_len_utf16, value_type, i, n;
uint32_t value_len;
- int ret, i;
- n = avio_rl16(pb);
+ int ret;
+ n = (uint16_t)avio_rl16(pb);
for (i = 0; i < n; i++) {
- uint8_t *name;
+ char *name;
avio_rl16(pb); // lang_list_index
stream_num = (uint16_t)avio_rl16(pb);
@@ -664,7 +683,7 @@ static int asf_read_metadata(AVFormatContext *s)
return AVERROR(ENOMEM);
if ((ret = avio_get_str16le(pb, name_len_utf16, name, name_len_utf8)) < name_len_utf16)
- avio_skip(pb, name_len_utf16 - ret);
+ avio_skip(pb, (int)name_len_utf16 - ret);
av_log(s, AV_LOG_TRACE, "%d stream %d name_len %2d type %d len %4d <%s>\n",
i, stream_num, name_len_utf16, value_type, value_len, name);
@@ -697,19 +716,21 @@ static int asf_read_marker(AVFormatContext *s)
{
AVIOContext *pb = s->pb;
ASFContext *asf = s->priv_data;
- int i, count, name_len, ret;
+ int ret;
+ unsigned count, i;
+ uint16_t name_len;
char name[1024];
avio_rl64(pb); // reserved 16 bytes
avio_rl64(pb); // ...
count = avio_rl32(pb); // markers count
avio_rl16(pb); // reserved 2 bytes
- name_len = avio_rl16(pb); // name length
+ name_len = (uint16_t)avio_rl16(pb); // name length
avio_skip(pb, name_len);
for (i = 0; i < count; i++) {
- int64_t pres_time;
- int name_len;
+ uint64_t pres_time;
+ unsigned name2_len;
if (avio_feof(pb))
return AVERROR_INVALIDDATA;
@@ -720,13 +741,18 @@ static int asf_read_marker(AVFormatContext *s)
avio_rl16(pb); // entry length
avio_rl32(pb); // send time
avio_rl32(pb); // flags
- name_len = avio_rl32(pb); // name length
- if ((unsigned)name_len > INT_MAX / 2)
+ name2_len = avio_rl32(pb); // name length
+ if (name2_len > INT_MAX / 2)
return AVERROR_INVALIDDATA;
- if ((ret = avio_get_str16le(pb, name_len * 2, name,
- sizeof(name))) < name_len)
- avio_skip(pb, name_len - ret);
- avpriv_new_chapter(s, i, (AVRational) { 1, 10000000 }, pres_time,
+ if ((ret = avio_get_str16le(pb, (int)name2_len, name,
+ sizeof(name))) < name2_len)
+ avio_skip(pb, name2_len - ret);
+
+ if (pres_time > INT64_MAX) {
+ av_log(s, AV_LOG_DEBUG, "Unsupported presentation time value: %"PRIu64"\n", pres_time);
+ return AVERROR(ENOTSUP);
+ }
+ avpriv_new_chapter(s, i, (AVRational) { 1, 10000000 }, (int64_t)pres_time,
AV_NOPTS_VALUE, name);
}
@@ -739,7 +765,7 @@ static int asf_read_header(AVFormatContext *s)
ff_asf_guid g;
AVIOContext *pb = s->pb;
int i;
- int64_t gsize;
+ uint64_t gsize;
ff_get_guid(pb, &g);
if (ff_guidcmp(&g, &ff_asf_header))
@@ -754,7 +780,7 @@ static int asf_read_header(AVFormatContext *s)
asf->streams[i].stream_language_index = 128; // invalid stream index means no language info
for (;;) {
- uint64_t gpos = avio_tell(pb);
+ const int64_t gpos = avio_tell(pb);
int ret = 0;
ff_get_guid(pb, &g);
gsize = avio_rl64(pb);
@@ -809,7 +835,12 @@ static int asf_read_header(AVFormatContext *s)
len= avio_rl32(pb);
av_log(s, AV_LOG_DEBUG, "Secret data:\n");
- if ((ret = av_get_packet(pb, pkt, len)) < 0)
+ if (len > INT32_MAX) {
+ av_log(s, AV_LOG_DEBUG, "Unsupported encryption packet length: %d\n", len);
+ return AVERROR(ENOTSUP);
+ }
+
+ if ((ret = av_get_packet(pb, pkt, (int)len)) < 0)
return ret;
av_hex_dump_log(s, AV_LOG_DEBUG, pkt->data, pkt->size);
av_packet_unref(pkt);
@@ -923,7 +954,7 @@ static int asf_read_header(AVFormatContext *s)
static int asf_get_packet(AVFormatContext *s, AVIOContext *pb)
{
ASFContext *asf = s->priv_data;
- uint32_t packet_length, padsize;
+ uint32_t packet_length, packet_ts, padsize;
int rsize = 8;
int c, d, e, off;
@@ -1011,7 +1042,12 @@ static int asf_get_packet(AVFormatContext *s, AVIOContext *pb)
return AVERROR_INVALIDDATA;
}
- asf->packet_timestamp = avio_rl32(pb);
+ packet_ts = avio_rl32(pb);
+ if (packet_ts > INT32_MAX) {
+ av_log(s, AV_LOG_DEBUG, "Unsupported packet_timestamp value: %d\n", packet_ts);
+ return AVERROR(ENOTSUP);
+ }
+ asf->packet_timestamp = (int)packet_ts;
avio_rl16(pb); /* duration */
// rsize has at least 11 bytes which have to be present
@@ -1030,10 +1066,21 @@ static int asf_get_packet(AVFormatContext *s, AVIOContext *pb)
rsize, packet_length, padsize, avio_tell(pb));
return AVERROR_INVALIDDATA;
}
- asf->packet_size_left = packet_length - padsize - rsize;
+
+ if (packet_length - padsize - rsize > INT32_MAX) {
+ av_log(s, AV_LOG_DEBUG, "Unsupported packet_size_left value: %d\n", packet_length - padsize - rsize);
+ return AVERROR(ENOTSUP);
+ }
+ asf->packet_size_left = (int)(packet_length - padsize - rsize);
+
if (packet_length < asf->hdr.min_pktsize)
padsize += asf->hdr.min_pktsize - packet_length;
- asf->packet_padsize = padsize;
+ if (padsize > INT32_MAX) {
+ av_log(s, AV_LOG_DEBUG, "Unsupported packet padsize value: %d\n", padsize);
+ return AVERROR(ENOTSUP);
+ }
+
+ asf->packet_padsize = (int)padsize;
av_log(s, AV_LOG_TRACE, "packet: size=%d padsize=%d left=%d\n",
s->packet_size, asf->packet_padsize, asf->packet_size_left);
return 0;
@@ -1068,22 +1115,23 @@ static int asf_read_frame_header(AVFormatContext *s, AVIOContext *pb)
return AVERROR_INVALIDDATA;
}
if (asf->packet_replic_size >= 8) {
- int64_t end = avio_tell(pb) + asf->packet_replic_size;
+ const int64_t end = avio_tell(pb) + asf->packet_replic_size;
AVRational aspect;
- asfst->packet_obj_size = avio_rl32(pb);
- if (asfst->packet_obj_size >= (1 << 24) || asfst->packet_obj_size < 0) {
+ const unsigned packet_obj_size = avio_rl32(pb);
+ if (packet_obj_size >= (1 << 24)) {
av_log(s, AV_LOG_ERROR, "packet_obj_size %d invalid\n", asfst->packet_obj_size);
asfst->packet_obj_size = 0;
return AVERROR_INVALIDDATA;
}
+ asfst->packet_obj_size = (int)packet_obj_size;
asf->packet_frag_timestamp = avio_rl32(pb); // timestamp
for (i = 0; i < asfst->payload_ext_ct; i++) {
ASFPayload *p = &asfst->payload[i];
- int size = p->size;
+ uint16_t size = p->size;
int64_t payend;
if (size == 0xFFFF)
- size = avio_rl16(pb);
+ size = (uint16_t)avio_rl16(pb);
payend = avio_tell(pb) + size;
if (payend > end) {
av_log(s, AV_LOG_ERROR, "too long payload\n");
@@ -1484,7 +1532,7 @@ static int64_t asf_read_pts(AVFormatContext *s, int stream_index,
ASFStream *asf_st;
int64_t pts;
int64_t pos = *ppos;
- int i;
+ unsigned i;
int64_t start_pos[ASF_MAX_STREAMS];
for (i = 0; i < s->nb_streams; i++)
@@ -1541,7 +1589,7 @@ static int asf_build_simple_index(AVFormatContext *s, int stream_index)
int64_t ret;
if((ret = avio_seek(s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET)) < 0) {
- return ret;
+ return (int)ret;
}
if ((ret = ff_get_guid(s->pb, &g)) < 0)
--
ffmpeg-codebot
More information about the ffmpeg-devel
mailing list