Implement "safe mode" for icinga::Deserialize.

Fixes #5035
This commit is contained in:
Gunnar Beutner 2013-12-18 10:18:57 +01:00
parent 19bc4e0baa
commit 21fb0d9872
14 changed files with 72 additions and 38 deletions

View File

@ -1030,7 +1030,7 @@ void ClusterListener::MessageHandler(const Endpoint::Ptr& sender, const Dictiona
return; return;
} }
CheckResult::Ptr cr = Deserialize(params->Get("check_result")); CheckResult::Ptr cr = Deserialize(params->Get("check_result"), true);
if (!cr) if (!cr)
return; return;
@ -1224,7 +1224,7 @@ void ClusterListener::MessageHandler(const Endpoint::Ptr& sender, const Dictiona
return; return;
} }
Comment::Ptr comment = Deserialize(params->Get("comment")); Comment::Ptr comment = Deserialize(params->Get("comment"), true);
service->AddComment(comment->GetEntryType(), comment->GetAuthor(), service->AddComment(comment->GetEntryType(), comment->GetAuthor(),
comment->GetText(), comment->GetExpireTime(), comment->GetId(), sender->GetName()); comment->GetText(), comment->GetExpireTime(), comment->GetId(), sender->GetName());
@ -1267,7 +1267,7 @@ void ClusterListener::MessageHandler(const Endpoint::Ptr& sender, const Dictiona
return; return;
} }
Downtime::Ptr downtime = Deserialize(params->Get("downtime")); Downtime::Ptr downtime = Deserialize(params->Get("downtime"), true);
service->AddDowntime(downtime->GetAuthor(), downtime->GetComment(), service->AddDowntime(downtime->GetAuthor(), downtime->GetComment(),
downtime->GetStartTime(), downtime->GetEndTime(), downtime->GetStartTime(), downtime->GetEndTime(),

View File

@ -327,7 +327,7 @@ void DynamicObject::RestoreObjects(const String& filename, int attributeTypes)
#ifdef _DEBUG #ifdef _DEBUG
Log(LogDebug, "base", "Restoring object '" + name + "' of type '" + type + "'."); Log(LogDebug, "base", "Restoring object '" + name + "' of type '" + type + "'.");
#endif /* _DEBUG */ #endif /* _DEBUG */
Deserialize(object, update, attributeTypes); Deserialize(object, update, false, attributeTypes);
object->OnStateLoaded(); object->OnStateLoaded();
} }

View File

@ -132,7 +132,7 @@ DynamicObject::Ptr DynamicType::CreateObject(const Dictionary::Ptr& serializedUp
Object::Ptr object = type->Instantiate(); Object::Ptr object = type->Instantiate();
Deserialize(object, serializedUpdate, FAConfig); Deserialize(object, serializedUpdate, false, FAConfig);
return static_pointer_cast<DynamicObject>(object); return static_pointer_cast<DynamicObject>(object);
} }

View File

@ -118,20 +118,20 @@ static Object::Ptr SerializeObject(const Object::Ptr& input, int attributeTypes)
return fields; 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>(); Array::Ptr result = make_shared<Array>();
ObjectLock olock(input); ObjectLock olock(input);
BOOST_FOREACH(const Value& value, input) { BOOST_FOREACH(const Value& value, input) {
result->Add(Deserialize(value, attributeTypes)); result->Add(Deserialize(value, safe_mode, attributeTypes));
} }
return result; 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>(); Dictionary::Ptr result = make_shared<Dictionary>();
@ -144,7 +144,7 @@ static Dictionary::Ptr DeserializeDictionary(const Dictionary::Ptr& input, int a
return result; 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; const Type *type;
@ -158,8 +158,12 @@ static Object::Ptr DeserializeObject(const Object::Ptr& object, const Dictionary
Object::Ptr instance = object; 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(); instance = type->Instantiate();
}
BOOST_FOREACH(const Dictionary::Pair& kv, input) { BOOST_FOREACH(const Dictionary::Pair& kv, input) {
if (kv.first.IsEmpty()) if (kv.first.IsEmpty())
@ -176,7 +180,7 @@ static Object::Ptr DeserializeObject(const Object::Ptr& object, const Dictionary
continue; continue;
try { try {
instance->SetField(fid, Deserialize(kv.second, attributeTypes)); instance->SetField(fid, Deserialize(kv.second, safe_mode, attributeTypes));
} catch (const std::exception&) { } catch (const std::exception&) {
instance->SetField(fid, Empty); instance->SetField(fid, Empty);
} }
@ -205,12 +209,12 @@ Value icinga::Serialize(const Value& value, int attributeTypes)
return SerializeObject(input, 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()) if (!value.IsObject())
return value; 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); Array::Ptr array = dynamic_pointer_cast<Array>(input);
if (array != NULL) if (array != NULL)
return DeserializeArray(array, attributeTypes); return DeserializeArray(array, safe_mode, attributeTypes);
Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(input); Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(input);
ASSERT(dict != NULL); ASSERT(dict != NULL);
if (!dict->Contains("__type")) 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);
} }

View 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 JsonDeserialize(const String& data);
I2_BASE_API Value Serialize(const Value& value, int attributeTypes = FAState); 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 Value& value, bool safe_mode = false, int attributeTypes = FAState);
I2_BASE_API Value Deserialize(const Object::Ptr& object, const Value& value, int attributeTypes = FAState); I2_BASE_API Value Deserialize(const Object::Ptr& object, const Value& value, bool safe_mode = false, int attributeTypes = FAState);
} }

View File

@ -52,6 +52,16 @@ Object::Ptr Type::Instantiate(void) const
return m_Factory(); 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 bool Type::IsAssignableFrom(const Type *other) const
{ {
for (const Type *t = other; t; t = t->GetBaseType()) { for (const Type *t = other; t; t = t->GetBaseType()) {

View File

@ -40,6 +40,12 @@ struct Field
{ } { }
}; };
enum TypeAttribute
{
TAAbstract = 1,
TASafe = 2
};
class I2_BASE_API Type class I2_BASE_API Type
{ {
public: public:
@ -47,7 +53,7 @@ public:
virtual String GetName(void) const = 0; virtual String GetName(void) const = 0;
virtual const Type *GetBaseType(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 int GetFieldId(const String& name) const = 0;
virtual Field GetFieldInfo(int id) const = 0; virtual Field GetFieldInfo(int id) const = 0;
virtual int GetFieldCount(void) const = 0; virtual int GetFieldCount(void) const = 0;
@ -56,6 +62,9 @@ public:
bool IsAssignableFrom(const Type *other) const; bool IsAssignableFrom(const Type *other) const;
bool IsAbstract(void) const;
bool IsSafe(void) const;
static void Register(const Type *type); static void Register(const Type *type);
static const Type *GetByName(const String& name); static const Type *GetByName(const String& name);

View File

@ -27,7 +27,7 @@ enum StateType
}; };
}}} }}}
class CheckResult safe class CheckResult
{ {
[state] double schedule_start; [state] double schedule_start;
[state] double schedule_end; [state] double schedule_end;

View File

@ -16,7 +16,7 @@ enum CommentType
}; };
}}} }}}
class Comment safe class Comment
{ {
[state] String id; [state] String id;
[state] double entry_time; [state] double entry_time;

View File

@ -1,7 +1,7 @@
namespace icinga namespace icinga
{ {
class Downtime safe class Downtime
{ {
[state] String id; [state] String id;
[state] double entry_time; [state] double entry_time;

View File

@ -118,7 +118,8 @@ static char *lb_steal(lex_buf *lb)
class { return T_CLASS; } class { return T_CLASS; }
namespace { return T_NAMESPACE; } namespace { return T_NAMESPACE; }
code { return T_CODE; } 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; } config { yylval->num = FAConfig; return T_FIELD_ATTRIBUTE; }
state { yylval->num = FAState; return T_FIELD_ATTRIBUTE; } state { yylval->num = FAState; return T_FIELD_ATTRIBUTE; }
enum { yylval->num = FAEnum; return T_FIELD_ATTRIBUTE; } enum { yylval->num = FAEnum; return T_FIELD_ATTRIBUTE; }

View File

@ -50,11 +50,11 @@ using namespace icinga;
%token T_INCLUDE "include (T_INCLUDE)" %token T_INCLUDE "include (T_INCLUDE)"
%token T_CLASS "class (T_CLASS)" %token T_CLASS "class (T_CLASS)"
%token T_CODE "code (T_CODE)" %token T_CODE "code (T_CODE)"
%token T_ABSTRACT "abstract (T_ABSTRACT)"
%token T_NAMESPACE "namespace (T_NAMESPACE)" %token T_NAMESPACE "namespace (T_NAMESPACE)"
%token T_STRING "string (T_STRING)" %token T_STRING "string (T_STRING)"
%token T_ANGLE_STRING "angle_string (T_ANGLE_STRING)" %token T_ANGLE_STRING "angle_string (T_ANGLE_STRING)"
%token T_FIELD_ATTRIBUTE "field_attribute (T_FIELD_ATTRIBUTE)" %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_IDENTIFIER "identifier (T_IDENTIFIER)"
%token T_GET "get (T_GET)" %token T_GET "get (T_GET)"
%token T_SET "set (T_SET)" %token T_SET "set (T_SET)"
@ -73,7 +73,8 @@ using namespace icinga;
%type <num> field_attributes %type <num> field_attributes
%type <num> field_attribute_list %type <num> field_attribute_list
%type <num> T_FIELD_ACCESSOR_TYPE %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 <field> class_field
%type <fields> class_fields %type <fields> class_fields
%type <klass> class %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(); $$ = new Klass();
@ -177,22 +178,25 @@ class: abstract_specifier T_CLASS T_IDENTIFIER inherits_specifier '{' class_fiel
free($4); free($4);
} }
$$->Abstract = $1; $$->Attributes = $1;
$$->Fields = *$6; $$->Fields = *$6;
delete $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 */ inherits_specifier: /* empty */
{ {

View File

@ -121,10 +121,10 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
<< "\t\t" << "return \"" << klass.Name << "\";" << std::endl << "\t\t" << "return \"" << klass.Name << "\";" << std::endl
<< "\t" << "}" << std::endl << std::endl; << "\t" << "}" << std::endl << std::endl;
/* IsAbstract */ /* GetAttributes */
std::cout << "\t" << "virtual bool IsAbstract(void) const" << std::endl std::cout << "\t" << "virtual int GetAttributes(void) const" << std::endl
<< "\t" << "{" << 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; << "\t" << "}" << std::endl << std::endl;
/* GetBaseType */ /* GetBaseType */
@ -447,7 +447,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo& locp)
std::cout << "};" << std::endl << std::endl; std::cout << "};" << std::endl << std::endl;
/* FactoryHelper */ /* FactoryHelper */
if (klass.Abstract) { if (klass.Attributes & TAAbstract) {
std::cout << "template<>" << std::endl std::cout << "template<>" << std::endl
<< "struct FactoryHelper<" << klass.Name << ">" << std::endl << "struct FactoryHelper<" << klass.Name << ">" << std::endl
<< "{" << std::endl << "{" << std::endl

View File

@ -103,11 +103,17 @@ struct Field
} }
}; };
enum TypeAttribute
{
TAAbstract = 1,
TASafe = 2
};
struct Klass struct Klass
{ {
std::string Name; std::string Name;
std::string Parent; std::string Parent;
bool Abstract; int Attributes;
std::vector<Field> Fields; std::vector<Field> Fields;
}; };