[vlc-commits] [Git][videolan/vlc][3.0.x] 12 commits: demux: ps: always clean the track format

Felix Paul Kühne (@fkuehne) gitlab at videolan.org
Fri Apr 17 11:37:49 UTC 2026



Felix Paul Kühne pushed to branch 3.0.x at VideoLAN / VLC


Commits:
88b9e431 by Alaric Senat at 2026-04-17T12:15:14+02:00
demux: ps: always clean the track format

Conditionally cleaning the track format leads to leaks on ill-formed ps
packets. Usually when a track started allocating fmt metadata and the
input has an unexpected EOF.

The format is always zero initialized so we can count on es_format_Clean
not to double free.

Fixes https://issues.oss-fuzz.com/issues/42503008
Fixes #29013

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/vlc
(cherry picked from commit d9f6f6a500e4394c194ab4dde7f5d5ba3c1e9d74)
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
a0d586e7 by Steve Lhomme at 2026-04-17T12:15:14+02:00
gstreamer: remove unneeded includes

We don't use anything specific to these headers that is not include by gstvlcpictureplaneallocator.h.

Fixes #29604

(cherry picked from commit eea0bacf625d910e37630743c864f96704047936)
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
fb00f9b5 by Steve Lhomme at 2026-04-17T12:15:14+02:00
test: adaptive: fix designated initializer usage in C++

Co-authored-by: Alexandre Janniaux <ajanni at videolabs.io>
(cherry picked from commit 4ca9a6ae6c4be8a251c99b23a3a182a0a2cfcb7c) (edited)
edited:
- VLC 3 doesn't have the same parameters in dropesout (no DummyEsOut or callback structure)
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
bf427b5c by unichronic at 2026-04-17T12:15:14+02:00
mkv: fix OOM vulnerability when parsing oversized child elements

Properly restricts the boundaries of child elements (i_ulev == 0) to their parent's boundaries, preventing libebml from bypassing MaxDataSize and allocating enormous amounts of memory when encountering spoofed UpperLevel IDs.

(cherry picked from commit 4bc8283e46de625057499127441e082c295ed2e4)
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
044a49f7 by Steve Lhomme at 2026-04-17T12:15:14+02:00
demux: ts: fix comparison of MPEG syncword

We don't want to compare with 0x00, 0x00, 0x01, 0x00.

Introduced in bfb2e970783cfcf9635556ca174bcd5691cbbbc2.

(cherry picked from commit 01f488820527ffb05dcae19f8ea66cd10c70c32b)
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
117fdf3e by Steve Lhomme at 2026-04-17T12:15:14+02:00
demux: mkv: debug the Dummy element buggy position

(cherry picked from commit f87900ad96250fd739538ffa9328f1f72206e592)
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
7285bc33 by Steve Lhomme at 2026-04-17T12:15:14+02:00
demux: mkv: use size_t for levels in m_el table

It should never be negative.

(cherry picked from commit 344e4f192a6342e8ae0c46c3fcdeeff047964ceb) (rebased)
rebased:
- VLC 3 uses EbmlStream instead of matroska_iostream_c
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
efc4854b by Steve Lhomme at 2026-04-17T12:15:14+02:00
demux: mkv: remove else after return

(cherry picked from commit 1e4088406663104e6ea810b1b30ec32f3db8e550)
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
7d55776f by Steve Lhomme at 2026-04-17T12:15:14+02:00
demux: mkv: only read the edition name once

(cherry picked from commit 0657a7baf5533c51c2c81c29352ca398cce344e7)
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
cdcd4b08 by Steve Lhomme at 2026-04-17T12:15:14+02:00
demux: mkv: fix title number reading

We are reading the 3rd and 4th bytes in the buffer.

(cherry picked from commit 65f4d092a6a54e376f063587bdd15e47fa9614e6) (edited)
edited:
- in VLC 3 the file is still called chapter_command.cpp
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
2b948be6 by Steve Lhomme at 2026-04-17T12:15:14+02:00
demux: ts: check block skip size

The result of PKTHeaderAndAFSize() is not checked against the available data.
There's a cap at 187 bytes but the block may contain less data (EOF).
We can't properly subtract i_skip from p_pkt->i_buffer.

If there is too much data to skip the pcr won't be updated.

(cherry picked from commit 93e847d1c02e8bb55c46f1d9c511e95e9e9bc2ec) (rebased)
rebased:
- VLC 4 uses a PKTHeaderAndAFSize() function to get the skip value
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
ee9d85e1 by Steve Lhomme at 2026-04-17T12:15:14+02:00
demux: ts: check block has enough data before checking payload flags

(cherry picked from commit 417a06caa26df76a51d09bdd5361ef4d9b7c96e3) (rebased)
rebased:
- VLC 4 uses a PKTHeaderAndAFSize() function to get the skip value
Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -


9 changed files:

- modules/codec/gstreamer/gstvlcvideopool.h
- modules/demux/adaptive/test/plumbing/FakeEsOut.cpp
- modules/demux/mkv/Ebml_parser.cpp
- modules/demux/mkv/Ebml_parser.hpp
- modules/demux/mkv/chapter_command.cpp
- modules/demux/mkv/demux.cpp
- modules/demux/mpeg/ps.c
- modules/demux/mpeg/ts.c
- modules/demux/mpeg/ts_hotfixes.c


Changes:

=====================================
modules/codec/gstreamer/gstvlcvideopool.h
=====================================
@@ -27,9 +27,6 @@
 #ifndef VLC_GST_VIDEO_POOL_H
 #define VLC_GST_VIDEO_POOL_H
 
-#include <gst/gstbufferpool.h>
-#include <gst/video/gstvideopool.h>
-
 #include "gstvlcpictureplaneallocator.h"
 
 typedef struct _GstVlcVideoPool GstVlcVideoPool;


=====================================
modules/demux/adaptive/test/plumbing/FakeEsOut.cpp
=====================================
@@ -365,16 +365,16 @@ static int check0(es_out_t *out, struct context *, FakeESOut *fakees)
 int FakeEsOut_test()
 {
     struct context ctx = {VLC_TICK_INVALID,VLC_TICK_INVALID,VLC_TICK_INVALID};
-    struct dropesout dummy = {
-            .ctx = &ctx,
-            .esout = {
+    struct dropesout dummy = {};
+    dummy.ctx = &ctx;
+    dummy.esout = {
                 .pf_add = dummy_callback_add,
                 .pf_send = dummy_callback_send,
                 .pf_del = dummy_callback_del,
                 .pf_control = dummy_callback_control,
                 .pf_destroy = dummy_callback_destroy,
                 .p_sys = nullptr,
-    } };
+    };
 
     int(* const tests[3])(es_out_t *, struct context *, FakeESOut *)
             = { check0, check1, check2 };


=====================================
modules/demux/mkv/Ebml_parser.cpp
=====================================
@@ -51,7 +51,7 @@ EbmlParser::~EbmlParser( void )
         return;
     }
 
-    for( int i = 1; i <= mi_level; i++ )
+    for( size_t i = 1; i <= mi_level; i++ )
     {
         if( !mb_keep )
         {
@@ -75,6 +75,7 @@ void EbmlParser::Up( void )
         msg_Warn( p_demux, "MKV/Ebml Parser: Up cannot escape itself" );
     }
 
+    assert(mi_user_level != 0);
     mi_user_level--;
 }
 
@@ -146,6 +147,15 @@ EbmlElement *EbmlParser::Get( bool allow_overshoot )
         EbmlElement *ret = m_got;
         m_got = NULL;
 
+        if( mi_level > 0 && m_el[mi_level-1]->IsFiniteSize() && ret->IsFiniteSize() &&
+            ret->GetEndPosition() > m_el[mi_level-1]->GetEndPosition() )
+        {
+            msg_Err( p_demux, "EBML element at %" PRIu64 " extends beyond parent boundary (%" PRIu64 " beyond %" PRIu64 ")",
+                m_el[mi_level]->GetElementPosition(), m_el[mi_level]->GetEndPosition(), m_el[mi_level-1]->GetEndPosition() );
+            delete ret;
+            m_el[mi_level] = NULL;
+            return NULL;
+        }
         return ret;
     }
 
@@ -247,7 +257,7 @@ next:
         }
         return NULL;
     }
-    else if( m_el[mi_level] == NULL )
+    if( m_el[mi_level] == NULL )
     {
         msg_Dbg( p_demux,"MKV/Ebml Parser: m_el[mi_level] == NULL" );
         /* go back to the end of the parent */
@@ -269,7 +279,8 @@ next:
             p_prev && p_prev->IsFiniteSize() &&
             p_prev->GetEndPosition() != m_el[mi_level]->GetElementPosition() )
         {
-            msg_Err( p_demux, "Dummy Element at unexpected position... corrupted file?" );
+            msg_Err( p_demux, "Dummy Element at unexpected position (%" PRIu64 " instead of %" PRIu64 ")... corrupted file?",
+                        m_el[mi_level]->GetElementPosition(), p_prev->GetEndPosition() );
             b_bad_position = true;
         }
 
@@ -338,7 +349,7 @@ next:
 
 bool EbmlParser::IsTopPresent( EbmlElement *el ) const
 {
-    for( int i = 0; i < mi_level; i++ )
+    for( size_t i = 0; i < mi_level; i++ )
     {
         if( m_el[i] && m_el[i] == el )
             return true;


=====================================
modules/demux/mkv/Ebml_parser.hpp
=====================================
@@ -55,12 +55,12 @@ class EbmlParser
 
     demux_t     *p_demux;
     EbmlStream  *m_es;
-    int          mi_level;
+    size_t       mi_level;
     EbmlElement *m_el[M_EL_MAXSIZE];
 
     EbmlElement *m_got;
 
-    int          mi_user_level;
+    size_t       mi_user_level;
     bool         mb_keep;
     /* Allow dummy/unknown EBML elements */
     bool         mb_dummy;


=====================================
modules/demux/mkv/chapter_command.cpp
=====================================
@@ -55,7 +55,7 @@ void chapter_codec_cmds_c::AddCommand( const KaxChapterProcessCommand & command
 
 int16 dvd_chapter_codec_c::GetTitleNumber()
 {
-    if ( p_private_data != nullptr && p_private_data->GetSize() >= 3)
+    if ( p_private_data != nullptr && p_private_data->GetSize() > 3)
     {
         const binary* p_data = p_private_data->GetBuffer();
         if ( p_data[0] == MATROSKA_DVD_LEVEL_SS )


=====================================
modules/demux/mkv/demux.cpp
=====================================
@@ -668,8 +668,9 @@ bool demux_sys_t::PreloadLinked()
                 // TODO use a name for each edition, let the TITLE deal with a codec name
                 if ( p_title->psz_name == NULL )
                 {
-                    if( p_ved->GetMainName().length() )
-                        p_title->psz_name = strdup( p_ved->GetMainName().c_str() );
+                    const auto edition_name = p_ved->GetMainName();
+                    if( edition_name.length() )
+                        p_title->psz_name = strdup( edition_name.c_str() );
                     else
                     {
                         /* Check in tags if the edition has a name */


=====================================
modules/demux/mpeg/ps.c
=====================================
@@ -270,11 +270,9 @@ static void Close( vlc_object_t *p_this )
     for( i = 0; i < PS_TK_COUNT; i++ )
     {
         ps_track_t *tk = &p_sys->tk[i];
-        if( tk->b_configured )
-        {
-            es_format_Clean( &tk->fmt );
-            if( tk->es ) es_out_Del( p_demux->out, tk->es );
-        }
+        es_format_Clean( &tk->fmt );
+        if( tk->b_configured && tk->es != NULL )
+            es_out_Del( p_demux->out, tk->es );
     }
 
     ps_psm_destroy( &p_sys->psm );


=====================================
modules/demux/mpeg/ts.c
=====================================
@@ -1961,7 +1961,7 @@ static int SeekToTime( demux_t *p_demux, const ts_pmt_t *p_pmt, vlc_tick_t i_see
                     }
                 }
 
-                if( i_pktpcr == TS_90KHZ_INVALID && p_pid->type == TYPE_STREAM &&
+                if( p_pkt->i_buffer > 4 && p_pkt->i_buffer > i_skip && i_pktpcr == TS_90KHZ_INVALID && p_pid->type == TYPE_STREAM &&
                     ts_stream_Find_es( p_pid->u.p_stream, p_pmt ) &&
                    (p_pkt->p_buffer[1] & 0xC0) == 0x40 && /* Payload start but not corrupt */
                    (p_pkt->p_buffer[3] & 0xD0) == 0x10    /* Has payload but is not encrypted */
@@ -2057,6 +2057,8 @@ static int ProbeChunk( demux_t *p_demux, int i_program, bool b_end, ts_90khz_t *
                 if ( b_adaptfield ) // adaptation field
                     i_skip += 1 + __MIN(p_pkt->p_buffer[4], 182);
 
+                if (p_pkt->i_buffer > i_skip)
+                {
                 if ( VLC_SUCCESS == ParsePESHeader( VLC_OBJECT(p_demux), &p_pkt->p_buffer[i_skip],
                                                     p_pkt->i_buffer - i_skip, &i_skip,
                                                     &i_dts, &i_pts, &i_stream_id, NULL ) )
@@ -2066,6 +2068,7 @@ static int ProbeChunk( demux_t *p_demux, int i_program, bool b_end, ts_90khz_t *
                     else if( i_pts != TS_90KHZ_INVALID )
                         *pi_pcr = i_pts;
                 }
+                }
             }
 
             if( *pi_pcr != TS_90KHZ_INVALID )


=====================================
modules/demux/mpeg/ts_hotfixes.c
=====================================
@@ -185,7 +185,7 @@ void ProbePES( demux_t *p_demux, ts_pid_t *pid, const uint8_t *p_pesstart, size_
         {
             pid->probed.i_fourcc = VLC_CODEC_H264;
         }
-        else if( !memcmp( p_data, "\x00\x00\x01", 4 ) )
+        else if( !memcmp( p_data, "\x00\x00\x01", 3 ) )
         {
             pid->probed.i_fourcc = VLC_CODEC_MPGV;
         }



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/871b608f56a732b1156a21bd5d923f8c0c4a6004...ee9d85e1d2de0da4456d2c03b39d706eed0527b0

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/871b608f56a732b1156a21bd5d923f8c0c4a6004...ee9d85e1d2de0da4456d2c03b39d706eed0527b0
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list