浏览代码

Merge https://github.com/tonttu/assimp

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@903 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
aramis_acg 14 年之前
父节点
当前提交
94767ecf8c

+ 1 - 1
code/BaseImporter.cpp

@@ -328,7 +328,7 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
 	if(*((uint16_t*)&data.front()) == 0xFEFF) {
 	if(*((uint16_t*)&data.front()) == 0xFEFF) {
 		DefaultLogger::get()->debug("Found UTF-16 BOM ...");
 		DefaultLogger::get()->debug("Found UTF-16 BOM ...");
 
 
-		const uint16_t* sstart = (uint16_t*)&data.front()+1, *send = (uint16_t*)&data.back()+1;
+		const uint16_t* sstart = (uint16_t*)&data.front()+1, *send = (uint16_t*)(&data.back()+1);
 		char* dstart,*dend;
 		char* dstart,*dend;
 		std::vector<char> output;
 		std::vector<char> output;
 		do {
 		do {

+ 3 - 3
code/ObjFileData.h

@@ -236,9 +236,9 @@ struct Mesh
 //!	\brief	Data structure to store all obj-specific model datas
 //!	\brief	Data structure to store all obj-specific model datas
 struct Model
 struct Model
 {
 {
-	typedef std::map<std::string*, std::vector<unsigned int>* > GroupMap;
-	typedef std::map<std::string*, std::vector<unsigned int>* >::iterator GroupMapIt;
-	typedef std::map<std::string*, std::vector<unsigned int>* >::const_iterator ConstGroupMapIt;
+	typedef std::map<std::string, std::vector<unsigned int>* > GroupMap;
+	typedef std::map<std::string, std::vector<unsigned int>* >::iterator GroupMapIt;
+	typedef std::map<std::string, std::vector<unsigned int>* >::const_iterator ConstGroupMapIt;
 
 
 	//!	Model name
 	//!	Model name
 	std::string m_ModelName;
 	std::string m_ModelName;

+ 14 - 13
code/ObjFileParser.cpp

@@ -66,6 +66,8 @@ ObjFileParser::ObjFileParser(std::vector<char> &Data,const std::string &strModel
 	m_uiLine(0),
 	m_uiLine(0),
 	m_pIO( io )
 	m_pIO( io )
 {
 {
+	memset(m_buffer, BUFFERSIZE, 0);
+
 	// Create the model instance to store all the data
 	// Create the model instance to store all the data
 	m_pModel = new ObjFile::Model();
 	m_pModel = new ObjFile::Model();
 	m_pModel->m_ModelName = strModelName;
 	m_pModel->m_ModelName = strModelName;
@@ -188,7 +190,7 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
 {
 {
 	size_t index = 0;
 	size_t index = 0;
 	m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
 	m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
-	while ( !isSeparator(*m_DataIt) && m_DataIt != m_DataItEnd )
+	while ( m_DataIt != m_DataItEnd && !isSeparator(*m_DataIt) )
 	{
 	{
 		pBuffer[index] = *m_DataIt;
 		pBuffer[index] = *m_DataIt;
 		index++;
 		index++;
@@ -262,7 +264,7 @@ void ObjFileParser::getFace()
 	char *pPtr = m_buffer;
 	char *pPtr = m_buffer;
 	char *pEnd = &pPtr[BUFFERSIZE];
 	char *pEnd = &pPtr[BUFFERSIZE];
 	pPtr = getNextToken<char*>(pPtr, pEnd);
 	pPtr = getNextToken<char*>(pPtr, pEnd);
-	if (pPtr == '\0')
+	if (pPtr == pEnd || *pPtr == '\0')
 		return;
 		return;
 
 
 	std::vector<unsigned int> *pIndices = new std::vector<unsigned int>;
 	std::vector<unsigned int> *pIndices = new std::vector<unsigned int>;
@@ -279,7 +281,7 @@ void ObjFileParser::getFace()
 		if (*pPtr == '\0')
 		if (*pPtr == '\0')
 			break;
 			break;
 
 
-		if (*pPtr=='\r')
+		if (*pPtr=='\r' || *pPtr=='\n')
 			break;
 			break;
 
 
 		if (*pPtr=='/' )
 		if (*pPtr=='/' )
@@ -372,7 +374,7 @@ void ObjFileParser::getMaterialDesc()
 		return;
 		return;
 
 
 	char *pStart = &(*m_DataIt);
 	char *pStart = &(*m_DataIt);
-	while ( !isSeparator(*m_DataIt) && m_DataIt != m_DataItEnd )
+	while ( m_DataIt != m_DataItEnd && !isSeparator(*m_DataIt) )
 		++m_DataIt;
 		++m_DataIt;
 
 
 	// Get name
 	// Get name
@@ -406,10 +408,9 @@ void ObjFileParser::getMaterialDesc()
 //	Get a comment, values will be skipped
 //	Get a comment, values will be skipped
 void ObjFileParser::getComment()
 void ObjFileParser::getComment()
 {
 {
-	bool running = true;
-	while (running)
+	while (m_DataIt != m_DataItEnd)
 	{
 	{
-		if ( '\n' == (*m_DataIt) || m_DataIt == m_DataItEnd ) 
+		if ( '\n' == (*m_DataIt))
 		{
 		{
 			++m_DataIt;
 			++m_DataIt;
 			break;
 			break;
@@ -431,7 +432,7 @@ void ObjFileParser::getMaterialLib()
 		return;
 		return;
 	
 	
 	char *pStart = &(*m_DataIt);
 	char *pStart = &(*m_DataIt);
-	while (!isNewLine(*m_DataIt))
+	while (m_DataIt != m_DataItEnd && !isNewLine(*m_DataIt))
 		m_DataIt++;
 		m_DataIt++;
 
 
 	// Check for existence
 	// Check for existence
@@ -465,7 +466,7 @@ void ObjFileParser::getNewMaterial()
 
 
 	char *pStart = &(*m_DataIt);
 	char *pStart = &(*m_DataIt);
 	std::string strMat( pStart, *m_DataIt );
 	std::string strMat( pStart, *m_DataIt );
-	while ( isSeparator( *m_DataIt ) )
+	while ( m_DataIt != m_DataItEnd && isSeparator( *m_DataIt ) )
 		m_DataIt++;
 		m_DataIt++;
 	std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
 	std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
 	if ( it == m_pModel->m_MaterialMap.end() )
 	if ( it == m_pModel->m_MaterialMap.end() )
@@ -516,7 +517,7 @@ void ObjFileParser::getGroupName()
 
 
 	// Store groupname in group library 
 	// Store groupname in group library 
 	char *pStart = &(*m_DataIt);
 	char *pStart = &(*m_DataIt);
-	while ( !isSeparator(*m_DataIt) )
+	while ( m_DataIt != m_DataItEnd && !isSeparator(*m_DataIt) )
 		m_DataIt++;
 		m_DataIt++;
 	std::string strGroupName(pStart, &(*m_DataIt));
 	std::string strGroupName(pStart, &(*m_DataIt));
 
 
@@ -524,7 +525,7 @@ void ObjFileParser::getGroupName()
 	if ( m_pModel->m_strActiveGroup != strGroupName )
 	if ( m_pModel->m_strActiveGroup != strGroupName )
 	{
 	{
 		// Search for already existing entry
 		// Search for already existing entry
-		ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(&strGroupName);
+		ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(strGroupName);
 		
 		
 		// We are mapping groups into the object structure
 		// We are mapping groups into the object structure
 		createObject( strGroupName );
 		createObject( strGroupName );
@@ -533,7 +534,7 @@ void ObjFileParser::getGroupName()
 		if (it == m_pModel->m_Groups.end())
 		if (it == m_pModel->m_Groups.end())
 		{
 		{
 			std::vector<unsigned int> *pFaceIDArray = new std::vector<unsigned int>;
 			std::vector<unsigned int> *pFaceIDArray = new std::vector<unsigned int>;
-			m_pModel->m_Groups[ &strGroupName ] = pFaceIDArray;
+			m_pModel->m_Groups[ strGroupName ] = pFaceIDArray;
 			m_pModel->m_pGroupFaceIDs = (pFaceIDArray);
 			m_pModel->m_pGroupFaceIDs = (pFaceIDArray);
 		}
 		}
 		else
 		else
@@ -563,7 +564,7 @@ void ObjFileParser::getObjectName()
 	if (m_DataIt == m_DataItEnd)
 	if (m_DataIt == m_DataItEnd)
 		return;
 		return;
 	char *pStart = &(*m_DataIt);
 	char *pStart = &(*m_DataIt);
-	while ( !isSeparator( *m_DataIt ) )
+	while ( m_DataIt != m_DataItEnd && !isSeparator( *m_DataIt ) )
 		++m_DataIt;
 		++m_DataIt;
 
 
 	std::string strObjectName(pStart, &(*m_DataIt));
 	std::string strObjectName(pStart, &(*m_DataIt));

+ 1 - 1
code/RemoveRedundantMaterials.cpp

@@ -147,7 +147,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene)
 			uint32_t me = aiHashes[i] = ((MaterialHelper*)pScene->mMaterials[i])->ComputeHash();
 			uint32_t me = aiHashes[i] = ((MaterialHelper*)pScene->mMaterials[i])->ComputeHash();
 			for (unsigned int a = 0; a < i;++a)
 			for (unsigned int a = 0; a < i;++a)
 			{
 			{
-				if (me == aiHashes[a])	{				
+				if (abReferenced[a] && me == aiHashes[a]) {
 					++iCnt;
 					++iCnt;
 					me = 0;
 					me = 0;
 					aiMappingTable[i] = aiMappingTable[a];
 					aiMappingTable[i] = aiMappingTable[a];

+ 6 - 4
code/SplitByBoneCountProcess.cpp

@@ -47,6 +47,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // internal headers of the post-processing framework
 // internal headers of the post-processing framework
 #include "SplitByBoneCountProcess.h"
 #include "SplitByBoneCountProcess.h"
 
 
+#include <limits>
+
 using namespace Assimp;
 using namespace Assimp;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -262,7 +264,7 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
 		// and copy over the data, generating faces with linear indices along the way
 		// and copy over the data, generating faces with linear indices along the way
 		newMesh->mFaces = new aiFace[subMeshFaces.size()];
 		newMesh->mFaces = new aiFace[subMeshFaces.size()];
 		size_t nvi = 0; // next vertex index
 		size_t nvi = 0; // next vertex index
-		std::vector<size_t> previousVertexIndices( numSubMeshVertices, SIZE_MAX); // per new vertex: its index in the source mesh
+		std::vector<size_t> previousVertexIndices( numSubMeshVertices, std::numeric_limits<size_t>::max()); // per new vertex: its index in the source mesh
 		for( size_t a = 0; a < subMeshFaces.size(); ++a )
 		for( size_t a = 0; a < subMeshFaces.size(); ++a )
 		{
 		{
 			const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]];
 			const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]];
@@ -306,7 +308,7 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
 		newMesh->mNumBones = 0;
 		newMesh->mNumBones = 0;
 		newMesh->mBones = new aiBone*[numBones];
 		newMesh->mBones = new aiBone*[numBones];
 
 
-		std::vector<size_t> mappedBoneIndex( pMesh->mNumBones, SIZE_MAX);
+		std::vector<size_t> mappedBoneIndex( pMesh->mNumBones, std::numeric_limits<size_t>::max());
 		for( size_t a = 0; a < pMesh->mNumBones; ++a )
 		for( size_t a = 0; a < pMesh->mNumBones; ++a )
 		{
 		{
 			if( !isBoneUsed[a] )
 			if( !isBoneUsed[a] )
@@ -333,7 +335,7 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
 			for( size_t b = 0; b < bonesOnThisVertex.size(); ++b )
 			for( size_t b = 0; b < bonesOnThisVertex.size(); ++b )
 			{
 			{
 				size_t newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
 				size_t newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
-				if( newBoneIndex != SIZE_MAX )
+				if( newBoneIndex != std::numeric_limits<size_t>::max() )
 					newMesh->mBones[newBoneIndex]->mNumWeights++;
 					newMesh->mBones[newBoneIndex]->mNumWeights++;
 			}
 			}
 		}
 		}
@@ -359,7 +361,7 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
 			for( size_t b = 0; b < bonesOnThisVertex.size(); ++b)
 			for( size_t b = 0; b < bonesOnThisVertex.size(); ++b)
 			{
 			{
 				size_t newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
 				size_t newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
-				ai_assert( newBoneIndex != SIZE_MAX );
+				ai_assert( newBoneIndex != std::numeric_limits<size_t>::max() );
 				aiVertexWeight* dstWeight = newMesh->mBones[newBoneIndex]->mWeights + newMesh->mBones[newBoneIndex]->mNumWeights;
 				aiVertexWeight* dstWeight = newMesh->mBones[newBoneIndex]->mWeights + newMesh->mBones[newBoneIndex]->mNumWeights;
 				newMesh->mBones[newBoneIndex]->mNumWeights++;
 				newMesh->mBones[newBoneIndex]->mNumWeights++;
 
 

+ 1 - 1
code/XFileImporter.cpp

@@ -101,7 +101,7 @@ void XFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, I
 	mImportedMats.clear();
 	mImportedMats.clear();
 
 
 	// in the hope that binary files will never start with a BOM ...
 	// in the hope that binary files will never start with a BOM ...
-	mBuffer.resize( fileSize);
+	mBuffer.resize( fileSize + 1);
 	file->Read( &mBuffer.front(), 1, fileSize);
 	file->Read( &mBuffer.front(), 1, fileSize);
 	ConvertToUTF8(mBuffer);
 	ConvertToUTF8(mBuffer);
 
 

+ 52 - 17
code/XFileParser.cpp

@@ -91,7 +91,7 @@ XFileParser::XFileParser( const std::vector<char>& pBuffer)
 
 
 	// set up memory pointers
 	// set up memory pointers
 	P = &pBuffer.front();
 	P = &pBuffer.front();
-	End = P + pBuffer.size();
+	End = P + pBuffer.size() - 1;
 
 
 	// check header
 	// check header
 	if( strncmp( P, "xof ", 4) != 0)
 	if( strncmp( P, "xof ", 4) != 0)
@@ -180,7 +180,8 @@ XFileParser::XFileParser( const std::vector<char>& pBuffer)
 		// First find out how much storage we'll need. Count sections.
 		// First find out how much storage we'll need. Count sections.
 		const char* P1       = P;
 		const char* P1       = P;
 		unsigned int est_out = 0;
 		unsigned int est_out = 0;
-		while (P1 < End)
+
+		while (P1 + 3 < End)
 		{
 		{
 			// read next offset
 			// read next offset
 			uint16_t ofs = *((uint16_t*)P1);
 			uint16_t ofs = *((uint16_t*)P1);
@@ -199,12 +200,16 @@ XFileParser::XFileParser( const std::vector<char>& pBuffer)
 			// and advance to the next offset
 			// and advance to the next offset
 			P1 += ofs;
 			P1 += ofs;
 			est_out += MSZIP_BLOCK; // one decompressed block is 32786 in size
 			est_out += MSZIP_BLOCK; // one decompressed block is 32786 in size
+
+			// this block would continue past the file end, abort
+			if (P1 > End)
+				throw DeadlyImportError("X: Unexpected end of file while uncompressing");
 		}
 		}
 		
 		
-		// Allocate storage and do the actual uncompressing
-		uncompressed.resize(est_out);
+		// Allocate storage and terminating zero and do the actual uncompressing
+		uncompressed.resize(est_out + 1);
 		char* out = &uncompressed.front();
 		char* out = &uncompressed.front();
-		while (P < End)
+		while (P + 3 < End)
 		{
 		{
 			uint16_t ofs = *((uint16_t*)P);
 			uint16_t ofs = *((uint16_t*)P);
 			AI_SWAP2(ofs); 
 			AI_SWAP2(ofs); 
@@ -592,6 +597,9 @@ void XFileParser::ParseDataObjectMeshNormals( Mesh* pMesh)
 void XFileParser::ParseDataObjectMeshTextureCoords( Mesh* pMesh)
 void XFileParser::ParseDataObjectMeshTextureCoords( Mesh* pMesh)
 {
 {
 	readHeadOfDataObject();
 	readHeadOfDataObject();
+	if( pMesh->mNumTextures + 1 > AI_MAX_NUMBER_OF_TEXTURECOORDS)
+		ThrowException( "Too many sets of texture coordinates");
+
 	std::vector<aiVector2D>& coords = pMesh->mTexCoords[pMesh->mNumTextures++];
 	std::vector<aiVector2D>& coords = pMesh->mTexCoords[pMesh->mNumTextures++];
 
 
 	unsigned int numCoords = ReadInt();
 	unsigned int numCoords = ReadInt();
@@ -609,6 +617,8 @@ void XFileParser::ParseDataObjectMeshTextureCoords( Mesh* pMesh)
 void XFileParser::ParseDataObjectMeshVertexColors( Mesh* pMesh)
 void XFileParser::ParseDataObjectMeshVertexColors( Mesh* pMesh)
 {
 {
 	readHeadOfDataObject();
 	readHeadOfDataObject();
+	if( pMesh->mNumColorSets + 1 > AI_MAX_NUMBER_OF_COLOR_SETS)
+		ThrowException( "Too many colorsets");
 	std::vector<aiColor4D>& colors = pMesh->mColors[pMesh->mNumColorSets++];
 	std::vector<aiColor4D>& colors = pMesh->mColors[pMesh->mNumColorSets++];
 
 
 	unsigned int numColors = ReadInt();
 	unsigned int numColors = ReadInt();
@@ -659,7 +669,7 @@ void XFileParser::ParseDataObjectMeshMaterialList( Mesh* pMesh)
 	// commented out version check, as version 03.03 exported from blender also has 2 semicolons
 	// commented out version check, as version 03.03 exported from blender also has 2 semicolons
 	if( !mIsBinaryFormat) // && MajorVersion == 3 && MinorVersion <= 2)
 	if( !mIsBinaryFormat) // && MajorVersion == 3 && MinorVersion <= 2)
 	{
 	{
-		if( *P == ';')
+		if(P < End && *P == ';')
 			++P;
 			++P;
 	}
 	}
 
 
@@ -1043,6 +1053,7 @@ std::string XFileParser::GetNextToken()
 		// in binary mode it will only return NAME and STRING token
 		// in binary mode it will only return NAME and STRING token
 		// and (correctly) skip over other tokens.
 		// and (correctly) skip over other tokens.
 
 
+		if( End - P < 2) return s;
 		unsigned int tok = ReadBinWord();
 		unsigned int tok = ReadBinWord();
 		unsigned int len;
 		unsigned int len;
 
 
@@ -1051,13 +1062,17 @@ std::string XFileParser::GetNextToken()
 		{
 		{
 			case 1:
 			case 1:
 				// name token
 				// name token
+				if( End - P < 4) return s;
 				len = ReadBinDWord();
 				len = ReadBinDWord();
+				if( End - P < len) return s;
 				s = std::string(P, len);
 				s = std::string(P, len);
 				P += len;
 				P += len;
 				return s;
 				return s;
 			case 2:
 			case 2:
 				// string token
 				// string token
+				if( End - P < 4) return s;
 				len = ReadBinDWord();
 				len = ReadBinDWord();
+				if( End - P < len) return s;
 				s = std::string(P, len);
 				s = std::string(P, len);
 				P += (len + 2);
 				P += (len + 2);
 				return s;
 				return s;
@@ -1070,10 +1085,12 @@ std::string XFileParser::GetNextToken()
 				P += 16;
 				P += 16;
 				return "<guid>";
 				return "<guid>";
 			case 6:
 			case 6:
+				if( End - P < 4) return s;
 				len = ReadBinDWord();
 				len = ReadBinDWord();
 				P += (len * 4);
 				P += (len * 4);
 				return "<int_list>";
 				return "<int_list>";
 			case 7:
 			case 7:
+				if( End - P < 4) return s;
 				len = ReadBinDWord();
 				len = ReadBinDWord();
 				P += (len * mBinaryFloatSize);
 				P += (len * mBinaryFloatSize);
 				return "<flt_list>";
 				return "<flt_list>";
@@ -1227,6 +1244,7 @@ void XFileParser::ReadUntilEndOfLine()
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 unsigned short XFileParser::ReadBinWord()
 unsigned short XFileParser::ReadBinWord()
 {
 {
+	assert(End - P >= 2);
 	const unsigned char* q = (const unsigned char*) P;
 	const unsigned char* q = (const unsigned char*) P;
 	unsigned short tmp = q[0] | (q[1] << 8);
 	unsigned short tmp = q[0] | (q[1] << 8);
 	P += 2;
 	P += 2;
@@ -1236,6 +1254,7 @@ unsigned short XFileParser::ReadBinWord()
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 unsigned int XFileParser::ReadBinDWord()
 unsigned int XFileParser::ReadBinDWord()
 {
 {
+	assert(End - P >= 4);
 	const unsigned char* q = (const unsigned char*) P;
 	const unsigned char* q = (const unsigned char*) P;
 	unsigned int tmp = q[0] | (q[1] << 8) | (q[2] << 16) | (q[3] << 24);
 	unsigned int tmp = q[0] | (q[1] << 8) | (q[2] << 16) | (q[3] << 24);
 	P += 4;
 	P += 4;
@@ -1247,17 +1266,22 @@ unsigned int XFileParser::ReadInt()
 {
 {
 	if( mIsBinaryFormat)
 	if( mIsBinaryFormat)
 	{
 	{
-		if( mBinaryNumCount == 0)
+		if( mBinaryNumCount == 0 && End - P >= 2)
 		{
 		{
 			unsigned short tmp = ReadBinWord(); // 0x06 or 0x03
 			unsigned short tmp = ReadBinWord(); // 0x06 or 0x03
-			if( tmp == 0x06) // array of ints follows
+			if( tmp == 0x06 && End - P >= 4) // array of ints follows
 				mBinaryNumCount = ReadBinDWord();
 				mBinaryNumCount = ReadBinDWord();
 			else // single int follows
 			else // single int follows
 				mBinaryNumCount = 1; 
 				mBinaryNumCount = 1; 
 		}
 		}
 
 
 		--mBinaryNumCount;
 		--mBinaryNumCount;
-		return ReadBinDWord();
+		if ( End - P >= 4) {
+			return ReadBinDWord();
+		} else {
+			P = End;
+			return 0;
+		}
 	} else
 	} else
 	{
 	{
 		FindNextNoneWhiteSpace();
 		FindNextNoneWhiteSpace();
@@ -1296,10 +1320,10 @@ float XFileParser::ReadFloat()
 {
 {
 	if( mIsBinaryFormat)
 	if( mIsBinaryFormat)
 	{
 	{
-		if( mBinaryNumCount == 0)
+		if( mBinaryNumCount == 0 && End - P >= 2)
 		{
 		{
 			unsigned short tmp = ReadBinWord(); // 0x07 or 0x42
 			unsigned short tmp = ReadBinWord(); // 0x07 or 0x42
-			if( tmp == 0x07) // array of floats following
+			if( tmp == 0x07 && End - P >= 4) // array of floats following
 				mBinaryNumCount = ReadBinDWord();
 				mBinaryNumCount = ReadBinDWord();
 			else // single float following
 			else // single float following
 				mBinaryNumCount = 1; 
 				mBinaryNumCount = 1; 
@@ -1308,14 +1332,24 @@ float XFileParser::ReadFloat()
 		--mBinaryNumCount;
 		--mBinaryNumCount;
 		if( mBinaryFloatSize == 8)
 		if( mBinaryFloatSize == 8)
 		{
 		{
-			float result = (float) (*(double*) P);
-			P += 8;
-			return result;
+			if( End - P >= 8) {
+				float result = (float) (*(double*) P);
+				P += 8;
+				return result;
+			} else {
+				P = End;
+				return 0;
+			}
 		} else
 		} else
 		{
 		{
-			float result = *(float*) P;
-			P += 4;
-			return result;
+			if( End - P >= 4) {
+				float result = *(float*) P;
+				P += 4;
+				return result;
+			} else {
+				P = End;
+				return 0;
+			}
 		}
 		}
 	}
 	}
 
 
@@ -1323,6 +1357,7 @@ float XFileParser::ReadFloat()
 	FindNextNoneWhiteSpace();
 	FindNextNoneWhiteSpace();
 	// check for various special strings to allow reading files from faulty exporters
 	// check for various special strings to allow reading files from faulty exporters
 	// I mean you, Blender!
 	// I mean you, Blender!
+	// Reading is safe because of the terminating zero
 	if( strncmp( P, "-1.#IND00", 9) == 0 || strncmp( P, "1.#IND00", 8) == 0)
 	if( strncmp( P, "-1.#IND00", 9) == 0 || strncmp( P, "1.#IND00", 8) == 0)
 	{ 
 	{ 
 		P += 9;
 		P += 9;

+ 1 - 1
code/XFileParser.h

@@ -66,7 +66,7 @@ class XFileParser
 {
 {
 public:
 public:
 	/** Constructor. Creates a data structure out of the XFile given in the memory block. 
 	/** Constructor. Creates a data structure out of the XFile given in the memory block. 
-	 * @param pBuffer Memory buffer containing the XFile
+	 * @param pBuffer Null-terminated memory buffer containing the XFile
 	 */
 	 */
 	XFileParser( const std::vector<char>& pBuffer);
 	XFileParser( const std::vector<char>& pBuffer);
 
 

+ 1 - 0
include/export.h

@@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "aiTypes.h"
 #include "aiTypes.h"
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
+#include <boost/noncopyable.hpp>
 extern "C" {
 extern "C" {
 #endif
 #endif