[vlc-commits] xiph: rewrite ParseFlacPicture() w/o integer overflows (fixes #17592)

Rémi Denis-Courmont git at videolan.org
Tue Nov 1 15:30:26 CET 2016


vlc/vlc-2.2 | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Tue Nov  1 16:27:30 2016 +0200| [c6afb1a6bd64669fc2f09971a7e35a8566d7ba21] | committer: Rémi Denis-Courmont

xiph: rewrite ParseFlacPicture() w/o integer overflows (fixes #17592)

(cherry picked from commit d076af4e46cdb25d2b33494fa57d444ceb591ae3)

> http://git.videolan.org/gitweb.cgi/vlc/vlc-2.2.git/?a=commit;h=c6afb1a6bd64669fc2f09971a7e35a8566d7ba21
---

 modules/demux/xiph_metadata.c | 112 +++++++++++++++++++++++++++++-------------
 modules/demux/xiph_metadata.h |   2 +-
 2 files changed, 79 insertions(+), 35 deletions(-)

diff --git a/modules/demux/xiph_metadata.c b/modules/demux/xiph_metadata.c
index e4ef767..f68d5e0 100644
--- a/modules/demux/xiph_metadata.c
+++ b/modules/demux/xiph_metadata.c
@@ -26,13 +26,15 @@
 # include "config.h"
 #endif
 
+#include <assert.h>
+
 #include <vlc_common.h>
 #include <vlc_charset.h>
 #include <vlc_strings.h>
 #include <vlc_input.h>
 #include "xiph_metadata.h"
 
-input_attachment_t* ParseFlacPicture( const uint8_t *p_data, int i_data,
+input_attachment_t* ParseFlacPicture( const uint8_t *p_data, size_t size,
     int i_attachments, int *i_cover_score, int *i_cover_idx )
 {
     /* TODO: Merge with ID3v2 copy in modules/meta_engine/taglib.cpp. */
@@ -60,58 +62,100 @@ input_attachment_t* ParseFlacPicture( const uint8_t *p_data, int i_data,
         2   /* Logo of the publisher (record company). */
     };
 
-    int i_len;
-    int i_type;
-    char *psz_mime = NULL;
-    char psz_name[128];
-    char *psz_description = NULL;
-    input_attachment_t *p_attachment = NULL;
+    uint32_t type, len;
+
+    if( size < 8 )
+        return NULL;
+#define RM(x) \
+    do { \
+        assert(size >= (x)); \
+        size -= (x); \
+        p_data += (x); \
+    } while (0)
+
+    type = GetDWBE( p_data );
+    RM(4);
+    len = GetDWBE( p_data );
+    RM(4);
+
+    if( size < len )
+        return NULL;
+
+    char *mime = strndup( (const char *)p_data, len );
+    if( unlikely(mime == NULL) )
+        return NULL;
+    RM(len);
 
-    if( i_data < 4 + 3*4 )
+    if( size < 4 )
+    {
+        free( mime );
         return NULL;
-#define RM(x) do { i_data -= (x); p_data += (x); } while(0)
+    }
 
-    i_type = GetDWBE( p_data ); RM(4);
-    i_len = GetDWBE( p_data ); RM(4);
+    len = GetDWBE( p_data );
+    RM(4);
+
+    if( size < len )
+    {
+        free( mime );
+        return NULL;
+    }
 
-    if( i_len < 0 || i_data < i_len + 4 )
+    input_attachment_t *p_attachment = NULL;
+    char *description = strndup( (const char *)p_data, len );
+    if( unlikely(description == NULL) )
         goto error;
-    psz_mime = strndup( (const char*)p_data, i_len ); RM(i_len);
-    i_len = GetDWBE( p_data ); RM(4);
-    if( i_len < 0 || i_data < i_len + 4*4 + 4)
+    RM(len);
+
+    EnsureUTF8( description );
+
+    if( size < 20 )
         goto error;
-    psz_description = strndup( (const char*)p_data, i_len ); RM(i_len);
-    EnsureUTF8( psz_description );
-    RM(4*4);
-    i_len = GetDWBE( p_data ); RM(4);
-    if( i_len < 0 || i_len > i_data )
+
+    RM(4 * 4); /* skip */
+
+    len = GetDWBE( p_data );
+    RM(4);
+
+    if( size < len )
         goto error;
 
-    /* printf( "Picture type=%d mime=%s description='%s' file length=%d\n",
-             i_type, psz_mime, psz_description, i_len ); */
+    /* printf( "Picture type=%"PRIu32" mime=%s description='%s' "
+               "file length=%zu\n", type, mime, description, len ); */
+
+    char name[7 + (sizeof (i_attachments) * 3) + 4 + 1];
+
+    snprintf( name, sizeof (name), "picture%u", i_attachments );
 
-    snprintf( psz_name, sizeof(psz_name), "picture%d", i_attachments );
-    if( !strcasecmp( psz_mime, "image/jpeg" ) )
-        strcat( psz_name, ".jpg" );
-    else if( !strcasecmp( psz_mime, "image/png" ) )
-        strcat( psz_name, ".png" );
+    if( !strcasecmp( mime, "image/jpeg" ) )
+        strcat( name, ".jpg" );
+    else if( !strcasecmp( mime, "image/png" ) )
+        strcat( name, ".png" );
 
-    p_attachment = vlc_input_attachment_New( psz_name, psz_mime,
-            psz_description, p_data, i_data );
+    p_attachment = vlc_input_attachment_New( name, mime, description, p_data,
+                                             size /* XXX: len instead? */ );
 
-    if( i_type >= 0 && (unsigned int)i_type < sizeof(pi_cover_score)/sizeof(pi_cover_score[0]) &&
-        *i_cover_score < pi_cover_score[i_type] )
+    if( type < sizeof(pi_cover_score)/sizeof(pi_cover_score[0]) &&
+        *i_cover_score < pi_cover_score[type] )
     {
         *i_cover_idx = i_attachments;
-        *i_cover_score = pi_cover_score[i_type];
+        *i_cover_score = pi_cover_score[type];
     }
 
 error:
-    free( psz_mime );
-    free( psz_description );
+    free( mime );
+    free( description );
     return p_attachment;
 }
 
+#undef RM
+#define RM(x) \
+    do { \
+        i_data -= (x); \
+        p_data += (x); \
+    } while (0)
+
+
 typedef struct chapters_array_t
 {
     unsigned int i_size;
diff --git a/modules/demux/xiph_metadata.h b/modules/demux/xiph_metadata.h
index 7a152b1..dc06760 100644
--- a/modules/demux/xiph_metadata.h
+++ b/modules/demux/xiph_metadata.h
@@ -29,7 +29,7 @@
 extern "C" {
 # endif
 
-input_attachment_t* ParseFlacPicture( const uint8_t *p_data, int i_data,
+input_attachment_t* ParseFlacPicture( const uint8_t *p_data, size_t i_data,
     int i_attachments, int *i_cover_score, int *i_cover_idx );
 
 void vorbis_ParseComment( es_format_t *p_fmt, vlc_meta_t **pp_meta,



More information about the vlc-commits mailing list