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
|
struct ScriptFuncDescriptor_t
|
||||||
{
|
{
|
||||||
ScriptFuncDescriptor_t()
|
ScriptFuncDescriptor_t()
|
||||||
@ -270,11 +272,13 @@ struct ScriptFuncDescriptor_t
|
|||||||
m_pszFunction = NULL;
|
m_pszFunction = NULL;
|
||||||
m_ReturnType = FIELD_TYPEUNKNOWN;
|
m_ReturnType = FIELD_TYPEUNKNOWN;
|
||||||
m_pszDescription = NULL;
|
m_pszDescription = NULL;
|
||||||
|
m_pScriptClassDesc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *m_pszScriptName;
|
const char *m_pszScriptName;
|
||||||
const char *m_pszFunction;
|
const char *m_pszFunction;
|
||||||
const char *m_pszDescription;
|
const char *m_pszDescription;
|
||||||
|
ScriptClassDesc_t *m_pScriptClassDesc;
|
||||||
ScriptDataType_t m_ReturnType;
|
ScriptDataType_t m_ReturnType;
|
||||||
CUtlVector<ScriptDataType_t> m_Parameters;
|
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 );
|
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 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 )
|
#define ScriptInitFuncDescriptor( pDesc, func ) ScriptInitFuncDescriptorNamed( pDesc, func, #func )
|
||||||
|
@ -1427,18 +1427,30 @@ SQInteger function_stub(HSQUIRRELVM vm)
|
|||||||
|
|
||||||
if (pFunc->m_flags & SF_MEMBER_FUNC)
|
if (pFunc->m_flags & SF_MEMBER_FUNC)
|
||||||
{
|
{
|
||||||
SQUserPointer self;
|
ClassInstanceData* classInstanceData;
|
||||||
if (SQ_FAILED(sq_getinstanceup(vm, 1, &self, 0)))
|
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");
|
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;
|
ScriptVariant_t script_retval;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user