[vlc-commits] [Git][videolan/vlc][master] 9 commits: meta_engine: i3dtag: early on ID3 size values

Steve Lhomme (@robUx4) gitlab at videolan.org
Wed Apr 29 03:52:34 UTC 2026



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
acc9fa38 by Steve Lhomme at 2026-04-29T03:31:25+00:00
meta_engine: i3dtag: early on ID3 size values

i_peek = 10 is OK to read the size.

- - - - -
8f8ac233 by Steve Lhomme at 2026-04-29T03:31:25+00:00
meta_engine: id3tag: fix indentation

No functional changes.

- - - - -
bd4d5b07 by Steve Lhomme at 2026-04-29T03:31:25+00:00
meta_engine: id3tag: pass the buffer size to ID3TAG_IsTag()

- - - - -
de5014df by Steve Lhomme at 2026-04-29T03:31:25+00:00
meta_engine: id3tag: simplify test

- - - - -
89448363 by Steve Lhomme at 2026-04-29T03:31:25+00:00
meta_engine: id3tag: use a different variable for the rolling p_frame buffer size

- - - - -
e74b7d13 by Steve Lhomme at 2026-04-29T03:31:25+00:00
meta_engine: id3tag: undo the i_framesize shift by 10

Apply it where i_framesize is evaluated (no functional changes).

- - - - -
756d1b50 by Steve Lhomme at 2026-04-29T03:31:25+00:00
meta_engine: id3tag: check frame size against remaining frame length

This avoids a potential addition overflow. We know frame_length is a least 10.

Fixes #29803

- - - - -
b134ec88 by Steve Lhomme at 2026-04-29T03:31:25+00:00
meta_engine: id3tag: simplify tag length check before calling callback

- - - - -
149b9b79 by Steve Lhomme at 2026-04-29T03:31:25+00:00
meta_engine: id3tag: return size of ID3 tag data even if they are bogus

We should skip the data, not keep trying to parse them by the caller.

- - - - -


3 changed files:

- modules/demux/adaptive/StreamFormat.cpp
- modules/demux/hls/HLSStreams.cpp
- modules/meta_engine/ID3Tag.h


Changes:

=====================================
modules/demux/adaptive/StreamFormat.cpp
=====================================
@@ -147,7 +147,7 @@ StreamFormat::StreamFormat(const void *data_, size_t sz)
     }
 
     /* Skipped ID3 if any */
-    while(sz > 10 && ID3TAG_IsTag(data, false))
+    while(ID3TAG_IsTag(data, sz, false))
     {
         size_t tagsize = ID3TAG_Parse(data, sz, ID3Callback, this);
         if(tagsize >= sz || tagsize == 0)


=====================================
modules/demux/hls/HLSStreams.cpp
=====================================
@@ -112,7 +112,7 @@ block_t * HLSStream::checkBlock(block_t *p_block, bool b_first)
 {
     if(b_first && p_block)
     {
-        while(p_block->i_buffer >= 10 && ID3TAG_IsTag(p_block->p_buffer, false))
+        while(ID3TAG_IsTag(p_block->p_buffer, p_block->i_buffer, false))
         {
             size_t i_size = ID3TAG_Parse( p_block->p_buffer, p_block->i_buffer,
                                           ID3TAG_Parse_Handler, static_cast<void *>(this) );


=====================================
modules/meta_engine/ID3Tag.h
=====================================
@@ -20,6 +20,8 @@
 #ifndef ID3TAG_H
 #define ID3TAG_H
 
+#include <limits.h>
+
 static uint32_t ID3TAG_ReadSize( const uint8_t *p_buffer, bool b_syncsafe )
 {
     if( !b_syncsafe )
@@ -30,9 +32,9 @@ static uint32_t ID3TAG_ReadSize( const uint8_t *p_buffer, bool b_syncsafe )
             (( (uint32_t)p_buffer[0] & 0x7F ) << 21);
 }
 
-static bool ID3TAG_IsTag( const uint8_t *p_buffer, bool b_footer )
+static bool ID3TAG_IsTag( const uint8_t *p_buffer, size_t buffer_len, bool b_footer )
 {
-    return( memcmp(p_buffer, (b_footer) ? "3DI" : "ID3", 3) == 0 &&
+    return( buffer_len >= 10 && memcmp(p_buffer, (b_footer) ? "3DI" : "ID3", 3) == 0 &&
             p_buffer[3] < 0xFF &&
             p_buffer[4] < 0xFF &&
            ((GetDWBE(&p_buffer[6]) & 0x80808080) == 0) );
@@ -41,59 +43,62 @@ static bool ID3TAG_IsTag( const uint8_t *p_buffer, bool b_footer )
 static size_t ID3TAG_Parse( const uint8_t *p_peek, size_t i_peek,
                             int (*pf_callback)(uint32_t, const uint8_t *, size_t, void *), void *p_priv )
 {
-    size_t i_total_size = 0;
-    uint32_t i_ID3size = 0;
-    if( i_peek > 10 && ID3TAG_IsTag( p_peek, false ) )
-    {
-        const uint8_t i_ID3major = p_peek[3];
-        const uint8_t i_ID3flags = p_peek[5];
-        i_ID3size = ID3TAG_ReadSize( &p_peek[6], true );
-        if( i_ID3size > i_peek - 10 )
-            return 0;
-        i_total_size = i_ID3size + 10;
+    if( !ID3TAG_IsTag( p_peek, i_peek, false ) )
+        return 0; /* not an ID3 tag */
 
-        const uint8_t *p_frame = &p_peek[10];
+    const uint32_t i_ID3size = ID3TAG_ReadSize( &p_peek[6], true );
+    if( i_ID3size > i_peek - 10 )
+        return 0; /* not enough peek */
+#if UINT32_MAX >= SIZE_MAX
+    if( i_ID3size > SIZE_MAX - 10 )
+        return 0; /* total size overflow */
+#endif
 
-        if( i_ID3major >= 3 && i_ID3major <= 4 && (i_ID3flags & 0x40) ) /* ext header */
-        {
-            if( i_ID3size < 6 ) /* can't be less than 6 */
-                return 0;
-            uint32_t i_exthdr = ID3TAG_ReadSize( p_frame, true );
-            if( i_ID3major == 3 )
-            {
-                /* 6 or 10 bytes not including size storage */
-                if( i_exthdr != 6 && i_exthdr != 10 )
-                    return 0;
-                i_exthdr += 4;
-            }
-            if( i_ID3size < i_exthdr )
-                return 0;
-            p_frame += i_exthdr;
-            i_ID3size -= i_exthdr;
-        }
+    size_t i_total_size = i_ID3size + 10;
+    /* Count footer if any */
+    if( i_peek > i_total_size &&
+        ID3TAG_IsTag( &p_peek[i_total_size], i_peek - i_total_size, true ) )
+    {
+        i_total_size += 10;
+    }
 
-        /* Tags */
-        while( i_ID3size > 10 )
+    const uint8_t i_ID3major = p_peek[3];
+    const uint8_t i_ID3flags = p_peek[5];
+    const uint8_t *p_frame = &p_peek[10];
+    size_t frame_length = i_ID3size;
+
+    if( (i_ID3major == 3 || i_ID3major == 4) && (i_ID3flags & 0x40) ) /* ext header */
+    {
+        if( frame_length < 6 ) /* can't be less than 6 */
+            return 0;
+        uint32_t i_exthdr = ID3TAG_ReadSize( p_frame, true );
+        if( i_ID3major == 3 )
         {
-            uint32_t i_tagname = VLC_FOURCC( p_frame[0], p_frame[1], p_frame[2], p_frame[3] );
-            uint32_t i_framesize = ID3TAG_ReadSize( &p_frame[4], i_ID3major != 3 ) + 10;
-            if( i_framesize > i_ID3size )
+            /* 6 or 10 bytes not including size storage */
+            if( i_exthdr != 6 && i_exthdr != 10 )
                 return 0;
-
-            if( i_framesize > 10 &&
-                pf_callback( i_tagname, &p_frame[10], i_framesize - 10, p_priv ) != VLC_SUCCESS )
-                break;
-
-            p_frame += i_framesize;
-            i_ID3size -= i_framesize;
+            i_exthdr += 4;
         }
+        if( frame_length < i_exthdr )
+            return 0;
+        p_frame += i_exthdr;
+        frame_length -= i_exthdr;
     }
 
-    /* Count footer if any */
-    if( i_total_size && i_peek - i_total_size >= 10 &&
-        ID3TAG_IsTag( &p_peek[i_total_size], true ) )
+    /* Tags */
+    while( frame_length > 10 )
     {
-        i_total_size += 10;
+        uint32_t i_tagname = VLC_FOURCC( p_frame[0], p_frame[1], p_frame[2], p_frame[3] );
+        uint32_t i_framesize = ID3TAG_ReadSize( &p_frame[4], i_ID3major != 3 );
+        if( i_framesize > frame_length - 10 )
+            break; /* not enough peek */
+
+        if( i_framesize != 0 &&
+            pf_callback( i_tagname, &p_frame[10], i_framesize, p_priv ) != VLC_SUCCESS )
+            break;
+
+        p_frame += i_framesize + 10;
+        frame_length -= i_framesize + 10;
     }
 
     return i_total_size;



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/471e6c6c5840ad1f26d041c8e26dcfeffaa07f11...149b9b79cb04bd5a042a52ba86ea7e508da1c07d

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/471e6c6c5840ad1f26d041c8e26dcfeffaa07f11...149b9b79cb04bd5a042a52ba86ea7e508da1c07d
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list