[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