Fix 16-bit string length desync on offset recovery

The decoder recovered offset-encoded 16-bit string lengths into a
uint16_t, so sz += ProtocolOffset8Bit truncated lengths in [65536,
65791] back into [0, 255] in release builds, desynchronizing the
stream. Read the wire value into uint16_t sz16 and recover into a
uint32_t sz, relying on automatic promotion for the addition.

Align the client asserts with the encoder's actual capacity
(ProtocolOffset8Bit + uint16 max).
This commit is contained in:
Bartosz Taudul
2026-08-13 18:10:43 +02:00
parent 821d43c6b5
commit edc09a4e97
2 changed files with 18 additions and 18 deletions

View File

@@ -3519,9 +3519,8 @@ void Profiler::SendSingleString16( const char* ptr, size_t len )
QueueItem item;
MemWrite( &item.hdr.type, QueueType::SingleStringData );
// Ignoring u16+ range by design
assert( len > std::numeric_limits<uint8_t>::max() );
assert( len <= std::numeric_limits<uint16_t>::max() );
assert( len <= ProtocolOffset8Bit + std::numeric_limits<uint16_t>::max() );
auto l16 = uint16_t( len - ProtocolOffset8Bit );
NeedDataSize( QueueDataSize[(int)QueueType::SingleStringData] + sizeof( l16 ) + len );
@@ -3551,9 +3550,8 @@ void Profiler::SendSecondString16( const char* ptr, size_t len )
QueueItem item;
MemWrite( &item.hdr.type, QueueType::SecondStringData );
// Ignoring u16+ range by design
assert( len > std::numeric_limits<uint8_t>::max() );
assert( len <= std::numeric_limits<uint16_t>::max() );
assert( len <= ProtocolOffset8Bit + std::numeric_limits<uint16_t>::max() );
auto l16 = uint16_t( len - ProtocolOffset8Bit );
NeedDataSize( QueueDataSize[(int)QueueType::SecondStringData] + sizeof( l16 ) + len );

View File

@@ -3191,22 +3191,23 @@ void Worker::DispatchFailure( const QueueItem& ev, const char*& ptr )
else
{
uint8_t sz8;
uint16_t sz;
uint16_t sz16;
uint32_t sz;
switch( ev.hdr.type )
{
case QueueType::SingleStringData:
ptr += sizeof( QueueHeader );
memcpy( &sz, ptr, sizeof( sz ) );
ptr += sizeof( sz );
sz += ProtocolOffset8Bit;
memcpy( &sz16, ptr, sizeof( sz16 ) );
ptr += sizeof( sz16 );
sz = sz16 + ProtocolOffset8Bit;
AddSingleStringFailure( ptr, sz );
ptr += sz;
break;
case QueueType::SecondStringData:
ptr += sizeof( QueueHeader );
memcpy( &sz, ptr, sizeof( sz ) );
ptr += sizeof( sz );
sz += ProtocolOffset8Bit;
memcpy( &sz16, ptr, sizeof( sz16 ) );
ptr += sizeof( sz16 );
sz = sz16 + ProtocolOffset8Bit;
AddSecondString( ptr, sz );
ptr += sz;
break;
@@ -3408,22 +3409,23 @@ bool Worker::DispatchProcess( const QueueItem& ev, const char*& ptr )
else
{
uint8_t sz8;
uint16_t sz;
uint16_t sz16;
uint32_t sz;
switch( ev.hdr.type )
{
case QueueType::SingleStringData:
ptr += sizeof( QueueHeader );
memcpy( &sz, ptr, sizeof( sz ) );
ptr += sizeof( sz );
sz += ProtocolOffset8Bit;
memcpy( &sz16, ptr, sizeof( sz16 ) );
ptr += sizeof( sz16 );
sz = sz16 + ProtocolOffset8Bit;
AddSingleString( ptr, sz );
ptr += sz;
return true;
case QueueType::SecondStringData:
ptr += sizeof( QueueHeader );
memcpy( &sz, ptr, sizeof( sz ) );
ptr += sizeof( sz );
sz += ProtocolOffset8Bit;
memcpy( &sz16, ptr, sizeof( sz16 ) );
ptr += sizeof( sz16 );
sz = sz16 + ProtocolOffset8Bit;
AddSecondString( ptr, sz );
ptr += sz;
return true;