Guard against script stack overflow on the first script call, too

This can happen when an engine function is made to call a script function
when the stack is almost exhausted. Since there was nothing catching that
exception, it'd mean a program abort. Move the bulk of the exception
handler to the outer Exec function, and only keep the saving of the exact
code position in the inner one.

While at it, simplify the pushing of the parameters to simply push the
right amount of parameters instead of pushing ten and then popping the
excess. Also move the creation of dummy parameters for DirectExec into
DirectExec().
liquid_container
Günther Brammer 2016-01-15 23:39:44 +01:00
parent 5bb3d7cb77
commit 45003d55fb
2 changed files with 48 additions and 49 deletions

View File

@ -146,37 +146,53 @@ void C4AulExec::ClearPointers(C4Object * obj)
C4Value C4AulExec::Exec(C4AulScriptFunc *pSFunc, C4PropList * p, C4Value *pnPars, bool fPassErrors)
{
// Push parameters
C4Value *pPars = pCurVal + 1;
if (pnPars)
for (int i = 0; i < C4AUL_MAX_Par; i++)
PushValue(pnPars[i]);
if (pCurVal + 1 - pPars > pSFunc->GetParCount())
PopValues(pCurVal + 1 - pPars - pSFunc->GetParCount());
else
PushNullVals(pSFunc->GetParCount() - (pCurVal + 1 - pPars));
// Push a new context
C4AulScriptContext ctx;
ctx.tTime = 0;
ctx.Obj = p;
ctx.Return = NULL;
ctx.Pars = pPars;
ctx.Vars = pCurVal + 1;
ctx.Func = pSFunc;
ctx.CPos = NULL;
PushContext(ctx);
// Execute
return Exec(pSFunc->GetCode(), fPassErrors);
}
C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
{
// Save start context
C4AulScriptContext *pOldCtx = pCurCtx;
C4Value *pPars = pCurVal + 1;
try
{
// Push parameters
assert(pnPars);
for (int i = 0; i < pSFunc->GetParCount(); i++)
PushValue(pnPars[i]);
// Push a new context
C4AulScriptContext ctx;
ctx.tTime = 0;
ctx.Obj = p;
ctx.Return = NULL;
ctx.Pars = pPars;
ctx.Vars = pCurVal + 1;
ctx.Func = pSFunc;
ctx.CPos = NULL;
PushContext(ctx);
// Execute
return Exec(pSFunc->GetCode());
}
catch (C4AulError &e)
{
if(!e.shown) e.show();
// Unwind stack
while (pCurCtx > pOldCtx)
{
pCurCtx->dump(StdStrBuf(" by: "));
PopContext();
}
PopValuesUntil(pPars - 1);
// Pass?
if (fPassErrors)
throw;
// Trace
LogCallStack();
}
// Return nothing
return C4VNull;
}
C4Value C4AulExec::Exec(C4AulBCC *pCPos)
{
try
{
@ -792,29 +808,11 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
}
catch (C4AulError &e)
{
if(!e.shown) e.show();
// Save current position
assert(pCurCtx->Func->GetCode() <= pCPos);
pCurCtx->CPos = pCPos;
// Unwind stack
C4Value *pUntil = NULL;
while (pCurCtx >= pOldCtx)
{
pCurCtx->dump(StdStrBuf(" by: "));
pUntil = pCurCtx->Pars - 1;
PopContext();
}
if (pUntil)
PopValuesUntil(pUntil);
// Pass?
if (fPassErrors)
throw;
// Trace
LogCallStack();
throw;
}
// Return nothing
return C4VNull;
}
C4AulBCC *C4AulExec::Call(C4AulFunc *pFunc, C4Value *pReturn, C4Value *pPars, C4PropList *pContext)
@ -1038,7 +1036,8 @@ C4Value C4AulExec::DirectExec(C4PropList *p, const char *szScript, const char *s
try
{
pFunc->ParseFn(&::ScriptEngine, context);
C4Value vRetVal(Exec(pFunc.get(), p, NULL, fPassErrors));
C4AulParSet Pars;
C4Value vRetVal(Exec(pFunc.get(), p, Pars.Par, fPassErrors));
// profiler
StopDirectExec();
return vRetVal;

View File

@ -79,7 +79,6 @@ private:
friend class C4AulProfiler;
public:
C4Value Exec(C4AulScriptFunc *pSFunc, C4PropList * p, C4Value pPars[], bool fPassErrors);
C4Value Exec(C4AulBCC *pCPos, bool fPassErrors);
C4Value DirectExec(C4PropList *p, const char *szScript, const char *szContext, bool fPassErrors = false, C4AulScriptContext* context = NULL);
void StartTrace();
@ -94,6 +93,7 @@ public:
void ClearPointers(C4Object *);
private:
C4Value Exec(C4AulBCC *pCPos);
void PushContext(const C4AulScriptContext &rContext);
void PopContext();