Mercurial > libavformat.hg
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;