boost::thread_specific_ptr<std::stack<ScriptFrame *> > ScriptFrame::m_ScriptFrames;
ScriptFrame::ScriptFrame(void)
- : Locals(new Dictionary()), Self(ScriptGlobal::GetGlobals()), Sandboxed(false)
+ : Locals(new Dictionary()), Self(ScriptGlobal::GetGlobals()), Sandboxed(false), Depth(0)
{
PushFrame(this);
}
ScriptFrame::ScriptFrame(const Value& self)
- : Locals(new Dictionary()), Self(self), Sandboxed(false)
+ : Locals(new Dictionary()), Self(self), Sandboxed(false), Depth(0)
{
PushFrame(this);
}
ASSERT(frame == this);
}
+void ScriptFrame::IncreaseStackDepth(void)
+{
+ if (Depth + 1 > 300)
+ BOOST_THROW_EXCEPTION(ScriptError("Stack overflow while evaluating expression: Recursion level too deep."));
+
+ Depth++;
+}
+
+void ScriptFrame::DecreaseStackDepth(void)
+{
+ Depth--;
+}
+
ScriptFrame *ScriptFrame::GetCurrentFrame(void)
{
std::stack<ScriptFrame *> *frames = m_ScriptFrames.get();
m_ScriptFrames.reset(frames);
}
- if (frames->size() > 500)
- BOOST_THROW_EXCEPTION(ScriptError("Recursion level too deep."));
+ if (!frames->empty()) {
+ ScriptFrame *parent = frames->top();
+ frame->Depth += parent->Depth;
+ }
frames->push(frame);
}
Dictionary::Ptr Locals;
Value Self;
bool Sandboxed;
+ int Depth;
ScriptFrame(void);
ScriptFrame(const Value& self);
~ScriptFrame(void);
+ void IncreaseStackDepth(void);
+ void DecreaseStackDepth(void);
+
static ScriptFrame *GetCurrentFrame(void);
private:
<< "Executing:\n" << msgbuf.str();*/
#endif /* I2_DEBUG */
- return DoEvaluate(frame, dhint);
+ frame.IncreaseStackDepth();
+ ExpressionResult result = DoEvaluate(frame, dhint);
+ frame.DecreaseStackDepth();
+ return result;
} catch (ScriptError& ex) {
+ frame.DecreaseStackDepth();
+
ScriptBreakpoint(frame, &ex, GetDebugInfo());
throw;
} catch (const std::exception& ex) {
+ frame.DecreaseStackDepth();
+
BOOST_THROW_EXCEPTION(ScriptError("Error while evaluating expression: " + String(ex.what()), GetDebugInfo())
<< boost::errinfo_nested_exception(boost::current_exception()));
}
+
+ frame.DecreaseStackDepth();
}
bool Expression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const