Merge pull request #3070 from ms-maxvollmer/GLTF2_recursive_references_fix

GLTF2: Detect and abort recursive references
pull/3131/head^2
Kim Kulling 2020-04-16 11:47:39 +02:00 committed by GitHub
commit 4314fc0521
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 1 deletions

View File

@ -58,6 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <algorithm> #include <algorithm>
#include <list> #include <list>
#include <map> #include <map>
#include <set>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <vector> #include <vector>
@ -81,14 +82,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP #define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
#else #else
#define gltf_unordered_map map #define gltf_unordered_map map
#define gltf_unordered_set set
#endif #endif
#ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP #ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
#if _MSC_VER > 1600 #if _MSC_VER > 1600
#define gltf_unordered_map unordered_map #define gltf_unordered_map unordered_map
#define gltf_unordered_set unordered_set
#else #else
#define gltf_unordered_map tr1::unordered_map #define gltf_unordered_map tr1::unordered_map
#define gltf_unordered_set tr1::unordered_set
#endif #endif
#endif #endif
@ -874,6 +879,8 @@ class LazyDict : public LazyDictBase {
Value *mDict; //! JSON dictionary object Value *mDict; //! JSON dictionary object
Asset &mAsset; //! The asset instance Asset &mAsset; //! The asset instance
std::gltf_unordered_set<unsigned int> mRecursiveReferenceCheck; //! Used by Retrieve to prevent recursive lookups
void AttachToDocument(Document &doc); void AttachToDocument(Document &doc);
void DetachFromDocument(); void DetachFromDocument();

View File

@ -280,6 +280,11 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" is not a JSON object"); 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 // Unique ptr prevents memory leak in case of Read throws an exception
auto inst = std::unique_ptr<T>(new T()); auto inst = std::unique_ptr<T>(new T());
inst->id = std::string(mDictId) + "_" + to_string(i); inst->id = std::string(mDictId) + "_" + to_string(i);
@ -287,7 +292,9 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
ReadMember(obj, "name", inst->name); ReadMember(obj, "name", inst->name);
inst->Read(obj, mAsset); inst->Read(obj, mAsset);
return Add(inst.release()); Ref<T> result = Add(inst.release());
mRecursiveReferenceCheck.erase(i);
return result;
} }
template <class T> template <class T>

View File

@ -0,0 +1,25 @@
{
"asset": {
"version": "2.0"
},
"scene": 0,
"scenes": [
{
"nodes": [
0
]
}
],
"nodes": [
{
"children": [
1
]
},
{
"children": [
0
]
}
]
}

View File

@ -491,6 +491,12 @@ TEST_F(utglTF2ImportExport, texcoords) {
EXPECT_EQ(uvIndex, 1); EXPECT_EQ(uvIndex, 1);
} }
TEST_F(utglTF2ImportExport, recursive_nodes) {
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/RecursiveNodes/RecursiveNodes.gltf", aiProcess_ValidateDataStructure);
EXPECT_EQ(nullptr, scene);
}
TEST_F(utglTF2ImportExport, norootnode_noscene) { TEST_F(utglTF2ImportExport, norootnode_noscene) {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/TestNoRootNode/NoScene.gltf", aiProcess_ValidateDataStructure); const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/TestNoRootNode/NoScene.gltf", aiProcess_ValidateDataStructure);