LWO: replace legacy reinterpret_cast based code by memcpy to solve Android SIGBUS problems due to unaligned accesses. Fixes #351

This commit is contained in:
acgessler
2014-09-04 20:49:48 -07:00
parent 1a594b861a
commit 185f01963f
5 changed files with 182 additions and 144 deletions

View File

@@ -787,7 +787,8 @@ void LWOImporter::LoadLWO2Polygons(unsigned int length)
CountVertsAndFacesLWO2(iNumVertices,iNumFaces,cursor,end);
// allocate the output array and copy face indices
if (iNumFaces) {
if (iNumFaces)
{
cursor = (uint16_t*)mFileBuffer;
mCurLayer->mFaces.resize(iNumFaces,LWO::Face(type));
@@ -802,13 +803,18 @@ void LWOImporter::CountVertsAndFacesLWO2(unsigned int& verts, unsigned int& face
{
while (cursor < end && max--)
{
AI_LSWAP2P(cursor);
uint16_t numIndices = *cursor++;
uint16_t numIndices;
::memcpy(&numIndices, cursor++, 2);
AI_LSWAP2(numIndices);
numIndices &= 0x03FF;
verts += numIndices;++faces;
verts += numIndices;
++faces;
for(uint16_t i = 0; i < numIndices; i++)
{
ReadVSizedIntLWO2((uint8_t*&)cursor);
}
}
}
@@ -817,10 +823,16 @@ void LWOImporter::CopyFaceIndicesLWO2(FaceList::iterator& it,
uint16_t*& cursor,
const uint16_t* const end)
{
while (cursor < end) {
LWO::Face& face = *it++;;
if((face.mNumIndices = (*cursor++) & 0x03FF)) /* byte swapping has already been done */ {
while (cursor < end)
{
LWO::Face& face = *it++;
uint16_t numIndices;
::memcpy(&numIndices, cursor++, 2);
AI_LSWAP2(numIndices);
face.mNumIndices = numIndices & 0x03FF;
if(face.mNumIndices) /* byte swapping has already been done */
{
face.mIndices = new unsigned int[face.mNumIndices];
for(unsigned int i = 0; i < face.mNumIndices; i++)
{
@@ -848,8 +860,8 @@ void LWOImporter::LoadLWO2PolygonTags(unsigned int length)
if (type != AI_LWO_SURF && type != AI_LWO_SMGP)
return;
while (mFileBuffer < end) {
while (mFileBuffer < end)
{
unsigned int i = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs;
unsigned int j = GetU2();
@@ -1106,19 +1118,19 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
// first - get the index of the clip
clip.idx = GetU4();
IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
switch (head->type)
IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
switch (head.type)
{
case AI_LWO_STIL:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,STIL,1);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,STIL,1);
// "Normal" texture
GetS0(clip.path,head->length);
GetS0(clip.path,head.length);
clip.type = Clip::STILL;
break;
case AI_LWO_ISEQ:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ISEQ,16);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,ISEQ,16);
// Image sequence. We'll later take the first.
{
uint8_t digits = GetU1(); mFileBuffer++;
@@ -1127,12 +1139,12 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
std::string s;
std::ostringstream ss;
GetS0(s,head->length);
GetS0(s,head.length);
head->length -= (unsigned int)s.length()+1;
head.length -= (unsigned int)s.length()+1;
ss << s;
ss << std::setw(digits) << offset + start;
GetS0(s,head->length);
GetS0(s,head.length);
ss << s;
clip.path = ss.str();
clip.type = Clip::SEQ;
@@ -1148,7 +1160,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
break;
case AI_LWO_XREF:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,XREF,4);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,XREF,4);
// Just a cross-reference to another CLIp
clip.type = Clip::REF;
@@ -1156,7 +1168,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
break;
case AI_LWO_NEGA:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,NEGA,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,NEGA,2);
clip.negate = (0 != GetU2());
break;
@@ -1194,17 +1206,17 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
while (true)
{
if (mFileBuffer + 6 >= end)break;
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
LE_NCONST IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
if (mFileBuffer + head->length > end)
if (mFileBuffer + head.length > end)
throw DeadlyImportError("LWO2: Invalid envelope chunk length");
uint8_t* const next = mFileBuffer+head->length;
switch (head->type)
uint8_t* const next = mFileBuffer+head.length;
switch (head.type)
{
// Type & representation of the envelope
case AI_LWO_TYPE:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TYPE,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TYPE,2);
mFileBuffer++; // skip user format
// Determine type of envelope
@@ -1214,20 +1226,20 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
// precondition
case AI_LWO_PRE:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,PRE,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,PRE,2);
envelope.pre = (LWO::PrePostBehaviour)GetU2();
break;
// postcondition
case AI_LWO_POST:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,POST,2);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,POST,2);
envelope.post = (LWO::PrePostBehaviour)GetU2();
break;
// keyframe
case AI_LWO_KEY:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,KEY,8);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,KEY,8);
envelope.keys.push_back(LWO::Key());
LWO::Key& key = envelope.keys.back();
@@ -1240,7 +1252,7 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
// interval interpolation
case AI_LWO_SPAN:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPAN,4);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPAN,4);
if (envelope.keys.size()<2)
DefaultLogger::get()->warn("LWO2: Unexpected SPAN chunk");
else {
@@ -1286,22 +1298,22 @@ void LWOImporter::LoadLWO2File()
while (true)
{
if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
IFF::ChunkHeader* const head = IFF::LoadChunk(mFileBuffer);
const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
if (mFileBuffer + head->length > end)
if (mFileBuffer + head.length > end)
{
throw DeadlyImportError("LWO2: Chunk length points behind the file");
break;
}
uint8_t* const next = mFileBuffer+head->length;
uint8_t* const next = mFileBuffer+head.length;
unsigned int iUnnamed = 0;
if(!head->length) {
if(!head.length) {
mFileBuffer = next;
continue;
}
switch (head->type)
switch (head.type)
{
// new layer
case AI_LWO_LAYR:
@@ -1311,7 +1323,7 @@ void LWOImporter::LoadLWO2File()
LWO::Layer& layer = mLayers->back();
mCurLayer = &layer;
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LAYR,16);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LAYR,16);
// layer index.
layer.mIndex = GetU2();
@@ -1327,7 +1339,7 @@ void LWOImporter::LoadLWO2File()
mCurLayer->mPivot.x = GetF4();
mCurLayer->mPivot.y = GetF4();
mCurLayer->mPivot.z = GetF4();
GetS0(layer.mName,head->length-16);
GetS0(layer.mName,head.length-16);
// if the name is empty, generate a default name
if (layer.mName.empty()) {
@@ -1360,7 +1372,7 @@ void LWOImporter::LoadLWO2File()
break;
unsigned int old = (unsigned int)mCurLayer->mTempPoints.size();
LoadLWOPoints(head->length);
LoadLWOPoints(head.length);
mCurLayer->mPointIDXOfs = old;
break;
}
@@ -1379,7 +1391,7 @@ void LWOImporter::LoadLWO2File()
if (mCurLayer->mTempPoints.empty())
DefaultLogger::get()->warn("LWO2: Unexpected VMAP chunk");
else LoadLWO2VertexMap(head->length,head->type == AI_LWO_VMAD);
else LoadLWO2VertexMap(head.length,head.type == AI_LWO_VMAD);
break;
}
// face list
@@ -1389,7 +1401,7 @@ void LWOImporter::LoadLWO2File()
break;
unsigned int old = (unsigned int)mCurLayer->mFaces.size();
LoadLWO2Polygons(head->length);
LoadLWO2Polygons(head.length);
mCurLayer->mFaceIDXOfs = old;
break;
}
@@ -1401,7 +1413,7 @@ void LWOImporter::LoadLWO2File()
if (mCurLayer->mFaces.empty())
DefaultLogger::get()->warn("LWO2: Unexpected PTAG");
else LoadLWO2PolygonTags(head->length);
else LoadLWO2PolygonTags(head.length);
break;
}
// list of tags
@@ -1409,28 +1421,28 @@ void LWOImporter::LoadLWO2File()
{
if (!mTags->empty())
DefaultLogger::get()->warn("LWO2: SRFS chunk encountered twice");
else LoadLWOTags(head->length);
else LoadLWOTags(head.length);
break;
}
// surface chunk
case AI_LWO_SURF:
{
LoadLWO2Surface(head->length);
LoadLWO2Surface(head.length);
break;
}
// clip chunk
case AI_LWO_CLIP:
{
LoadLWO2Clip(head->length);
LoadLWO2Clip(head.length);
break;
}
// envelope chunk
case AI_LWO_ENVL:
{
LoadLWO2Envelope(head->length);
LoadLWO2Envelope(head.length);
break;
}
}