[vlc-commits] [Git][videolan/vlc][3.0.x] 6 commits: update: fix potential double free

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Sun Jul 5 21:10:41 UTC 2026



Jean-Baptiste Kempf pushed to branch 3.0.x at VideoLAN / VLC


Commits:
d50f118e by Thomas Guillem at 2026-07-05T23:03:33+02:00
update: fix potential double free

`parse_public_key()` and `parse_signature_packet()` free the same
pointers; the callee leaves them dangling on error, the caller swallows
the failure and keeps looping, so a later bad packet frees them again ->
double free.

(cherry picked from commit 9c7e488ac4e9227c6be738223a2c301fa52c83cb)
Signed-off-by: Thomas Guillem <thomas at gllm.fr>

- - - - -
c29e4082 by Thomas Guillem at 2026-07-05T23:03:33+02:00
update: check the signature algo matches the key

Fix union/type-confusion OOB read.

(cherry picked from commit ed534191105da907516faac1344f231e5c0c0472)
Signed-off-by: Thomas Guillem <thomas at gllm.fr>

- - - - -
e71c91fd by Thomas Guillem at 2026-07-05T23:03:33+02:00
update: fix OOB read

Both buffers ends in pgp_unarmor() that call unbounded strcspn().

(cherry picked from commit 9936a1662da8e9e7cc59f3a4b3c6029513251b0a)
Signed-off-by: Thomas Guillem <thomas at gllm.fr>

- - - - -
81766b02 by Thomas Guillem at 2026-07-05T23:03:33+02:00
update: fix pointer overflow in packet bounds check

Since we have `max_pos >= pos`. Use a size_t to fix a new sign
comparison warning.

(cherry picked from commit 94b4022b54cb0ea5720f6c28d934b3e718157a18)
Signed-off-by: Thomas Guillem <thomas at gllm.fr>

- - - - -
d8990e64 by Thomas Guillem at 2026-07-05T23:03:33+02:00
update: fix pointer overflow in the v4 signature subpacket loop

Since we have `max_pos >= pos`.

(cherry picked from commit 57ccd671a0607892aca78359328e8f2b040da5d3)
Signed-off-by: Thomas Guillem <thomas at gllm.fr>

- - - - -
1251b4ee by Thomas Guillem at 2026-07-05T23:03:33+02:00
update: fix OOB read in the v4 signature subpacket loop

The subpacket length is attacker controlled (parsed before authentication).
The loop dereferenced *p while only checking p > max_pos, reading past
unhashed_data when p == max_pos, and advanced p by an unchecked length.

Stop at p == max_pos and bound the length against the remaining bytes.

(cherry picked from commit 2ca77de610f333bf619be8676032a57e8c117a71)
Signed-off-by: Thomas Guillem <thomas at gllm.fr>

- - - - -


1 changed file:

- src/misc/update_crypto.c


Changes:

=====================================
src/misc/update_crypto.c
=====================================
@@ -54,7 +54,7 @@
 #define packet_header_len( c ) ( ( c & 0x03 ) + 1 ) /* number of bytes in a packet header */
 
 
-static inline uint32_t scalar_number( const uint8_t *p, int header_len )
+static inline uint32_t scalar_number( const uint8_t *p, size_t header_len )
 {
     assert( header_len == 1 || header_len == 2 || header_len == 4 );
 
@@ -235,34 +235,37 @@ static size_t parse_signature_v4_packet( signature_packet_t *p_sig,
 
     for( ;; )
     {
-        if( p > max_pos )
+        if( p >= max_pos )
             return 0;
 
         size_t i_subpacket_len;
         if( *p < 192 )
         {
-            if( p + 1 > max_pos )
-                return 0;
             i_subpacket_len = *p++;
         }
         else if( *p < 255 )
         {
-            if( p + 2 > max_pos )
+            if( 2 > (size_t)( max_pos - p ) )
                 return 0;
             i_subpacket_len = (*p++ - 192) << 8;
             i_subpacket_len += *p++ + 192;
         }
         else
         {
-            if( ++p + 4 > max_pos )
+            if( 5 > (size_t)( max_pos - p ) )
                 return 0;
+            p++;
             i_subpacket_len = U32_AT(p);
             p += 4;
         }
 
+        if( i_subpacket_len == 0 ||
+            i_subpacket_len > (size_t)( max_pos - p ) )
+            return 0;
+
         if( *p == ISSUER_SUBPACKET )
         {
-            if( p + 9 > max_pos )
+            if( i_subpacket_len < 9 )
                 return 0;
 
             memcpy( &p_sig->issuer_longid, p+1, 8 );
@@ -340,6 +343,8 @@ error:
     {
         free( p_sig->specific.v4.hashed_data );
         free( p_sig->specific.v4.unhashed_data );
+        p_sig->specific.v4.hashed_data = NULL;
+        p_sig->specific.v4.unhashed_data = NULL;
     }
 
     return VLC_EGENERIC;
@@ -589,6 +594,9 @@ out:
 int verify_signature( signature_packet_t *sign, public_key_packet_t *p_key,
                       uint8_t *p_hash )
 {
+    if( sign->public_key_algo != p_key->algo )
+        return VLC_EGENERIC;
+
     if (sign->public_key_algo == GCRY_PK_DSA)
         return verify_signature_dsa(sign, p_key, p_hash);
     else if (sign->public_key_algo == GCRY_PK_RSA)
@@ -643,15 +651,15 @@ int parse_public_key( const uint8_t *p_key_data, size_t i_key_len,
 
         int i_type = packet_type( *pos );
 
-        int i_header_len = packet_header_len( *pos++ );
-        if( pos + i_header_len > max_pos ||
+        size_t i_header_len = packet_header_len( *pos++ );
+        if( i_header_len > (size_t)( max_pos - pos ) ||
             ( i_header_len != 1 && i_header_len != 2 && i_header_len != 4 ) )
             goto error;
 
         size_t i_packet_len = scalar_number( pos, i_header_len );
         pos += i_header_len;
 
-        if( pos + i_packet_len > max_pos )
+        if( i_packet_len > (size_t)( max_pos - pos ) )
             goto error;
 
         switch( i_type )
@@ -715,6 +723,8 @@ error:
     {
         free( p_key->sig.specific.v4.hashed_data );
         free( p_key->sig.specific.v4.unhashed_data );
+        p_key->sig.specific.v4.hashed_data = NULL;
+        p_key->sig.specific.v4.unhashed_data = NULL;
     }
     free( p_key->psz_username );
     free( p_key_unarmored );
@@ -961,7 +971,7 @@ public_key_t *download_key( vlc_object_t *p_this,
         return NULL;
     }
 
-    uint8_t *p_buf = (uint8_t*)malloc( i_size );
+    uint8_t *p_buf = (uint8_t*)malloc( i_size + 1 );
     if( !p_buf )
     {
         vlc_stream_Delete( p_stream );
@@ -978,6 +988,8 @@ public_key_t *download_key( vlc_object_t *p_this,
         return NULL;
     }
 
+    p_buf[i_size] = '\0';
+
     public_key_t *p_pkey = (public_key_t*) malloc( sizeof( public_key_t ) );
     if( !p_pkey )
     {
@@ -1029,7 +1041,7 @@ int download_signature( vlc_object_t *p_this, signature_packet_t *p_sig,
     }
 
     msg_Dbg( p_this, "Downloading signature (%"PRIu64" bytes)", i_size );
-    uint8_t *p_buf = (uint8_t*)malloc( i_size );
+    uint8_t *p_buf = (uint8_t*)malloc( i_size + 1 );
     if( !p_buf )
     {
         vlc_stream_Delete( p_stream );
@@ -1048,6 +1060,8 @@ int download_signature( vlc_object_t *p_this, signature_packet_t *p_sig,
         return VLC_EGENERIC;
     }
 
+    p_buf[i_size] = '\0';
+
     if( (uint8_t)*p_buf < 0x80 ) /* ASCII */
     {
         msg_Dbg( p_this, "Unarmoring signature" );



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/9f473bd370269e5bfe41f38c4011bd65453e8849...1251b4ee0958421b30cf15e0630c1750c4c15e61

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/9f473bd370269e5bfe41f38c4011bd65453e8849...1251b4ee0958421b30cf15e0630c1750c4c15e61
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help




More information about the vlc-commits mailing list