OSDN Git Service

Merge commit 'aa3c77998404cc32233cb76e961ca27db8565459'
authorMichael Niedermayer <michaelni@gmx.at>
Sat, 16 Mar 2013 14:12:21 +0000 (15:12 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Sat, 16 Mar 2013 14:38:13 +0000 (15:38 +0100)
* commit 'aa3c77998404cc32233cb76e961ca27db8565459':
  lavf: sanity check size in av_get/append_packet().

Conflicts:
libavformat/utils.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavformat/utils.c

@@@ -251,48 -214,61 +251,93 @@@ AVInputFormat *av_find_input_format(con
      return NULL;
  }
  
- int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
+ /* an arbitrarily chosen "sane" max packet size -- 50M */
+ #define SANE_CHUNK_SIZE (50000000)
 +int ffio_limit(AVIOContext *s, int size)
 +{
 +    if(s->maxsize>=0){
 +        int64_t remaining= s->maxsize - avio_tell(s);
 +        if(remaining < size){
 +            int64_t newsize= avio_size(s);
 +            if(!s->maxsize || s->maxsize<newsize)
 +                s->maxsize= newsize - !newsize;
 +            remaining= s->maxsize - avio_tell(s);
 +            remaining= FFMAX(remaining, 0);
 +        }
 +
 +        if(s->maxsize>=0 && remaining+1 < size){
 +            av_log(NULL, remaining ? AV_LOG_ERROR : AV_LOG_DEBUG, "Truncating packet of size %d to %"PRId64"\n", size, remaining+1);
 +            size= remaining+1;
 +        }
 +    }
 +    return size;
 +}
 +
+ /*
+  * Read the data in sane-sized chunks and append to pkt.
+  * Return the number of bytes read or an error.
+  */
+ static int append_packet_chunked(AVIOContext *s, AVPacket *pkt, int size)
  {
-     int ret;
-     int orig_size = size;
-     size= ffio_limit(s, size);
+     int64_t chunk_size = size;
+     int orig_pos       = pkt->pos; // av_grow_packet might reset pos
+     int orig_size      = pkt->size;
+     int ret = 0;
+     do {
+         int prev_size = pkt->size;
+         int read_size;
+         /*
+          * When the caller requests a lot of data, limit it to the amount left
+          * in file or SANE_CHUNK_SIZE when it is not known
+          */
++#if 0
+         if (size > SANE_CHUNK_SIZE) {
+             int64_t filesize = avio_size(s) - avio_tell(s);
+             chunk_size = FFMAX(filesize, SANE_CHUNK_SIZE);
+         }
+         read_size = FFMIN(size, chunk_size);
++#else
++        read_size = size;
++        if (read_size > SANE_CHUNK_SIZE/10) {
++            read_size = ffio_limit(s, read_size);
++            // If filesize/maxsize is unknown, limit to SANE_CHUNK_SIZE
++            if (s->maxsize < 0)
++                read_size = FFMIN(read_size, SANE_CHUNK_SIZE);
++        }
++#endif
  
-     ret= av_new_packet(pkt, size);
+         ret = av_grow_packet(pkt, read_size);
+         if (ret < 0)
+             break;
  
-     if(ret<0)
-         return ret;
+         ret = avio_read(s, pkt->data + prev_size, read_size);
+         if (ret != read_size) {
+             av_shrink_packet(pkt, prev_size + FFMAX(ret, 0));
+             break;
+         }
  
-     pkt->pos= avio_tell(s);
+         size -= read_size;
+     } while (size > 0);
++    if (size > 0)
++        pkt->flags |= AV_PKT_FLAG_CORRUPT;
  
-     ret= avio_read(s, pkt->data, size);
-     if(ret<=0)
+     pkt->pos = orig_pos;
+     if (!pkt->size)
          av_free_packet(pkt);
-     else
-         av_shrink_packet(pkt, ret);
-     if (pkt->size < orig_size)
-         pkt->flags |= AV_PKT_FLAG_CORRUPT;
+     return pkt->size > orig_size ? pkt->size - orig_size : ret;
+ }
+ int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
+ {
+     av_init_packet(pkt);
+     pkt->data = NULL;
+     pkt->size = 0;
+     pkt->pos  = avio_tell(s);
  
-     return ret;
+     return append_packet_chunked(s, pkt, size);
  }
  
  int av_append_packet(AVIOContext *s, AVPacket *pkt, int size)