forked from Mirrors/openclonk
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
parent
5bb3d7cb77
commit
45003d55fb
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in New Issue