Merge pull request #431 from samisalreadytaken/dev

vscript saverestore and debugger fixes
This commit is contained in:
Blixibon 2025-07-23 22:18:01 -05:00 committed by GitHub
commit 734130a497
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 654 additions and 322 deletions

View File

@ -5146,6 +5146,11 @@ bool CScriptConvarAccessor::Init()
AddBlockedConVar( "cl_allowdownload" ); AddBlockedConVar( "cl_allowdownload" );
AddBlockedConVar( "cl_allowupload" ); AddBlockedConVar( "cl_allowupload" );
AddBlockedConVar( "cl_downloadfilter" ); AddBlockedConVar( "cl_downloadfilter" );
#ifdef GAME_DLL
AddBlockedConVar( "script_connect_debugger_on_mapspawn" );
#else
AddBlockedConVar( "script_connect_debugger_on_mapspawn_client" );
#endif
return true; return true;
} }

View File

@ -106,6 +106,7 @@
} while(0) } while(0)
#endif #endif
#define Verify( x ) Assert(x) #define Verify( x ) Assert(x)
#define STATIC_ASSERT( x ) static_assert( x, #x )
#else #else
#define DebuggerBreak() ((void)0) #define DebuggerBreak() ((void)0)
#define Assert( x ) ((void)0) #define Assert( x ) ((void)0)
@ -113,12 +114,15 @@
#define AssertMsg1( x, msg, a1 ) ((void)0) #define AssertMsg1( x, msg, a1 ) ((void)0)
#define AssertMsg2( x, msg, a1, a2 ) ((void)0) #define AssertMsg2( x, msg, a1, a2 ) ((void)0)
#define Verify( x ) x #define Verify( x ) x
#define STATIC_ASSERT( x )
#endif // _DEBUG #endif // _DEBUG
#endif #endif
#include <tier0/dbg.h> #include <tier0/dbg.h>
#define STATIC_ASSERT COMPILE_TIME_ASSERT
// Misdefined for GCC in platform.h // Misdefined for GCC in platform.h
#undef UNREACHABLE #undef UNREACHABLE

View File

@ -275,9 +275,13 @@ static inline void PutStr( CBuffer *buffer, const string_t &str )
#ifdef SQDBG_VALIDATE_SENT_MSG #ifdef SQDBG_VALIDATE_SENT_MSG
for ( unsigned int i = 0; i < str.len; i++ ) for ( unsigned int i = 0; i < str.len; i++ )
{ {
AssertMsg( IN_RANGE_CHAR( str.ptr[i], 0x20, 0x7E ) && if ( str.ptr[i] == '\\' && ( str.ptr[i+1] == '\\' || str.ptr[i+1] == '\"' ) )
( ( str.ptr[i] != '\\' && str.ptr[i] != '\"' ) || ( i && str.ptr[i-1] == '\\' ) ), {
"control char in json string" ); i++;
continue;
}
AssertMsg( str.ptr[i] != '\\' && IN_RANGE_CHAR( str.ptr[i], 0x20, 0x7E ), "control char in json string" );
} }
#endif #endif
} }
@ -433,7 +437,7 @@ static inline void PutStr( CBuffer *buffer, const string_t &str, bool quote )
idx += printhex< true, false >( idx += printhex< true, false >(
mem + idx, mem + idx,
buffer->Capacity() - idx, buffer->Capacity() - idx,
(SQChar)*(unsigned char*)c ); (SQUnsignedChar)*(unsigned char*)c );
} }
} }
} }
@ -503,6 +507,7 @@ static inline void PutInt( CBuffer *buffer, I val )
template < bool padding, typename I > template < bool padding, typename I >
static inline void PutHex( CBuffer *buffer, I val ) static inline void PutHex( CBuffer *buffer, I val )
{ {
STATIC_ASSERT( IS_UNSIGNED( I ) );
buffer->base.Ensure( buffer->Size() + countdigits<16>( val ) + 1 ); buffer->base.Ensure( buffer->Size() + countdigits<16>( val ) + 1 );
int len = printhex< padding >( buffer->Base() + buffer->Size(), buffer->Capacity() - buffer->Size(), val ); int len = printhex< padding >( buffer->Base() + buffer->Size(), buffer->Capacity() - buffer->Size(), val );
buffer->size += len; buffer->size += len;
@ -699,7 +704,7 @@ public:
} }
else else
{ {
PutHex< false >( m_pBuffer, val ); PutHex< false >( m_pBuffer, cast_unsigned( I, val ) );
} }
PutChar( m_pBuffer, ']' ); PutChar( m_pBuffer, ']' );
PutChar( m_pBuffer, '\"' ); PutChar( m_pBuffer, '\"' );
@ -850,7 +855,7 @@ private:
else else
{ {
buf = m_Allocator->Alloc(5); buf = m_Allocator->Alloc(5);
int i = printhex< true, true, false >( buf, 5, token ); int i = printhex< true, true, false >( buf, 5, (unsigned char)token );
Assert( i == 4 ); Assert( i == 4 );
buf[i] = 0; buf[i] = 0;
} }
@ -877,6 +882,24 @@ private:
m_error[len] = 0; m_error[len] = 0;
} }
bool IsValue( char token )
{
switch ( token )
{
case Token_String:
case Token_Integer:
case Token_Float:
case Token_False:
case Token_True:
case Token_Null:
case Token_Table:
case Token_Array:
return true;
default:
return false;
}
}
char NextToken( string_t &token ) char NextToken( string_t &token )
{ {
while ( m_cur < m_end ) while ( m_cur < m_end )
@ -1206,7 +1229,7 @@ err_eof:
type = NextToken( token ); type = NextToken( token );
type = ParseValue( type, token, &kv->val ); type = ParseValue( type, token, &kv->val );
if ( type == Token_Error ) if ( !IsValue( type ) )
{ {
SetError( "invalid token %s @ %i", Char(type), Index() ); SetError( "invalid token %s @ %i", Char(type), Index() );
return Token_Error; return Token_Error;
@ -1239,7 +1262,7 @@ err_eof:
for (;;) for (;;)
{ {
if ( type == Token_Error ) if ( !IsValue( type ) )
{ {
SetError( "expected '%c', got %s @ %i", ']', Char(type), Index() ); SetError( "expected '%c', got %s @ %i", ']', Char(type), Index() );
return Token_Error; return Token_Error;
@ -1315,7 +1338,7 @@ err_eof:
value->type = JSON_NULL; value->type = JSON_NULL;
return type; return type;
default: default:
return type; return Token_Error;
} }
} }
}; };

View File

@ -842,7 +842,7 @@ public:
m_pRecvBufPtr( m_pRecvBuf ), m_pRecvBufPtr( m_pRecvBuf ),
m_bWSAInit( false ) m_bWSAInit( false )
{ {
Assert( sizeof(m_pRecvBuf) <= ( 1 << ( sizeof(CMessagePool::message_t::len) * 8 ) ) ); STATIC_ASSERT( sizeof(m_pRecvBuf) <= ( 1 << ( sizeof(CMessagePool::message_t::len) * 8 ) ) );
} }
}; };

File diff suppressed because it is too large Load Diff

View File

@ -75,6 +75,21 @@ bool atox( string_t str, I *out );
template < typename I > template < typename I >
bool atoo( string_t str, I *out ); bool atoo( string_t str, I *out );
template < typename I >
struct _as_unsigned { typedef I T; };
template <>
struct _as_unsigned< int > { typedef unsigned int T; };
#ifdef _SQ64
template <>
struct _as_unsigned< SQInteger > { typedef SQUnsignedInteger T; };
#endif
#define as_unsigned_type( I ) typename _as_unsigned<I>::T
#define cast_unsigned( I, v ) (as_unsigned_type(I)(v))
#define IS_UNSIGNED( I ) ((I)0 < (I)-1)
#define _isdigit( c ) \ #define _isdigit( c ) \
IN_RANGE_CHAR( c, '0', '9' ) IN_RANGE_CHAR( c, '0', '9' )
@ -403,9 +418,10 @@ struct sqstring_t
unsigned int i = 0; unsigned int i = 0;
do do
{ {
if ( ptr[i] > 0x7E || other.ptr[i] != (char)ptr[i] ) if ( (SQUnsignedChar)ptr[i] > 0x7E || other.ptr[i] != (char)ptr[i] )
{ {
AssertMsg( ptr[i] <= 0x7E, "not implemented" ); // > 0x7E can be reached through completions request
// unicode identifiers are not supported, ignore them
return false; return false;
} }
} }
@ -556,6 +572,8 @@ struct stringbufbase_t
template < typename I > template < typename I >
void PutHex( I value, bool padding = true ) void PutHex( I value, bool padding = true )
{ {
STATIC_ASSERT( IS_UNSIGNED( I ) );
int space = BytesLeft(); int space = BytesLeft();
if ( space < 3 ) if ( space < 3 )
@ -590,9 +608,9 @@ bool string_t::IsEqualTo( const sqstring_t &other ) const
{ {
// Used for comparing against locals and outers, // Used for comparing against locals and outers,
// implement unicode conversion if locals can have unicode characters // implement unicode conversion if locals can have unicode characters
if ( other.ptr[i] > 0x7E || (char)other.ptr[i] != ptr[i] ) if ( (SQUnsignedChar)other.ptr[i] > 0x7E || (char)other.ptr[i] != ptr[i] )
{ {
AssertMsg( other.ptr[i] <= 0x7E, "not implemented" ); AssertMsg( (SQUnsignedChar)other.ptr[i] <= 0x7E, "not implemented" );
return false; return false;
} }
} }
@ -675,7 +693,7 @@ inline int printint( C *buf, int size, I value )
value /= 10; value /= 10;
buf[i--] = !neg ? ( '0' + c ) : ( '0' - c ); buf[i--] = !neg ? ( '0' + c ) : ( '0' - c );
} }
while ( value && i >= 0 ); while ( value );
return len; return len;
} }
@ -683,10 +701,11 @@ inline int printint( C *buf, int size, I value )
template < bool padding, bool prefix, bool uppercase, typename C, typename I > template < bool padding, bool prefix, bool uppercase, typename C, typename I >
inline int printhex( C *buf, int size, I value ) inline int printhex( C *buf, int size, I value )
{ {
STATIC_ASSERT( IS_UNSIGNED( as_unsigned_type( I ) ) );
Assert( buf ); Assert( buf );
Assert( size > 0 ); Assert( size > 0 );
int len = ( prefix ? 2 : 0 ) + ( padding ? sizeof(I) * 2 : countdigits<16>( value ) ); int len = ( prefix ? 2 : 0 ) + ( padding ? sizeof(I) * 2 : countdigits<16>( cast_unsigned( I, value ) ) );
if ( len > size ) if ( len > size )
len = size; len = size;
@ -695,11 +714,11 @@ inline int printhex( C *buf, int size, I value )
do do
{ {
C c = value & 0xf; C c = cast_unsigned( I, value ) & 0xf;
value >>= 4; *(as_unsigned_type(I)*)&value >>= 4;
buf[i--] = c + ( ( c < 10 ) ? '0' : ( ( uppercase ? 'A' : 'a' ) - 10 ) ); buf[i--] = c + ( ( c < 10 ) ? '0' : ( ( uppercase ? 'A' : 'a' ) - 10 ) );
} }
while ( value && i >= 0 ); while ( value );
if ( padding ) if ( padding )
{ {
@ -725,6 +744,7 @@ inline int printhex( C *buf, int size, I value )
template < typename C, typename I > template < typename C, typename I >
inline int printoct( C *buf, int size, I value ) inline int printoct( C *buf, int size, I value )
{ {
STATIC_ASSERT( IS_UNSIGNED( I ) );
Assert( buf ); Assert( buf );
Assert( size > 0 ); Assert( size > 0 );
@ -741,7 +761,7 @@ inline int printoct( C *buf, int size, I value )
value >>= 3; value >>= 3;
buf[i--] = '0' + c; buf[i--] = '0' + c;
} }
while ( value && i >= 0 ); while ( value );
if ( i >= 0 ) if ( i >= 0 )
buf[i--] = '0'; buf[i--] = '0';
@ -1302,7 +1322,7 @@ doescape:
else else
{ {
mbc[bytes++] = 'x'; mbc[bytes++] = 'x';
bytes += printhex< true, false >( mbc + bytes, sizeof(mbc) - bytes, (SQChar)cp ); bytes += printhex< true, false >( mbc + bytes, sizeof(mbc) - bytes, (SQUnsignedChar)cp );
} }
goto write; goto write;
@ -1339,7 +1359,7 @@ x7ff:
mbc[bytes++] = '\\'; mbc[bytes++] = '\\';
mbc[bytes++] = 'x'; mbc[bytes++] = 'x';
bytes = bytes + printhex< true, false >( mbc + bytes, sizeof(mbc) - bytes, (SQChar)cp ); bytes = bytes + printhex< true, false >( mbc + bytes, sizeof(mbc) - bytes, (SQUnsignedChar)cp );
goto write; goto write;
} }
} }

View File

@ -306,7 +306,7 @@ public:
void Free( void *ptr ) void Free( void *ptr )
{ {
Assert( !SEQUENTIAL ); STATIC_ASSERT( !SEQUENTIAL );
Assert( m_Memory ); Assert( m_Memory );
Assert( ptr ); Assert( ptr );
@ -364,7 +364,7 @@ public:
void ReleaseShrink() void ReleaseShrink()
{ {
Assert( SEQUENTIAL ); STATIC_ASSERT( SEQUENTIAL );
if ( !m_Memory ) if ( !m_Memory )
return; return;
@ -412,7 +412,7 @@ public:
void Release() void Release()
{ {
Assert( SEQUENTIAL ); STATIC_ASSERT( SEQUENTIAL );
if ( !m_Memory || ( !m.LastFreeChunk() && !m.LastFreeIndex() ) ) if ( !m_Memory || ( !m.LastFreeChunk() && !m.LastFreeIndex() ) )
return; return;
@ -437,7 +437,7 @@ public:
void ReleaseTop() void ReleaseTop()
{ {
Assert( SEQUENTIAL ); STATIC_ASSERT( SEQUENTIAL );
m.SetLastFreeChunk( m.PrevChunk() ); m.SetLastFreeChunk( m.PrevChunk() );
m.SetLastFreeIndex( m.PrevIndex() ); m.SetLastFreeIndex( m.PrevIndex() );
@ -455,23 +455,23 @@ public:
vector() : base(), size(0) vector() : base(), size(0)
{ {
Assert( !bExternalMem ); STATIC_ASSERT( !bExternalMem );
} }
vector( CAllocator &a ) : base(a), size(0) vector( CAllocator &a ) : base(a), size(0)
{ {
Assert( bExternalMem ); STATIC_ASSERT( bExternalMem );
} }
vector( I count ) : base(), size(0) vector( I count ) : base(), size(0)
{ {
Assert( !bExternalMem ); STATIC_ASSERT( !bExternalMem );
base.Alloc( count * sizeof(T) ); base.Alloc( count * sizeof(T) );
} }
vector( const vector< T > &src ) : base() vector( const vector< T > &src ) : base()
{ {
Assert( !bExternalMem ); STATIC_ASSERT( !bExternalMem );
base.Alloc( src.base.Size() ); base.Alloc( src.base.Size() );
size = src.size; size = src.size;

View File

@ -284,6 +284,14 @@ public:
WriteObject( (const SQObjectPtr&)obj, pBuffer, writeState ); WriteObject( (const SQObjectPtr&)obj, pBuffer, writeState );
} }
void WriteObject( SQGenerator *pObj, CUtlBuffer* pBuffer, WriteStateMap& writeState )
{
SQObject obj;
obj._type = OT_GENERATOR;
obj._unVal.pUserPointer = pObj;
WriteObject( (const SQObjectPtr&)obj, pBuffer, writeState );
}
void ReadObject( SQObjectPtr &obj, CUtlBuffer* pBuffer, ReadStateMap& readState ); void ReadObject( SQObjectPtr &obj, CUtlBuffer* pBuffer, ReadStateMap& readState );
// Do not implicity add/remove ref // Do not implicity add/remove ref
@ -3405,7 +3413,8 @@ void SquirrelVM::WriteObject( const SQObjectPtr &obj, CUtlBuffer* pBuffer, Write
#ifdef _DEBUG #ifdef _DEBUG
bool bAsserted = false; bool bAsserted = false;
if ( pThis->_noutervalues && pThis->_name._type == OT_STRING && pThis->_name._unVal.pString ) if ( pThis->_noutervalues && pThis->_name._type == OT_STRING && pThis->_name._unVal.pString &&
pThis->_outervalues[0]._type == OT_USERPOINTER )
{ {
Assert( pThis->_noutervalues == 1 ); Assert( pThis->_noutervalues == 1 );
Assert( pThis->_outervalues[0]._type == OT_USERPOINTER ); Assert( pThis->_outervalues[0]._type == OT_USERPOINTER );
@ -3708,23 +3717,25 @@ void SquirrelVM::WriteObject( const SQObjectPtr &obj, CUtlBuffer* pBuffer, Write
if ( pThis->_callsstacksize ) if ( pThis->_callsstacksize )
{ {
int stackidx = -1; for ( int i = 0; i < pThis->_callsstacksize; i++ )
for ( int i = pThis->_callsstacksize; i--; )
{ {
const SQVM::CallInfo *ci = &pThis->_callsstack[i]; const SQVM::CallInfo *ci = &pThis->_callsstack[i];
if ( pThis->ci == ci ) Assert( ci->_ip >= ci->_closure._unVal.pClosure->_function->_instructions &&
stackidx = i; ci->_ip < ci->_closure._unVal.pClosure->_function->_instructions +
ci->_closure._unVal.pClosure->_function->_ninstructions );
Assert( !ci->_generator );
Assert( ci->_ip && ci->_ip >= ci->_closure._unVal.pClosure->_function->_instructions );
Assert( pThis->_etraps.size() >= (SQUnsignedInteger)ci->_etraps ); Assert( pThis->_etraps.size() >= (SQUnsignedInteger)ci->_etraps );
Assert( ci->_closure._type == OT_CLOSURE && ci->_closure._unVal.pClosure ); Assert( ci->_closure._type == OT_CLOSURE && ci->_closure._unVal.pClosure );
WriteObject( ci->_closure, pBuffer, writeState ); WriteObject( ci->_closure, pBuffer, writeState );
int offset = (int)ci->_ip - (int)ci->_closure._unVal.pClosure->_function->_instructions; Assert( ci->_ip - ci->_closure._unVal.pClosure->_function->_instructions <= INT_MAX );
pBuffer->PutChar( ci->_generator != 0 );
if ( ci->_generator )
WriteObject( ci->_generator, pBuffer, writeState );
int offset = ci->_ip - ci->_closure._unVal.pClosure->_function->_instructions;
pBuffer->PutInt( offset ); pBuffer->PutInt( offset );
pBuffer->PutInt( ci->_etraps ); pBuffer->PutInt( ci->_etraps );
pBuffer->PutInt( ci->_prevstkbase ); pBuffer->PutInt( ci->_prevstkbase );
@ -3733,16 +3744,18 @@ void SquirrelVM::WriteObject( const SQObjectPtr &obj, CUtlBuffer* pBuffer, Write
pBuffer->PutInt( ci->_ncalls ); pBuffer->PutInt( ci->_ncalls );
pBuffer->PutChar( ci->_root ); pBuffer->PutChar( ci->_root );
for ( int j = ci->_etraps; j--; ) for ( int j = 0; j < ci->_etraps; j++ )
{ {
const SQExceptionTrap &et = pThis->_etraps[j]; const SQExceptionTrap &et = pThis->_etraps[j];
pBuffer->PutInt( et._extarget );
pBuffer->PutInt( et._stackbase );
pBuffer->PutInt( et._stacksize ); pBuffer->PutInt( et._stacksize );
Assert( et._ip == ci->_ip ); pBuffer->PutInt( et._stackbase );
Assert( et._ip - ci->_ip <= INT_MAX );
pBuffer->PutInt( et._ip - ci->_ip );
pBuffer->PutInt( et._extarget );
} }
} }
int stackidx = pThis->ci - pThis->_callsstack;
Assert( stackidx >= 0 && stackidx < pThis->_callsstacksize ); Assert( stackidx >= 0 && stackidx < pThis->_callsstacksize );
pBuffer->PutInt( stackidx ); pBuffer->PutInt( stackidx );
} }
@ -3773,29 +3786,37 @@ void SquirrelVM::WriteObject( const SQObjectPtr &obj, CUtlBuffer* pBuffer, Write
WriteObject( pThis->_closure, pBuffer, writeState ); WriteObject( pThis->_closure, pBuffer, writeState );
const SQVM::CallInfo &ci = pThis->_ci; const SQVM::CallInfo *ci = &pThis->_ci;
Assert( !ci._generator ); Assert( pThis->_closure._unVal.pClosure == ci->_closure._unVal.pClosure );
Assert( pThis->_closure._unVal.pClosure == ci._closure._unVal.pClosure ); Assert( ci->_ip >= ci->_closure._unVal.pClosure->_function->_instructions &&
Assert( ci._ip && ci._ip >= ci._closure._unVal.pClosure->_function->_instructions ); ci->_ip < ci->_closure._unVal.pClosure->_function->_instructions +
Assert( pThis->_etraps.size() >= (SQUnsignedInteger)ci._etraps ); ci->_closure._unVal.pClosure->_function->_ninstructions );
Assert( pThis->_etraps.size() >= (SQUnsignedInteger)ci->_etraps );
int offset = (int)ci._ip - (int)ci._closure._unVal.pClosure->_function->_instructions; Assert( ci->_ip - ci->_closure._unVal.pClosure->_function->_instructions <= INT_MAX );
pBuffer->PutChar( ci->_generator != 0 );
if ( ci->_generator )
WriteObject( ci->_generator, pBuffer, writeState );
int offset = ci->_ip - ci->_closure._unVal.pClosure->_function->_instructions;
pBuffer->PutInt( offset ); pBuffer->PutInt( offset );
pBuffer->PutInt( ci._etraps ); pBuffer->PutInt( ci->_etraps );
pBuffer->PutInt( ci._prevstkbase ); pBuffer->PutInt( ci->_prevstkbase );
pBuffer->PutInt( ci._prevtop ); pBuffer->PutInt( ci->_prevtop );
pBuffer->PutInt( ci._target ); pBuffer->PutInt( ci->_target );
pBuffer->PutInt( ci._ncalls ); pBuffer->PutInt( ci->_ncalls );
pBuffer->PutChar( ci._root ); pBuffer->PutChar( ci->_root );
for ( int j = ci._etraps; j--; ) for ( int j = 0; j < ci->_etraps; j++ )
{ {
const SQExceptionTrap &et = pThis->_etraps[j]; const SQExceptionTrap &et = pThis->_etraps[j];
pBuffer->PutInt( et._extarget );
pBuffer->PutInt( et._stackbase );
pBuffer->PutInt( et._stacksize ); pBuffer->PutInt( et._stacksize );
Assert( et._ip == ci._ip ); pBuffer->PutInt( et._stackbase );
Assert( et._ip - ci->_ip <= INT_MAX );
pBuffer->PutInt( et._ip - ci->_ip );
pBuffer->PutInt( et._extarget );
} }
int stacksize = pThis->_stack.size(); int stacksize = pThis->_stack.size();
@ -3809,7 +3830,6 @@ void SquirrelVM::WriteObject( const SQObjectPtr &obj, CUtlBuffer* pBuffer, Write
} }
case OT_USERDATA: case OT_USERDATA:
case OT_USERPOINTER: case OT_USERPOINTER:
Assert(0);
break; break;
default: default:
AssertMsgAlways( 0, "SquirrelVM::WriteObject: unknown type" ); AssertMsgAlways( 0, "SquirrelVM::WriteObject: unknown type" );
@ -3853,26 +3873,10 @@ void SquirrelVM::ReadObject( SQObjectPtr &pObj, CUtlBuffer* pBuffer, ReadStateMa
case OT_STRING: case OT_STRING:
{ {
int len = pBuffer->GetInt(); int len = pBuffer->GetInt();
char *psz; char *psz = (char*)pBuffer->PeekGet( 0 );
pBuffer->SeekGet( CUtlBuffer::SEEK_CURRENT, len );
if ( len < 1024 ) Assert( pBuffer->IsValid() );
{
psz = (char*)stackalloc( len );
}
else
{
psz = (char*)malloc( len );
}
pBuffer->Get( psz, len );
obj._unVal.pString = SQString::Create( _ss(vm_), psz, len ); obj._unVal.pString = SQString::Create( _ss(vm_), psz, len );
if ( len >= 1024 )
{
free( psz );
}
break; break;
} }
case OT_TABLE: case OT_TABLE:
@ -4358,10 +4362,10 @@ void SquirrelVM::ReadObject( SQObjectPtr &pObj, CUtlBuffer* pBuffer, ReadStateMa
if ( pThis->_callsstacksize ) if ( pThis->_callsstacksize )
{ {
if ( pThis->_callsstacksize >= pThis->_alloccallsstacksize ) while ( pThis->_callsstacksize >= pThis->_alloccallsstacksize )
pThis->GrowCallStack(); pThis->GrowCallStack();
for ( int i = pThis->_callsstacksize; i--; ) for ( int i = 0; i < pThis->_callsstacksize; i++ )
{ {
SQVM::CallInfo *ci = &pThis->_callsstack[i]; SQVM::CallInfo *ci = &pThis->_callsstack[i];
@ -4369,23 +4373,31 @@ void SquirrelVM::ReadObject( SQObjectPtr &pObj, CUtlBuffer* pBuffer, ReadStateMa
ReadObject( closure, pBuffer, readState ); ReadObject( closure, pBuffer, readState );
Assert( closure._type == OT_CLOSURE && closure._unVal.pClosure ); Assert( closure._type == OT_CLOSURE && closure._unVal.pClosure );
int offset = pBuffer->GetInt(); if ( pBuffer->GetChar() )
int funcsize = sizeof(SQInstruction) * closure._unVal.pClosure->_function->_ninstructions;
int start = (int)(closure._unVal.pClosure->_function->_instructions);
int pos = start + offset;
ci->_ip = (SQInstruction*)pos;
Assert( pos < (start + funcsize) );
// don't read past boundary
if ( pos >= (start + funcsize) )
{ {
ci->_ip = (SQInstruction*)start; SQObject generator;
ReadObject( generator, pBuffer, readState );
Assert( generator._type == OT_GENERATOR && generator._unVal.pGenerator );
ci->_generator = generator._unVal.pGenerator;
}
else
{
ci->_generator = NULL;
} }
int offset = pBuffer->GetInt();
SQInstruction *start = closure._unVal.pClosure->_function->_instructions;
SQInstruction *end = start + closure._unVal.pClosure->_function->_ninstructions;
SQInstruction *pos = start + offset;
Assert( pos >= start && pos < end );
if ( pos < start || pos >= end )
pos = start;
ci->_ip = pos;
ci->_literals = closure._unVal.pClosure->_function->_literals; ci->_literals = closure._unVal.pClosure->_function->_literals;
ci->_closure = closure; ci->_closure = closure;
ci->_generator = NULL;
ci->_etraps = pBuffer->GetInt(); ci->_etraps = pBuffer->GetInt();
ci->_prevstkbase = pBuffer->GetInt(); ci->_prevstkbase = pBuffer->GetInt();
ci->_prevtop = pBuffer->GetInt(); ci->_prevtop = pBuffer->GetInt();
@ -4395,13 +4407,13 @@ void SquirrelVM::ReadObject( SQObjectPtr &pObj, CUtlBuffer* pBuffer, ReadStateMa
pThis->_etraps.resize( ci->_etraps ); pThis->_etraps.resize( ci->_etraps );
for ( int j = ci->_etraps; j--; ) for ( int j = 0; j < ci->_etraps; j++ )
{ {
SQExceptionTrap &et = pThis->_etraps[j]; SQExceptionTrap &et = pThis->_etraps[j];
et._extarget = pBuffer->GetInt();
et._stackbase = pBuffer->GetInt();
et._stacksize = pBuffer->GetInt(); et._stacksize = pBuffer->GetInt();
et._ip = ci->_ip; et._stackbase = pBuffer->GetInt();
et._ip = ci->_ip + pBuffer->GetInt();
et._extarget = pBuffer->GetInt();
} }
} }
@ -4448,41 +4460,49 @@ void SquirrelVM::ReadObject( SQObjectPtr &pObj, CUtlBuffer* pBuffer, ReadStateMa
pThis->_state = (SQGenerator::SQGeneratorState)state; pThis->_state = (SQGenerator::SQGeneratorState)state;
SQVM::CallInfo &ci = pThis->_ci; SQVM::CallInfo *ci = &pThis->_ci;
int offset = pBuffer->GetInt(); if ( pBuffer->GetChar() )
int funcsize = sizeof(SQInstruction) * closure._unVal.pClosure->_function->_ninstructions;
int start = (int)(closure._unVal.pClosure->_function->_instructions);
int pos = start + offset;
ci._ip = (SQInstruction*)pos;
Assert( pos < (start + funcsize) );
// don't read past boundary
if ( pos >= (start + funcsize) )
{ {
ci._ip = (SQInstruction*)start; SQObject generator;
ReadObject( generator, pBuffer, readState );
Assert( generator._type == OT_GENERATOR && generator._unVal.pGenerator );
ci->_generator = generator._unVal.pGenerator;
}
else
{
ci->_generator = NULL;
} }
ci._literals = closure._unVal.pClosure->_function->_literals; int offset = pBuffer->GetInt();
ci._closure = closure; SQInstruction *start = closure._unVal.pClosure->_function->_instructions;
ci._generator = NULL; SQInstruction *end = start + closure._unVal.pClosure->_function->_ninstructions;
ci._etraps = pBuffer->GetInt(); SQInstruction *pos = start + offset;
ci._prevstkbase = pBuffer->GetInt();
ci._prevtop = pBuffer->GetInt();
ci._target = pBuffer->GetInt();
ci._ncalls = pBuffer->GetInt();
ci._root = pBuffer->GetChar();
pThis->_etraps.resize( ci._etraps ); Assert( pos >= start && pos < end );
for ( int j = ci._etraps; j--; ) if ( pos < start || pos >= end )
pos = start;
ci->_ip = pos;
ci->_literals = closure._unVal.pClosure->_function->_literals;
ci->_closure = closure;
ci->_etraps = pBuffer->GetInt();
ci->_prevstkbase = pBuffer->GetInt();
ci->_prevtop = pBuffer->GetInt();
ci->_target = pBuffer->GetInt();
ci->_ncalls = pBuffer->GetInt();
ci->_root = pBuffer->GetChar();
pThis->_etraps.resize( ci->_etraps );
for ( int j = 0; j < ci->_etraps; j++ )
{ {
SQExceptionTrap &et = pThis->_etraps[j]; SQExceptionTrap &et = pThis->_etraps[j];
et._extarget = pBuffer->GetInt();
et._stackbase = pBuffer->GetInt();
et._stacksize = pBuffer->GetInt(); et._stacksize = pBuffer->GetInt();
et._ip = ci._ip; et._stackbase = pBuffer->GetInt();
et._ip = ci->_ip + pBuffer->GetInt();
et._extarget = pBuffer->GetInt();
} }
int stacksize = pBuffer->GetInt(); int stacksize = pBuffer->GetInt();
@ -4496,10 +4516,7 @@ void SquirrelVM::ReadObject( SQObjectPtr &pObj, CUtlBuffer* pBuffer, ReadStateMa
} }
case OT_USERDATA: case OT_USERDATA:
case OT_USERPOINTER: case OT_USERPOINTER:
{
Assert(0);
break; break;
}
default: default:
AssertMsgAlways( 0, "SquirrelVM::ReadObject: serialisation error" ); AssertMsgAlways( 0, "SquirrelVM::ReadObject: serialisation error" );
} }