Merge pull request #3514 from ms-maxvollmer/gltf_fixes

GLTF: Fix crash on invalid base64 data + improved error messages
pull/3527/head^2
Kim Kulling 2020-12-08 19:48:53 +01:00 committed by GitHub
commit aee01e8345
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 30 additions and 17 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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];

View File

@ -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];