mirror of https://github.com/Icinga/icinga2.git
Implement recursion limit for AST expressions which don't use a separate stack frame
fixes #11106
This commit is contained in:
parent
71060be89a
commit
6ba0c5fe01
|
@ -26,13 +26,13 @@ using namespace icinga;
|
||||||
boost::thread_specific_ptr<std::stack<ScriptFrame *> > ScriptFrame::m_ScriptFrames;
|
boost::thread_specific_ptr<std::stack<ScriptFrame *> > ScriptFrame::m_ScriptFrames;
|
||||||
|
|
||||||
ScriptFrame::ScriptFrame(void)
|
ScriptFrame::ScriptFrame(void)
|
||||||
: Locals(new Dictionary()), Self(ScriptGlobal::GetGlobals()), Sandboxed(false)
|
: Locals(new Dictionary()), Self(ScriptGlobal::GetGlobals()), Sandboxed(false), Depth(0)
|
||||||
{
|
{
|
||||||
PushFrame(this);
|
PushFrame(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptFrame::ScriptFrame(const Value& self)
|
ScriptFrame::ScriptFrame(const Value& self)
|
||||||
: Locals(new Dictionary()), Self(self), Sandboxed(false)
|
: Locals(new Dictionary()), Self(self), Sandboxed(false), Depth(0)
|
||||||
{
|
{
|
||||||
PushFrame(this);
|
PushFrame(this);
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,19 @@ ScriptFrame::~ScriptFrame(void)
|
||||||
ASSERT(frame == 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)
|
ScriptFrame *ScriptFrame::GetCurrentFrame(void)
|
||||||
{
|
{
|
||||||
std::stack<ScriptFrame *> *frames = m_ScriptFrames.get();
|
std::stack<ScriptFrame *> *frames = m_ScriptFrames.get();
|
||||||
|
@ -72,8 +85,10 @@ void ScriptFrame::PushFrame(ScriptFrame *frame)
|
||||||
m_ScriptFrames.reset(frames);
|
m_ScriptFrames.reset(frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frames->size() > 500)
|
if (!frames->empty()) {
|
||||||
BOOST_THROW_EXCEPTION(ScriptError("Recursion level too deep."));
|
ScriptFrame *parent = frames->top();
|
||||||
|
frame->Depth += parent->Depth;
|
||||||
|
}
|
||||||
|
|
||||||
frames->push(frame);
|
frames->push(frame);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,11 +33,15 @@ struct I2_BASE_API ScriptFrame
|
||||||
Dictionary::Ptr Locals;
|
Dictionary::Ptr Locals;
|
||||||
Value Self;
|
Value Self;
|
||||||
bool Sandboxed;
|
bool Sandboxed;
|
||||||
|
int Depth;
|
||||||
|
|
||||||
ScriptFrame(void);
|
ScriptFrame(void);
|
||||||
ScriptFrame(const Value& self);
|
ScriptFrame(const Value& self);
|
||||||
~ScriptFrame(void);
|
~ScriptFrame(void);
|
||||||
|
|
||||||
|
void IncreaseStackDepth(void);
|
||||||
|
void DecreaseStackDepth(void);
|
||||||
|
|
||||||
static ScriptFrame *GetCurrentFrame(void);
|
static ScriptFrame *GetCurrentFrame(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -61,14 +61,23 @@ ExpressionResult Expression::Evaluate(ScriptFrame& frame, DebugHint *dhint) cons
|
||||||
<< "Executing:\n" << msgbuf.str();*/
|
<< "Executing:\n" << msgbuf.str();*/
|
||||||
#endif /* I2_DEBUG */
|
#endif /* I2_DEBUG */
|
||||||
|
|
||||||
return DoEvaluate(frame, dhint);
|
frame.IncreaseStackDepth();
|
||||||
|
ExpressionResult result = DoEvaluate(frame, dhint);
|
||||||
|
frame.DecreaseStackDepth();
|
||||||
|
return result;
|
||||||
} catch (ScriptError& ex) {
|
} catch (ScriptError& ex) {
|
||||||
|
frame.DecreaseStackDepth();
|
||||||
|
|
||||||
ScriptBreakpoint(frame, &ex, GetDebugInfo());
|
ScriptBreakpoint(frame, &ex, GetDebugInfo());
|
||||||
throw;
|
throw;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
|
frame.DecreaseStackDepth();
|
||||||
|
|
||||||
BOOST_THROW_EXCEPTION(ScriptError("Error while evaluating expression: " + String(ex.what()), GetDebugInfo())
|
BOOST_THROW_EXCEPTION(ScriptError("Error while evaluating expression: " + String(ex.what()), GetDebugInfo())
|
||||||
<< boost::errinfo_nested_exception(boost::current_exception()));
|
<< boost::errinfo_nested_exception(boost::current_exception()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frame.DecreaseStackDepth();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Expression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
|
bool Expression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
|
||||||
|
|
Loading…
Reference in New Issue