changeset 639:0b52743104ac libavformat

integer overflows, heap corruption possible arbitrary code execution cannot be ruled out in some cases precautionary checks
author michael
date Sat, 08 Jan 2005 14:21:33 +0000
parents 5188094c6ec4
children 6f3a6774df82
files 4xm.c allformats.c avformat.h avidec.c aviobuf.c gifdec.c grab.c http.c img.c img2.c matroska.c mov.c nsvdec.c nut.c ogg.c segafilm.c sgi.c utils.c wc3movie.c
diffstat 19 files changed, 108 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/4xm.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/4xm.c	Sat Jan 08 14:21:33 2005 +0000
@@ -185,6 +185,8 @@
             current_track = LE_32(&header[i + 8]);
             if (current_track + 1 > fourxm->track_count) {
                 fourxm->track_count = current_track + 1;
+                if((unsigned)fourxm->track_count >= UINT_MAX / sizeof(AudioTrack))
+                    return -1;
                 fourxm->tracks = av_realloc(fourxm->tracks, 
                     fourxm->track_count * sizeof(AudioTrack));
                 if (!fourxm->tracks) {
--- a/allformats.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/allformats.c	Sat Jan 08 14:21:33 2005 +0000
@@ -125,8 +125,8 @@
 #endif
     av_register_image_format(&jpeg_image_format);
 #endif
-    av_register_image_format(&gif_image_format);
-    av_register_image_format(&sgi_image_format);
+    av_register_image_format(&gif_image_format);  
+//    av_register_image_format(&sgi_image_format); heap corruption, dont enable
 #endif //CONFIG_ENCODERS
 
     /* file protocols */
--- a/avformat.h	Thu Jan 06 00:54:03 2005 +0000
+++ b/avformat.h	Sat Jan 08 14:21:33 2005 +0000
@@ -546,7 +546,7 @@
 int fifo_read(FifoBuffer *f, uint8_t *buf, int buf_size, uint8_t **rptr_ptr);
 void fifo_write(FifoBuffer *f, uint8_t *buf, int size, uint8_t **wptr_ptr);
 int put_fifo(ByteIOContext *pb, FifoBuffer *f, int buf_size, uint8_t **rptr_ptr);
-void fifo_realloc(FifoBuffer *f, int size);
+void fifo_realloc(FifoBuffer *f, unsigned int size);
 
 /* media file input */
 AVInputFormat *av_find_input_format(const char *short_name);
--- a/avidec.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/avidec.c	Sat Jan 08 14:21:33 2005 +0000
@@ -302,9 +302,11 @@
                     get_le32(pb); /* ClrUsed */
                     get_le32(pb); /* ClrImportant */
 
+                 if(size > 10*4 && size<(1<<30)){
                     st->codec.extradata_size= size - 10*4;
                     st->codec.extradata= av_malloc(st->codec.extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
                     get_buffer(pb, st->codec.extradata, st->codec.extradata_size);
+                 }
                     
                     if(st->codec.extradata_size & 1) //FIXME check if the encoder really did this correctly
                         get_byte(pb);
@@ -549,6 +551,8 @@
     nb_index_entries = size / 16;
     if (nb_index_entries <= 0)
         return -1;
+    if(nb_index_entries + 1 >= UINT_MAX / sizeof(AVIIndexEntry))
+        return -1;
 
     /* read the entries and sort them in each stream component */
     for(i = 0; i < nb_index_entries; i++) {
--- a/aviobuf.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/aviobuf.c	Sat Jan 08 14:21:33 2005 +0000
@@ -629,11 +629,13 @@
     /* reallocate buffer if needed */
     new_size = d->pos + buf_size;
     new_allocated_size = d->allocated_size;
+    if(new_size < d->pos || new_size > INT_MAX/2)
+        return -1;
     while (new_size > new_allocated_size) {
         if (!new_allocated_size)
             new_allocated_size = new_size;
         else
-            new_allocated_size = (new_allocated_size * 3) / 2 + 1;    
+            new_allocated_size += new_allocated_size / 2 + 1;    
     }
     
     if (new_allocated_size > d->allocated_size) {
@@ -691,6 +693,8 @@
     else
         io_buffer_size = 1024;
         
+    if(sizeof(DynBuffer) + io_buffer_size < io_buffer_size)
+        return -1;
     d = av_malloc(sizeof(DynBuffer) + io_buffer_size);
     if (!d)
         return -1;
--- a/gifdec.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/gifdec.c	Sat Jan 08 14:21:33 2005 +0000
@@ -474,6 +474,12 @@
     s->transparent_color_index = -1;
     s->screen_width = get_le16(f);
     s->screen_height = get_le16(f);
+    if(   (unsigned)s->screen_width  > 32767 
+       || (unsigned)s->screen_height > 32767){
+        av_log(NULL, AV_LOG_ERROR, "picture size too large\n");
+        return -1;
+    } 
+
     v = get_byte(f);
     s->color_resolution = ((v & 0x70) >> 4) + 1;
     has_global_palette = (v & 0x80);
--- a/grab.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/grab.c	Sat Jan 08 14:21:33 2005 +0000
@@ -76,6 +76,9 @@
     frame_rate      = ap->frame_rate;
     frame_rate_base = ap->frame_rate_base;
 
+    if((unsigned)width > 32767 || (unsigned)height > 32767)
+        return -1;
+    
     st = av_new_stream(s1, 0);
     if (!st)
         return -ENOMEM;
--- a/http.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/http.c	Sat Jan 08 14:21:33 2005 +0000
@@ -290,12 +290,16 @@
 static char *b64_encode( unsigned char *src )
 {
     static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-                                                                                
-    char *dst = av_malloc( strlen( src ) * 4 / 3 + 12 );
-    char *ret = dst;
+    unsigned int len= strlen(src);
+    char *ret, *dst;
     unsigned i_bits = 0;
     unsigned i_shift = 0;
-                                                                                
+
+    if(len < UINT_MAX/4){
+        ret=dst= av_malloc( len * 4 / 3 + 12 );
+    }else
+        return NULL;
+
     for( ;; )
     {
         if( *src )
--- a/img.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/img.c	Sat Jan 08 14:21:33 2005 +0000
@@ -123,7 +123,7 @@
     if (ap && ap->image_format)
         s->img_fmt = ap->image_format;
 
-    strcpy(s->path, s1->filename);
+    pstrcpy(s->path, sizeof(s->path), s1->filename);
     s->img_number = 0;
     s->img_count = 0;
     
@@ -289,7 +289,7 @@
     VideoData *img = s->priv_data;
 
     img->img_number = 1;
-    strcpy(img->path, s->filename);
+    pstrcpy(img->path, sizeof(img->path), s->filename);
 
     /* find format */
     if (s->oformat->flags & AVFMT_NOFILE)
--- a/img2.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/img2.c	Sat Jan 08 14:21:33 2005 +0000
@@ -184,7 +184,7 @@
         return -ENOMEM;
     }
 
-    strcpy(s->path, s1->filename);
+    pstrcpy(s->path, sizeof(s->path), s1->filename);
     s->img_number = 0;
     s->img_count = 0;
     
@@ -310,7 +310,7 @@
     VideoData *img = s->priv_data;
 
     img->img_number = 1;
-    strcpy(img->path, s->filename);
+    pstrcpy(img->path, sizeof(img->path), s->filename);
 
     /* find format */
     if (s->oformat->flags & AVFMT_NOFILE)
--- a/matroska.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/matroska.c	Sat Jan 08 14:21:33 2005 +0000
@@ -669,7 +669,7 @@
 
     /* ebml strings are usually not 0-terminated, so we allocate one
      * byte more, read the string and NULL-terminate it ourselves. */
-    if (!(*str = av_malloc(size + 1))) {
+    if (size < 0 || !(*str = av_malloc(size + 1))) {
         av_log(matroska->ctx, AV_LOG_ERROR, "Memory allocation failed\n");
         return AVERROR_NOMEM;
     }
--- a/mov.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/mov.c	Sat Jan 08 14:21:33 2005 +0000
@@ -367,6 +367,10 @@
 	    /* empty */;
 
 	a.size -= 8;
+        
+        if(a.size < 0)
+            break;
+        
 //        av_log(NULL, AV_LOG_DEBUG, " i=%ld\n", i);
 	if (c->parse_table[i].type == 0) { /* skip leaf atoms data */
 //            url_seek(pb, atom.offset+atom.size, SEEK_SET);
@@ -401,7 +405,10 @@
 {
     unsigned int len;
     MOV_ctab_t *t;
-    //url_fskip(pb, atom.size); // for now
+#if 1
+    url_fskip(pb, atom.size); // for now
+#else
+    VERY VERY BROKEN, NEVER execute this, needs rewrite
     c->ctab = av_realloc(c->ctab, ++c->ctab_size);
     t = c->ctab[c->ctab_size];
     t->seed = get_be32(pb);
@@ -413,6 +420,7 @@
 	if (t->clrs)
 	    get_buffer(pb, t->clrs, len);
     }
+#endif
 
     return 0;
 }
@@ -677,6 +685,9 @@
 {
     AVStream *st = c->fc->streams[c->fc->nb_streams-1];
 
+    if((uint64_t)atom.size > (1<<30))
+        return -1;
+    
     // currently SVQ3 decoder expect full STSD header - so let's fake it
     // this should be fixed and just SMI header should be passed
     av_free(st->codec.extradata);
@@ -697,6 +708,9 @@
 {
     AVStream *st = c->fc->streams[c->fc->nb_streams-1];
 
+    if((uint64_t)atom.size > (1<<30))
+        return -1;
+
     av_free(st->codec.extradata);
 
     st->codec.extradata_size = atom.size;
@@ -714,7 +728,7 @@
 {
     AVStream *st = c->fc->streams[c->fc->nb_streams-1];
     MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
-    int entries, i;
+    unsigned int i, entries;
 
     print_atom("stco", atom);
 
@@ -722,6 +736,10 @@
     get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
 
     entries = get_be32(pb);
+        
+    if(entries >= UINT_MAX/sizeof(int64_t))
+        return -1;
+ 
     sc->chunk_count = entries;
     sc->chunk_offsets = (int64_t*) av_malloc(entries * sizeof(int64_t));
     if (!sc->chunk_offsets)
@@ -1138,7 +1156,7 @@
 {
     AVStream *st = c->fc->streams[c->fc->nb_streams-1];
     MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
-    int entries, i;
+    unsigned int i, entries;
 
     print_atom("stsc", atom);
 
@@ -1146,6 +1164,10 @@
     get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
 
     entries = get_be32(pb);
+    
+    if(entries >= UINT_MAX / sizeof(MOV_sample_to_chunk_tbl))
+        return -1;
+    
 #ifdef DEBUG
 av_log(NULL, AV_LOG_DEBUG, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);
 #endif
@@ -1168,7 +1190,7 @@
 {
     AVStream *st = c->fc->streams[c->fc->nb_streams-1];
     MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
-    int entries, i;
+    unsigned int i, entries;
 
     print_atom("stss", atom);
 
@@ -1176,6 +1198,10 @@
     get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
 
     entries = get_be32(pb);
+    
+    if(entries >= UINT_MAX / sizeof(long))
+        return -1;
+    
     sc->keyframe_count = entries;
 #ifdef DEBUG
     av_log(NULL, AV_LOG_DEBUG, "keyframe_count = %ld\n", sc->keyframe_count);
@@ -1196,7 +1222,7 @@
 {
     AVStream *st = c->fc->streams[c->fc->nb_streams-1];
     MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
-    int entries, i;
+    unsigned int i, entries;
 
     print_atom("stsz", atom);
 
@@ -1205,6 +1231,9 @@
 
     sc->sample_size = get_be32(pb);
     entries = get_be32(pb);
+    if(entries >= UINT_MAX / sizeof(long))
+        return -1;
+
     sc->sample_count = entries;
 #ifdef DEBUG
     av_log(NULL, AV_LOG_DEBUG, "sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count);
@@ -1227,7 +1256,7 @@
 {
     AVStream *st = c->fc->streams[c->fc->nb_streams-1];
     //MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
-    int entries, i;
+    unsigned int i, entries;
     int64_t duration=0;
     int64_t total_sample_count=0;
 
@@ -1236,6 +1265,8 @@
     get_byte(pb); /* version */
     get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
     entries = get_be32(pb);
+    if(entries >= UINT_MAX / sizeof(uint64_t))
+        return -1;
 
     c->streams[c->fc->nb_streams-1]->stts_count = entries;
     c->streams[c->fc->nb_streams-1]->stts_data = (uint64_t*) av_malloc(entries * sizeof(uint64_t));
--- a/nsvdec.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/nsvdec.c	Sat Jan 08 14:21:33 2005 +0000
@@ -365,6 +365,8 @@
 
     if (table_entries_used > 0) {
         nsv->index_entries = table_entries_used;
+        if((unsigned)table_entries >= UINT_MAX / sizeof(uint32_t))
+            return -1;
         nsv->nsvf_index_data = av_malloc(table_entries * sizeof(uint32_t));
         get_buffer(pb, nsv->nsvf_index_data, table_entries * sizeof(uint32_t));
     }
--- a/nut.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/nut.c	Sat Jan 08 14:21:33 2005 +0000
@@ -82,7 +82,7 @@
     int written_packet_size;
     int64_t packet_start[3]; //0-> startcode less, 1-> short startcode 2-> long startcodes
     FrameCode frame_code[256];
-    int stream_count;
+    unsigned int stream_count;
     uint64_t next_startcode;     ///< stores the next startcode if it has alraedy been parsed but the stream isnt seekable
     StreamContext *stream;
     int max_distance;
@@ -255,8 +255,8 @@
     return -1;
 }
 
-static int get_str(ByteIOContext *bc, char *string, int maxlen){
-    int len= get_v(bc);
+static int get_str(ByteIOContext *bc, char *string, unsigned int maxlen){
+    unsigned int len= get_v(bc);
     
     if(len && maxlen)
         get_buffer(bc, string, FFMIN(len, maxlen));
@@ -283,7 +283,7 @@
 
 static uint64_t get_vb(ByteIOContext *bc){
     uint64_t val=0;
-    int i= get_v(bc);
+    unsigned int i= get_v(bc);
     
     if(i>8)
         return UINT64_MAX;
@@ -877,6 +877,10 @@
     }
     
     nut->stream_count = get_v(bc);
+    if(nut->stream_count > MAX_STREAMS){
+        av_log(s, AV_LOG_ERROR, "too many streams\n");
+        return -1;
+    }
     nut->max_distance = get_v(bc);
     nut->max_short_distance = get_v(bc);
     nut->rate_num= get_v(bc);
@@ -982,6 +986,8 @@
     /* codec specific data headers */
     while(get_v(bc) != 0){
         st->codec.extradata_size= get_v(bc);
+        if((unsigned)st->codec.extradata_size > (1<<30))
+            return -1;
         st->codec.extradata= av_mallocz(st->codec.extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
         get_buffer(bc, st->codec.extradata, st->codec.extradata_size);            
 //	    url_fskip(bc, get_v(bc));
--- a/ogg.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/ogg.c	Sat Jan 08 14:21:33 2005 +0000
@@ -195,6 +195,8 @@
         if(next_packet(avfcontext, &op)){
             return -1;
         }
+        if(op.bytes >= (1<<16) || op.bytes < 0)
+            return -1;
         codec->extradata_size+= 2 + op.bytes;
         codec->extradata= av_realloc(codec->extradata, codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
         p= codec->extradata + codec->extradata_size - 2 - op.bytes;
--- a/segafilm.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/segafilm.c	Sat Jan 08 14:21:33 2005 +0000
@@ -171,6 +171,8 @@
         return AVERROR_INVALIDDATA;
     film->base_clock = BE_32(&scratch[8]);
     film->sample_count = BE_32(&scratch[12]);
+    if(film->sample_count >= UINT_MAX / sizeof(film_sample_t))
+        return -1;
     film->sample_table = av_malloc(film->sample_count * sizeof(film_sample_t));
     
     for(i=0; i<s->nb_streams; i++)
--- a/sgi.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/sgi.c	Sat Jan 08 14:21:33 2005 +0000
@@ -65,6 +65,9 @@
     info->xsize = (unsigned short) get_be16(f);
     info->ysize = (unsigned short) get_be16(f);
     info->zsize = (unsigned short) get_be16(f);
+    
+    if(info->zsize > 4096) 
+        info->zsize= 0;
 
 #ifdef DEBUG
     printf("sgi header fields:\n");
--- a/utils.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/utils.c	Sat Jan 08 14:21:33 2005 +0000
@@ -180,7 +180,10 @@
  */
 int av_new_packet(AVPacket *pkt, int size)
 {
-    void *data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
+    void *data;
+    if((unsigned)size > (unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE)
+        return AVERROR_NOMEM;        
+    data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
     if (!data)
         return AVERROR_NOMEM;
     memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
@@ -200,6 +203,8 @@
         uint8_t *data;
         /* we duplicate the packet and don't forget to put the padding
            again */
+        if((unsigned)pkt->size > (unsigned)pkt->size + FF_INPUT_BUFFER_PADDING_SIZE)
+            return AVERROR_NOMEM;        
         data = av_malloc(pkt->size + FF_INPUT_BUFFER_PADDING_SIZE);
         if (!data) {
             return AVERROR_NOMEM;
@@ -277,8 +282,8 @@
     return 0;
 }
 
-void fifo_realloc(FifoBuffer *f, int new_size){
-    int old_size= f->end - f->buffer;
+void fifo_realloc(FifoBuffer *f, unsigned int new_size){
+    unsigned int old_size= f->end - f->buffer;
     
     if(old_size < new_size){
         uint8_t *old= f->buffer;
@@ -1007,10 +1012,16 @@
     AVIndexEntry *entries, *ie;
     int index;
     
+    if((unsigned)st->nb_index_entries + 1 >= UINT_MAX / sizeof(AVIndexEntry))
+        return -1;
+    
     entries = av_fast_realloc(st->index_entries,
                               &st->index_entries_allocated_size,
                               (st->nb_index_entries + 1) * 
                               sizeof(AVIndexEntry));
+    if(!entries)
+        return -1;
+
     st->index_entries= entries;
 
     index= av_index_search_timestamp(st, timestamp, 0);
--- a/wc3movie.c	Thu Jan 06 00:54:03 2005 +0000
+++ b/wc3movie.c	Sat Jan 08 14:21:33 2005 +0000
@@ -169,6 +169,8 @@
             if ((ret = get_buffer(pb, preamble, 4)) != 4)
                 return AVERROR_IO;
             wc3->palette_count = LE_32(&preamble[0]);
+            if((unsigned)wc3->palette_count >= UINT_MAX / PALETTE_SIZE)
+                return -1;
             wc3->palettes = av_malloc(wc3->palette_count * PALETTE_SIZE);
             break;