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
Günther Brammer 2015-01-30 20:33:57 +01:00
parent 915ae02178
commit a5af9089a8
4 changed files with 20 additions and 7 deletions

View File

@ -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();

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}