]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/flvdec.c
avformat: Constify all muxer/demuxers
[ffmpeg] / libavformat / flvdec.c
index 07ef342278d5117a3c7c0648d445721c4214537d..718d690421987ed960b114a1332c703318de1de1 100644 (file)
@@ -41,6 +41,8 @@
 
 #define RESYNC_BUFFER_SIZE (1<<20)
 
+#define MAX_DEPTH 16      ///< arbitrary limit to prevent unbounded recursion
+
 typedef struct FLVContext {
     const AVClass *class; ///< Class for private options.
     int trust_metadata;   ///< configure streams according onMetaData
@@ -382,13 +384,18 @@ static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream,
 
 static int amf_get_string(AVIOContext *ioc, char *buffer, int buffsize)
 {
+    int ret;
     int length = avio_rb16(ioc);
     if (length >= buffsize) {
         avio_skip(ioc, length);
         return -1;
     }
 
-    avio_read(ioc, buffer, length);
+    ret = avio_read(ioc, buffer, length);
+    if (ret < 0)
+        return ret;
+    if (ret < length)
+        return AVERROR_INVALIDDATA;
 
     buffer[length] = '\0';
 
@@ -446,9 +453,13 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, int64_t m
         }
 
         for (i = 0; i < arraylen && avio_tell(ioc) < max_pos - 1; i++) {
+            double d;
             if (avio_r8(ioc) != AMF_DATA_TYPE_NUMBER)
                 goto invalid;
-            current_array[0][i] = av_int2double(avio_rb64(ioc));
+            d = av_int2double(avio_rb64(ioc));
+            if (isnan(d) || d < INT64_MIN || d > INT64_MAX)
+                goto invalid;
+            current_array[0][i] = d;
         }
         if (times && filepositions) {
             // All done, exiting at a position allowing amf_parse_object
@@ -493,6 +504,9 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream,
     double num_val;
     amf_date date;
 
+    if (depth > MAX_DEPTH)
+        return AVERROR_PATCHWELCOME;
+
     num_val  = 0;
     ioc      = s->pb;
     if (avio_feof(ioc))
@@ -837,10 +851,16 @@ static void clear_index_entries(AVFormatContext *s, int64_t pos)
     }
 }
 
-static int amf_skip_tag(AVIOContext *pb, AMFDataType type)
+static int amf_skip_tag(AVIOContext *pb, AMFDataType type, int depth)
 {
     int nb = -1, ret, parse_name = 1;
 
+    if (depth > MAX_DEPTH)
+        return AVERROR_PATCHWELCOME;
+
+    if (avio_feof(pb))
+        return AVERROR_EOF;
+
     switch (type) {
     case AMF_DATA_TYPE_NUMBER:
         avio_skip(pb, 8);
@@ -855,6 +875,8 @@ static int amf_skip_tag(AVIOContext *pb, AMFDataType type)
         parse_name = 0;
     case AMF_DATA_TYPE_MIXEDARRAY:
         nb = avio_rb32(pb);
+        if (nb < 0)
+            return AVERROR_INVALIDDATA;
     case AMF_DATA_TYPE_OBJECT:
         while(!pb->eof_reached && (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY)) {
             if (parse_name) {
@@ -865,7 +887,7 @@ static int amf_skip_tag(AVIOContext *pb, AMFDataType type)
                 }
                 avio_skip(pb, size);
             }
-            if ((ret = amf_skip_tag(pb, avio_r8(pb))) < 0)
+            if ((ret = amf_skip_tag(pb, avio_r8(pb), depth + 1)) < 0)
                 return ret;
         }
         break;
@@ -909,7 +931,7 @@ static int flv_data_packet(AVFormatContext *s, AVPacket *pkt,
             else
                 break;
         } else {
-            if ((ret = amf_skip_tag(pb, type)) < 0)
+            if ((ret = amf_skip_tag(pb, type, 0)) < 0)
                 goto skip;
         }
     }
@@ -1158,7 +1180,7 @@ retry_duration:
             avio_seek(s->pb, fsize - 3 - size, SEEK_SET);
             if (size == avio_rb24(s->pb) + 11) {
                 uint32_t ts = avio_rb24(s->pb);
-                ts         |= avio_r8(s->pb) << 24;
+                ts         |= (unsigned)avio_r8(s->pb) << 24;
                 if (ts)
                     s->duration = ts * (int64_t)AV_TIME_BASE / 1000;
                 else if (fsize >= 8 && fsize - 8 >= size) {
@@ -1350,7 +1372,7 @@ static const AVClass flv_class = {
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
-AVInputFormat ff_flv_demuxer = {
+const AVInputFormat ff_flv_demuxer = {
     .name           = "flv",
     .long_name      = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"),
     .priv_data_size = sizeof(FLVContext),
@@ -1370,7 +1392,7 @@ static const AVClass live_flv_class = {
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
-AVInputFormat ff_live_flv_demuxer = {
+const AVInputFormat ff_live_flv_demuxer = {
     .name           = "live_flv",
     .long_name      = NULL_IF_CONFIG_SMALL("live RTMP FLV (Flash Video)"),
     .priv_data_size = sizeof(FLVContext),
@@ -1391,7 +1413,7 @@ static const AVClass kux_class = {
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
-AVInputFormat ff_kux_demuxer = {
+const AVInputFormat ff_kux_demuxer = {
     .name           = "kux",
     .long_name      = NULL_IF_CONFIG_SMALL("KUX (YouKu)"),
     .priv_data_size = sizeof(FLVContext),