mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-07-27 07:31:49 +03:00
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.
This commit is contained in:
parent
c851fc9bfb
commit
681a75a6a7
@ -263,6 +263,8 @@ inline const char * ScriptFieldTypeName( int16 eType)
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
struct ScriptClassDesc_t;
|
||||
|
||||
struct ScriptFuncDescriptor_t
|
||||
{
|
||||
ScriptFuncDescriptor_t()
|
||||
@ -270,11 +272,13 @@ struct ScriptFuncDescriptor_t
|
||||
m_pszFunction = NULL;
|
||||
m_ReturnType = FIELD_TYPEUNKNOWN;
|
||||
m_pszDescription = NULL;
|
||||
m_pScriptClassDesc = NULL;
|
||||
}
|
||||
|
||||
const char *m_pszScriptName;
|
||||
const char *m_pszFunction;
|
||||
const char *m_pszDescription;
|
||||
ScriptClassDesc_t *m_pScriptClassDesc;
|
||||
ScriptDataType_t m_ReturnType;
|
||||
CUtlVector<ScriptDataType_t> m_Parameters;
|
||||
};
|
||||
|
@ -61,7 +61,7 @@ FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNC_TYPE_DEDUCER );
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNC_TYPE_DEDUCER );
|
||||
|
||||
#define ScriptInitMemberFuncDescriptor_( pDesc, class, func, scriptName ) if ( 0 ) {} else { (pDesc)->m_pszScriptName = scriptName; (pDesc)->m_pszFunction = #func; ScriptDeduceFunctionSignature( pDesc, (class *)(0), &class::func ); }
|
||||
#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); }
|
||||
|
||||
#define ScriptInitFuncDescriptorNamed( pDesc, func, scriptName ) if ( 0 ) {} else { (pDesc)->m_pszScriptName = scriptName; (pDesc)->m_pszFunction = #func; ScriptDeduceFunctionSignature( pDesc, &func ); }
|
||||
#define ScriptInitFuncDescriptor( pDesc, func ) ScriptInitFuncDescriptorNamed( pDesc, func, #func )
|
||||
|
@ -1427,18 +1427,30 @@ SQInteger function_stub(HSQUIRRELVM vm)
|
||||
|
||||
if (pFunc->m_flags & SF_MEMBER_FUNC)
|
||||
{
|
||||
SQUserPointer self;
|
||||
if (SQ_FAILED(sq_getinstanceup(vm, 1, &self, 0)))
|
||||
ClassInstanceData* classInstanceData;
|
||||
if (SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&classInstanceData, 0)))
|
||||
{
|
||||
return sq_throwerror(vm, "Expected class userpointer");
|
||||
return SQ_ERROR;
|
||||
}
|
||||
|
||||
if (!self)
|
||||
if (!classInstanceData)
|
||||
{
|
||||
return sq_throwerror(vm, "Accessed null instance");
|
||||
}
|
||||
|
||||
instance = ((ClassInstanceData*)self)->instance;
|
||||
// check that the type of self, or any basetype, matches the function description
|
||||
ScriptClassDesc_t *selfType = classInstanceData->desc;
|
||||
while (selfType != pFunc->m_desc.m_pScriptClassDesc)
|
||||
{
|
||||
if (!selfType)
|
||||
{
|
||||
return sq_throwerror(vm, "Mismatched instance type");
|
||||
}
|
||||
selfType = selfType->m_pBaseDesc;
|
||||
Assert(selfType != classInstanceData->desc); // there should be no infinite loop
|
||||
}
|
||||
|
||||
instance = classInstanceData->instance;
|
||||
}
|
||||
|
||||
ScriptVariant_t script_retval;
|
||||
|
Loading…
x
Reference in New Issue
Block a user