Disallow calling strings as functions

fixes #8040
This commit is contained in:
Gunnar Beutner 2014-12-12 20:40:24 +01:00
parent ae95918da0
commit 05485ea2d6
16 changed files with 35 additions and 75 deletions

View File

@ -896,7 +896,7 @@ Attributes:
Name |Description Name |Description
----------------|---------------- ----------------|----------------
methods |**Required.** The "execute" script method takes care of executing the check. In virtually all cases you should import the "plugin-check-command" template to take care of this setting. execute |**Required.** The "execute" script method takes care of executing the check. In virtually all cases you should import the "plugin-check-command" template to take care of this setting.
command |**Required.** The command. This can either be an array of individual command arguments. Alternatively a string can be specified in which case the shell interpreter (usually /bin/sh) takes care of parsing the command. When using the "arguments" attribute this must be an array. command |**Required.** The command. This can either be an array of individual command arguments. Alternatively a string can be specified in which case the shell interpreter (usually /bin/sh) takes care of parsing the command. When using the "arguments" attribute this must be an array.
env |**Optional.** A dictionary of macros which should be exported as environment variables prior to executing the command. env |**Optional.** A dictionary of macros which should be exported as environment variables prior to executing the command.
vars |**Optional.** A dictionary containing custom attributes that are specific to this command. vars |**Optional.** A dictionary containing custom attributes that are specific to this command.
@ -998,7 +998,7 @@ Attributes:
Name |Description Name |Description
----------------|---------------- ----------------|----------------
methods |**Required.** The "execute" script method takes care of executing the notification. In virtually all cases you should import the "plugin-notification-command" template to take care of this setting. execute |**Required.** The "execute" script method takes care of executing the notification. In virtually all cases you should import the "plugin-notification-command" template to take care of this setting.
command |**Required.** The command. This can either be an array of individual command arguments. Alternatively a string can be specified in which case the shell interpreter (usually /bin/sh) takes care of parsing the command. command |**Required.** The command. This can either be an array of individual command arguments. Alternatively a string can be specified in which case the shell interpreter (usually /bin/sh) takes care of parsing the command.
env |**Optional.** A dictionary of macros which should be exported as environment variables prior to executing the command. env |**Optional.** A dictionary of macros which should be exported as environment variables prior to executing the command.
vars |**Optional.** A dictionary containing custom attributes that are specific to this command. vars |**Optional.** A dictionary containing custom attributes that are specific to this command.
@ -1026,7 +1026,7 @@ Attributes:
Name |Description Name |Description
----------------|---------------- ----------------|----------------
methods |**Required.** The "execute" script method takes care of executing the event handler. In virtually all cases you should import the "plugin-event-command" template to take care of this setting. execute |**Required.** The "execute" script method takes care of executing the event handler. In virtually all cases you should import the "plugin-event-command" template to take care of this setting.
command |**Required.** The command. This can either be an array of individual command arguments. Alternatively a string can be specified in which case the shell interpreter (usually /bin/sh) takes care of parsing the command. command |**Required.** The command. This can either be an array of individual command arguments. Alternatively a string can be specified in which case the shell interpreter (usually /bin/sh) takes care of parsing the command.
env |**Optional.** A dictionary of macros which should be exported as environment variables prior to executing the command. env |**Optional.** A dictionary of macros which should be exported as environment variables prior to executing the command.
vars |**Optional.** A dictionary containing custom attributes that are specific to this command. vars |**Optional.** A dictionary containing custom attributes that are specific to this command.
@ -1130,7 +1130,7 @@ Attributes:
Name |Description Name |Description
----------------|---------------- ----------------|----------------
display_name |**Optional.** A short description of the time period. display_name |**Optional.** A short description of the time period.
methods |**Required.** The "update" script method takes care of updating the internal representation of the time period. In virtually all cases you should import the "legacy-timeperiod" template to take care of this setting. update |**Required.** The "update" script method takes care of updating the internal representation of the time period. In virtually all cases you should import the "legacy-timeperiod" template to take care of this setting.
zone |**Optional.** The zone this object is a member of. zone |**Optional.** The zone this object is a member of.
ranges |**Required.** A dictionary containing information which days and durations apply to this timeperiod. ranges |**Required.** A dictionary containing information which days and durations apply to this timeperiod.

View File

@ -20,29 +20,29 @@
library "methods" library "methods"
template CheckCommand "icinga-check-command" { template CheckCommand "icinga-check-command" {
methods.execute = "IcingaCheck" execute = IcingaCheck
} }
template CheckCommand "cluster-check-command" { template CheckCommand "cluster-check-command" {
methods.execute = "ClusterCheck" execute = ClusterCheck
} }
template CheckCommand "cluster-zone-check-command" { template CheckCommand "cluster-zone-check-command" {
methods.execute = "ClusterZoneCheck" execute = ClusterZoneCheck
} }
template CheckCommand "plugin-check-command" { template CheckCommand "plugin-check-command" {
methods.execute = "PluginCheck" execute = PluginCheck
} }
template CheckCommand "clr-check-command" { template CheckCommand "clr-check-command" {
methods.execute = "ClrCheck" execute = ClrCheck
} }
template NotificationCommand "plugin-notification-command" { template NotificationCommand "plugin-notification-command" {
methods.execute = "PluginNotification" execute = PluginNotification
} }
template EventCommand "plugin-event-command" { template EventCommand "plugin-event-command" {
methods.execute = "PluginEvent" execute = PluginEvent
} }

View File

@ -18,5 +18,5 @@
******************************************************************************/ ******************************************************************************/
template TimePeriod "legacy-timeperiod" { template TimePeriod "legacy-timeperiod" {
methods.update = "LegacyTimePeriod" update = LegacyTimePeriod
} }

View File

@ -219,35 +219,6 @@ void DynamicObject::SetAuthority(bool authority)
} }
} }
Value DynamicObject::InvokeMethod(const String& method,
const std::vector<Value>& arguments)
{
Dictionary::Ptr methods;
methods = GetMethods();
if (!methods)
BOOST_THROW_EXCEPTION(std::invalid_argument("Method '" + method + "' does not exist."));
Value funcName = methods->Get(method);
if (funcName.IsEmpty())
BOOST_THROW_EXCEPTION(std::invalid_argument("Method '" + method + "' does not exist."));
ScriptFunction::Ptr func;
if (funcName.IsObjectType<ScriptFunction>()) {
func = funcName;
} else {
func = ScriptFunction::GetByName(funcName);
if (!func)
BOOST_THROW_EXCEPTION(std::invalid_argument("Function '" + String(funcName) + "' does not exist."));
}
return func->Invoke(arguments);
}
void DynamicObject::DumpObjects(const String& filename, int attributeTypes) void DynamicObject::DumpObjects(const String& filename, int attributeTypes)
{ {
Log(LogInformation, "DynamicObject") Log(LogInformation, "DynamicObject")

View File

@ -50,8 +50,6 @@ public:
static boost::signals2::signal<void (const DynamicObject::Ptr&)> OnResumed; static boost::signals2::signal<void (const DynamicObject::Ptr&)> OnResumed;
static boost::signals2::signal<void (const DynamicObject::Ptr&)> OnStateChanged; static boost::signals2::signal<void (const DynamicObject::Ptr&)> OnStateChanged;
Value InvokeMethod(const String& method, const std::vector<Value>& arguments);
intrusive_ptr<DynamicType> GetType(void) const; intrusive_ptr<DynamicType> GetType(void) const;
DebugInfo GetDebugInfo(void) const; DebugInfo GetDebugInfo(void) const;

View File

@ -47,7 +47,6 @@ abstract class DynamicObject
[config, internal, get_protected] String type (TypeName); [config, internal, get_protected] String type (TypeName);
[config] String zone; [config] String zone;
[config, internal, get_protected] Array::Ptr templates; [config, internal, get_protected] Array::Ptr templates;
[config] Dictionary::Ptr methods;
[get_protected] bool active; [get_protected] bool active;
[get_protected] bool paused { [get_protected] bool paused {
default {{{ return true; }}} default {{{ return true; }}}

View File

@ -32,8 +32,6 @@
%attribute %string "*" %attribute %string "*"
}, },
%attribute %dictionary "methods",
%attribute %dictionary "vars" %attribute %dictionary "vars"
} }

View File

@ -224,7 +224,7 @@ Value LogicalOrExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) cons
Value FunctionCallExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const Value FunctionCallExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{ {
Value self, funcName; Value self, vfunc;
if (!m_IName.empty()) { if (!m_IName.empty()) {
Value result = m_IName[0]->Evaluate(frame); Value result = m_IName[0]->Evaluate(frame);
@ -243,18 +243,23 @@ Value FunctionCallExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) c
self = result; self = result;
} }
funcName = result; vfunc= result;
} }
if (m_FName) if (m_FName)
funcName = m_FName->Evaluate(frame); vfunc = m_FName->Evaluate(frame);
if (!vfunc.IsObjectType<ScriptFunction>())
BOOST_THROW_EXCEPTION(ScriptError("Argument is not a callable object.", GetDebugInfo()));
ScriptFunction::Ptr func = vfunc;
std::vector<Value> arguments; std::vector<Value> arguments;
BOOST_FOREACH(Expression *arg, m_Args) { BOOST_FOREACH(Expression *arg, m_Args) {
arguments.push_back(arg->Evaluate(frame)); arguments.push_back(arg->Evaluate(frame));
} }
return VMOps::FunctionCall(frame, self, funcName, arguments); return VMOps::FunctionCall(frame, self, func, arguments);
} }
Value ArrayExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const Value ArrayExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const

View File

@ -58,18 +58,8 @@ public:
return ScriptVariable::Get(name); return ScriptVariable::Get(name);
} }
static inline Value FunctionCall(ScriptFrame& frame, const Value& self, const Value& funcName, const std::vector<Value>& arguments) static inline Value FunctionCall(ScriptFrame& frame, const Value& self, const ScriptFunction::Ptr& func, const std::vector<Value>& arguments)
{ {
ScriptFunction::Ptr func;
if (funcName.IsObjectType<ScriptFunction>())
func = funcName;
else
func = ScriptFunction::GetByName(funcName);
if (!func)
BOOST_THROW_EXCEPTION(ScriptError("Function '" + funcName + "' does not exist."));
boost::shared_ptr<ScriptFrame> vframe; boost::shared_ptr<ScriptFrame> vframe;
if (!self.IsEmpty()) if (!self.IsEmpty())

View File

@ -32,5 +32,5 @@ void CheckCommand::Execute(const Checkable::Ptr& checkable, const CheckResult::P
arguments.push_back(cr); arguments.push_back(cr);
arguments.push_back(resolvedMacros); arguments.push_back(resolvedMacros);
arguments.push_back(useResolvedMacros); arguments.push_back(useResolvedMacros);
InvokeMethod("execute", arguments); GetExecute()->Invoke(arguments);
} }

View File

@ -18,6 +18,7 @@
******************************************************************************/ ******************************************************************************/
#include "icinga/customvarobject.hpp" #include "icinga/customvarobject.hpp"
#include "base/scriptfunction.hpp"
namespace icinga namespace icinga
{ {
@ -30,6 +31,7 @@ abstract class Command : CustomVarObject
default {{{ return 60; }}} default {{{ return 60; }}}
}; };
[config] Dictionary::Ptr env; [config] Dictionary::Ptr env;
[config] ScriptFunction::Ptr execute;
}; };
} }

View File

@ -30,5 +30,5 @@ void EventCommand::Execute(const Checkable::Ptr& checkable,
arguments.push_back(checkable); arguments.push_back(checkable);
arguments.push_back(resolvedMacros); arguments.push_back(resolvedMacros);
arguments.push_back(useResolvedMacros); arguments.push_back(useResolvedMacros);
InvokeMethod("execute", arguments); GetExecute()->Invoke(arguments);
} }

View File

@ -173,11 +173,8 @@
%type TimePeriod { %type TimePeriod {
%attribute %string "display_name", %attribute %string "display_name",
%require "methods",
%attribute %dictionary "methods" {
%require "update", %require "update",
%attribute %string "update" %attribute %any "update",
},
/* %if (methods.update == "LegacyTimePeriod") { */ /* %if (methods.update == "LegacyTimePeriod") { */
// %require "ranges", // %require "ranges",
@ -189,11 +186,9 @@
%type Command { %type Command {
%validator "ValidateCommandAttributes", %validator "ValidateCommandAttributes",
%require "methods",
%attribute %dictionary "methods" {
%require "execute", %require "execute",
%attribute %string "execute" %attribute %any "execute",
},
/* %if (methods.execute == "PluginNotification" || methods.execute == "PluginCheck" || methods.execute == "PluginEvent") { */ /* %if (methods.execute == "PluginNotification" || methods.execute == "PluginCheck" || methods.execute == "PluginEvent") { */
// %require "command", // %require "command",

View File

@ -37,5 +37,5 @@ Dictionary::Ptr NotificationCommand::Execute(const Notification::Ptr& notificati
arguments.push_back(comment); arguments.push_back(comment);
arguments.push_back(resolvedMacros); arguments.push_back(resolvedMacros);
arguments.push_back(useResolvedMacros); arguments.push_back(useResolvedMacros);
return InvokeMethod("execute", arguments); return GetExecute()->Invoke(arguments);
} }

View File

@ -199,7 +199,7 @@ void TimePeriod::UpdateRegion(double begin, double end, bool clearExisting)
arguments.push_back(begin); arguments.push_back(begin);
arguments.push_back(end); arguments.push_back(end);
Array::Ptr segments = InvokeMethod("update", arguments); Array::Ptr segments = GetUpdate()->Invoke(arguments);
{ {
ObjectLock olock(this); ObjectLock olock(this);

View File

@ -18,6 +18,7 @@
******************************************************************************/ ******************************************************************************/
#include "icinga/customvarobject.hpp" #include "icinga/customvarobject.hpp"
#include "base/scriptfunction.hpp"
namespace icinga namespace icinga
{ {
@ -33,6 +34,7 @@ class TimePeriod : CustomVarObject
}}} }}}
}; };
[config] Dictionary::Ptr ranges; [config] Dictionary::Ptr ranges;
[config] ScriptFunction::Ptr update;
[state] Value valid_begin; [state] Value valid_begin;
[state] Value valid_end; [state] Value valid_end;
[state] Array::Ptr segments; [state] Array::Ptr segments;