瀏覽代碼

Cap glTFv1 & 2 json size to ~4GB

Ensures size_t cannot overflow
Limits the maximum contiguous memory allocation to something plausible.
RichardTea 3 年之前
父節點
當前提交
69cafe64b4
共有 2 個文件被更改,包括 24 次插入6 次删除
  1. 11 2
      code/AssetLib/glTF/glTFAsset.inl
  2. 13 4
      code/AssetLib/glTF2/glTF2Asset.inl

+ 11 - 2
code/AssetLib/glTF/glTFAsset.inl

@@ -1148,7 +1148,7 @@ inline void Asset::ReadBinaryHeader(IOStream &stream) {
     AI_SWAP4(header.length);
     AI_SWAP4(header.sceneLength);
 
-    mSceneLength = static_cast<size_t>(header.sceneLength);
+    mSceneLength = static_cast<size_t>(header.sceneLength); // Can't be larger than 4GB (max. uint32_t)
 
     mBodyOffset = sizeof(header) + mSceneLength;
     mBodyOffset = (mBodyOffset + 3) & ~3; // Round up to next multiple of 4
@@ -1179,8 +1179,17 @@ inline void Asset::Load(const std::string &pFile, bool isBinary) {
         mBodyLength = 0;
     }
 
-    // read the scene data
+    // Smallest legal JSON file is "{}" Smallest loadable glTF file is larger than that but catch it later
+    if (mSceneLength < 2) {
+      throw DeadlyImportError("GLTF: No JSON file contents");
+    }
+
+    // Binary format only supports up to 4GB of JSON so limit it there to avoid extreme memory allocation
+    if (mSceneLength > std::numeric_limits<uint32_t>::max()) {
+      throw DeadlyImportError("GLTF: JSON size greater than 4GB");
+    }
 
+    // read the scene data, ensure null termination
     std::vector<char> sceneData(mSceneLength + 1);
     sceneData[mSceneLength] = '\0';
 

+ 13 - 4
code/AssetLib/glTF2/glTF2Asset.inl

@@ -1777,9 +1777,9 @@ inline void Asset::ReadBinaryHeader(IOStream &stream, std::vector<char> &sceneDa
         throw DeadlyImportError("GLTF: JSON chunk missing");
     }
 
-    // read the scene data
+    // read the scene data, ensure null termination
 
-    mSceneLength = chunk.chunkLength;
+    mSceneLength = chunk.chunkLength; // Can't be larger than 4GB (max. uint32_t)
     sceneData.resize(mSceneLength + 1);
     sceneData[mSceneLength] = '\0';
 
@@ -1835,9 +1835,13 @@ inline void Asset::Load(const std::string &pFile, bool isBinary) {
     } else {
         mSceneLength = stream->FileSize();
         mBodyLength = 0;
+        
+        // Binary format only supports up to 4GB of JSON, use that as a maximum
+        if (mSceneLength > std::numeric_limits<uint32_t>::max()) {
+            throw DeadlyImportError("GLTF: JSON size greater than 4GB");
+        }
 
-        // read the scene data
-
+        // read the scene data, ensure null termination
         sceneData.resize(mSceneLength + 1);
         sceneData[mSceneLength] = '\0';
 
@@ -1846,6 +1850,11 @@ inline void Asset::Load(const std::string &pFile, bool isBinary) {
         }
     }
 
+    // Smallest legal JSON file is "{}" Smallest loadable glTF file is larger than that but catch it later
+    if (mSceneLength < 2) {
+      throw DeadlyImportError("GLTF: No JSON file contents");
+    }
+
     // parse the JSON document
     ASSIMP_LOG_DEBUG("Parsing GLTF2 JSON");
     Document doc;