Merge pull request #3514 from ms-maxvollmer/gltf_fixes
GLTF: Fix crash on invalid base64 data + improved error messagespull/3527/head^2
commit
aee01e8345
|
@ -49,7 +49,9 @@ using namespace glTFCommon::Util;
|
|||
namespace Util {
|
||||
|
||||
size_t DecodeBase64(const char *in, size_t inLength, uint8_t *&out) {
|
||||
ai_assert(inLength % 4 == 0);
|
||||
if (inLength % 4 != 0) {
|
||||
throw DeadlyImportError("Invalid base64 encoded data: \"", std::string(in, std::min(size_t(32), inLength)), "\", length:", inLength);
|
||||
}
|
||||
|
||||
if (inLength < 4) {
|
||||
out = 0;
|
||||
|
|
|
@ -249,7 +249,10 @@ inline char EncodeCharBase64(uint8_t b) {
|
|||
}
|
||||
|
||||
inline uint8_t DecodeCharBase64(char c) {
|
||||
return DATA<true>::tableDecodeBase64[size_t(c)]; // TODO faster with lookup table or ifs?
|
||||
if (c & 0x80) {
|
||||
throw DeadlyImportError("Invalid base64 char value: ", size_t(c));
|
||||
}
|
||||
return DATA<true>::tableDecodeBase64[size_t(c & 0x7F)]; // TODO faster with lookup table or ifs?
|
||||
}
|
||||
|
||||
size_t DecodeBase64(const char *in, size_t inLength, uint8_t *&out);
|
||||
|
|
|
@ -1124,6 +1124,14 @@ private:
|
|||
IOStream *OpenFile(std::string path, const char *mode, bool absolute = false);
|
||||
};
|
||||
|
||||
inline std::string getContextForErrorMessages(const std::string &id, const std::string &name) {
|
||||
std::string context = id;
|
||||
if (!name.empty()) {
|
||||
context += " (\"" + name + "\")";
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
} // namespace glTF2
|
||||
|
||||
// Include the implementation of the methods
|
||||
|
|
|
@ -273,17 +273,21 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
|
|||
}
|
||||
|
||||
if (!mDict->IsArray()) {
|
||||
throw DeadlyImportError("GLTF: Field is not an array \"", mDictId, "\"");
|
||||
throw DeadlyImportError("GLTF: Field \"", mDictId, "\" is not an array");
|
||||
}
|
||||
|
||||
if (i >= mDict->Size()) {
|
||||
throw DeadlyImportError("GLTF: Array index ", i, " is out of bounds (", mDict->Size(), ") for \"", mDictId, "\"");
|
||||
}
|
||||
|
||||
Value &obj = (*mDict)[i];
|
||||
|
||||
if (!obj.IsObject()) {
|
||||
throw DeadlyImportError("GLTF: Object at index \"", to_string(i), "\" is not a JSON object");
|
||||
throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" 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");
|
||||
throw DeadlyImportError("GLTF: Object at index ", i, " in array \"", mDictId, "\" has recursive reference to itself");
|
||||
}
|
||||
mRecursiveReferenceCheck.insert(i);
|
||||
|
||||
|
@ -741,14 +745,6 @@ inline void CopyData(size_t count,
|
|||
}
|
||||
}
|
||||
|
||||
inline std::string getContextForErrorMessages(const std::string& id, const std::string& name) {
|
||||
std::string context = id;
|
||||
if (!name.empty()) {
|
||||
context += " (\"" + name + "\")";
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
template <class T>
|
||||
|
@ -766,11 +762,12 @@ void Accessor::ExtractData(T *&outData) {
|
|||
const size_t targetElemSize = sizeof(T);
|
||||
|
||||
if (elemSize > targetElemSize) {
|
||||
throw DeadlyImportError("GLTF: elemSize > targetElemSize");
|
||||
throw DeadlyImportError("GLTF: elemSize ", elemSize, " > targetElemSize ", targetElemSize, " in ", getContextForErrorMessages(id, name));
|
||||
}
|
||||
|
||||
if (count*stride > (bufferView ? bufferView->byteLength : sparse->data.size())) {
|
||||
throw DeadlyImportError("GLTF: count*stride out of range");
|
||||
const size_t maxSize = (bufferView ? bufferView->byteLength : sparse->data.size());
|
||||
if (count*stride > maxSize) {
|
||||
throw DeadlyImportError("GLTF: count*stride ", (count * stride), " > maxSize ", maxSize, " in ", getContextForErrorMessages(id, name));
|
||||
}
|
||||
|
||||
outData = new T[count];
|
||||
|
|
|
@ -918,7 +918,10 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
|
|||
|
||||
if (!node.meshes.empty()) {
|
||||
// GLTF files contain at most 1 mesh per node.
|
||||
assert(node.meshes.size() == 1);
|
||||
if (node.meshes.size() > 1)
|
||||
{
|
||||
throw DeadlyImportError("GLTF: Invalid input, found ", node.meshes.size(), " meshes in ", getContextForErrorMessages(node.id, node.name), ", but only 1 mesh per node allowed.");
|
||||
}
|
||||
int mesh_idx = node.meshes[0].GetIndex();
|
||||
int count = meshOffsets[mesh_idx + 1] - meshOffsets[mesh_idx];
|
||||
|
||||
|
|
Loading…
Reference in New Issue