forked from Mirrors/openclonk
Script: Check parameter types of engine callbacks, too
This prevents a crash when an incompatible engine function is used as an engine callback function. Unfortunately, this breaks any scripts that have wrong type information in engine callbacks and only worked because those were ignored.objectmenu
parent
915ae02178
commit
a5af9089a8
|
@ -828,7 +828,7 @@ C4AulBCC *C4AulExec::Call(C4AulFunc *pFunc, C4Value *pReturn, C4Value *pPars, C4
|
|||
pContext = pCurCtx->Obj;
|
||||
}
|
||||
|
||||
pFunc->CheckParTypes(pPars);
|
||||
pFunc->CheckParTypes(pPars, true);
|
||||
|
||||
// Script function?
|
||||
C4AulScriptFunc *pSFunc = pFunc->SFunc();
|
||||
|
|
|
@ -61,14 +61,24 @@ StdStrBuf C4AulFunc::GetFullName()
|
|||
return r;
|
||||
}
|
||||
|
||||
void C4AulFunc::CheckParTypes(const C4Value pPars[]) const {
|
||||
bool C4AulFunc::CheckParTypes(const C4Value pPars[], bool fPassErrors) const {
|
||||
// Convert parameters (typecheck)
|
||||
const C4V_Type *pTypes = GetParType();
|
||||
int parcount = GetParCount();
|
||||
for (int i = 0; i < parcount; i++) {
|
||||
if (!pPars[i].CheckParConversion(pTypes[i]))
|
||||
throw C4AulExecError(FormatString("call to \"%s\" parameter %d: passed %s, but expected %s",
|
||||
GetName(), i + 1, pPars[i].GetTypeName(), GetC4VName(pTypes[i])
|
||||
).getData());
|
||||
{
|
||||
C4AulExecError e(FormatString(
|
||||
"call to \"%s\" parameter %d: passed %s, but expected %s",
|
||||
GetName(), i + 1, pPars[i].GetTypeName(), GetC4VName(pTypes[i])).getData());
|
||||
if (fPassErrors)
|
||||
throw e;
|
||||
else
|
||||
{
|
||||
e.show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -79,10 +79,14 @@ public:
|
|||
virtual C4V_Type GetRetType() const = 0;
|
||||
C4Value Exec(C4PropList * p = NULL, C4AulParSet *pPars = NULL, bool fPassErrors=false)
|
||||
{
|
||||
// Every parameter type allows conversion from nil, so no parameters are always allowed
|
||||
if (!pPars)
|
||||
return Exec(p, C4AulParSet().Par, fPassErrors);
|
||||
if (!CheckParTypes(pPars->Par, fPassErrors)) return C4Value();
|
||||
return Exec(p, pPars->Par, fPassErrors);
|
||||
}
|
||||
virtual C4Value Exec(C4PropList * p, C4Value pPars[], bool fPassErrors=false) = 0;
|
||||
void CheckParTypes(const C4Value pPars[]) const;
|
||||
bool CheckParTypes(const C4Value pPars[], bool fPassErrors) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -349,7 +349,6 @@ static C4Value FnCall(C4PropList * _this, C4Value * Pars)
|
|||
}
|
||||
if (!fn)
|
||||
throw C4AulExecError(FormatString("Call: no function %s", Pars[0].GetDataString().getData()).getData());
|
||||
fn->CheckParTypes(ParSet.Par);
|
||||
return fn->Exec(_this, &ParSet, true);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue