Fail gltf/gltf2 export whenever invalid / incomplete JSON is generated

This can happen currently for example if NaNs are introduced in accessor bounds as rapidjson cannot write NaN/inf floats (see subsequent commit for fix there) and will halt writing to buffer at this point.  Fix here ensures that whenever anything like this happens we throw an exception so this ends up as a registered export failure case, rather than silently exporting the incomplete JSON
pull/3214/head
Jeremy Cytryn 2020-05-06 23:41:05 -07:00
parent 578dc09810
commit aef4ecada5
4 changed files with 24 additions and 8 deletions

View File

@ -59,7 +59,7 @@ namespace glTF {
namespace { namespace {
template<typename T, size_t N> template<typename T, size_t N>
inline inline
Value& MakeValue(Value& val, T(&r)[N], MemoryPoolAllocator<>& al) { Value& MakeValue(Value& val, T(&r)[N], MemoryPoolAllocator<>& al) {
val.SetArray(); val.SetArray();
val.Reserve(N, al); val.Reserve(N, al);
@ -70,7 +70,7 @@ namespace glTF {
} }
template<typename T> template<typename T>
inline inline
Value& MakeValue(Value& val, const std::vector<T> & r, MemoryPoolAllocator<>& al) { Value& MakeValue(Value& val, const std::vector<T> & r, MemoryPoolAllocator<>& al) {
val.SetArray(); val.SetArray();
val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al); val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al);
@ -530,7 +530,9 @@ namespace glTF {
StringBuffer docBuffer; StringBuffer docBuffer;
PrettyWriter<StringBuffer> writer(docBuffer); PrettyWriter<StringBuffer> writer(docBuffer);
mDoc.Accept(writer); if (!mDoc.Accept(writer)) {
throw DeadlyExportError("Failed to write scene data!");
}
if (jsonOutFile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) { if (jsonOutFile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) {
throw DeadlyExportError("Failed to write scene data!"); throw DeadlyExportError("Failed to write scene data!");
@ -569,7 +571,9 @@ namespace glTF {
StringBuffer docBuffer; StringBuffer docBuffer;
Writer<StringBuffer> writer(docBuffer); Writer<StringBuffer> writer(docBuffer);
mDoc.Accept(writer); if (!mDoc.Accept(writer)) {
throw DeadlyExportError("Failed to write scene data!");
}
if (outfile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) { if (outfile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) {
throw DeadlyExportError("Failed to write scene data!"); throw DeadlyExportError("Failed to write scene data!");

View File

@ -613,7 +613,9 @@ namespace glTF2 {
StringBuffer docBuffer; StringBuffer docBuffer;
PrettyWriter<StringBuffer> writer(docBuffer); PrettyWriter<StringBuffer> writer(docBuffer);
mDoc.Accept(writer); if (!mDoc.Accept(writer)) {
throw DeadlyExportError("Failed to write scene data!");
}
if (jsonOutFile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) { if (jsonOutFile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) {
throw DeadlyExportError("Failed to write scene data!"); throw DeadlyExportError("Failed to write scene data!");
@ -664,7 +666,9 @@ namespace glTF2 {
StringBuffer docBuffer; StringBuffer docBuffer;
Writer<StringBuffer> writer(docBuffer); Writer<StringBuffer> writer(docBuffer);
mDoc.Accept(writer); if (!mDoc.Accept(writer)) {
throw DeadlyExportError("Failed to write scene data!");
}
uint32_t jsonChunkLength = (docBuffer.GetSize() + 3) & ~3; // Round up to next multiple of 4 uint32_t jsonChunkLength = (docBuffer.GetSize() + 3) & ~3; // Round up to next multiple of 4
auto paddingLength = jsonChunkLength - docBuffer.GetSize(); auto paddingLength = jsonChunkLength - docBuffer.GetSize();
@ -816,5 +820,3 @@ namespace glTF2 {
} }
} }

View File

@ -436,6 +436,16 @@ TEST_F(utglTF2ImportExport, error_string_preserved) {
ASSERT_NE(error.find("BoxTextured0.bin"), std::string::npos) << "Error string should contain an error about missing .bin file"; ASSERT_NE(error.find("BoxTextured0.bin"), std::string::npos) << "Error string should contain an error about missing .bin file";
} }
TEST_F(utglTF2ImportExport, export_bad_accessor_bounds) {
Assimp::Importer importer;
Assimp::Exporter exporter;
const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxWithInfinites-glTF-Binary/BoxWithInfinites.glb", aiProcess_ValidateDataStructure);
ASSERT_NE(scene, nullptr);
EXPECT_EQ(aiReturn_FAILURE, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxWithInfinites-glTF-Binary/BoxWithInfinites_out.glb"));
EXPECT_EQ(aiReturn_FAILURE, exporter.Export(scene, "gltf2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxWithInfinites-glTF-Binary/BoxWithInfinites_out.gltf"));
}
#endif // ASSIMP_BUILD_NO_EXPORT #endif // ASSIMP_BUILD_NO_EXPORT
TEST_F(utglTF2ImportExport, sceneMetadata) { TEST_F(utglTF2ImportExport, sceneMetadata) {