From 6cbeca5518d8be6f91d4803427f0dd6d670bbd54 Mon Sep 17 00:00:00 2001 From: Krishty Date: Fri, 16 Apr 2021 20:44:40 +0200 Subject: [PATCH 01/11] fixed glTF export stuff being pulled into the EXE even if building with ASSIMP_BUILD_NO_EXPORT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit “LazyDictBase::WriteObjects()” in the two glTF implementations is only used for export. Since it’s a virtual method, and many compilers have trouble removing unreferenced virtual methods, glTF export stuff is pulled into the binary even if compiling without exports. This commit removes said virtual function if only compiling for import. This removes 75 KiB of useless code when compiled with Visual Studio for x64. --- code/AssetLib/glTF/glTFAsset.h | 4 ++++ code/AssetLib/glTF/glTFImporter.cpp | 2 ++ code/AssetLib/glTF2/glTF2Asset.h | 4 ++++ code/AssetLib/glTF2/glTF2Importer.cpp | 2 ++ 4 files changed, 12 insertions(+) diff --git a/code/AssetLib/glTF/glTFAsset.h b/code/AssetLib/glTF/glTFAsset.h index 1da70832b5..623f18173c 100644 --- a/code/AssetLib/glTF/glTFAsset.h +++ b/code/AssetLib/glTF/glTFAsset.h @@ -954,7 +954,9 @@ namespace glTF virtual void AttachToDocument(Document& doc) = 0; virtual void DetachFromDocument() = 0; +#if !defined(ASSIMP_BUILD_NO_EXPORT) virtual void WriteObjects(AssetWriter& writer) = 0; +#endif }; @@ -986,8 +988,10 @@ namespace glTF void AttachToDocument(Document& doc); void DetachFromDocument(); +#if !defined(ASSIMP_BUILD_NO_EXPORT) void WriteObjects(AssetWriter& writer) { WriteLazyDict(*this, writer); } +#endif Ref Add(T* obj); diff --git a/code/AssetLib/glTF/glTFImporter.cpp b/code/AssetLib/glTF/glTFImporter.cpp index 3335fc109e..5e072dd2a0 100644 --- a/code/AssetLib/glTF/glTFImporter.cpp +++ b/code/AssetLib/glTF/glTFImporter.cpp @@ -43,7 +43,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AssetLib/glTF/glTFImporter.h" #include "AssetLib/glTF/glTFAsset.h" +#if !defined(ASSIMP_BUILD_NO_EXPORT) #include "AssetLib/glTF/glTFAssetWriter.h" +#endif #include "PostProcessing/MakeVerboseFormat.h" #include diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 53b0791174..fad5cba83b 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -997,7 +997,9 @@ class LazyDictBase { virtual void AttachToDocument(Document &doc) = 0; virtual void DetachFromDocument() = 0; +#if !defined(ASSIMP_BUILD_NO_EXPORT) virtual void WriteObjects(AssetWriter &writer) = 0; +#endif }; template @@ -1030,7 +1032,9 @@ class LazyDict : public LazyDictBase { void AttachToDocument(Document &doc); void DetachFromDocument(); +#if !defined(ASSIMP_BUILD_NO_EXPORT) void WriteObjects(AssetWriter &writer) { WriteLazyDict(*this, writer); } +#endif Ref Add(T *obj); diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index dca6fcb2dc..ab1f01bf85 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -44,7 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AssetLib/glTF2/glTF2Importer.h" #include "PostProcessing/MakeVerboseFormat.h" #include "AssetLib/glTF2/glTF2Asset.h" +#if !defined(ASSIMP_BUILD_NO_EXPORT) #include "AssetLib/glTF2/glTF2AssetWriter.h" +#endif #include #include From 3fead344ad06446ce2dca9ea528fcca7b6948e35 Mon Sep 17 00:00:00 2001 From: Krishty Date: Mon, 19 Apr 2021 07:37:12 +0200 Subject: [PATCH 02/11] updated version string (if anyone cares) --- code/Common/Version.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Common/Version.cpp b/code/Common/Version.cpp index baa83940ea..205dde52bd 100644 --- a/code/Common/Version.cpp +++ b/code/Common/Version.cpp @@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. static const char *LEGAL_INFORMATION = "Open Asset Import Library (Assimp).\n" "A free C/C++ library to import various 3D file formats into applications\n\n" - "(c) 2006-2020, assimp team\n" + "(c) 2006-2021, Assimp team\n" "License under the terms and conditions of the 3-clause BSD license\n" "https://www.assimp.org\n"; From 930cc25c0e6426ccc6a92fdaab9b5eefe76c2a31 Mon Sep 17 00:00:00 2001 From: Krishty Date: Mon, 19 Apr 2021 09:51:44 +0200 Subject: [PATCH 03/11] fixed version string test --- test/unit/utVersion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/utVersion.cpp b/test/unit/utVersion.cpp index 15d3366fa2..0189cd2a91 100644 --- a/test/unit/utVersion.cpp +++ b/test/unit/utVersion.cpp @@ -48,7 +48,7 @@ TEST_F( utVersion, aiGetLegalStringTest ) { EXPECT_NE( lv, nullptr ); std::string text( lv ); - size_t pos( text.find( std::string( "2020" ) ) ); + size_t pos( text.find( std::string( "2021" ) ) ); EXPECT_NE( pos, std::string::npos ); } From 55dd5faafb4b80dd5f58147d56e69cd442eee29f Mon Sep 17 00:00:00 2001 From: Krishty Date: Mon, 19 Apr 2021 19:33:41 +0200 Subject: [PATCH 04/11] fixed export exceptions on import Ogre and 3MF imports threw DeadlyExportErrors under some circumstances. Bad for people who assumed that they only needed to catch DeadlyImportErrors. Changed them to DeadlyImportErrors. --- code/AssetLib/3MF/D3MFOpcPackage.cpp | 2 +- code/AssetLib/Ogre/OgreBinarySerializer.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/code/AssetLib/3MF/D3MFOpcPackage.cpp b/code/AssetLib/3MF/D3MFOpcPackage.cpp index 514e3c2f36..16e659ea3c 100644 --- a/code/AssetLib/3MF/D3MFOpcPackage.cpp +++ b/code/AssetLib/3MF/D3MFOpcPackage.cpp @@ -156,7 +156,7 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) : mRootStream = mZipArchive->Open(rootFile.c_str()); ai_assert(mRootStream != nullptr); if (nullptr == mRootStream) { - throw DeadlyExportError("Cannot open root-file in archive : " + rootFile); + throw DeadlyImportError("Cannot open root-file in archive : " + rootFile); } } else if (file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) { diff --git a/code/AssetLib/Ogre/OgreBinarySerializer.cpp b/code/AssetLib/Ogre/OgreBinarySerializer.cpp index 13bf54e9f7..0fc18feb98 100644 --- a/code/AssetLib/Ogre/OgreBinarySerializer.cpp +++ b/code/AssetLib/Ogre/OgreBinarySerializer.cpp @@ -181,13 +181,13 @@ Mesh *OgreBinarySerializer::ImportMesh(MemoryStreamReader *stream) { uint16_t id = serializer.ReadHeader(false); if (id != HEADER_CHUNK_ID) { - throw DeadlyExportError("Invalid Ogre Mesh file header."); + throw DeadlyImportError("Invalid Ogre Mesh file header."); } /// @todo Check what we can actually support. std::string version = serializer.ReadLine(); if (version != MESH_VERSION_1_8) { - throw DeadlyExportError("Mesh version ", version, " not supported by this importer. Run OgreMeshUpgrader tool on the file and try again.", + throw DeadlyImportError("Mesh version ", version, " not supported by this importer. Run OgreMeshUpgrader tool on the file and try again.", " Supported versions: ", MESH_VERSION_1_8); } @@ -797,13 +797,13 @@ MemoryStreamReaderPtr OgreBinarySerializer::OpenReader(Assimp::IOSystem *pIOHand void OgreBinarySerializer::ReadSkeleton(Skeleton *skeleton) { uint16_t id = ReadHeader(false); if (id != HEADER_CHUNK_ID) { - throw DeadlyExportError("Invalid Ogre Skeleton file header."); + throw DeadlyImportError("Invalid Ogre Skeleton file header."); } // This deserialization supports both versions of the skeleton spec std::string version = ReadLine(); if (version != SKELETON_VERSION_1_8 && version != SKELETON_VERSION_1_1) { - throw DeadlyExportError("Skeleton version ", version, " not supported by this importer.", + throw DeadlyImportError("Skeleton version ", version, " not supported by this importer.", " Supported versions: ", SKELETON_VERSION_1_8, " and ", SKELETON_VERSION_1_1); } From 746d5cf964120967a72322ad98723390707f15f4 Mon Sep 17 00:00:00 2001 From: "Max Vollmer (Microsoft Havok)" <60260460+ms-maxvollmer@users.noreply.github.com> Date: Wed, 21 Apr 2021 16:17:03 +0100 Subject: [PATCH 05/11] * Throw instead of assert on invalid file input * Check JSON object type before accessing members * Ensure samplers input and output references are set before accessing them --- code/AssetLib/glTF2/glTF2Asset.inl | 27 ++++++++++++++++++++-- code/AssetLib/glTF2/glTF2Importer.cpp | 6 ++--- code/PostProcessing/SortByPTypeProcess.cpp | 4 +++- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 77537028fb..8a793c144f 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -162,6 +162,9 @@ inline static bool ReadValue(Value &val, T &out) { template inline static bool ReadMember(Value &obj, const char *id, T &out) { + if (!obj.IsObject()) { + return false; + } Value::MemberIterator it = obj.FindMember(id); if (it != obj.MemberEnd()) { return ReadHelper::Read(it->value, out); @@ -176,6 +179,9 @@ inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) { } inline Value *FindMember(Value &val, const char *id) { + if (!val.IsObject()) { + return nullptr; + } Value::MemberIterator it = val.FindMember(id); return (it != val.MemberEnd()) ? &it->value : nullptr; } @@ -193,6 +199,9 @@ inline void throwUnexpectedTypeError(const char (&expectedTypeName)[N], const ch // Look-up functions with type checks. Context and extra context help the user identify the problem if there's an error. inline Value *FindStringInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) { + if (!val.IsObject()) { + return nullptr; + } Value::MemberIterator it = val.FindMember(memberId); if (it == val.MemberEnd()) { return nullptr; @@ -204,6 +213,9 @@ inline Value *FindStringInContext(Value &val, const char *memberId, const char* } inline Value *FindNumberInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) { + if (!val.IsObject()) { + return nullptr; + } Value::MemberIterator it = val.FindMember(memberId); if (it == val.MemberEnd()) { return nullptr; @@ -215,6 +227,9 @@ inline Value *FindNumberInContext(Value &val, const char *memberId, const char* } inline Value *FindUIntInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) { + if (!val.IsObject()) { + return nullptr; + } Value::MemberIterator it = val.FindMember(memberId); if (it == val.MemberEnd()) { return nullptr; @@ -226,6 +241,9 @@ inline Value *FindUIntInContext(Value &val, const char *memberId, const char* co } inline Value *FindArrayInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) { + if (!val.IsObject()) { + return nullptr; + } Value::MemberIterator it = val.FindMember(memberId); if (it == val.MemberEnd()) { return nullptr; @@ -237,6 +255,9 @@ inline Value *FindArrayInContext(Value &val, const char *memberId, const char* c } inline Value *FindObjectInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) { + if (!val.IsObject()) { + return nullptr; + } Value::MemberIterator it = val.FindMember(memberId); if (it == val.MemberEnd()) { return nullptr; @@ -886,7 +907,7 @@ inline void Accessor::Read(Value &obj, Asset &r) { componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE); { const Value* countValue = FindUInt(obj, "count"); - if (!countValue || countValue->GetInt() < 1) + if (!countValue || countValue->GetUint() < 1) { throw DeadlyImportError("A strictly positive count value is required, when reading ", id.c_str(), name.empty() ? "" : " (" + name + ")"); } @@ -1105,7 +1126,9 @@ inline Accessor::Indexer::Indexer(Accessor &acc) : template T Accessor::Indexer::GetValue(int i) { ai_assert(data); - ai_assert(i * stride < accessor.GetMaxByteSize()); + if (i * stride >= accessor.GetMaxByteSize()) { + throw DeadlyImportError("GLTF: Invalid index ", i, ", count out of range for buffer with stride ", stride, " and size ", accessor.GetMaxByteSize(), "."); + } // Ensure that the memcpy doesn't overwrite the local. const size_t sizeToCopy = std::min(elemSize, sizeof(T)); T value = T(); diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index dca6fcb2dc..b6b6a364c3 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -1170,7 +1170,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler static const float kMillisecondsFromSeconds = 1000.f; - if (samplers.translation) { + if (samplers.translation && samplers.translation->input && samplers.translation->output) { float *times = nullptr; samplers.translation->input->ExtractData(times); aiVector3D *values = nullptr; @@ -1194,7 +1194,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler anim->mPositionKeys->mValue.z = node.translation.value[2]; } - if (samplers.rotation) { + if (samplers.rotation && samplers.rotation->input && samplers.rotation->output) { float *times = nullptr; samplers.rotation->input->ExtractData(times); aiQuaternion *values = nullptr; @@ -1222,7 +1222,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler anim->mRotationKeys->mValue.w = node.rotation.value[3]; } - if (samplers.scale) { + if (samplers.scale && samplers.scale->input && samplers.scale->output) { float *times = nullptr; samplers.scale->input->ExtractData(times); aiVector3D *values = nullptr; diff --git a/code/PostProcessing/SortByPTypeProcess.cpp b/code/PostProcessing/SortByPTypeProcess.cpp index dd69026925..38549b9a03 100644 --- a/code/PostProcessing/SortByPTypeProcess.cpp +++ b/code/PostProcessing/SortByPTypeProcess.cpp @@ -135,7 +135,9 @@ void SortByPTypeProcess::Execute(aiScene *pScene) { std::vector::iterator meshIdx = replaceMeshIndex.begin(); for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { aiMesh *const mesh = pScene->mMeshes[i]; - ai_assert(0 != mesh->mPrimitiveTypes); + if (mesh->mPrimitiveTypes == 0) { + throw DeadlyImportError("GLTF: Mesh with invalid primitive type: ", mesh->mName.C_Str()); + } // if there's just one primitive type in the mesh there's nothing to do for us unsigned int num = 0; From 44dc08f128c97667104a5dc6a85bf1ea645ce1b5 Mon Sep 17 00:00:00 2001 From: "Max Vollmer (Microsoft Havok)" <60260460+ms-maxvollmer@users.noreply.github.com> Date: Wed, 21 Apr 2021 16:20:58 +0100 Subject: [PATCH 06/11] Remove GLTF tag, postprocessing is format independent --- code/PostProcessing/SortByPTypeProcess.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/PostProcessing/SortByPTypeProcess.cpp b/code/PostProcessing/SortByPTypeProcess.cpp index 38549b9a03..20ab63249b 100644 --- a/code/PostProcessing/SortByPTypeProcess.cpp +++ b/code/PostProcessing/SortByPTypeProcess.cpp @@ -136,7 +136,7 @@ void SortByPTypeProcess::Execute(aiScene *pScene) { for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { aiMesh *const mesh = pScene->mMeshes[i]; if (mesh->mPrimitiveTypes == 0) { - throw DeadlyImportError("GLTF: Mesh with invalid primitive type: ", mesh->mName.C_Str()); + throw DeadlyImportError("Mesh with invalid primitive type: ", mesh->mName.C_Str()); } // if there's just one primitive type in the mesh there's nothing to do for us From 31438a03a6430ee35c686b2bb7b3294fb55588cb Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 23 Apr 2021 14:52:31 +0200 Subject: [PATCH 07/11] Add Codacy Badge - Add assimp to codacy - Add batch to readme --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index 9fecfedf5b..e6c5fdbac4 100644 --- a/Readme.md +++ b/Readme.md @@ -8,6 +8,7 @@ A library to import and export various 3d-model-formats including scene-post-pro Coverity Scan Build Status +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9973693b7bdd4543b07084d5d9cf4745)](https://www.codacy.com/gh/assimp/assimp/dashboard?utm_source=github.com&utm_medium=referral&utm_content=assimp/assimp&utm_campaign=Badge_Grade) [![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master) [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue") From 4db4e7206da36f80136f85912beb2110866edb0d Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 23 Apr 2021 15:14:38 +0200 Subject: [PATCH 08/11] Update Readme.md --- Readme.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Readme.md b/Readme.md index e6c5fdbac4..81fd9fd9dc 100644 --- a/Readme.md +++ b/Readme.md @@ -12,7 +12,6 @@ A library to import and export various 3d-model-formats including scene-post-pro [![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master) [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue") -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/5be56faac64f46fc941ac890fb4febef)](https://www.codacy.com/app/kimkulling/assimp?utm_source=github.com&utm_medium=referral&utm_content=assimp/assimp&utm_campaign=Badge_Grade) [![Total alerts](https://img.shields.io/lgtm/alerts/g/assimp/assimp.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/assimp/assimp/alerts/)
From 708d124745a4256e8e8850dd9cbce4853a971e9f Mon Sep 17 00:00:00 2001 From: Jason C Date: Mon, 26 Apr 2021 19:42:22 -0400 Subject: [PATCH 09/11] Update aiProcess_PreTransformVertices docs to match behavior. Addresses #3820, the easy way. --- include/assimp/postprocess.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/include/assimp/postprocess.h b/include/assimp/postprocess.h index 01eabaef98..ca2c2c22d3 100644 --- a/include/assimp/postprocess.h +++ b/include/assimp/postprocess.h @@ -209,9 +209,14 @@ enum aiPostProcessSteps /**
Removes the node graph and pre-transforms all vertices with * the local transformation matrices of their nodes. * - * The output scene still contains nodes, however there is only a - * root node with children, each one referencing only one mesh, - * and each mesh referencing one material. For rendering, you can + * If the resulting scene can be reduced to a single mesh, with a single + * material, no lights, and no cameras, then the output scene will contain + * only a root node (with no children) that references the single mesh. + * Otherwise, the output scene will be reduced to a root node with a single + * level of child nodes, each one referencing one mesh, and each mesh + * referencing one material. + * + * In either case, for rendering, you can * simply render all meshes in order - you don't need to pay * attention to local transformations and the node hierarchy. * Animations are removed during this step. From 3acd42c22ed48225919cf03a092262a2e706fbdd Mon Sep 17 00:00:00 2001 From: Jason C Date: Mon, 26 Apr 2021 20:27:28 -0400 Subject: [PATCH 10/11] Remove newline from name of Blender importer. Addresses #3797. Re-submitting this as a quick fix to the immediate issue while I think about the website field. --- code/AssetLib/Blender/BlenderLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/AssetLib/Blender/BlenderLoader.cpp b/code/AssetLib/Blender/BlenderLoader.cpp index 989e9d59a9..71ab67721a 100644 --- a/code/AssetLib/Blender/BlenderLoader.cpp +++ b/code/AssetLib/Blender/BlenderLoader.cpp @@ -88,7 +88,7 @@ using namespace Assimp::Blender; using namespace Assimp::Formatter; static const aiImporterDesc blenderDesc = { - "Blender 3D Importer \nhttp://www.blender3d.org", + "Blender 3D Importer (http://www.blender3d.org)", "", "", "No animation support yet", From 6abdd0cd3e5f199f0c3bd5f4b08eb3c296edce81 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 28 Apr 2021 16:38:22 +0200 Subject: [PATCH 11/11] Fix crash when reading 0 bytes - This is a valid option so crash shall not happen --- code/Common/DefaultIOStream.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/Common/DefaultIOStream.cpp b/code/Common/DefaultIOStream.cpp index 115fea63c2..ba9b9d625c 100644 --- a/code/Common/DefaultIOStream.cpp +++ b/code/Common/DefaultIOStream.cpp @@ -90,10 +90,12 @@ DefaultIOStream::~DefaultIOStream() { size_t DefaultIOStream::Read(void *pvBuffer, size_t pSize, size_t pCount) { + if (0 == pCount) { + return 0; + } ai_assert(nullptr != pvBuffer); ai_assert(0 != pSize); - ai_assert(0 != pCount); - + return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0); }