Mercurial > mplayer.hg
changeset 18444:fa603193eccf
Fix potential integer overflows in memory allocation. Patch by Reimar and me, SIZE_MAX by Rich
author | rtognimp |
---|---|
date | Thu, 11 May 2006 18:50:46 +0000 |
parents | 1bcd97461b7b |
children | 59831ed83cfd |
files | libmpdemux/demux_mov.c libmpdemux/demux_real.c |
diffstat | 2 files changed, 41 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/libmpdemux/demux_mov.c Thu May 11 15:39:43 2006 +0000 +++ b/libmpdemux/demux_mov.c Thu May 11 18:50:46 2006 +0000 @@ -145,6 +145,16 @@ void* desc; // image/sound/etc description (pointer to ImageDescription etc) } mov_track_t; +#ifndef SIZE_MAX +#define SIZE_MAX ((size_t)-1) +#endif + +void *realloc_struct(void *ptr, size_t nmemb, size_t size) { + if (nmemb > SIZE_MAX / size) + return NULL; + return realloc(ptr, nmemb * size); +} + void mov_build_index(mov_track_t* trak,int timescale){ int i,j,s; int last=trak->chunks_size; @@ -206,7 +216,7 @@ // workaround for fixed-size video frames (dv and uncompressed) if(!trak->samples_size && trak->type!=MOV_TRAK_AUDIO){ trak->samples_size=s; - trak->samples=malloc(sizeof(mov_sample_t)*s); + trak->samples=calloc(s, sizeof(mov_sample_t)); for(i=0;i<s;i++) trak->samples[i].size=trak->samplesize; trak->samplesize=0; @@ -225,7 +235,7 @@ "MOV: durmap or chunkmap bigger than sample count (%i vs %i)\n", s, trak->samples_size); trak->samples_size = s; - trak->samples = realloc(trak->samples, sizeof(mov_sample_t) * s); + trak->samples = realloc_struct(trak->samples, s, sizeof(mov_sample_t)); } // calc pts: @@ -899,7 +909,7 @@ // 82 char[4] atom type // 86 ... atom data - { ImageDescription* id=malloc(8+trak->stdata_len); + { ImageDescription* id=malloc(8+trak->stdata_len); // safe trak->desc=id; id->idSize=8+trak->stdata_len; // id->cType=bswap_32(trak->fourcc); @@ -1145,6 +1155,10 @@ else { if (trak->fourcc == mmioFOURCC('a','v','c','1')) { + if (trak->stream_header_len > 0xffffffff - sizeof(BITMAPINFOHEADER)) { + mp_msg(MSGT_DEMUXER, MSGL_ERR, "Invalid extradata size %d, skipping\n"); + trak->stream_header_len = 0; + } sh->bih=malloc(sizeof(BITMAPINFOHEADER) + trak->stream_header_len); memset(sh->bih,0,sizeof(BITMAPINFOHEADER) + trak->stream_header_len); sh->bih->biSize=40 + trak->stream_header_len; @@ -1258,12 +1272,18 @@ // int temp=stream_read_dword(demuxer->stream); unsigned int moov_sz=stream_read_dword(demuxer->stream); unsigned int cmov_sz=len-4; - unsigned char* cmov_buf=malloc(cmov_sz); - unsigned char* moov_buf=malloc(moov_sz+16); + unsigned char* cmov_buf; + unsigned char* moov_buf; int zret; z_stream zstrm; stream_t* backup; + if (moov_sz > 0xffffffff - 16) { + mp_msg(MSGT_DEMUX, MSGL_ERR, "Invalid cmvd atom size %d\n", moov_sz); + break; + } + cmov_buf=malloc(cmov_sz); + moov_buf=malloc(moov_sz+16); mp_msg(MSGT_DEMUX, MSGL_V, "Compressed header size: %d / %d\n",cmov_sz,moov_sz); stream_read(demuxer->stream,cmov_buf,cmov_sz); @@ -1582,8 +1602,7 @@ mp_msg(MSGT_DEMUX, MSGL_V, "MOV: %*sSample duration table! (%d blocks)\n", level, "", len); - trak->durmap = malloc(sizeof(mov_durmap_t) * len); - memset(trak->durmap, 0, sizeof(mov_durmap_t) * len); + trak->durmap = calloc(len, sizeof(mov_durmap_t)); trak->durmap_size = len; for (i = 0; i < len; i++) { trak->durmap[i].num = stream_read_dword(demuxer->stream); @@ -1606,7 +1625,7 @@ len, ver, flags); // read data: trak->chunkmap_size = len; - trak->chunkmap = malloc(sizeof(mov_chunkmap_t) * len); + trak->chunkmap = calloc(len, sizeof(mov_chunkmap_t)); for (i = 0; i < len; i++) { trak->chunkmap[i].first = stream_read_dword(demuxer->stream) - 1; trak->chunkmap[i].spc = stream_read_dword(demuxer->stream); @@ -1627,7 +1646,7 @@ trak->samplesize = ss; if (!ss) { // variable samplesize - trak->samples = realloc(trak->samples,sizeof(mov_sample_t)*entries); + trak->samples = realloc_struct(trak->samples, entries, sizeof(mov_sample_t)); trak->samples_size = entries; for (i = 0; i < entries; i++) trak->samples[i].size = stream_read_dword(demuxer->stream); @@ -1643,7 +1662,7 @@ len); // extend array if needed: if (len > trak->chunks_size) { - trak->chunks = realloc(trak->chunks, sizeof(mov_chunk_t) * len); + trak->chunks = realloc_struct(trak->chunks, len, sizeof(mov_chunk_t)); trak->chunks_size = len; } // read elements: @@ -1660,7 +1679,7 @@ len); // extend array if needed: if (len > trak->chunks_size) { - trak->chunks = realloc(trak->chunks, sizeof(mov_chunk_t) * len); + trak->chunks = realloc_struct(trak->chunks, len, sizeof(mov_chunk_t)); trak->chunks_size = len; } // read elements: @@ -1685,7 +1704,7 @@ "MOV: %*sSyncing samples (keyframes) table! (%d entries) (ver:%d,flags:%d)\n", level, "", entries, ver, flags); trak->keyframes_size = entries; - trak->keyframes = malloc(sizeof(unsigned int) * entries); + trak->keyframes = calloc(entries, sizeof(unsigned int)); for (i = 0; i < entries; i++) trak->keyframes[i] = stream_read_dword(demuxer->stream) - 1; break; @@ -1721,7 +1740,7 @@ entries, ver, flags); #if 1 trak->editlist_size = entries; - trak->editlist = malloc(trak->editlist_size * sizeof(mov_editlist_t)); + trak->editlist = calloc(trak->editlist_size, sizeof(mov_editlist_t)); for (i = 0; i < entries; i++) { int dur = stream_read_dword(demuxer->stream); int mt = stream_read_dword(demuxer->stream);
--- a/libmpdemux/demux_real.c Thu May 11 15:39:43 2006 +0000 +++ b/libmpdemux/demux_real.c Thu May 11 18:50:46 2006 +0000 @@ -122,6 +122,9 @@ int audio_filepos; ///< file position of first audio packet in block } real_priv_t; +//! use at most 200 MB of memory for index, corresponds to around 25 million entries +#define MAX_INDEX_ENTRIES (200*1024*1024 / sizeof(real_index_table_t)) + /* originally from FFmpeg */ static void get_str(int isbyte, demuxer_t *demuxer, char *buf, int buf_size) { @@ -222,7 +225,7 @@ next_header_pos = stream_read_dword(demuxer->stream); mp_msg(MSGT_DEMUX, MSGL_V,"next_header_pos: %d\n", next_header_pos); - if (entries <= 0) + if (entries <= 0 || entries > MAX_INDEX_ENTRIES) { if (next_header_pos) goto read_index; @@ -231,7 +234,7 @@ } priv->index_table_size[stream_id] = entries; - priv->index_table[stream_id] = malloc(priv->index_table_size[stream_id] * sizeof(real_index_table_t)); + priv->index_table[stream_id] = calloc(priv->index_table_size[stream_id], sizeof(real_index_table_t)); for (i = 0; i < entries; i++) { @@ -267,6 +270,10 @@ { real_priv_t *priv = demuxer->priv; real_index_table_t *index; + if (priv->index_table_size[stream_id] >= MAX_INDEX_ENTRIES) { + mp_msg(MSGT_DEMUXER, MSGL_WARN, "Index too large during building\n"); + return; + } if (priv->index_table_size[stream_id] >= priv->index_malloc_size[stream_id]) { if (priv->index_malloc_size[stream_id] == 0)