[vlc-commits] demux: libavi: force chunk type check

Francois Cartegnie git at videolan.org
Tue Nov 21 18:32:58 CET 2017


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Tue Nov 21 15:57:26 2017 +0100| [2be0155e2895ad45d6f8bae3e1e8ef712182a57c] | committer: Francois Cartegnie

demux: libavi: force chunk type check

avi breakable since 2002 by mutating single chunks as LIST

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

 modules/demux/avi/avi.c    | 66 +++++++++++++++++++++++-----------------------
 modules/demux/avi/libavi.c | 63 +++++++++++++++++++------------------------
 modules/demux/avi/libavi.h | 12 ++++-----
 3 files changed, 66 insertions(+), 75 deletions(-)

diff --git a/modules/demux/avi/avi.c b/modules/demux/avi/avi.c
index a769a07a75..4193e38bf2 100644
--- a/modules/demux/avi/avi.c
+++ b/modules/demux/avi/avi.c
@@ -350,17 +350,17 @@ static int Open( vlc_object_t * p_this )
         return VLC_EGENERIC;
     }
 
-    if( AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF ) > 1 )
+    if( AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF, true ) > 1 )
     {
         unsigned int i_count =
-            AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF );
+            AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF, true );
 
         msg_Warn( p_demux, "multiple riff -> OpenDML ?" );
         for( unsigned i = 1; i < i_count; i++ )
         {
             avi_chunk_list_t *p_sysx;
 
-            p_sysx = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, i );
+            p_sysx = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, i, true );
             if( p_sysx->i_type == AVIFOURCC_AVIX )
             {
                 msg_Warn( p_demux, "detected OpenDML file" );
@@ -370,11 +370,11 @@ static int Open( vlc_object_t * p_this )
         }
     }
 
-    p_riff  = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0 );
-    p_hdrl  = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );
-    p_movi  = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0 );
+    p_riff  = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0, true );
+    p_hdrl  = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0, true );
+    p_movi  = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0, true );
     if( !p_movi )
-        p_movi  = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_movi, 0 );
+        p_movi  = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_movi, 0, true );
 
     if( !p_hdrl || !p_movi )
     {
@@ -382,12 +382,12 @@ static int Open( vlc_object_t * p_this )
         goto error;
     }
 
-    if( !( p_avih = AVI_ChunkFind( p_hdrl, AVIFOURCC_avih, 0 ) ) )
+    if( !( p_avih = AVI_ChunkFind( p_hdrl, AVIFOURCC_avih, 0, false ) ) )
     {
         msg_Err( p_demux, "invalid file: cannot find avih chunk" );
         goto error;
     }
-    i_track = AVI_ChunkCount( p_hdrl, AVIFOURCC_strl );
+    i_track = AVI_ChunkCount( p_hdrl, AVIFOURCC_strl, true );
     if( p_avih->i_streams != i_track )
     {
         msg_Warn( p_demux,
@@ -426,16 +426,16 @@ static int Open( vlc_object_t * p_this )
         if( unlikely( !tk ) )
             goto error;
 
-        avi_chunk_list_t      *p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );
-        avi_chunk_strh_t      *p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0 );
-        avi_chunk_STRING_t    *p_strn = AVI_ChunkFind( p_strl, AVIFOURCC_strn, 0 );
+        avi_chunk_list_t      *p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i, true );
+        avi_chunk_strh_t      *p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0, false );
+        avi_chunk_STRING_t    *p_strn = AVI_ChunkFind( p_strl, AVIFOURCC_strn, 0, false );
         avi_chunk_strf_auds_t *p_auds = NULL;
         avi_chunk_strf_vids_t *p_vids = NULL;
 
         tk->b_eof = false;
         tk->b_activated = true;
 
-        p_vids = (avi_chunk_strf_vids_t*)AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 );
+        p_vids = (avi_chunk_strf_vids_t*)AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0, false );
         p_auds = (avi_chunk_strf_auds_t*)p_vids;
 
         if( p_strl == NULL || p_strh == NULL || p_vids == NULL )
@@ -515,11 +515,11 @@ static int Open( vlc_object_t * p_this )
                 tk->fmt.audio.i_bitspersample   = p_auds->p_wf->wBitsPerSample;
                 tk->fmt.b_packetized            = !tk->i_blocksize;
 
-                avi_chunk_list_t *p_info = AVI_ChunkFind( p_riff, AVIFOURCC_INFO, 0 );
+                avi_chunk_list_t *p_info = AVI_ChunkFind( p_riff, AVIFOURCC_INFO, 0, true );
                 if( p_info )
                 {
                     int i_chunk = AVIFOURCC_IAS1 + ((i - 1) << 24);
-                    avi_chunk_STRING_t *p_lang = AVI_ChunkFind( p_info, i_chunk, 0 );
+                    avi_chunk_STRING_t *p_lang = AVI_ChunkFind( p_info, i_chunk, 0, false );
                     if( p_lang != NULL && p_lang->p_str != NULL )
                         tk->fmt.psz_language = FromACP( p_lang->p_str );
                 }
@@ -651,7 +651,7 @@ static int Open( vlc_object_t * p_this )
                     tk->fmt.video.i_height =
                         (unsigned int)(-(int)p_vids->p_bih->biHeight);
 
-                avi_chunk_vprp_t *p_vprp = AVI_ChunkFind( p_strl, AVIFOURCC_vprp, 0 );
+                avi_chunk_vprp_t *p_vprp = AVI_ChunkFind( p_strl, AVIFOURCC_vprp, 0, false );
                 if( p_vprp )
                 {
                     uint32_t i_frame_aspect_ratio = p_vprp->i_frame_aspect_ratio;
@@ -848,8 +848,8 @@ aviindex:
         {
             continue;
         }
-        p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );
-        p_auds = AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 );
+        p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i, true );
+        p_auds = AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0, false );
 
         if( p_auds->p_wf->wFormatTag != WAVE_FORMAT_PCM &&
             tk->i_rate == p_auds->p_wf->nSamplesPerSec )
@@ -1512,7 +1512,7 @@ static int Seek( demux_t *p_demux, mtime_t i_date, int i_percent, bool b_accurat
         /* Check and lazy load indexes if it was not done (not fastseekable) */
         if ( !p_sys->b_indexloaded && ( p_sys->i_avih_flags & AVIF_HASINDEX ) )
         {
-            avi_chunk_t *p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0 );
+            avi_chunk_t *p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0, true );
             if (unlikely( !p_riff ))
                 return VLC_EGENERIC;
 
@@ -2370,8 +2370,8 @@ static int AVI_IndexFind_idx1( demux_t *p_demux,
 {
     demux_sys_t *p_sys = p_demux->p_sys;
 
-    avi_chunk_list_t *p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0);
-    avi_chunk_idx1_t *p_idx1 = AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0);
+    avi_chunk_list_t *p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0, true);
+    avi_chunk_idx1_t *p_idx1 = AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0, false);
 
     if( !p_idx1 )
     {
@@ -2385,7 +2385,7 @@ static int AVI_IndexFind_idx1( demux_t *p_demux,
      * checking the offset of the first packet is not enough as some files
      * has unused chunk at the beginning of the movi content.
      */
-    avi_chunk_list_t *p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
+    avi_chunk_list_t *p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0, true );
     uint64_t i_first_pos = UINT64_MAX;
     for( unsigned i = 0; i < __MIN( p_idx1->i_entry_count, 100 ); i++ )
     {
@@ -2532,8 +2532,8 @@ static void AVI_IndexLoad_indx( demux_t *p_demux,
     avi_chunk_list_t    *p_riff;
     avi_chunk_list_t    *p_hdrl;
 
-    p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0);
-    p_hdrl = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );
+    p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0, true);
+    p_hdrl = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0, true );
 
     for( unsigned i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
     {
@@ -2541,8 +2541,8 @@ static void AVI_IndexLoad_indx( demux_t *p_demux,
         avi_chunk_indx_t    *p_indx;
 
 #define p_stream  p_sys->track[i_stream]
-        p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i_stream );
-        p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0 );
+        p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i_stream, true );
+        p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0, false );
 
         if( !p_indx )
         {
@@ -2654,8 +2654,8 @@ static void AVI_IndexCreate( demux_t *p_demux )
     mtime_t i_dialog_update;
     vlc_dialog_id *p_dialog_id = NULL;
 
-    p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0);
-    p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
+    p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0, true );
+    p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0, true );
 
     if( !p_movi )
     {
@@ -2726,7 +2726,7 @@ static void AVI_IndexCreate( demux_t *p_demux )
                 {
                     avi_chunk_list_t *p_sysx;
                     p_sysx = AVI_ChunkFind( &p_sys->ck_root,
-                                            AVIFOURCC_RIFF, 1 );
+                                            AVIFOURCC_RIFF, 1, true );
 
                     msg_Dbg( p_demux, "looking for new RIFF chunk" );
                     if( vlc_stream_Seek( p_demux->s,
@@ -2790,7 +2790,7 @@ static void AVI_MetaLoad( demux_t *p_demux,
               p_avih->i_flags&AVIF_TRUSTCKTYPE   ? " TRUST_CKTYPE"   : "" );
     vlc_meta_SetSetting( p_meta, buffer );
 
-    avi_chunk_list_t *p_info = AVI_ChunkFind( p_riff, AVIFOURCC_INFO, 0 );
+    avi_chunk_list_t *p_info = AVI_ChunkFind( p_riff, AVIFOURCC_INFO, 0, true );
     if( !p_info )
         return;
 
@@ -2813,7 +2813,7 @@ static void AVI_MetaLoad( demux_t *p_demux,
     };
     for( int i = 0; p_dsc[i].i_id != 0; i++ )
     {
-        avi_chunk_STRING_t *p_strz = AVI_ChunkFind( p_info, p_dsc[i].i_id, 0 );
+        avi_chunk_STRING_t *p_strz = AVI_ChunkFind( p_info, p_dsc[i].i_id, 0, false );
         if( !p_strz || !p_strz->p_str )
             continue;
         char *psz_value = FromACP( p_strz->p_str );
@@ -2837,7 +2837,7 @@ static void AVI_MetaLoad( demux_t *p_demux,
 
     for( int i = 0; p_extra[i] != 0; i++ )
     {
-        avi_chunk_STRING_t *p_strz = AVI_ChunkFind( p_info, p_extra[i], 0 );
+        avi_chunk_STRING_t *p_strz = AVI_ChunkFind( p_info, p_extra[i], 0, false );
         if( !p_strz || !p_strz->p_str )
             continue;
         char *psz_value = FromACP( p_strz->p_str );
@@ -2901,7 +2901,7 @@ static void AVI_ExtractSubtitle( demux_t *p_demux,
     if( !p_sys->b_seekable )
         goto exit;
 
-    p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0 );
+    p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0, false );
     avi_chunk_t ck;
     int64_t  i_position;
     unsigned i_size;
diff --git a/modules/demux/avi/libavi.c b/modules/demux/avi/libavi.c
index 8a9e844165..e529348b57 100644
--- a/modules/demux/avi/libavi.c
+++ b/modules/demux/avi/libavi.c
@@ -230,7 +230,7 @@ static int AVI_ChunkRead_list( stream_t *s, avi_chunk_t *p_container )
 /* Allow to append indexes after starting playback */
 int AVI_ChunkFetchIndexes( stream_t *s, avi_chunk_t *p_riff )
 {
-    avi_chunk_t *p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0 );
+    avi_chunk_t *p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0, true );
     if ( !p_movi )
         return VLC_EGENERIC;
 
@@ -413,7 +413,7 @@ static int AVI_ChunkRead_strf( stream_t *s, avi_chunk_t *p_chk )
         msg_Err( (vlc_object_t*)s, "malformed avi file" );
         AVI_READCHUNK_EXIT( VLC_EGENERIC );
     }
-    if( !( p_strh = AVI_ChunkFind( p_chk->common.p_father, AVIFOURCC_strh, 0 ) ) )
+    if( !( p_strh = AVI_ChunkFind( p_chk->common.p_father, AVIFOURCC_strh, 0, false ) ) )
     {
         msg_Err( (vlc_object_t*)s, "malformed avi file" );
         AVI_READCHUNK_EXIT( p_chk->common.i_chunk_size > 0  ? VLC_EGENERIC : AVI_ZEROSIZED_CHUNK );
@@ -1168,57 +1168,48 @@ void AVI_ChunkFreeRoot( stream_t *s,
 }
 
 
-int  AVI_ChunkCount_( avi_chunk_t *p_chk, vlc_fourcc_t i_fourcc )
+int  AVI_ChunkCount_( avi_chunk_t *p_chk, vlc_fourcc_t i_fourcc, bool b_list )
 {
-    int i_count;
-    avi_chunk_t *p_child;
-
     if( !p_chk )
-    {
         return 0;
-    }
 
-    i_count = 0;
-    p_child = p_chk->common.p_first;
-    while( p_child )
+    int i_count = 0;
+    for( avi_chunk_t *p_child = p_chk->common.p_first;
+                      p_child; p_child = p_child->common.p_next )
     {
-        if( p_child->common.i_chunk_fourcc == i_fourcc ||
-            ( p_child->common.i_chunk_fourcc == AVIFOURCC_LIST &&
-              p_child->list.i_type == i_fourcc ) )
-        {
-            i_count++;
-        }
-        p_child = p_child->common.p_next;
+        if( b_list && p_child->list.i_type == 0 )
+            continue;
+
+        if( p_child->common.i_chunk_fourcc != i_fourcc &&
+            p_child->list.i_type != i_fourcc )
+            continue;
+
+        i_count++;
     }
+
     return i_count;
 }
 
 void *AVI_ChunkFind_( avi_chunk_t *p_chk,
-                      vlc_fourcc_t i_fourcc, int i_number )
+                      vlc_fourcc_t i_fourcc, int i_number, bool b_list )
 {
-    avi_chunk_t *p_child;
     if( !p_chk )
-    {
         return NULL;
-    }
-    p_child = p_chk->common.p_first;
 
-    while( p_child )
+    for( avi_chunk_t *p_child = p_chk->common.p_first;
+                      p_child; p_child = p_child->common.p_next )
     {
-        if( p_child->common.i_chunk_fourcc == i_fourcc ||
-            ( p_child->common.i_chunk_fourcc == AVIFOURCC_LIST &&
-              p_child->list.i_type == i_fourcc ) )
-        {
-            if( i_number == 0 )
-            {
-                /* We found it */
-                return p_child;
-            }
+        if( b_list && p_child->list.i_type == 0 )
+            continue;
 
-            i_number--;
-        }
-        p_child = p_child->common.p_next;
+        if( p_child->common.i_chunk_fourcc != i_fourcc &&
+            p_child->list.i_type != i_fourcc )
+            continue;
+
+        if( i_number-- == 0 )
+            return p_child; /* We found it */
     }
+
     return NULL;
 }
 
diff --git a/modules/demux/avi/libavi.h b/modules/demux/avi/libavi.h
index 5092996412..5fda4435ef 100644
--- a/modules/demux/avi/libavi.h
+++ b/modules/demux/avi/libavi.h
@@ -254,17 +254,17 @@ int     AVI_ChunkRead( stream_t *,
                        avi_chunk_t *p_father );
 void    AVI_ChunkClean( stream_t *, avi_chunk_t * );
 
-int     AVI_ChunkCount_( avi_chunk_t *, vlc_fourcc_t );
-void   *AVI_ChunkFind_ ( avi_chunk_t *, vlc_fourcc_t, int );
+int     AVI_ChunkCount_( avi_chunk_t *, vlc_fourcc_t, bool );
+void   *AVI_ChunkFind_ ( avi_chunk_t *, vlc_fourcc_t, int, bool );
 
 int     AVI_ChunkReadRoot( stream_t *, avi_chunk_t *p_root );
 void    AVI_ChunkFreeRoot( stream_t *, avi_chunk_t *p_chk  );
 int     AVI_ChunkFetchIndexes( stream_t *, avi_chunk_t *p_riff );
 
-#define AVI_ChunkCount( p_chk, i_fourcc ) \
-    AVI_ChunkCount_( AVI_CHUNK(p_chk), i_fourcc )
-#define AVI_ChunkFind( p_chk, i_fourcc, i_number ) \
-    AVI_ChunkFind_( AVI_CHUNK(p_chk), i_fourcc, i_number )
+#define AVI_ChunkCount( p_chk, i_fourcc, b_list ) \
+    AVI_ChunkCount_( AVI_CHUNK(p_chk), i_fourcc, b_list )
+#define AVI_ChunkFind( p_chk, i_fourcc, i_number, b_list ) \
+    AVI_ChunkFind_( AVI_CHUNK(p_chk), i_fourcc, i_number, b_list )
 
 /* *** avi stuff *** */
 



More information about the vlc-commits mailing list