]> granicus.if.org Git - icinga2/commitdiff
Implement "safe mode" for icinga::Deserialize.
authorGunnar Beutner <gunnar.beutner@netways.de>
Wed, 18 Dec 2013 09:18:57 +0000 (10:18 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Wed, 18 Dec 2013 09:27:58 +0000 (10:27 +0100)
Fixes #5035

14 files changed:
components/cluster/clusterlistener.cpp
lib/base/dynamicobject.cpp
lib/base/dynamictype.cpp
lib/base/serializer.cpp
lib/base/serializer.h
lib/base/type.cpp
lib/base/type.h
lib/icinga/checkresult.ti
lib/icinga/comment.ti
lib/icinga/downtime.ti
tools/mkclass/class_lexer.ll
tools/mkclass/class_parser.yy
tools/mkclass/classcompiler.cpp
tools/mkclass/classcompiler.h

index a56ff286cb037998f88e35e23a4b371a192b4043..fe3b91ef7c35c199a106fc8a8bc03f4753b2d721 100644 (file)
@@ -1030,7 +1030,7 @@ void ClusterListener::MessageHandler(const Endpoint::Ptr& sender, const Dictiona
                        return;
                }
 
-               CheckResult::Ptr cr = Deserialize(params->Get("check_result"));
+               CheckResult::Ptr cr = Deserialize(params->Get("check_result"), true);
 
                if (!cr)
                        return;
@@ -1224,7 +1224,7 @@ void ClusterListener::MessageHandler(const Endpoint::Ptr& sender, const Dictiona
                        return;
                }
 
-               Comment::Ptr comment = Deserialize(params->Get("comment"));
+               Comment::Ptr comment = Deserialize(params->Get("comment"), true);
 
                service->AddComment(comment->GetEntryType(), comment->GetAuthor(),
                    comment->GetText(), comment->GetExpireTime(), comment->GetId(), sender->GetName());
@@ -1267,7 +1267,7 @@ void ClusterListener::MessageHandler(const Endpoint::Ptr& sender, const Dictiona
                        return;
                }
 
-               Downtime::Ptr downtime = Deserialize(params->Get("downtime"));
+               Downtime::Ptr downtime = Deserialize(params->Get("downtime"), true);
 
                service->AddDowntime(downtime->GetAuthor(), downtime->GetComment(),
                    downtime->GetStartTime(), downtime->GetEndTime(),
index 39a4647680f595df8214e4300eee7d8fb9e0f3b8..7575e53bc76c634074e88bcbc3a17aa93cafcf61 100644 (file)
@@ -327,7 +327,7 @@ void DynamicObject::RestoreObjects(const String& filename, int attributeTypes)
 #ifdef _DEBUG
                        Log(LogDebug, "base", "Restoring object '" + name + "' of type '" + type + "'.");
 #endif /* _DEBUG */
-                       Deserialize(object, update, attributeTypes);
+                       Deserialize(object, update, false, attributeTypes);
                        object->OnStateLoaded();
                }
 
index 1f0ad3f764aa9c4788841378807d16c844708d6e..de99a0feaada4232a43a13dbdd555f1f74504b06 100644 (file)
@@ -132,7 +132,7 @@ DynamicObject::Ptr DynamicType::CreateObject(const Dictionary::Ptr& serializedUp
 
        Object::Ptr object = type->Instantiate();
 
-       Deserialize(object, serializedUpdate, FAConfig);
+       Deserialize(object, serializedUpdate, false, FAConfig);
 
        return static_pointer_cast<DynamicObject>(object);
 }
index 7f5faa900ccf7b1e602307bb5122ce952bd957fa..63ca0e6b50bc4fda7cec8c0f27bdaee5c095eada 100644 (file)
@@ -118,20 +118,20 @@ static Object::Ptr SerializeObject(const Object::Ptr& input, int attributeTypes)
        return fields;
 }
 
-static Array::Ptr DeserializeArray(const Array::Ptr& input, int attributeTypes)
+static Array::Ptr DeserializeArray(const Array::Ptr& input, bool safe_mode, int attributeTypes)
 {
        Array::Ptr result = make_shared<Array>();
 
        ObjectLock olock(input);
 
        BOOST_FOREACH(const Value& value, input) {
-               result->Add(Deserialize(value, attributeTypes));
+               result->Add(Deserialize(value, safe_mode, attributeTypes));
        }
 
        return result;
 }
 
-static Dictionary::Ptr DeserializeDictionary(const Dictionary::Ptr& input, int attributeTypes)
+static Dictionary::Ptr DeserializeDictionary(const Dictionary::Ptr& input, bool safe_mode, int attributeTypes)
 {
        Dictionary::Ptr result = make_shared<Dictionary>();
 
@@ -144,7 +144,7 @@ static Dictionary::Ptr DeserializeDictionary(const Dictionary::Ptr& input, int a
        return result;
 }
 
-static Object::Ptr DeserializeObject(const Object::Ptr& object, const Dictionary::Ptr& input, int attributeTypes)
+static Object::Ptr DeserializeObject(const Object::Ptr& object, const Dictionary::Ptr& input, bool safe_mode, int attributeTypes)
 {
        const Type *type;
 
@@ -158,8 +158,12 @@ static Object::Ptr DeserializeObject(const Object::Ptr& object, const Dictionary
 
        Object::Ptr instance = object;
 
-       if (!instance)
+       if (!instance) {
+               if (safe_mode && !type->IsSafe())
+                       BOOST_THROW_EXCEPTION(std::runtime_error("Tried to instantiate type '" + type->GetName() + "' which is not marked as safe."));
+
                instance = type->Instantiate();
+       }
 
        BOOST_FOREACH(const Dictionary::Pair& kv, input) {
                if (kv.first.IsEmpty())
@@ -176,7 +180,7 @@ static Object::Ptr DeserializeObject(const Object::Ptr& object, const Dictionary
                        continue;
 
                try {
-                       instance->SetField(fid, Deserialize(kv.second, attributeTypes));
+                       instance->SetField(fid, Deserialize(kv.second, safe_mode, attributeTypes));
                } catch (const std::exception&) {
                        instance->SetField(fid, Empty);
                }
@@ -205,12 +209,12 @@ Value icinga::Serialize(const Value& value, int attributeTypes)
        return SerializeObject(input, attributeTypes);
 }
 
-Value icinga::Deserialize(const Value& value, int attributeTypes)
+Value icinga::Deserialize(const Value& value, bool safe_mode, int attributeTypes)
 {
-       return Deserialize(Object::Ptr(), value, attributeTypes);
+       return Deserialize(Object::Ptr(), value, safe_mode, attributeTypes);
 }
 
-Value icinga::Deserialize(const Object::Ptr& object, const Value& value, int attributeTypes)
+Value icinga::Deserialize(const Object::Ptr& object, const Value& value, bool safe_mode, int attributeTypes)
 {
        if (!value.IsObject())
                return value;
@@ -220,14 +224,14 @@ Value icinga::Deserialize(const Object::Ptr& object, const Value& value, int att
        Array::Ptr array = dynamic_pointer_cast<Array>(input);
 
        if (array != NULL)
-               return DeserializeArray(array, attributeTypes);
+               return DeserializeArray(array, safe_mode, attributeTypes);
 
        Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(input);
 
        ASSERT(dict != NULL);
 
        if (!dict->Contains("__type"))
-               return DeserializeDictionary(dict, attributeTypes);
+               return DeserializeDictionary(dict, safe_mode, attributeTypes);
 
-       return DeserializeObject(object, dict, attributeTypes);
+       return DeserializeObject(object, dict, safe_mode, attributeTypes);
 }
index cce692dd7b836a9e0ab902e082830433d9ef7bb8..5f697203560702897d3386af5957caf98902d442 100644 (file)
@@ -36,8 +36,8 @@ I2_BASE_API String JsonSerialize(const Value& value);
 I2_BASE_API Value JsonDeserialize(const String& data);
 
 I2_BASE_API Value Serialize(const Value& value, int attributeTypes = FAState);
-I2_BASE_API Value Deserialize(const Value& value, int attributeTypes = FAState);
-I2_BASE_API Value Deserialize(const Object::Ptr& object, const Value& value, int attributeTypes = FAState);
+I2_BASE_API Value Deserialize(const Value& value, bool safe_mode = false, int attributeTypes = FAState);
+I2_BASE_API Value Deserialize(const Object::Ptr& object, const Value& value, bool safe_mode = false, int attributeTypes = FAState);
 
 }
 
index 94f504316435cf1042e49fa72732c6021e4cf8fc..c0f97496dea3cce8b5d1e8d7295ef9a85631f70e 100644 (file)
@@ -52,6 +52,16 @@ Object::Ptr Type::Instantiate(void) const
        return m_Factory();
 }
 
+bool Type::IsAbstract(void) const
+{
+       return GetAttributes() & TAAbstract;
+}
+
+bool Type::IsSafe(void) const
+{
+       return GetAttributes() & TASafe;
+}
+
 bool Type::IsAssignableFrom(const Type *other) const
 {
        for (const Type *t = other; t; t = t->GetBaseType()) {
index b508a153876b07aa2c51e66f8b90e2a237927a1b..af168667d161fe8dcd27d804959e39997ee9512d 100644 (file)
@@ -40,6 +40,12 @@ struct Field
        { }
 };
 
+enum TypeAttribute
+{
+       TAAbstract = 1,
+       TASafe = 2
+};
+
 class I2_BASE_API Type
 {
 public:
@@ -47,7 +53,7 @@ public:
 
        virtual String GetName(void) const = 0;
        virtual const Type *GetBaseType(void) const = 0;
-       virtual bool IsAbstract(void) const = 0;
+       virtual int GetAttributes(void) const = 0;
        virtual int GetFieldId(const String& name) const = 0;
        virtual Field GetFieldInfo(int id) const = 0;
        virtual int GetFieldCount(void) const = 0;
@@ -56,6 +62,9 @@ public:
 
        bool IsAssignableFrom(const Type *other) const;
 
+       bool IsAbstract(void) const;
+       bool IsSafe(void) const;
+
        static void Register(const Type *type);
        static const Type *GetByName(const String& name);
 
index 45e10aa9cd5a0625c61e631d5af1eb0936bfdcee..a209dbd456a0716486bd7e547e0cb5e1ced9d985 100644 (file)
@@ -27,7 +27,7 @@ enum StateType
 };
 }}}
 
-class CheckResult
+safe class CheckResult
 {
        [state] double schedule_start;
        [state] double schedule_end;
index 955832baf6b260b74cd8ccb89c70b839b92a9226..5c2e73ad8beef63f31bb0f623ff8b42e0e0ba99b 100644 (file)
@@ -16,7 +16,7 @@ enum CommentType
 };
 }}}
 
-class Comment
+safe class Comment
 {
        [state] String id;
        [state] double entry_time;
index 69f91ec4b95c23c53ca3c62b48fd0643554930f5..b1d8ee658db20fd30e160ab9c1dba682e7ef45dc 100644 (file)
@@ -1,7 +1,7 @@
 namespace icinga
 {
 
-class Downtime
+safe class Downtime
 {
        [state] String id;
        [state] double entry_time;
index 5460de8535692fbbe29599b24fe4fa158d2e9d98..1bc8ea84277c04db5989015e9265161cd9c8af7e 100644 (file)
@@ -118,7 +118,8 @@ static char *lb_steal(lex_buf *lb)
 class                          { return T_CLASS; }
 namespace                      { return T_NAMESPACE; }
 code                           { return T_CODE; }
-abstract                       { return T_ABSTRACT; }
+abstract                       { yylval->num = TAAbstract; return T_CLASS_ATTRIBUTE; }
+safe                           { yylval->num = TASafe; return T_CLASS_ATTRIBUTE; }
 config                         { yylval->num = FAConfig; return T_FIELD_ATTRIBUTE; }
 state                          { yylval->num = FAState; return T_FIELD_ATTRIBUTE; }
 enum                           { yylval->num = FAEnum; return T_FIELD_ATTRIBUTE; }
index c988c3045527f9a99d8e85f4fa6061d0985bce59..95f2af6562ac16fa394fff25263202abe2342e0f 100644 (file)
@@ -50,11 +50,11 @@ using namespace icinga;
 %token T_INCLUDE "include (T_INCLUDE)"
 %token T_CLASS "class (T_CLASS)"
 %token T_CODE "code (T_CODE)"
-%token T_ABSTRACT "abstract (T_ABSTRACT)"
 %token T_NAMESPACE "namespace (T_NAMESPACE)"
 %token T_STRING "string (T_STRING)"
 %token T_ANGLE_STRING "angle_string (T_ANGLE_STRING)"
 %token T_FIELD_ATTRIBUTE "field_attribute (T_FIELD_ATTRIBUTE)"
+%token T_CLASS_ATTRIBUTE "class_attribute (T_CLASS_ATTRIBUTE)"
 %token T_IDENTIFIER "identifier (T_IDENTIFIER)"
 %token T_GET "get (T_GET)"
 %token T_SET "set (T_SET)"
@@ -73,7 +73,8 @@ using namespace icinga;
 %type <num> field_attributes
 %type <num> field_attribute_list
 %type <num> T_FIELD_ACCESSOR_TYPE
-%type <num> abstract_specifier
+%type <num> T_CLASS_ATTRIBUTE
+%type <num> class_attribute_list
 %type <field> class_field
 %type <fields> class_fields
 %type <klass> class
@@ -165,7 +166,7 @@ code: T_CODE T_STRING
        }
        ;
 
-class: abstract_specifier T_CLASS T_IDENTIFIER inherits_specifier '{' class_fields '}' ';'
+class: class_attribute_list T_CLASS T_IDENTIFIER inherits_specifier '{' class_fields '}' ';'
        {
                $$ = new Klass();
 
@@ -177,22 +178,25 @@ class: abstract_specifier T_CLASS T_IDENTIFIER inherits_specifier '{' class_fiel
                        free($4);
                }
 
-               $$->Abstract = $1;
+               $$->Attributes = $1;
 
                $$->Fields = *$6;
                delete $6;
        }
        ;
 
-abstract_specifier: /* empty */
+class_attribute_list: /* empty */
        {
-               $$ = false;
+               $$ = 0;
        }
-       | T_ABSTRACT
+       | T_CLASS_ATTRIBUTE
        {
-               $$ = true;
+               $$ = $1;
+       }
+       | class_attribute_list T_CLASS_ATTRIBUTE
+       {
+               $$ = $1 | $2;
        }
-       ;
 
 inherits_specifier: /* empty */
        {
index 6b57a86259c2949f2f8d0b6dcc1a2d663fc2822e..2b223565c89412e358cef279c60d6d1a59e68c35 100644 (file)
@@ -121,10 +121,10 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
                  << "\t\t" << "return \"" << klass.Name << "\";" << std::endl
                  << "\t" << "}" << std::endl << std::endl;
 
-       /* IsAbstract */
-       std::cout << "\t" << "virtual bool IsAbstract(void) const" << std::endl
+       /* GetAttributes */
+       std::cout << "\t" << "virtual int GetAttributes(void) const" << std::endl
                  << "\t" << "{" << std::endl
-                 << "\t\t" << "return " << (klass.Abstract ? "true" : "false") << ";" << std::endl
+                 << "\t\t" << "return " << klass.Attributes << ";" << std::endl
                  << "\t" << "}" << std::endl << std::endl;
 
        /* GetBaseType */
@@ -447,7 +447,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
        std::cout << "};" << std::endl << std::endl;
 
        /* FactoryHelper */
-       if (klass.Abstract) {
+       if (klass.Attributes & TAAbstract) {
                std::cout << "template<>" << std::endl
                          << "struct FactoryHelper<" << klass.Name << ">" << std::endl
                          << "{" << std::endl
index 386d212440bc001e24d8a8a20b50e7a37a7f7c73..a19e5e3b08e828e97930dd80674d711b2f0ae7ee 100644 (file)
@@ -103,11 +103,17 @@ struct Field
        }
 };
 
+enum TypeAttribute
+{
+       TAAbstract = 1,
+       TASafe = 2
+};
+
 struct Klass
 {
        std::string Name;
        std::string Parent;
-       bool Abstract;
+       int Attributes;
        std::vector<Field> Fields;
 };