diff mbox series

[FFmpeg-devel,v6,11/11] libavformat/asfdec: Fix variable types and add checks for unsupported values

Message ID MN2PR04MB5981AD373BC605E2041987B9BAB09@MN2PR04MB5981.namprd04.prod.outlook.com
State New
Headers show
Series [FFmpeg-devel,v6,01/11] libavformat/asf: Fix handling of byte array length values
Related show

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished
andriy/make_ppc success Make finished
andriy/make_fate_ppc success Make fate finished

Commit Message

Soft Works Oct. 6, 2021, 6:01 a.m. UTC
Signed-off-by: softworkz <softworkz@hotmail.com>
---
 libavformat/asfdec_f.c | 168 ++++++++++++++++++++++++++---------------
 1 file changed, 108 insertions(+), 60 deletions(-)
diff mbox series

Patch

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)