Skip to content

Commit 3e2f0f9

Browse files
committed
Check ScriptClassDesc_t of squirrel instance for native member function call
This enhances the ScriptFuncDescriptor_t to record the ScriptClassDesc_t of the class for which it gets invoked. The ScriptClassDesc_t are traversed in the function_stub() for native function calls for member functions, to ensure the passed in instance has a compatible type. This prevents memory errors when incorrectly invoking native member functions from Squirrel.
1 parent a03e6b0 commit 3e2f0f9

3 files changed

Lines changed: 20 additions & 2 deletions

File tree

sp/src/public/vscript/ivscript.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,18 +263,22 @@ inline const char * ScriptFieldTypeName( int16 eType)
263263

264264
//---------------------------------------------------------
265265

266+
struct ScriptClassDesc_t;
267+
266268
struct ScriptFuncDescriptor_t
267269
{
268270
ScriptFuncDescriptor_t()
269271
{
270272
m_pszFunction = NULL;
271273
m_ReturnType = FIELD_TYPEUNKNOWN;
272274
m_pszDescription = NULL;
275+
m_pScriptClassDesc = NULL;
273276
}
274277

275278
const char *m_pszScriptName;
276279
const char *m_pszFunction;
277280
const char *m_pszDescription;
281+
ScriptClassDesc_t *m_pScriptClassDesc;
278282
ScriptDataType_t m_ReturnType;
279283
CUtlVector<ScriptDataType_t> m_Parameters;
280284
};

sp/src/public/vscript/vscript_templates.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNC_TYPE_DEDUCER );
6161

6262
FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNC_TYPE_DEDUCER );
6363

64-
#define ScriptInitMemberFuncDescriptor_( pDesc, class, func, scriptName ) if ( 0 ) {} else { (pDesc)->m_pszScriptName = scriptName; (pDesc)->m_pszFunction = #func; ScriptDeduceFunctionSignature( pDesc, (class *)(0), &class::func ); }
64+
#define ScriptInitMemberFuncDescriptor_( pDesc, class, func, scriptName ) if ( 0 ) {} else { (pDesc)->m_pszScriptName = scriptName; (pDesc)->m_pszFunction = #func; ScriptDeduceFunctionSignature( pDesc, (class *)(0), &class::func ); (pDesc)->m_pScriptClassDesc = GetScriptDesc<class>(nullptr); }
6565

6666
#define ScriptInitFuncDescriptorNamed( pDesc, func, scriptName ) if ( 0 ) {} else { (pDesc)->m_pszScriptName = scriptName; (pDesc)->m_pszFunction = #func; ScriptDeduceFunctionSignature( pDesc, &func ); }
6767
#define ScriptInitFuncDescriptor( pDesc, func ) ScriptInitFuncDescriptorNamed( pDesc, func, #func )

sp/src/vscript/vscript_squirrel.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1435,7 +1435,21 @@ SQInteger function_stub(HSQUIRRELVM vm)
14351435
return sq_throwerror(vm, "Accessed null instance");
14361436
}
14371437

1438-
instance = ((ClassInstanceData*)self)->instance;
1438+
ClassInstanceData* classInstanceData = (ClassInstanceData*)self;
1439+
1440+
// check that the type of self, or any basetype, matches the function description
1441+
ScriptClassDesc_t *selfType = classInstanceData->desc;
1442+
while (selfType != pFunc->m_desc.m_pScriptClassDesc)
1443+
{
1444+
selfType = selfType->m_pBaseDesc;
1445+
Assert(selfType != classInstanceData->desc); // there should be no infinite loop
1446+
if (!selfType)
1447+
{
1448+
return sq_throwerror(vm, "Mismatched instance type");
1449+
}
1450+
}
1451+
1452+
instance = classInstanceData->instance;
14391453
}
14401454

14411455
ScriptVariant_t script_retval;

0 commit comments

Comments
 (0)