* Improved error messages

* Throw instead of asserts on invalid file input
pull/3514/head
Max Vollmer 2020-11-30 15:04:06 +00:00
parent 9ae112309f
commit 6ed1488e6e
5 changed files with 28 additions and 16 deletions

View File

@ -49,7 +49,9 @@ using namespace glTFCommon::Util;
namespace Util { namespace Util {
size_t DecodeBase64(const char *in, size_t inLength, uint8_t *&out) { 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) { if (inLength < 4) {
out = 0; out = 0;

View File

@ -249,7 +249,10 @@ inline char EncodeCharBase64(uint8_t b) {
} }
inline uint8_t DecodeCharBase64(char c) { inline uint8_t DecodeCharBase64(char c) {
return DATA<true>::tableDecodeBase64[size_t(c)]; // TODO faster with lookup table or ifs? if (c & 0xF0) {
throw DeadlyImportError("Invalid base64 char value: ", size_t(c));
}
return DATA<true>::tableDecodeBase64[size_t(c & 0x0F)]; // TODO faster with lookup table or ifs?
} }
size_t DecodeBase64(const char *in, size_t inLength, uint8_t *&out); 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); 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 } // namespace glTF2
// Include the implementation of the methods // Include the implementation of the methods

View File

@ -273,17 +273,21 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
} }
if (!mDict->IsArray()) { 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]; Value &obj = (*mDict)[i];
if (!obj.IsObject()) { if (!obj.IsObject()) {
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()) { 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 ", to_string(i), " has recursive reference to itself");
} }
mRecursiveReferenceCheck.insert(i); 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 } // namespace
template <class T> template <class T>
@ -766,11 +762,11 @@ void Accessor::ExtractData(T *&outData) {
const size_t targetElemSize = sizeof(T); const size_t targetElemSize = sizeof(T);
if (elemSize > targetElemSize) { 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())) { if (count*stride > (bufferView ? bufferView->byteLength : sparse->data.size())) {
throw DeadlyImportError("GLTF: count*stride out of range"); throw DeadlyImportError("GLTF: count*stride ", (count * stride), " > bufferView->byteLength ", bufferView->byteLength, " in ", getContextForErrorMessages(id, name));
} }
outData = new T[count]; 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()) { if (!node.meshes.empty()) {
// GLTF files contain at most 1 mesh per node. // 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 mesh_idx = node.meshes[0].GetIndex();
int count = meshOffsets[mesh_idx + 1] - meshOffsets[mesh_idx]; int count = meshOffsets[mesh_idx + 1] - meshOffsets[mesh_idx];