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;
}
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(),

View 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();
}

View 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);
}

View 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);
}

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 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);
}

View 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()) {

View 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);

View File

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

View File

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

View File

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

View 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; }

View 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 */
{

View 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

View 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;
};