[MPlayer-cvslog] r32357 - in branches/1.0rc4: . libmpdemux/demux_mkv.c

siretart subversion at mplayerhq.hu
Sun Sep 26 11:34:50 CEST 2010


Author: siretart
Date: Sun Sep 26 11:34:50 2010
New Revision: 32357

Log:
Add many integer overflow checks to mkv demuxer.
Patch by Yuriy Kaminskiy [yumkam mail ru] with some
minor modifications by me.

backport r32304 by reimar

Modified:
   branches/1.0rc4/   (props changed)
   branches/1.0rc4/libmpdemux/demux_mkv.c

Modified: branches/1.0rc4/libmpdemux/demux_mkv.c
==============================================================================
--- branches/1.0rc4/libmpdemux/demux_mkv.c	Sun Sep 26 10:45:40 2010	(r32356)
+++ branches/1.0rc4/libmpdemux/demux_mkv.c	Sun Sep 26 11:34:50 2010	(r32357)
@@ -84,7 +84,7 @@ typedef struct {
     uint32_t order, type, scope;
     uint32_t comp_algo;
     uint8_t *comp_settings;
-    int comp_settings_len;
+    size_t comp_settings_len;
 } mkv_content_encoding_t;
 
 typedef struct mkv_track {
@@ -109,7 +109,7 @@ typedef struct mkv_track {
     int default_track;
 
     void *private_data;
-    unsigned int private_size;
+    size_t private_size;
 
     /* stuff for realmedia */
     int realmedia;
@@ -291,7 +291,7 @@ static void free_cached_dps(demuxer_t *d
 }
 
 static int demux_mkv_decode(mkv_track_t *track, uint8_t *src,
-                            uint8_t **dest, uint32_t *size, uint32_t type)
+                            uint8_t **dest, size_t *size, uint32_t type)
 {
     int i, result;
     int modified = 0;
@@ -324,11 +324,15 @@ static int demux_mkv_decode(mkv_track_t 
             *dest = NULL;
             zstream.avail_out = *size;
             do {
+                if (*size > SIZE_MAX - 4000)
+                    goto zlib_fail;
+
                 *size += 4000;
                 *dest = realloc(*dest, *size);
                 zstream.next_out = (Bytef *) (*dest + zstream.total_out);
                 result = inflate(&zstream, Z_NO_FLUSH);
                 if (result != Z_OK && result != Z_STREAM_END) {
+zlib_fail:
                     mp_msg(MSGT_DEMUX, MSGL_WARN,
                            MSGTR_MPDEMUX_MKV_ZlibDecompressionFailed);
                     free(*dest);
@@ -346,7 +350,7 @@ static int demux_mkv_decode(mkv_track_t 
 #endif
         if (track->encodings[i].comp_algo == 2) {
             /* lzo encoded track */
-            int dstlen = *size * 3;
+            int dstlen = *size > SIZE_MAX/3 ? *size : *size * 3;
 
             *dest = NULL;
             while (1) {
@@ -367,6 +371,8 @@ static int demux_mkv_decode(mkv_track_t 
                 }
                 mp_msg(MSGT_DEMUX, MSGL_DBG2,
                        "[mkv] lzo decompression buffer too small.\n");
+                if (dstlen > (SIZE_MAX - AV_LZO_OUTPUT_PADDING)/2)
+                    goto lzo_fail;
                 dstlen *= 2;
             }
             *size = dstlen;
@@ -508,6 +514,8 @@ static int demux_mkv_read_trackencodings
 
                         case MATROSKA_ID_CONTENTCOMPSETTINGS:
                             l = ebml_read_length(s, &i);
+                            if (l > SIZE_MAX)
+                                goto err_out;
                             e.comp_settings = malloc(l);
                             stream_read(s, e.comp_settings, l);
                             e.comp_settings_len = l;
@@ -1233,6 +1241,8 @@ static int demux_mkv_read_attachments(de
                     uint64_t num = ebml_read_length(s, &x);
                     l = x + num;
                     free(data);
+                    if (num > SIZE_MAX)
+                        return 0;
                     data = malloc(num);
                     if (stream_read(s, data, num) != (int) num) {
                         free(data);
@@ -1286,6 +1296,9 @@ static int demux_mkv_read_seekhead(demux
             ebml_read_skip(s, NULL);
             return 0;
         }
+    if (mkv_d->parsed_seekhead_num >= INT_MAX ||
+        mkv_d->parsed_seekhead_num > SIZE_MAX/sizeof(off_t))
+        return 0;
     mkv_d->parsed_seekhead = realloc(mkv_d->parsed_seekhead,
                                      (mkv_d->parsed_seekhead_num + 1)
                                      * sizeof(off_t));
@@ -1476,7 +1489,8 @@ static int demux_mkv_open_video(demuxer_
         BITMAPINFOHEADER *src;
 
         if (track->private_data == NULL
-            || track->private_size < sizeof(BITMAPINFOHEADER))
+            || track->private_size >= INT_MAX - 1000
+            || track->private_size < sizeof(*bih))
             return 1;
 
         src = (BITMAPINFOHEADER *) track->private_data;
@@ -1515,12 +1529,16 @@ static int demux_mkv_open_video(demuxer_
                 || !strcmp(track->codec_id, MKV_V_REALV40))) {
             unsigned char *dst, *src;
             uint32_t type2;
-            unsigned int cnt;
+            size_t cnt;
 
             src = (uint8_t *) track->private_data + RVPROPERTIES_SIZE;
 
             cnt = track->private_size - RVPROPERTIES_SIZE;
-            bih = realloc(bih, sizeof(BITMAPINFOHEADER) + 8 + cnt);
+            if (cnt > INT_MAX - sizeof(*bih) - 8) {
+                mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] Integer overflow!\n");
+                return 1;
+            }
+            bih = realloc(bih, sizeof(*bih) + 8 + cnt);
             bih->biSize = 48 + cnt;
             bih->biPlanes = 1;
             type2 = AV_RB32(src - 4);
@@ -1628,6 +1646,11 @@ static int demux_mkv_open_audio(demuxer_
     sh_a->wf = malloc(sizeof(WAVEFORMATEX));
     if (track->ms_compat && (track->private_size >= sizeof(WAVEFORMATEX))) {
         WAVEFORMATEX *wf = (WAVEFORMATEX *) track->private_data;
+        if (track->private_size > USHRT_MAX + sizeof(WAVEFORMATEX)) {
+            mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] Integer overflow!\n");
+            free_sh_audio(demuxer, track->tnum);
+            return 1;
+        }
         sh_a->wf = realloc(sh_a->wf, track->private_size);
         sh_a->wf->wFormatTag = le2me_16(wf->wFormatTag);
         sh_a->wf->nChannels = le2me_16(wf->nChannels);
@@ -1738,6 +1761,11 @@ static int demux_mkv_open_audio(demuxer_
         track->fix_i_bps = 1;
         track->qt_last_a_pts = 0.0;
         if (track->private_data != NULL) {
+            if (track->private_size > INT_MAX) {
+                mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] Integer overflow!\n");
+                free_sh_audio(demuxer, track->tnum);
+                return 1;
+            }
             sh_a->codecdata = malloc(track->private_size);
             memcpy(sh_a->codecdata, track->private_data, track->private_size);
             sh_a->codecdata_len = track->private_size;
@@ -1750,6 +1778,11 @@ static int demux_mkv_open_audio(demuxer_
 
         if (!strcmp(track->codec_id, MKV_A_AAC)
             && (NULL != track->private_data)) {
+            if (track->private_size > INT_MAX) {
+                mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] Integer overflow!\n");
+                free_sh_audio(demuxer, track->tnum);
+                return 1;
+            }
             sh_a->codecdata = malloc(track->private_size);
             memcpy(sh_a->codecdata, track->private_data, track->private_size);
             sh_a->codecdata_len = track->private_size;
@@ -1788,6 +1821,11 @@ static int demux_mkv_open_audio(demuxer_
             track->default_duration = 1024.0 / (float) sh_a->samplerate;
         }
     } else if (track->a_formattag == mmioFOURCC('v', 'r', 'b', 's')) {  /* VORBIS */
+        if (track->private_size > USHRT_MAX) {
+            mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] Integer overflow!\n");
+            free_sh_audio(demuxer, track->tnum);
+            return 1;
+        }
         sh_a->wf->cbSize = track->private_size;
         sh_a->wf = realloc(sh_a->wf, sizeof(WAVEFORMATEX) + sh_a->wf->cbSize);
         memcpy((unsigned char *) (sh_a->wf + 1), track->private_data,
@@ -1862,7 +1900,7 @@ static int demux_mkv_open_audio(demuxer_
     } else if (!strcmp(track->codec_id, MKV_A_FLAC)
                || (track->a_formattag == 0xf1ac)) {
         unsigned char *ptr;
-        int size;
+        size_t size;
         free(sh_a->wf);
         sh_a->wf = NULL;
 
@@ -1901,7 +1939,8 @@ static int demux_mkv_open_sub(demuxer_t 
                               int sid)
 {
     if (track->subtitle_type != MATROSKA_SUBTYPE_UNKNOWN) {
-        int size, m;
+        size_t size;
+        int m;
         uint8_t *buffer;
         sh_sub_t *sh = new_sh_sub_sid(demuxer, track->tnum, sid);
         track->sh_sub = sh;
@@ -1917,6 +1956,10 @@ static int demux_mkv_open_sub(demuxer_t 
             track->private_data = buffer;
             track->private_size = size;
         }
+        if (track->private_size > INT_MAX) {
+            mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] Integer overflow!\n");
+            return 1;
+        }
         sh->extradata = malloc(track->private_size);
         memcpy(sh->extradata, track->private_data, track->private_size);
         sh->extradata_len = track->private_size;
@@ -2584,7 +2627,8 @@ static int handle_block(demuxer_t *demux
                 handle_video_bframes(demuxer, track, block, lace_size[i],
                                      block_bref, block_fref);
             else {
-                int modified, size = lace_size[i];
+                int modified;
+                size_t size = lace_size[i];
                 demux_packet_t *dp;
                 uint8_t *buffer;
                 modified = demux_mkv_decode(track, block, &buffer, &size, 1);
@@ -2721,6 +2765,8 @@ static int demux_mkv_fill_buffer(demuxer
                 {
                     int res;
                     block_length = ebml_read_length(s, &tmp);
+                    if (block_length > SIZE_MAX)
+                        return 0;
                     block = malloc(block_length);
                     demuxer->filepos = stream_tell(s);
                     if (stream_read(s, block, block_length) !=


More information about the MPlayer-cvslog mailing list