From 1bc7c710d645a55f488857614c7c8d08eb6a137d Mon Sep 17 00:00:00 2001 From: Max Vollmer Date: Wed, 11 Mar 2020 09:54:24 +0000 Subject: [PATCH] Added a check to detect and prevent recursive references in GLTF2 files --- code/glTF2/glTF2Asset.h | 7 +++++++ code/glTF2/glTF2Asset.inl | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/code/glTF2/glTF2Asset.h b/code/glTF2/glTF2Asset.h index d3c1654d0..171400368 100644 --- a/code/glTF2/glTF2Asset.h +++ b/code/glTF2/glTF2Asset.h @@ -56,6 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include #include #include @@ -82,14 +83,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP # else # define gltf_unordered_map map +# define gltf_unordered_set set #endif #ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP # include +# include # if _MSC_VER > 1600 # define gltf_unordered_map unordered_map +# define gltf_unordered_set unordered_set # else # define gltf_unordered_map tr1::unordered_map +# define gltf_unordered_set tr1::unordered_set # endif #endif @@ -942,6 +947,8 @@ namespace glTF2 Value* mDict; //! JSON dictionary object Asset& mAsset; //! The asset instance + std::gltf_unordered_set mRecursiveReferenceCheck; //! Used by Retrieve to prevent recursive lookups + void AttachToDocument(Document& doc); void DetachFromDocument(); diff --git a/code/glTF2/glTF2Asset.inl b/code/glTF2/glTF2Asset.inl index 35ecfa62d..270020aef 100644 --- a/code/glTF2/glTF2Asset.inl +++ b/code/glTF2/glTF2Asset.inl @@ -270,6 +270,11 @@ Ref LazyDict::Retrieve(unsigned int i) throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" is not a JSON object"); } + if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) { + throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" has recursive reference to itself"); + } + mRecursiveReferenceCheck.insert(i); + // Unique ptr prevents memory leak in case of Read throws an exception auto inst = std::unique_ptr(new T()); inst->id = std::string(mDictId) + "_" + to_string(i); @@ -277,7 +282,9 @@ Ref LazyDict::Retrieve(unsigned int i) ReadMember(obj, "name", inst->name); inst->Read(obj, mAsset); - return Add(inst.release()); + Ref result = Add(inst.release()); + mRecursiveReferenceCheck.erase(i); + return result; } template