From 016eda6cf13fdbaba417b6efc2c63f5e5d3039e3 Mon Sep 17 00:00:00 2001 From: AMZN-koppersr <82230785+AMZN-koppersr@users.noreply.github.com> Date: Wed, 8 Dec 2021 13:57:45 -0800 Subject: [PATCH] Fixed infinite recursion when adding prefabs While processing prefabs into spawnables new prefabs can be added for later processing. Because the new prefabs were immediately added to the list of prefabs it could happen that the new prefabs would be added to the active processor for processing, which could lead to infinite recursion. Adding prefabs while iterating prefabs now delays the addition until the iteration has completed. Signed-off-by: AMZN-koppersr <82230785+AMZN-koppersr@users.noreply.github.com> --- .../Spawnable/PrefabProcessorContext.cpp | 26 +++++++++++++++++-- .../Prefab/Spawnable/PrefabProcessorContext.h | 1 + 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.cpp index efef0f53de..ff32ac2ea5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.cpp @@ -32,8 +32,24 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils bool PrefabProcessorContext::AddPrefab(AZStd::string prefabName, PrefabDom prefab) { - auto result = m_prefabs.emplace(AZStd::move(prefabName), AZStd::move(prefab)); - return result.second; + if (!m_isIterating) + { + auto result = m_prefabs.emplace(AZStd::move(prefabName), AZStd::move(prefab)); + return result.second; + } + else + { + auto it = m_prefabs.find(prefabName); + if (it == m_prefabs.end()) + { + auto result = m_pendingPrefabAdditions.emplace(AZStd::move(prefabName), AZStd::move(prefab)); + return result.second; + } + else + { + return false; + } + } } void PrefabProcessorContext::ListPrefabs(const AZStd::function& callback) @@ -43,7 +59,13 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils { callback(it.first, it.second); } + m_isIterating = false; + for (auto& prefab : m_pendingPrefabAdditions) + { + m_prefabs.emplace(AZStd::move(prefab.first), AZStd::move(prefab.second)); + } + m_pendingPrefabAdditions.clear(); } void PrefabProcessorContext::ListPrefabs(const AZStd::function& callback) const diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h index d35a09a574..ade17e2ff0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabProcessorContext.h @@ -134,6 +134,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils AZ::Data::AssetLoadBehavior ToAssetLoadBehavior(EntityAliasSpawnableLoadBehavior loadBehavior) const; NamedPrefabContainer m_prefabs; + NamedPrefabContainer m_pendingPrefabAdditions; SpawnableEntityAliasStore m_entityAliases; ProcessedObjectStoreContainer m_products; ProductAssetDependencyContainer m_registeredProductAssetDependencies;