diff --git a/lib/compressMG1.c b/lib/compressMG1.c index 4cc00aa..f70206f 100644 --- a/lib/compressMG1.c +++ b/lib/compressMG1.c @@ -324,6 +324,8 @@ int _ctmUncompressMesh_MG1(_CTMcontext * self) } _ctmStreamReadSTRING(self, &map->mName); _ctmStreamReadSTRING(self, &map->mFileName); + if(self->mError != CTM_NONE) + return CTM_FALSE; if(!_ctmStreamReadPackedFloats(self, map->mValues, self->mVertexCount, 2)) return CTM_FALSE; map = map->mNext; @@ -339,6 +341,8 @@ int _ctmUncompressMesh_MG1(_CTMcontext * self) return 0; } _ctmStreamReadSTRING(self, &map->mName); + if(self->mError != CTM_NONE) + return CTM_FALSE; if(!_ctmStreamReadPackedFloats(self, map->mValues, self->mVertexCount, 4)) return CTM_FALSE; map = map->mNext; diff --git a/lib/compressMG2.c b/lib/compressMG2.c index abe0759..a87845e 100644 --- a/lib/compressMG2.c +++ b/lib/compressMG2.c @@ -1280,6 +1280,11 @@ int _ctmUncompressMesh_MG2(_CTMcontext * self) } _ctmStreamReadSTRING(self, &map->mName); _ctmStreamReadSTRING(self, &map->mFileName); + if(self->mError != CTM_NONE) + { + free((void *) intUVCoords); + return CTM_FALSE; + } map->mPrecision = _ctmStreamReadFLOAT(self); if(map->mPrecision <= 0.0f) { @@ -1319,6 +1324,11 @@ int _ctmUncompressMesh_MG2(_CTMcontext * self) return CTM_FALSE; } _ctmStreamReadSTRING(self, &map->mName); + if(self->mError != CTM_NONE) + { + free((void *) intAttribs); + return CTM_FALSE; + } map->mPrecision = _ctmStreamReadFLOAT(self); if(map->mPrecision <= 0.0f) { diff --git a/lib/compressRAW.c b/lib/compressRAW.c index b3c7811..8e58978 100644 --- a/lib/compressRAW.c +++ b/lib/compressRAW.c @@ -157,6 +157,8 @@ int _ctmUncompressMesh_RAW(_CTMcontext * self) } _ctmStreamReadSTRING(self, &map->mName); _ctmStreamReadSTRING(self, &map->mFileName); + if(self->mError != CTM_NONE) + return 0; for(i = 0; i < self->mVertexCount * 2; ++ i) map->mValues[i] = _ctmStreamReadFLOAT(self); map = map->mNext; @@ -172,6 +174,8 @@ int _ctmUncompressMesh_RAW(_CTMcontext * self) return 0; } _ctmStreamReadSTRING(self, &map->mName); + if(self->mError != CTM_NONE) + return 0; for(i = 0; i < self->mVertexCount * 4; ++ i) map->mValues[i] = _ctmStreamReadFLOAT(self); map = map->mNext; diff --git a/lib/openctm.c b/lib/openctm.c index ae1c659..8310a59 100644 --- a/lib/openctm.c +++ b/lib/openctm.c @@ -1201,8 +1201,9 @@ CTMEXPORT void CTMCALL ctmLoadCustom(CTMcontext aContext, CTMreadfn aReadFn, self->mReadFn = aReadFn; self->mUserData = aUserData; - // Clear any old mesh arrays + // Clear any old mesh arrays and any stale error from a previous call _ctmClearMesh(self); + self->mError = CTM_NONE; // Read header from stream if(_ctmStreamReadUINT(self) != FOURCC("OCTM")) @@ -1234,6 +1235,11 @@ CTMEXPORT void CTMCALL ctmLoadCustom(CTMcontext aContext, CTMreadfn aReadFn, self->mAttribMapCount = _ctmStreamReadUINT(self); flags = _ctmStreamReadUINT(self); _ctmStreamReadSTRING(self, &self->mFileComment); + if(self->mError != CTM_NONE) + { + _ctmClearMesh(self); + return; + } // Allocate memory for the mesh arrays self->mVertices = (CTMfloat *) malloc(self->mVertexCount * sizeof(CTMfloat) * 3); diff --git a/lib/stream.c b/lib/stream.c index 02f491f..51c600d 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -129,18 +129,38 @@ void _ctmStreamReadSTRING(_CTMcontext * self, char ** aValue) *aValue = (char *) 0; } + // Do not keep parsing after an earlier read has already failed + if(self->mError != CTM_NONE) + return; + // Get string length len = _ctmStreamReadUINT(self); + // len + 1 would wrap to 0 (also for a 32-bit size_t), giving a tiny buffer + if(len == ~(CTMuint) 0) + { + self->mError = CTM_BAD_FORMAT; + return; + } + // Read string if(len > 0) { - *aValue = (char *) malloc(len + 1); + *aValue = (char *) malloc((size_t) len + 1); if(*aValue) { - _ctmStreamRead(self, (void *) *aValue, len); + // A short read means a truncated or crafted file + if(_ctmStreamRead(self, (void *) *aValue, len) != len) + { + free(*aValue); + *aValue = (char *) 0; + self->mError = CTM_BAD_FORMAT; + return; + } (*aValue)[len] = 0; } + else + self->mError = CTM_OUT_OF_MEMORY; } }