From bec878cc11f33500b2208d189176f5a222c4da53 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 16 Nov 2023 15:47:42 +0100 Subject: [PATCH] Fix crashes in various dictionary usages caused by duplicated keys #1925 #1924 --- Source/Engine/Level/Prefabs/Prefab.Apply.cpp | 16 +++++++--------- Source/Engine/Level/Prefabs/PrefabManager.cpp | 4 ++-- Source/Engine/Scripting/Scripting.cpp | 12 +++++------- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/Source/Engine/Level/Prefabs/Prefab.Apply.cpp b/Source/Engine/Level/Prefabs/Prefab.Apply.cpp index 454b68006..c10ea532d 100644 --- a/Source/Engine/Level/Prefabs/Prefab.Apply.cpp +++ b/Source/Engine/Level/Prefabs/Prefab.Apply.cpp @@ -253,7 +253,7 @@ void PrefabInstanceData::SerializePrefabInstances(PrefabInstancesData& prefabIns for (int32 i = 0; i < sceneObjects->Count(); i++) { SceneObject* obj = sceneObjects.Value->At(i); - instance.PrefabInstanceIdToDataIndex.Add(obj->GetSceneObjectId(), i); + instance.PrefabInstanceIdToDataIndex[obj->GetSceneObjectId()] = i; } } tmpBuffer.Clear(); @@ -313,15 +313,13 @@ bool PrefabInstanceData::SynchronizePrefabInstances(PrefabInstancesData& prefabI continue; } - modifier.Value->IdsMapping.Add(obj->GetPrefabObjectID(), obj->GetSceneObjectId()); + modifier.Value->IdsMapping[obj->GetPrefabObjectID()] = obj->GetSceneObjectId(); } } // Generate new IDs for the added objects (objects in prefab has to have a unique Ids, other than the targetActor instance objects to prevent Id collisions) for (int32 i = 0; i < newPrefabObjectIds.Count(); i++) - { - modifier->IdsMapping.Add(newPrefabObjectIds[i], Guid::New()); - } + modifier->IdsMapping[newPrefabObjectIds[i]] = Guid::New(); // Create new objects added to prefab int32 deserializeSceneObjectIndex = sceneObjects->Count(); @@ -786,7 +784,7 @@ bool Prefab::ApplyAllInternal(Actor* targetActor, bool linkTargetActorObjectToPr } // Cache connection for fast lookup - diffPrefabObjectIdToDataIndex.Add(obj->GetPrefabObjectID(), i); + diffPrefabObjectIdToDataIndex[obj->GetPrefabObjectID()] = i; // Strip unwanted data data.RemoveMember("ID"); @@ -796,7 +794,7 @@ bool Prefab::ApplyAllInternal(Actor* targetActor, bool linkTargetActorObjectToPr else { // Object if a new thing - newPrefabInstanceIdToDataIndex.Add(obj->GetSceneObjectId(), i); + newPrefabInstanceIdToDataIndex[obj->GetSceneObjectId()] = i; } } @@ -836,8 +834,8 @@ bool Prefab::ApplyAllInternal(Actor* targetActor, bool linkTargetActorObjectToPr for (auto i = newPrefabInstanceIdToDataIndex.Begin(); i.IsNotEnd(); ++i) { const auto prefabObjectId = Guid::New(); - newPrefabInstanceIdToPrefabObjectId.Add(i->Key, prefabObjectId); - modifier->IdsMapping.Add(i->Key, prefabObjectId); + newPrefabInstanceIdToPrefabObjectId[i->Key] = prefabObjectId; + modifier->IdsMapping[i->Key] = prefabObjectId; } // Add inverse IDs mapping to link added objects and references inside them to the prefab objects diff --git a/Source/Engine/Level/Prefabs/PrefabManager.cpp b/Source/Engine/Level/Prefabs/PrefabManager.cpp index de164343b..c7b42b7d2 100644 --- a/Source/Engine/Level/Prefabs/PrefabManager.cpp +++ b/Source/Engine/Level/Prefabs/PrefabManager.cpp @@ -374,13 +374,13 @@ bool PrefabManager::CreatePrefab(Actor* targetActor, const StringView& outputPat if (targetActor->HasParent()) { // Unlink from parent actor - objectInstanceIdToPrefabObjectId.Add(targetActor->GetParent()->GetID(), Guid::Empty); + objectInstanceIdToPrefabObjectId[targetActor->GetParent()->GetID()] = Guid::Empty; } for (int32 i = 0; i < sceneObjects->Count(); i++) { // Generate new IDs for the prefab objects (other than reference instance used to create prefab) const SceneObject* obj = sceneObjects->At(i); - objectInstanceIdToPrefabObjectId.Add(obj->GetSceneObjectId(), Guid::New()); + objectInstanceIdToPrefabObjectId[obj->GetSceneObjectId()] = Guid::New(); } { // Parse json to DOM document diff --git a/Source/Engine/Scripting/Scripting.cpp b/Source/Engine/Scripting/Scripting.cpp index e9dc0421c..6cabbc0dd 100644 --- a/Source/Engine/Scripting/Scripting.cpp +++ b/Source/Engine/Scripting/Scripting.cpp @@ -1026,30 +1026,28 @@ bool Scripting::IsTypeFromGameScripts(MClass* type) void Scripting::RegisterObject(ScriptingObject* obj) { + const Guid id = obj->GetID(); ScopeLock lock(_objectsLocker); //ASSERT(!_objectsDictionary.ContainsValue(obj)); #if ENABLE_ASSERTION #if USE_OBJECTS_DISPOSE_CRASHES_DEBUGGING ScriptingObjectData other; - if (_objectsDictionary.TryGet(obj->GetID(), other)) + if (_objectsDictionary.TryGet(id, other)) #else ScriptingObject* other; - if (_objectsDictionary.TryGet(obj->GetID(), other)) + if (_objectsDictionary.TryGet(id, other)) #endif { // Something went wrong... - LOG(Error, "Objects registry already contains object with ID={0} (type '{3}')! Trying to register object {1} (type '{2}').", obj->GetID(), obj->ToString(), String(obj->GetClass()->GetFullName()), String(other->GetClass()->GetFullName())); - _objectsDictionary.Remove(obj->GetID()); + LOG(Error, "Objects registry already contains object with ID={0} (type '{3}')! Trying to register object {1} (type '{2}').", id, obj->ToString(), String(obj->GetClass()->GetFullName()), String(other->GetClass()->GetFullName())); } -#else - ASSERT(!_objectsDictionary.ContainsKey(obj->_id)); #endif #if USE_OBJECTS_DISPOSE_CRASHES_DEBUGGING LOG(Info, "[RegisterObject] obj = 0x{0:x}, {1}", (uint64)obj, String(ScriptingObjectData(obj).TypeName)); #endif - _objectsDictionary.Add(obj->GetID(), obj); + _objectsDictionary[id] = obj; } void Scripting::UnregisterObject(ScriptingObject* obj)