possible arbitrary code execution cannot be ruled out in some cases precautionary checks Originally committed as revision 3813 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
| @@ -185,6 +185,8 @@ static int fourxm_read_header(AVFormatContext *s, | |||
| 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) { | |||
| @@ -125,8 +125,8 @@ void av_register_all(void) | |||
| #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 */ | |||
| @@ -546,7 +546,7 @@ int fifo_size(FifoBuffer *f, uint8_t *rptr); | |||
| 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); | |||
| @@ -302,9 +302,11 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) | |||
| 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 @@ static int avi_read_idx1(AVFormatContext *s, int size) | |||
| 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++) { | |||
| @@ -629,11 +629,13 @@ static int dyn_buf_write(void *opaque, uint8_t *buf, int buf_size) | |||
| /* 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 @@ static int url_open_dyn_buf_internal(ByteIOContext *s, int max_packet_size) | |||
| 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; | |||
| @@ -474,6 +474,12 @@ static int gif_read_header1(GifState *s) | |||
| 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); | |||
| @@ -76,6 +76,9 @@ static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) | |||
| 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; | |||
| @@ -290,12 +290,16 @@ URLProtocol http_protocol = { | |||
| 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 ) | |||
| @@ -123,7 +123,7 @@ static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap) | |||
| 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 @@ static int img_write_header(AVFormatContext *s) | |||
| 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) | |||
| @@ -184,7 +184,7 @@ static int img_read_header(AVFormatContext *s1, AVFormatParameters *ap) | |||
| 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 @@ static int img_write_header(AVFormatContext *s) | |||
| 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) | |||
| @@ -669,7 +669,7 @@ ebml_read_ascii (MatroskaDemuxContext *matroska, | |||
| /* 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; | |||
| } | |||
| @@ -367,6 +367,10 @@ static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |||
| /* 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 @@ static int mov_read_ctab(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |||
| { | |||
| 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 @@ static int mov_read_ctab(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |||
| if (t->clrs) | |||
| get_buffer(pb, t->clrs, len); | |||
| } | |||
| #endif | |||
| return 0; | |||
| } | |||
| @@ -677,6 +685,9 @@ static int mov_read_smi(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |||
| { | |||
| 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 @@ static int mov_read_avcC(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |||
| { | |||
| 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 @@ static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |||
| { | |||
| 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 @@ static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |||
| 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 @@ static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |||
| { | |||
| 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 @@ static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |||
| 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 @@ static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |||
| { | |||
| 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 @@ static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |||
| 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 @@ static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |||
| { | |||
| 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 @@ static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |||
| 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 @@ static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |||
| { | |||
| 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 @@ static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) | |||
| 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)); | |||
| @@ -365,6 +365,8 @@ static int nsv_parse_NSVf_header(AVFormatContext *s, AVFormatParameters *ap) | |||
| 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)); | |||
| } | |||
| @@ -82,7 +82,7 @@ typedef struct { | |||
| 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 @@ static uint64_t get_v(ByteIOContext *bc) | |||
| 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 int64_t get_s(ByteIOContext *bc){ | |||
| 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 @@ static int decode_main_header(NUTContext *nut){ | |||
| } | |||
| 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 @@ static int decode_stream_header(NUTContext *nut){ | |||
| /* 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)); | |||
| @@ -195,6 +195,8 @@ static int ogg_read_header(AVFormatContext *avfcontext, AVFormatParameters *ap) | |||
| 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; | |||
| @@ -171,6 +171,8 @@ static int film_read_header(AVFormatContext *s, | |||
| 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++) | |||
| @@ -65,6 +65,9 @@ static void read_sgi_header(ByteIOContext *f, SGIInfo *info) | |||
| 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"); | |||
| @@ -180,7 +180,10 @@ static void av_destruct_packet(AVPacket *pkt) | |||
| */ | |||
| 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 @@ int av_dup_packet(AVPacket *pkt) | |||
| 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 @@ int fifo_read(FifoBuffer *f, uint8_t *buf, int buf_size, uint8_t **rptr_ptr) | |||
| 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 @@ int av_add_index_entry(AVStream *st, | |||
| 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); | |||
| @@ -169,6 +169,8 @@ static int wc3_read_header(AVFormatContext *s, | |||
| 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; | |||