Skip to content

Commit 0d721a5

Browse files
committed
Detect overflow in DeserializeVarInt to ensure that we never do UB
1 parent 1835c6c commit 0d721a5

1 file changed

Lines changed: 10 additions & 8 deletions

File tree

src/steamnetworkingsockets/steamnetworkingsockets_internal.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@
133133

134134
enum EDualWifiEnable {
135135
k_nDualWifiEnable_Disable = 0,
136-
k_nDualWifiEnable_Enable = 1, //
136+
k_nDualWifiEnable_Enable = 1, //
137137
k_nDualWifiEnable_DoNotEnumerate = 2, // Enumerate primary adapters, but don't actually try to enable any Dual Wifi support
138138
k_nDualWifiEnable_DoNotBind = 3, // Try to turn on Dual Wifi and locate the secondary adapter, but don't actually bind
139139
k_nDualWifiEnable_ForceSimulate = 4, // Don't really do any DualWifi work, just open up another "regular" socket
@@ -370,7 +370,7 @@ const uint32 k_nCurrentProtocolVersion = 12;
370370
/// when we introduce wire breaking protocol changes and do not wish to be
371371
/// backward compatible. This has been fine before the first major release,
372372
/// but once we make a big public release, we probably won't ever be able to
373-
/// do this again, and we'll need to have more sophisticated mechanisms.
373+
/// do this again, and we'll need to have more sophisticated mechanisms.
374374
const uint32 k_nMinRequiredProtocolVersion = 8;
375375

376376
/// SteamNetworkingMessages is built on top of SteamNetworkingSockets. We use a reserved
@@ -469,19 +469,21 @@ inline int VarIntSerializedSize( uint64 x )
469469

470470
// De-serialize a var-int encoded quantity. Returns pointer to the next byte,
471471
// or NULL if there was a decoding error (we hit the end of stream.)
472-
// https://developers.google.com/protocol-buffers/docs/encoding
473-
//
474-
// NOTE: We do not detect overflow.
472+
// https://developers.google.com/protocol-buffers/docs/encoding/
475473
template <typename T>
476474
inline byte *DeserializeVarInt( byte *p, const byte *end, T &x )
477475
{
478-
if ( p >= end )
476+
if ( unlikely( p >= end ) )
479477
return nullptr;
478+
const byte *max_end = p + ( (sizeof(T)*8 + 6) / 7 );
479+
if ( end > max_end )
480+
end = max_end;
481+
480482
T nResult = *p & 0x7f; // use local variable for working, to make sure compiler doesn't try to worry about pointer aliasing
481483
unsigned nShift = 7;
482484
while ( *(p++) & 0x80 )
483485
{
484-
if ( p >= end )
486+
if ( unlikely( p >= end ) )
485487
return nullptr;
486488
nResult |= ( T( *p & 0x7f ) << nShift );
487489
nShift += 7;
@@ -1611,7 +1613,7 @@ namespace vstd
16111613
{
16121614
// We need dynamic memory. If we're not exactly sized already,
16131615
// just nuke everyhing we have.
1614-
if ( n != capacity_ )
1616+
if ( n != capacity_ )
16151617
{
16161618
clear();
16171619
reserve( n );

0 commit comments

Comments
 (0)