Просмотр исходного кода

Fix #565 - avoid crash, packet buffer overruns/overflows, Fix #563 cavoid crash all getcurrentspell on dead lua state after reload spells called

Emagi 4 месяцев назад
Родитель
Сommit
79229a6de8

+ 6 - 2
EQ2/source/WorldServer/Items/Items.cpp

@@ -4069,11 +4069,13 @@ int8 PlayerItemList::FindFreeBankSlot() {
 }
 
 void PlayerItemList::ResetPackets() {
+	MPlayerItems.writelock(__FUNCTION__, __LINE__);
 	safe_delete_array(orig_packet);
 	safe_delete_array(xor_packet);
 	orig_packet = 0;
 	xor_packet = 0;
 	packet_count = 0;
+	MPlayerItems.writelock(__FUNCTION__, __LINE__);
 }
 
 
@@ -4177,10 +4179,12 @@ EquipmentItemList::~EquipmentItemList(){
 }
 
 void EquipmentItemList::ResetPackets() {
+	MEquipmentItems.lock();
 	safe_delete_array(orig_packet);
 	safe_delete_array(xor_packet);
 	orig_packet = 0;
 	xor_packet = 0;
+	MEquipmentItems.unlock();
 }
 
 bool EquipmentItemList::AddItem(int8 slot, Item* item){
@@ -4275,6 +4279,7 @@ EQ2Packet* EquipmentItemList::serialize(int16 version, Player* player){
 	EQ2Packet* app = 0;
 	Item* item = 0;
 	PacketStruct* packet = configReader.getStruct("WS_UpdateInventory", version);
+	MEquipmentItems.lock();
 	if(packet){
 		int8 packet_size = 0;
 		PacketStruct* packet2 = configReader.getStruct("Substruct_Item", version);
@@ -4288,7 +4293,6 @@ EQ2Packet* EquipmentItemList::serialize(int16 version, Player* player){
 			memset(xor_packet, 0, packet_size* num_slots);
 			memset(orig_packet, 0, packet_size* num_slots);
 		}
-		MEquipmentItems.lock();
 		int32 menu_data = 3;
 		int32 effective_level = player->GetInfoStructUInt("effective_level");
 
@@ -4384,11 +4388,11 @@ EQ2Packet* EquipmentItemList::serialize(int16 version, Player* player){
 			}
 			packet->setSubstructArrayDataByName("items", "index", i, 0, i);
 		}
-		MEquipmentItems.unlock();
 		packet->setDataByName("equip_flag", GetAppearanceType() ? 2 : 1);
 		app = packet->serializeCountPacket(version, 1, orig_packet, xor_packet);
 		safe_delete(packet);
 	}
+	MEquipmentItems.unlock();
 	return app;
 }
 ItemStatsValues* EquipmentItemList::CalculateEquipmentBonuses(Entity* entity){

+ 3 - 0
EQ2/source/WorldServer/LuaInterface.cpp

@@ -146,6 +146,9 @@ void LuaInterface::DestroySpells() {
 	map<string, LuaSpell*>::iterator itr;
 	MSpells.lock();
 	for(itr = spells.begin(); itr != spells.end(); itr++){
+		MSpellDelete.lock();
+		RemoveCurrentSpell(itr->second->state, false);
+		MSpellDelete.unlock();
 		lua_close(itr->second->state);
 		safe_delete(itr->second);
 	}

+ 2 - 0
EQ2/source/WorldServer/Player.cpp

@@ -2917,6 +2917,7 @@ EQ2Packet* Player::GetSpellSlotMappingPacket(int16 version){
 }
 
 EQ2Packet* Player::GetSpellBookUpdatePacket(int16 version) {
+    std::unique_lock lock(spell_packet_update_mutex);
 	PacketStruct* packet = configReader.getStruct("WS_UpdateSpellBook", version);
 	EQ2Packet* ret = 0;
 	if (packet) {
@@ -5752,6 +5753,7 @@ void Player::ResetSavedSpawns(){
 }
 
 void Player::SetReturningFromLD(bool val){
+    std::unique_lock lock(spell_packet_update_mutex);
 	if(val && val != returning_from_ld)
 	{
 		if(GetPlayerItemList())

+ 1 - 0
EQ2/source/WorldServer/Player.h

@@ -1119,6 +1119,7 @@ public:
 	void InitXPTable();
 	map<int8, int32> m_levelXPReq;
 
+	mutable std::shared_mutex spell_packet_update_mutex;
 private:
 	bool reset_mentorship;
 	bool range_attack;

+ 2 - 1
EQ2/source/WorldServer/Skills.cpp

@@ -345,7 +345,7 @@ int16 PlayerSkillList::CalculateSkillMaxValue(int32 skill_id, int16 max_val) {
 }
 
 EQ2Packet* PlayerSkillList::GetSkillPacket(int16 version){
-	std::shared_lock lock(MPlayerSkills);
+	std::unique_lock lock(MPlayerSkills);
 	PacketStruct* packet = configReader.getStruct("WS_UpdateSkillBook", version);
 	if(packet){
 			int16 skill_count = 0;
@@ -528,6 +528,7 @@ void PlayerSkillList::AddSkillBonus(int32 spell_id, int32 skill_id, float value)
 }
 
 void PlayerSkillList::ResetPackets() {
+	std::unique_lock lock(MPlayerSkills);
 	safe_delete_array(orig_packet);
 	safe_delete_array(xor_packet);
 	orig_packet_size = 0;