1 /******************************************************************************
3 * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/) *
5 * This program is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU General Public License *
7 * as published by the Free Software Foundation; either version 2 *
8 * of the License, or (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software Foundation *
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ******************************************************************************/
20 #include "config/expression.hpp"
21 #include "config/configitem.hpp"
22 #include "config/configcompiler.hpp"
23 #include "config/vmops.hpp"
24 #include "base/array.hpp"
25 #include "base/json.hpp"
26 #include "base/object.hpp"
27 #include "base/logger.hpp"
28 #include "base/exception.hpp"
29 #include "base/scriptglobal.hpp"
30 #include "base/loader.hpp"
31 #include "base/reference.hpp"
32 #include "base/namespace.hpp"
33 #include <boost/exception_ptr.hpp>
34 #include <boost/exception/errinfo_nested_exception.hpp>
36 using namespace icinga;
38 boost::signals2::signal<void (ScriptFrame&, ScriptError *ex, const DebugInfo&)> Expression::OnBreakpoint;
39 boost::thread_specific_ptr<bool> l_InBreakpointHandler;
41 Expression::~Expression()
44 void Expression::ScriptBreakpoint(ScriptFrame& frame, ScriptError *ex, const DebugInfo& di)
46 bool *inHandler = l_InBreakpointHandler.get();
47 if (!inHandler || !*inHandler) {
48 inHandler = new bool(true);
49 l_InBreakpointHandler.reset(inHandler);
50 OnBreakpoint(frame, ex, di);
55 ExpressionResult Expression::Evaluate(ScriptFrame& frame, DebugHint *dhint) const
59 /* std::ostringstream msgbuf;
60 ShowCodeLocation(msgbuf, GetDebugInfo(), false);
61 Log(LogDebug, "Expression")
62 << "Executing:\n" << msgbuf.str();*/
65 frame.IncreaseStackDepth();
66 ExpressionResult result = DoEvaluate(frame, dhint);
67 frame.DecreaseStackDepth();
69 } catch (ScriptError& ex) {
70 frame.DecreaseStackDepth();
72 ScriptBreakpoint(frame, &ex, GetDebugInfo());
74 } catch (const std::exception& ex) {
75 frame.DecreaseStackDepth();
77 BOOST_THROW_EXCEPTION(ScriptError("Error while evaluating expression: " + String(ex.what()), GetDebugInfo())
78 << boost::errinfo_nested_exception(boost::current_exception()));
81 frame.DecreaseStackDepth();
84 bool Expression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
89 const DebugInfo& Expression::GetDebugInfo() const
91 static DebugInfo debugInfo;
95 std::unique_ptr<Expression> icinga::MakeIndexer(ScopeSpecifier scopeSpec, const String& index)
97 std::unique_ptr<Expression> scope{new GetScopeExpression(scopeSpec)};
98 return std::unique_ptr<Expression>(new IndexerExpression(std::move(scope), MakeLiteral(index)));
101 void DictExpression::MakeInline()
106 LiteralExpression::LiteralExpression(Value value)
107 : m_Value(std::move(value))
110 ExpressionResult LiteralExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
115 const DebugInfo& DebuggableExpression::GetDebugInfo() const
120 VariableExpression::VariableExpression(String variable, std::vector<std::shared_ptr<Expression> > imports, const DebugInfo& debugInfo)
121 : DebuggableExpression(debugInfo), m_Variable(std::move(variable)), m_Imports(std::move(imports))
123 m_Imports.push_back(MakeIndexer(ScopeGlobal, "System"));
124 m_Imports.push_back(std::unique_ptr<Expression>(new IndexerExpression(MakeIndexer(ScopeGlobal, "System"), MakeLiteral("Configuration"))));
125 m_Imports.push_back(MakeIndexer(ScopeGlobal, "Types"));
126 m_Imports.push_back(MakeIndexer(ScopeGlobal, "Icinga"));
129 ExpressionResult VariableExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
133 if (frame.Locals && frame.Locals->Get(m_Variable, &value))
135 else if (frame.Self.IsObject() && frame.Locals != frame.Self.Get<Object::Ptr>() && frame.Self.Get<Object::Ptr>()->GetOwnField(m_Variable, &value))
137 else if (VMOps::FindVarImport(frame, m_Imports, m_Variable, &value, m_DebugInfo))
140 return ScriptGlobal::Get(m_Variable);
143 bool VariableExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
147 if (frame.Locals && frame.Locals->Contains(m_Variable)) {
148 *parent = frame.Locals;
152 } else if (frame.Self.IsObject() && frame.Locals != frame.Self.Get<Object::Ptr>() && frame.Self.Get<Object::Ptr>()->HasOwnField(m_Variable)) {
153 *parent = frame.Self;
156 *dhint = new DebugHint((*dhint)->GetChild(m_Variable));
157 } else if (VMOps::FindVarImportRef(frame, m_Imports, m_Variable, parent, m_DebugInfo)) {
159 } else if (ScriptGlobal::Exists(m_Variable)) {
160 *parent = ScriptGlobal::GetGlobals();
165 *parent = frame.Self;
170 ExpressionResult RefExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
175 if (!m_Operand->GetReference(frame, false, &parent, &index, &dhint))
176 BOOST_THROW_EXCEPTION(ScriptError("Cannot obtain reference for expression.", m_DebugInfo));
178 if (!parent.IsObject())
179 BOOST_THROW_EXCEPTION(ScriptError("Cannot obtain reference for expression because parent is not an object.", m_DebugInfo));
181 return new Reference(parent, index);
184 ExpressionResult DerefExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
186 ExpressionResult operand = m_Operand->Evaluate(frame);
187 CHECK_RESULT(operand);
189 Object::Ptr obj = operand.GetValue();
190 Reference::Ptr ref = dynamic_pointer_cast<Reference>(obj);
193 BOOST_THROW_EXCEPTION(ScriptError("Invalid reference specified.", GetDebugInfo()));
198 bool DerefExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
200 ExpressionResult operand = m_Operand->Evaluate(frame);
201 if (operand.GetCode() != ResultOK)
204 Reference::Ptr ref = operand.GetValue();
206 *parent = ref->GetParent();
207 *index = ref->GetIndex();
211 ExpressionResult NegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
213 ExpressionResult operand = m_Operand->Evaluate(frame);
214 CHECK_RESULT(operand);
216 return ~(long)operand.GetValue();
219 ExpressionResult LogicalNegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
221 ExpressionResult operand = m_Operand->Evaluate(frame);
222 CHECK_RESULT(operand);
224 return !operand.GetValue().ToBool();
227 ExpressionResult AddExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
229 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
230 CHECK_RESULT(operand1);
232 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
233 CHECK_RESULT(operand2);
235 return operand1.GetValue() + operand2.GetValue();
238 ExpressionResult SubtractExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
240 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
241 CHECK_RESULT(operand1);
243 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
244 CHECK_RESULT(operand2);
246 return operand1.GetValue() - operand2.GetValue();
249 ExpressionResult MultiplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
251 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
252 CHECK_RESULT(operand1);
254 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
255 CHECK_RESULT(operand2);
257 return operand1.GetValue() * operand2.GetValue();
260 ExpressionResult DivideExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
262 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
263 CHECK_RESULT(operand1);
265 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
266 CHECK_RESULT(operand2);
268 return operand1.GetValue() / operand2.GetValue();
271 ExpressionResult ModuloExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
273 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
274 CHECK_RESULT(operand1);
276 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
277 CHECK_RESULT(operand2);
279 return operand1.GetValue() % operand2.GetValue();
282 ExpressionResult XorExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
284 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
285 CHECK_RESULT(operand1);
287 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
288 CHECK_RESULT(operand2);
290 return operand1.GetValue() ^ operand2.GetValue();
293 ExpressionResult BinaryAndExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
295 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
296 CHECK_RESULT(operand1);
298 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
299 CHECK_RESULT(operand2);
301 return operand1.GetValue() & operand2.GetValue();
304 ExpressionResult BinaryOrExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
306 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
307 CHECK_RESULT(operand1);
309 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
310 CHECK_RESULT(operand2);
312 return operand1.GetValue() | operand2.GetValue();
315 ExpressionResult ShiftLeftExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
317 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
318 CHECK_RESULT(operand1);
320 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
321 CHECK_RESULT(operand2);
323 return operand1.GetValue() << operand2.GetValue();
326 ExpressionResult ShiftRightExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
328 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
329 CHECK_RESULT(operand1);
331 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
332 CHECK_RESULT(operand2);
334 return operand1.GetValue() >> operand2.GetValue();
337 ExpressionResult EqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
339 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
340 CHECK_RESULT(operand1);
342 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
343 CHECK_RESULT(operand2);
345 return operand1.GetValue() == operand2.GetValue();
348 ExpressionResult NotEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
350 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
351 CHECK_RESULT(operand1);
353 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
354 CHECK_RESULT(operand2);
356 return operand1.GetValue() != operand2.GetValue();
359 ExpressionResult LessThanExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
361 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
362 CHECK_RESULT(operand1);
364 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
365 CHECK_RESULT(operand2);
367 return operand1.GetValue() < operand2.GetValue();
370 ExpressionResult GreaterThanExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
372 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
373 CHECK_RESULT(operand1);
375 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
376 CHECK_RESULT(operand2);
378 return operand1.GetValue() > operand2.GetValue();
381 ExpressionResult LessThanOrEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
383 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
384 CHECK_RESULT(operand1);
386 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
387 CHECK_RESULT(operand2);
389 return operand1.GetValue() <= operand2.GetValue();
392 ExpressionResult GreaterThanOrEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
394 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
395 CHECK_RESULT(operand1);
397 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
398 CHECK_RESULT(operand2);
400 return operand1.GetValue() >= operand2.GetValue();
403 ExpressionResult InExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
405 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
406 CHECK_RESULT(operand2);
408 if (operand2.GetValue().IsEmpty())
410 else if (!operand2.GetValue().IsObjectType<Array>())
411 BOOST_THROW_EXCEPTION(ScriptError("Invalid right side argument for 'in' operator: " + JsonEncode(operand2.GetValue()), m_DebugInfo));
413 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
414 CHECK_RESULT(operand1)
416 Array::Ptr arr = operand2.GetValue();
417 return arr->Contains(operand1.GetValue());
420 ExpressionResult NotInExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
422 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
423 CHECK_RESULT(operand2);
425 if (operand2.GetValue().IsEmpty())
427 else if (!operand2.GetValue().IsObjectType<Array>())
428 BOOST_THROW_EXCEPTION(ScriptError("Invalid right side argument for 'in' operator: " + JsonEncode(operand2.GetValue()), m_DebugInfo));
430 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
431 CHECK_RESULT(operand1);
433 Array::Ptr arr = operand2.GetValue();
434 return !arr->Contains(operand1.GetValue());
437 ExpressionResult LogicalAndExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
439 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
440 CHECK_RESULT(operand1);
442 if (!operand1.GetValue().ToBool())
445 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
446 CHECK_RESULT(operand2);
448 return operand2.GetValue();
452 ExpressionResult LogicalOrExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
454 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
455 CHECK_RESULT(operand1);
457 if (operand1.GetValue().ToBool())
460 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
461 CHECK_RESULT(operand2);
463 return operand2.GetValue();
467 ExpressionResult FunctionCallExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
472 if (m_FName->GetReference(frame, false, &self, &index))
473 vfunc = VMOps::GetField(self, index, frame.Sandboxed, m_DebugInfo);
475 ExpressionResult vfuncres = m_FName->Evaluate(frame);
476 CHECK_RESULT(vfuncres);
478 vfunc = vfuncres.GetValue();
481 if (vfunc.IsObjectType<Type>()) {
482 std::vector<Value> arguments;
483 arguments.reserve(m_Args.size());
484 for (const auto& arg : m_Args) {
485 ExpressionResult argres = arg->Evaluate(frame);
486 CHECK_RESULT(argres);
488 arguments.push_back(argres.GetValue());
491 return VMOps::ConstructorCall(vfunc, arguments, m_DebugInfo);
494 if (!vfunc.IsObjectType<Function>())
495 BOOST_THROW_EXCEPTION(ScriptError("Argument is not a callable object.", m_DebugInfo));
497 Function::Ptr func = vfunc;
499 if (!func->IsSideEffectFree() && frame.Sandboxed)
500 BOOST_THROW_EXCEPTION(ScriptError("Function is not marked as safe for sandbox mode.", m_DebugInfo));
502 std::vector<Value> arguments;
503 arguments.reserve(m_Args.size());
504 for (const auto& arg : m_Args) {
505 ExpressionResult argres = arg->Evaluate(frame);
506 CHECK_RESULT(argres);
508 arguments.push_back(argres.GetValue());
511 return VMOps::FunctionCall(frame, self, func, arguments);
514 ExpressionResult ArrayExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
517 result.reserve(m_Expressions.size());
519 for (const auto& aexpr : m_Expressions) {
520 ExpressionResult element = aexpr->Evaluate(frame);
521 CHECK_RESULT(element);
523 result.push_back(element.GetValue());
526 return new Array(std::move(result));
529 ExpressionResult DictExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
535 frame.Self = new Dictionary();
541 for (const auto& aexpr : m_Expressions) {
542 ExpressionResult element = aexpr->Evaluate(frame, m_Inline ? dhint : nullptr);
543 CHECK_RESULT(element);
544 result = element.GetValue();
548 std::swap(self, frame.Self);
555 std::swap(self, frame.Self);
560 ExpressionResult GetScopeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
562 if (m_ScopeSpec == ScopeLocal)
564 else if (m_ScopeSpec == ScopeThis)
566 else if (m_ScopeSpec == ScopeGlobal)
567 return ScriptGlobal::GetGlobals();
569 VERIFY(!"Invalid scope.");
572 ExpressionResult SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
575 BOOST_THROW_EXCEPTION(ScriptError("Assignments are not allowed in sandbox mode.", m_DebugInfo));
577 DebugHint *psdhint = dhint;
582 if (!m_Operand1->GetReference(frame, true, &parent, &index, &psdhint))
583 BOOST_THROW_EXCEPTION(ScriptError("Expression cannot be assigned to.", m_DebugInfo));
585 ExpressionResult operand2 = m_Operand2->Evaluate(frame, dhint);
586 CHECK_RESULT(operand2);
588 if (m_Op != OpSetLiteral) {
589 Value object = VMOps::GetField(parent, index, frame.Sandboxed, m_DebugInfo);
593 operand2 = object + operand2;
596 operand2 = object - operand2;
599 operand2 = object * operand2;
602 operand2 = object / operand2;
605 operand2 = object % operand2;
608 operand2 = object ^ operand2;
611 operand2 = object & operand2;
614 operand2 = object | operand2;
617 VERIFY(!"Invalid opcode.");
621 VMOps::SetField(parent, index, operand2.GetValue(), m_OverrideFrozen, m_DebugInfo);
624 psdhint->AddMessage("=", m_DebugInfo);
626 if (psdhint != dhint)
633 void SetExpression::SetOverrideFrozen()
635 m_OverrideFrozen = true;
638 ExpressionResult SetConstExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
640 auto globals = ScriptGlobal::GetGlobals();
642 auto attr = globals->GetAttribute(m_Name);
644 if (dynamic_pointer_cast<ConstEmbeddedNamespaceValue>(attr)) {
645 std::ostringstream msgbuf;
646 msgbuf << "Value for constant '" << m_Name << "' was modified. This behaviour is deprecated.\n";
647 ShowCodeLocation(msgbuf, GetDebugInfo(), false);
648 Log(LogWarning, msgbuf.str());
651 ExpressionResult operandres = m_Operand->Evaluate(frame);
652 CHECK_RESULT(operandres);
653 Value operand = operandres.GetValue();
655 globals->SetAttribute(m_Name, std::make_shared<ConstEmbeddedNamespaceValue>(operand));
660 ExpressionResult ConditionalExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
662 ExpressionResult condition = m_Condition->Evaluate(frame, dhint);
663 CHECK_RESULT(condition);
665 if (condition.GetValue().ToBool())
666 return m_TrueBranch->Evaluate(frame, dhint);
667 else if (m_FalseBranch)
668 return m_FalseBranch->Evaluate(frame, dhint);
673 ExpressionResult WhileExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
676 BOOST_THROW_EXCEPTION(ScriptError("While loops are not allowed in sandbox mode.", m_DebugInfo));
679 ExpressionResult condition = m_Condition->Evaluate(frame, dhint);
680 CHECK_RESULT(condition);
682 if (!condition.GetValue().ToBool())
685 ExpressionResult loop_body = m_LoopBody->Evaluate(frame, dhint);
686 CHECK_RESULT_LOOP(loop_body);
692 ExpressionResult ReturnExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
694 ExpressionResult operand = m_Operand->Evaluate(frame);
695 CHECK_RESULT(operand);
697 return ExpressionResult(operand.GetValue(), ResultReturn);
700 ExpressionResult BreakExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
702 return ExpressionResult(Empty, ResultBreak);
705 ExpressionResult ContinueExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
707 return ExpressionResult(Empty, ResultContinue);
710 ExpressionResult IndexerExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
712 ExpressionResult operand1 = m_Operand1->Evaluate(frame, dhint);
713 CHECK_RESULT(operand1);
715 ExpressionResult operand2 = m_Operand2->Evaluate(frame, dhint);
716 CHECK_RESULT(operand2);
718 return VMOps::GetField(operand1.GetValue(), operand2.GetValue(), frame.Sandboxed, m_DebugInfo);
721 bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
725 DebugHint *psdhint = nullptr;
726 bool free_psd = false;
734 if (m_Operand1->GetReference(frame, init_dict, &vparent, &vindex, &psdhint)) {
737 bool has_field = true;
739 if (vparent.IsObject()) {
740 Object::Ptr oparent = vparent;
741 has_field = oparent->HasOwnField(vindex);
745 old_value = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_Operand1->GetDebugInfo());
747 if (old_value.IsEmpty() && !old_value.IsString())
748 VMOps::SetField(vparent, vindex, new Dictionary(), m_OverrideFrozen, m_Operand1->GetDebugInfo());
751 *parent = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_DebugInfo);
754 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
755 *parent = operand1.GetValue();
758 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
759 *index = operand2.GetValue();
763 *dhint = new DebugHint(psdhint->GetChild(*index));
774 void IndexerExpression::SetOverrideFrozen()
776 m_OverrideFrozen = true;
779 void icinga::BindToScope(std::unique_ptr<Expression>& expr, ScopeSpecifier scopeSpec)
781 auto *dexpr = dynamic_cast<DictExpression *>(expr.get());
784 for (auto& expr : dexpr->m_Expressions)
785 BindToScope(expr, scopeSpec);
790 auto *aexpr = dynamic_cast<SetExpression *>(expr.get());
793 BindToScope(aexpr->m_Operand1, scopeSpec);
798 auto *iexpr = dynamic_cast<IndexerExpression *>(expr.get());
801 BindToScope(iexpr->m_Operand1, scopeSpec);
805 auto *lexpr = dynamic_cast<LiteralExpression *>(expr.get());
807 if (lexpr && lexpr->GetValue().IsString()) {
808 std::unique_ptr<Expression> scope{new GetScopeExpression(scopeSpec)};
809 expr.reset(new IndexerExpression(std::move(scope), std::move(expr), lexpr->GetDebugInfo()));
812 auto *vexpr = dynamic_cast<VariableExpression *>(expr.get());
815 std::unique_ptr<Expression> scope{new GetScopeExpression(scopeSpec)};
816 expr.reset(new IndexerExpression(std::move(scope), MakeLiteral(vexpr->GetVariable()), vexpr->GetDebugInfo()));
820 ExpressionResult ThrowExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
822 ExpressionResult messageres = m_Message->Evaluate(frame);
823 CHECK_RESULT(messageres);
824 Value message = messageres.GetValue();
825 BOOST_THROW_EXCEPTION(ScriptError(message, m_DebugInfo, m_IncompleteExpr));
828 ExpressionResult ImportExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
831 BOOST_THROW_EXCEPTION(ScriptError("Imports are not allowed in sandbox mode.", m_DebugInfo));
833 String type = VMOps::GetField(frame.Self, "type", frame.Sandboxed, m_DebugInfo);
834 ExpressionResult nameres = m_Name->Evaluate(frame);
835 CHECK_RESULT(nameres);
836 Value name = nameres.GetValue();
838 if (!name.IsString())
839 BOOST_THROW_EXCEPTION(ScriptError("Template/object name must be a string", m_DebugInfo));
841 ConfigItem::Ptr item = ConfigItem::GetByTypeAndName(Type::GetByName(type), name);
844 BOOST_THROW_EXCEPTION(ScriptError("Import references unknown template: '" + name + "'", m_DebugInfo));
846 Dictionary::Ptr scope = item->GetScope();
849 scope->CopyTo(frame.Locals);
851 ExpressionResult result = item->GetExpression()->Evaluate(frame, dhint);
852 CHECK_RESULT(result);
857 ExpressionResult ImportDefaultTemplatesExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
860 BOOST_THROW_EXCEPTION(ScriptError("Imports are not allowed in sandbox mode.", m_DebugInfo));
862 String type = VMOps::GetField(frame.Self, "type", frame.Sandboxed, m_DebugInfo);
863 Type::Ptr ptype = Type::GetByName(type);
865 for (const ConfigItem::Ptr& item : ConfigItem::GetDefaultTemplates(ptype)) {
866 Dictionary::Ptr scope = item->GetScope();
869 scope->CopyTo(frame.Locals);
871 ExpressionResult result = item->GetExpression()->Evaluate(frame, dhint);
872 CHECK_RESULT(result);
878 ExpressionResult FunctionExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
880 return VMOps::NewFunction(frame, m_Name, m_Args, m_ClosedVars, m_Expression);
883 ExpressionResult ApplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
886 BOOST_THROW_EXCEPTION(ScriptError("Apply rules are not allowed in sandbox mode.", m_DebugInfo));
888 ExpressionResult nameres = m_Name->Evaluate(frame);
889 CHECK_RESULT(nameres);
891 return VMOps::NewApply(frame, m_Type, m_Target, nameres.GetValue(), m_Filter,
892 m_Package, m_FKVar, m_FVVar, m_FTerm, m_ClosedVars, m_IgnoreOnError, m_Expression, m_DebugInfo);
895 ExpressionResult NamespaceExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
897 Namespace::Ptr ns = new Namespace(new ConstNamespaceBehavior());
899 ScriptFrame innerFrame(true, ns);
900 ExpressionResult result = m_Expression->Evaluate(innerFrame);
901 CHECK_RESULT(result);
906 ExpressionResult ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
909 BOOST_THROW_EXCEPTION(ScriptError("Object definitions are not allowed in sandbox mode.", m_DebugInfo));
911 ExpressionResult typeres = m_Type->Evaluate(frame, dhint);
912 CHECK_RESULT(typeres);
913 Type::Ptr type = typeres.GetValue();
918 ExpressionResult nameres = m_Name->Evaluate(frame, dhint);
919 CHECK_RESULT(nameres);
921 name = nameres.GetValue();
924 return VMOps::NewObject(frame, m_Abstract, type, name, m_Filter, m_Zone,
925 m_Package, m_DefaultTmpl, m_IgnoreOnError, m_ClosedVars, m_Expression, m_DebugInfo);
928 ExpressionResult ForExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
931 BOOST_THROW_EXCEPTION(ScriptError("For loops are not allowed in sandbox mode.", m_DebugInfo));
933 ExpressionResult valueres = m_Value->Evaluate(frame, dhint);
934 CHECK_RESULT(valueres);
936 return VMOps::For(frame, m_FKVar, m_FVVar, valueres.GetValue(), m_Expression, m_DebugInfo);
939 ExpressionResult LibraryExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
942 BOOST_THROW_EXCEPTION(ScriptError("Loading libraries is not allowed in sandbox mode.", m_DebugInfo));
944 ExpressionResult libres = m_Operand->Evaluate(frame, dhint);
945 CHECK_RESULT(libres);
947 Log(LogNotice, "config")
948 << "Ignoring explicit load request for library \"" << libres << "\".";
953 ExpressionResult IncludeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
956 BOOST_THROW_EXCEPTION(ScriptError("Includes are not allowed in sandbox mode.", m_DebugInfo));
958 std::unique_ptr<Expression> expr;
959 String name, path, pattern;
964 ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
965 CHECK_RESULT(pathres);
966 path = pathres.GetValue();
969 expr = ConfigCompiler::HandleInclude(m_RelativeBase, path, m_SearchIncludes, m_Zone, m_Package, m_DebugInfo);
972 case IncludeRecursive:
974 ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
975 CHECK_RESULT(pathres);
976 path = pathres.GetValue();
980 ExpressionResult patternres = m_Pattern->Evaluate(frame, dhint);
981 CHECK_RESULT(patternres);
982 pattern = patternres.GetValue();
985 expr = ConfigCompiler::HandleIncludeRecursive(m_RelativeBase, path, pattern, m_Zone, m_Package, m_DebugInfo);
990 ExpressionResult nameres = m_Name->Evaluate(frame, dhint);
991 CHECK_RESULT(nameres);
992 name = nameres.GetValue();
996 ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
997 CHECK_RESULT(pathres);
998 path = pathres.GetValue();
1002 ExpressionResult patternres = m_Pattern->Evaluate(frame, dhint);
1003 CHECK_RESULT(patternres);
1004 pattern = patternres.GetValue();
1007 expr = ConfigCompiler::HandleIncludeZones(m_RelativeBase, name, path, pattern, m_Package, m_DebugInfo);
1011 ExpressionResult res(Empty);
1014 res = expr->Evaluate(frame, dhint);
1015 } catch (const std::exception&) {
1022 ExpressionResult BreakpointExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
1024 ScriptBreakpoint(frame, nullptr, GetDebugInfo());
1029 ExpressionResult TryExceptExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
1032 ExpressionResult tryResult = m_TryBody->Evaluate(frame, dhint);
1033 CHECK_RESULT(tryResult);
1034 } catch (const std::exception&) {
1035 ExpressionResult exceptResult = m_ExceptBody->Evaluate(frame, dhint);
1036 CHECK_RESULT(exceptResult);