[vlc-devel] [PATCH] asf: fix error handling in codec_list

RĂ©mi Denis-Courmont remi at remlab.net
Sat Nov 11 14:45:23 CET 2017


Use a linked list rather than a large table, and actually handle errors
as errors.
---
 modules/demux/asf/libasf.c | 125 ++++++++++++++++++++++-----------------------
 modules/demux/asf/libasf.h |   7 +--
 2 files changed, 66 insertions(+), 66 deletions(-)

diff --git a/modules/demux/asf/libasf.c b/modules/demux/asf/libasf.c
index edcfcde9df..b115ddb84f 100644
--- a/modules/demux/asf/libasf.c
+++ b/modules/demux/asf/libasf.c
@@ -629,6 +629,21 @@ static void ASF_FreeObject_stream_properties( asf_object_t *p_obj )
     FREENULL( p_sp->p_error_correction_data );
 }
 
+static void ASF_FreeObject_codec_list( asf_object_t *p_obj )
+{
+    asf_object_codec_list_t *p_cl = &p_obj->codec_list;
+
+    for( asf_codec_entry_t *codec = p_cl->codecs, *next;
+         codec != NULL;
+         codec = next )
+    {
+        next = codec->p_next;
+        free( codec->psz_name );
+        free( codec->psz_description );
+        free( codec->p_information );
+        free( codec );
+    }
+}
 
 static int ASF_ReadObject_codec_list( stream_t *s, asf_object_t *p_obj )
 {
@@ -636,92 +651,76 @@ static int ASF_ReadObject_codec_list( stream_t *s, asf_object_t *p_obj )
     ssize_t   i_peek;
     const uint8_t *p_peek, *p_data;
 
-    uint32_t i_codec;
-
     if( ( i_peek = vlc_stream_Peek( s, &p_peek, p_cl->i_object_size ) ) < 44 )
        return VLC_EGENERIC;
 
     ASF_GetGUID( &p_cl->i_reserved, p_peek + ASF_OBJECT_COMMON_SIZE );
-    p_cl->i_codec_entries_count = GetDWLE( p_peek + 40 );
+    uint32_t count = GetDWLE( p_peek + 40 );
+#ifdef ASF_DEBUG
+    msg_Dbg( s, "read \"codec list object\" reserved_guid:" GUID_FMT
+             " codec_entries_count:%d", GUID_PRINT( p_cl->i_reserved ),
+             count );
+#endif
 
     p_data = p_peek + 44;
 
-    if( p_cl->i_codec_entries_count > 0 )
+    asf_codec_entry_t **pp = &p_cl->codecs;
+
+    for( uint32_t i = 0; i < count; i++ )
     {
-        p_cl->codec = calloc( p_cl->i_codec_entries_count,
-                              sizeof( asf_codec_entry_t ) );
-        if( !p_cl->codec )
-            return VLC_ENOMEM;
+        asf_codec_entry_t *p_codec = malloc( sizeof( *p_codec ) );
 
-        for( i_codec = 0; i_codec < p_cl->i_codec_entries_count; i_codec++ )
+        if( unlikely(p_codec == NULL) || !ASF_HAVE( 2+2+2 ) )
         {
-            asf_codec_entry_t *p_codec = &p_cl->codec[i_codec];
-
-            if( !ASF_HAVE( 2+2+2 ) )
-                break;
+            free( p_codec );
+            *pp = NULL;
+            goto error;
+        }
 
-            /* */
-            p_codec->i_type = ASF_READ2();
+        /* */
+        p_codec->i_type = ASF_READ2();
 
-            /* XXX the length here are the number of *unicode* characters and
-             * not of bytes like nearly every elsewhere */
+        /* XXX the length here are the number of *unicode* characters and
+         * not of bytes like nearly every elsewhere */
 
-            /* codec name */
-            p_codec->psz_name = ASF_READS( 2*ASF_READ2() );
+        /* codec name */
+        p_codec->psz_name = ASF_READS( 2*ASF_READ2() );
 
-            /* description */
-            p_codec->psz_description = ASF_READS( 2*ASF_READ2() );
+        /* description */
+        p_codec->psz_description = ASF_READS( 2*ASF_READ2() );
 
-            /* opaque information */
-            p_codec->i_information_length = ASF_READ2();
-            if( p_codec->i_information_length > 0 && ASF_HAVE( p_codec->i_information_length ) )
-            {
-                p_codec->p_information = malloc( p_codec->i_information_length );
-                if( p_codec->p_information )
-                    memcpy( p_codec->p_information, p_data, p_codec->i_information_length );
-                else
-                    p_codec->i_information_length = 0;
-                p_data += p_codec->i_information_length;
-            }
+        /* opaque information */
+        p_codec->i_information_length = ASF_READ2();
+        if( ASF_HAVE( p_codec->i_information_length ) )
+        {
+            p_codec->p_information = malloc( p_codec->i_information_length );
+            if( unlikely(p_codec->p_information == NULL
+                      && p_codec->i_information_length > 0) )
+                goto error;
+
+            memcpy( p_codec->p_information, p_data,
+                    p_codec->i_information_length );
+            p_data += p_codec->i_information_length;
         }
-        p_cl->i_codec_entries_count = i_codec;
-    }
 
 #ifdef ASF_DEBUG
-    msg_Dbg( s, "read \"codec list object\" reserved_guid:" GUID_FMT
-             " codec_entries_count:%d",
-            GUID_PRINT( p_cl->i_reserved ), p_cl->i_codec_entries_count );
-
-    for( i_codec = 0; i_codec < p_cl->i_codec_entries_count; i_codec++ )
-    {
-        const asf_codec_entry_t *p_codec = &p_cl->codec[i_codec];
-
         msg_Dbg( s, "  - codec[%"PRIu32"] %s name:\"%s\" "
-                 "description:\"%s\" information_length:%u",
-                 i_codec, ( p_codec->i_type == ASF_CODEC_TYPE_VIDEO ) ?
-                 "video" : ( ( p_codec->i_type == ASF_CODEC_TYPE_AUDIO ) ?
-                 "audio" : "unknown" ),
-                 p_codec->psz_name, p_codec->psz_description,
-                 p_codec->i_information_length );
-    }
+                 "description:\"%s\" information_length:%u", i,
+                 ( p_codec->i_type == ASF_CODEC_TYPE_VIDEO ) ? "video"
+                 : ( ( p_codec->i_type == ASF_CODEC_TYPE_AUDIO ) ? "audio"
+                 : "unknown" ), p_codec->psz_name,
+                 p_codec->psz_description, p_codec->i_information_length );
 #endif
+        *pp = p_codec;
+        pp = &p_codec->p_next;
+    }
 
+    *pp = NULL;
     return VLC_SUCCESS;
-}
-
-static void ASF_FreeObject_codec_list( asf_object_t *p_obj )
-{
-    asf_object_codec_list_t *p_cl = &p_obj->codec_list;
-
-    for( uint32_t i_codec = 0; i_codec < p_cl->i_codec_entries_count; i_codec++ )
-    {
-        asf_codec_entry_t *p_codec = &p_cl->codec[i_codec];
 
-        FREENULL( p_codec->psz_name );
-        FREENULL( p_codec->psz_description );
-        FREENULL( p_codec->p_information );
-    }
-    FREENULL( p_cl->codec );
+error:
+    ASF_FreeObject_codec_list( p_obj );
+    return VLC_EGENERIC;
 }
 
 static inline char *get_wstring( const uint8_t *p_data, size_t i_size )
diff --git a/modules/demux/asf/libasf.h b/modules/demux/asf/libasf.h
index b6079eb5da..c483b5f28b 100644
--- a/modules/demux/asf/libasf.h
+++ b/modules/demux/asf/libasf.h
@@ -189,7 +189,7 @@ typedef struct
 #define ASF_CODEC_TYPE_AUDIO    0x0002
 #define ASF_CODEC_TYPE_UNKNOWN  0xffff
 
-typedef struct
+typedef struct asf_codec_entry
 {
     uint16_t    i_type;
     char        *psz_name;
@@ -197,14 +197,15 @@ typedef struct
 
     uint16_t    i_information_length;
     uint8_t     *p_information;
+
+    struct asf_codec_entry *p_next;
 } asf_codec_entry_t;
 
 typedef struct
 {
     ASF_OBJECT_COMMON
     guid_t      i_reserved;
-    uint32_t    i_codec_entries_count;
-    asf_codec_entry_t *codec;
+    asf_codec_entry_t *codecs;
 
 } asf_object_codec_list_t;
 
-- 
2.15.0



More information about the vlc-devel mailing list