diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 5dce19eda..cea7c266b 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -7,6 +7,7 @@ #include "config/configcompiler.hpp" #include "base/application.hpp" #include "base/configtype.hpp" +#include "base/defer.hpp" #include "base/objectlock.hpp" #include "base/convert.hpp" #include "base/logger.hpp" @@ -31,6 +32,8 @@ using namespace icinga; std::mutex ConfigItem::m_Mutex; +thread_local bool ConfigItem::m_CommitInProgress = false; + ConfigItem::TypeMap ConfigItem::m_Items; ConfigItem::TypeMap ConfigItem::m_DefaultTemplates; ConfigItem::ItemList ConfigItem::m_UnnamedItems; @@ -190,6 +193,9 @@ ConfigObject::Ptr ConfigItem::Commit(bool discard) if (m_Scope) m_Scope->CopyTo(frame.Locals); try { + m_CommitInProgress = true; + Defer resetCommitInProgress ([this]() { m_CommitInProgress = false; }); + m_Expression->Evaluate(frame, &debugHints); } catch (const std::exception& ex) { if (m_IgnoreOnError) { diff --git a/lib/config/configitem.hpp b/lib/config/configitem.hpp index 007a3c08a..e765900c5 100644 --- a/lib/config/configitem.hpp +++ b/lib/config/configitem.hpp @@ -63,6 +63,12 @@ public: static void RemoveIgnoredItems(const String& allowedConfigPath); + static inline + bool RunsInCommitContext() + { + return m_CommitInProgress; + } + private: Type::Ptr m_Type; /**< The object type. */ String m_Name; /**< The name. */ @@ -81,6 +87,7 @@ private: ConfigObject::Ptr m_Object; static std::mutex m_Mutex; + static thread_local bool m_CommitInProgress; typedef std::map ItemMap; typedef std::map TypeMap; diff --git a/lib/config/expression.cpp b/lib/config/expression.cpp index 09b860cde..65cbb7985 100644 --- a/lib/config/expression.cpp +++ b/lib/config/expression.cpp @@ -912,6 +912,9 @@ ExpressionResult ApplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhin if (frame.Sandboxed) BOOST_THROW_EXCEPTION(ScriptError("Apply rules are not allowed in sandbox mode.", m_DebugInfo)); + if (ConfigItem::RunsInCommitContext()) + BOOST_THROW_EXCEPTION(ScriptError("Nested objects are not allowed", m_DebugInfo)); + ExpressionResult nameres = m_Name->Evaluate(frame); CHECK_RESULT(nameres); @@ -935,6 +938,9 @@ ExpressionResult ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhi if (frame.Sandboxed) BOOST_THROW_EXCEPTION(ScriptError("Object definitions are not allowed in sandbox mode.", m_DebugInfo)); + if (ConfigItem::RunsInCommitContext()) + BOOST_THROW_EXCEPTION(ScriptError("Nested objects are not allowed", m_DebugInfo)); + ExpressionResult typeres = m_Type->Evaluate(frame, dhint); CHECK_RESULT(typeres); Type::Ptr type = typeres.GetValue();