瀏覽代碼

Fix memory corruption during loading artifacts from mods

Vadim Markovtsev 9 年之前
父節點
當前提交
baa7a84db3
共有 8 個文件被更改,包括 37 次插入28 次删除
  1. 4 4
      lib/CArtHandler.cpp
  2. 1 1
      lib/CArtHandler.h
  3. 4 2
      lib/CModHandler.cpp
  4. 4 1
      lib/CModHandler.h
  5. 0 4
      lib/HeroBonus.cpp
  6. 0 1
      lib/HeroBonus.h
  7. 19 11
      lib/JsonNode.cpp
  8. 5 4
      lib/JsonNode.h

+ 4 - 4
lib/CArtHandler.cpp

@@ -439,13 +439,13 @@ void CArtHandler::loadGrowingArt(CGrowingArtifact * art, const JsonNode & node)
 {
 	for (auto b : node["growing"]["bonusesPerLevel"].Vector())
 	{
-		auto bonus = JsonUtils::parseBonus (b["bonus"]);
-		art->bonusesPerLevel.push_back (std::pair <ui16, Bonus> (b["level"].Float(), *bonus));
+		art->bonusesPerLevel.push_back(std::pair <ui16, Bonus>(b["level"].Float(), Bonus()));
+		JsonUtils::parseBonus(b["bonus"], &art->bonusesPerLevel.back().second);
 	}
 	for (auto b : node["growing"]["thresholdBonuses"].Vector())
 	{
-		auto bonus = JsonUtils::parseBonus (b["bonus"]);
-		art->thresholdBonuses.push_back (std::pair <ui16, Bonus> (b["level"].Float(), *bonus));
+		art->thresholdBonuses.push_back(std::pair <ui16, Bonus>(b["level"].Float(), Bonus()));
+		JsonUtils::parseBonus(b["bonus"], &art->thresholdBonuses.back().second);
 	}
 }
 

+ 1 - 1
lib/CArtHandler.h

@@ -98,7 +98,7 @@ public:
 	std::vector <std::pair <ui16, Bonus> > bonusesPerLevel; //bonus given each n levels
 	std::vector <std::pair <ui16, Bonus> > thresholdBonuses; //after certain level they will be added once
 
-	void levelUpArtifact (CArtifactInstance * art) override;
+	void levelUpArtifact(CArtifactInstance * art) override;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{

+ 4 - 2
lib/CModHandler.cpp

@@ -54,8 +54,10 @@ void CIdentifierStorage::checkIdentifier(std::string & ID)
 	}
 }
 
-CIdentifierStorage::ObjectCallback::ObjectCallback(std::string localScope, std::string remoteScope, std::string type,
-												   std::string name, const std::function<void(si32)> & callback, bool optional):
+CIdentifierStorage::ObjectCallback::ObjectCallback(
+		std::string localScope, std::string remoteScope, std::string type,
+		std::string name, const std::function<void(si32)> & callback,
+		bool optional):
 	localScope(localScope),
 	remoteScope(remoteScope),
 	type(type),

+ 4 - 1
lib/CModHandler.h

@@ -41,7 +41,10 @@ class CIdentifierStorage
 		std::function<void(si32)> callback;
 		bool optional;
 
-		ObjectCallback(std::string localScope, std::string remoteScope, std::string type, std::string name, const std::function<void(si32)> & callback, bool optional);
+		ObjectCallback(std::string localScope, std::string remoteScope,
+		               std::string type, std::string name,
+		               const std::function<void(si32)> & callback,
+		               bool optional);
 	};
 
 	struct ObjectData // entry created on ID registration

+ 0 - 4
lib/HeroBonus.cpp

@@ -1110,10 +1110,6 @@ Bonus::Bonus()
 	sid = 0;
 }
 
-Bonus::~Bonus()
-{
-}
-
 std::shared_ptr<Bonus> Bonus::addPropagator(TPropagatorPtr Propagator)
 {
 	propagator = Propagator;

+ 0 - 1
lib/HeroBonus.h

@@ -313,7 +313,6 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>
 	Bonus(ui16 Dur, BonusType Type, BonusSource Src, si32 Val, ui32 ID, std::string Desc, si32 Subtype=-1);
 	Bonus(ui16 Dur, BonusType Type, BonusSource Src, si32 Val, ui32 ID, si32 Subtype=-1, ValueType ValType = ADDITIVE_VALUE);
 	Bonus();
-	~Bonus();
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{

+ 19 - 11
lib/JsonNode.cpp

@@ -378,7 +378,7 @@ const T & parseByMap(const std::map<std::string, T> & map, const JsonNode * val,
 		return defaultValue;
 }
 
-void JsonUtils::resolveIdentifier (si32 &var, const JsonNode &node, std::string name)
+void JsonUtils::resolveIdentifier(si32 &var, const JsonNode &node, std::string name)
 {
 	const JsonNode &value = node[name];
 	if (!value.isNull())
@@ -400,7 +400,7 @@ void JsonUtils::resolveIdentifier (si32 &var, const JsonNode &node, std::string
 	}
 }
 
-void JsonUtils::resolveIdentifier (const JsonNode &node, si32 &var)
+void JsonUtils::resolveIdentifier(const JsonNode &node, si32 &var)
 {
 	switch (node.getType())
 	{
@@ -408,7 +408,7 @@ void JsonUtils::resolveIdentifier (const JsonNode &node, si32 &var)
 			var = node.Float();
 			break;
 		case JsonNode::DATA_STRING:
-			VLC->modh->identifiers.requestIdentifier (node, [&](si32 identifier)
+			VLC->modh->identifiers.requestIdentifier(node, [&](si32 identifier)
 			{
 				var = identifier;
 			});
@@ -420,8 +420,16 @@ void JsonUtils::resolveIdentifier (const JsonNode &node, si32 &var)
 
 std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonNode &ability)
 {
-
 	auto b = std::make_shared<Bonus>();
+	if (!parseBonus(ability, b.get()))
+	{
+		return nullptr;
+	}
+	return b;
+}
+
+bool JsonUtils::parseBonus(const JsonNode &ability, Bonus *b)
+{
 	const JsonNode *value;
 
 	std::string type = ability["type"].String();
@@ -429,11 +437,11 @@ std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonNode &ability)
 	if (it == bonusNameMap.end())
 	{
 		logGlobal->errorStream() << "Error: invalid ability type " << type;
-		return b;
+		return false;
 	}
 	b->type = it->second;
 
-	resolveIdentifier (b->subtype, ability, "subtype");
+	resolveIdentifier(b->subtype, ability, "subtype");
 
 	b->val = ability["val"].Float();
 
@@ -441,7 +449,7 @@ std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonNode &ability)
 	if (!value->isNull())
 		b->valType = static_cast<Bonus::ValueType>(parseByMap(bonusValueMap, value, "value type "));
 
-	resolveIdentifier (b->additionalInfo, ability, "addInfo");
+	resolveIdentifier(b->additionalInfo, ability, "addInfo");
 
 	b->turnsRemain = ability["turns"].Float();
 
@@ -499,7 +507,7 @@ std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonNode &ability)
 							const JsonVector vec = limiter["parameters"].Vector();
 							VLC->modh->identifiers.requestIdentifier("creature", vec[0], [=](si32 creature)
 							{
-								l2->setCreature (CreatureID(creature));
+								l2->setCreature(CreatureID(creature));
 							});
 							if (vec.size() > 1)
 							{
@@ -516,7 +524,7 @@ std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonNode &ability)
 							const JsonVector vec = limiter["parameters"].Vector();
 							std::string anotherBonusType = vec[0].String();
 
-							auto it = bonusNameMap.find (anotherBonusType);
+							auto it = bonusNameMap.find(anotherBonusType);
 							if (it == bonusNameMap.end())
 							{
 								logGlobal->errorStream() << "Error: invalid ability type " << anotherBonusType;
@@ -526,7 +534,7 @@ std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonNode &ability)
 
 							if (vec.size() > 1 )
 							{
-								resolveIdentifier (vec[1], l2->subtype);
+								resolveIdentifier(vec[1], l2->subtype);
 								l2->isSubtypeRelevant = true;
 							}
 							l = l2;
@@ -542,7 +550,7 @@ std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonNode &ability)
 	if (!value->isNull())
 		b->propagator = parseByMap(bonusPropagatorMap, value, "propagator type ");
 
-	return b;
+	return true;
 }
 
 //returns first Key with value equal to given one

+ 5 - 4
lib/JsonNode.h

@@ -130,11 +130,12 @@ namespace JsonUtils
 	DLL_LINKAGE void parseTypedBonusShort(const JsonVector &source, std::shared_ptr<Bonus> dest);
 
 	///
-	DLL_LINKAGE std::shared_ptr<Bonus> parseBonus (const JsonVector &ability_vec);
-	DLL_LINKAGE std::shared_ptr<Bonus> parseBonus (const JsonNode &bonus);
+	DLL_LINKAGE std::shared_ptr<Bonus> parseBonus(const JsonVector &ability_vec);
+	DLL_LINKAGE std::shared_ptr<Bonus> parseBonus(const JsonNode &ability);
+	DLL_LINKAGE bool parseBonus(const JsonNode &ability, Bonus *placement);
 	DLL_LINKAGE void unparseBonus (JsonNode &node, const std::shared_ptr<Bonus>& bonus);
-	DLL_LINKAGE void resolveIdentifier (si32 &var, const JsonNode &node, std::string name);
-	DLL_LINKAGE void resolveIdentifier (const JsonNode &node, si32 &var);
+	DLL_LINKAGE void resolveIdentifier(si32 &var, const JsonNode &node, std::string name);
+	DLL_LINKAGE void resolveIdentifier(const JsonNode &node, si32 &var);
 
 	/**
 	 * @brief recursively merges source into dest, replacing identical fields