Răsfoiți Sursa

Added a check to detect and prevent recursive references in GLTF2 files

Max Vollmer 5 ani în urmă
părinte
comite
1bc7c710d6
2 a modificat fișierele cu 15 adăugiri și 1 ștergeri
  1. 7 0
      code/glTF2/glTF2Asset.h
  2. 8 1
      code/glTF2/glTF2Asset.inl

+ 7 - 0
code/glTF2/glTF2Asset.h

@@ -56,6 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/Exceptional.h>
 
 #include <map>
+#include <set>
 #include <string>
 #include <list>
 #include <vector>
@@ -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 <unordered_map>
+#   include <unordered_set>
 #   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<unsigned int> mRecursiveReferenceCheck;  //! Used by Retrieve to prevent recursive lookups
+
         void AttachToDocument(Document& doc);
         void DetachFromDocument();
 

+ 8 - 1
code/glTF2/glTF2Asset.inl

@@ -270,6 +270,11 @@ Ref<T> LazyDict<T>::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<T>(new T());
     inst->id = std::string(mDictId) + "_" + to_string(i);
@@ -277,7 +282,9 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i)
     ReadMember(obj, "name", inst->name);
     inst->Read(obj, mAsset);
 
-    return Add(inst.release());
+    Ref<T> result = Add(inst.release());
+    mRecursiveReferenceCheck.erase(i);
+    return result;
 }
 
 template<class T>