[vlc-commits] [Git][videolan/vlc][master] 6 commits: update: fix potential double free

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Wed Jul 1 18:46:49 UTC 2026



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
9c7e488a by Thomas Guillem at 2026-07-01T20:35:40+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.

- - - - -
ed534191 by Thomas Guillem at 2026-07-01T20:35:40+02:00
update: check the signature algo matches the key

Fix union/type-confusion OOB read.

- - - - -
9936a166 by Thomas Guillem at 2026-07-01T20:35:40+02:00
update: fix OOB read

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

- - - - -
94b4022b by Thomas Guillem at 2026-07-01T20:35:40+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.

- - - - -
57ccd671 by Thomas Guillem at 2026-07-01T20:35:40+02:00
update: fix pointer overflow in the v4 signature subpacket loop

Since we have `max_pos >= pos`.

- - - - -
2ca77de6 by Thomas Guillem at 2026-07-01T20:35:40+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.

- - - - -


1 changed file:

- src/misc/update_crypto.c


Changes:

=====================================
src/misc/update_crypto.c
=====================================
@@ -53,7 +53,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 );
 
@@ -234,34 +234,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 );
@@ -339,6 +342,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;
@@ -588,6 +593,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)
@@ -642,15 +650,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 )
@@ -714,6 +722,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 );
@@ -949,7 +959,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 );
@@ -966,6 +976,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 )
     {
@@ -1017,7 +1029,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 );
@@ -1036,6 +1048,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/a3192f48f31d914113d3d35455886e6f038202f2...2ca77de610f333bf619be8676032a57e8c117a71

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/a3192f48f31d914113d3d35455886e6f038202f2...2ca77de610f333bf619be8676032a57e8c117a71
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