ref: 0d10306120037ce049a7699f9eaa5314d5b888f8
parent: d944b669101c3bc474050913f70dc5c324632459
author: Bernhard Schelling <[email protected]>
date: Wed Sep 13 22:35:36 EDT 2023
Avoid potential memory leak with realloc (#77)
--- a/tsf.h
+++ b/tsf.h
@@ -863,9 +863,9 @@
}
#ifdef STB_VORBIS_INCLUDE_STB_VORBIS_H
-static TSF_BOOL tsf_decode_ogg(const tsf_u8 *pSmpl, const tsf_u8 *pSmplEnd, float** pRes, tsf_u32* pResNum, tsf_u32* pResMax, tsf_u32 resInitial)
+static int tsf_decode_ogg(const tsf_u8 *pSmpl, const tsf_u8 *pSmplEnd, float** pRes, tsf_u32* pResNum, tsf_u32* pResMax, tsf_u32 resInitial)
{
- float* res = *pRes; tsf_u32 resNum = *pResNum; tsf_u32 resMax = *pResMax; stb_vorbis *v;
+ float *res = *pRes, *oldres; tsf_u32 resNum = *pResNum; tsf_u32 resMax = *pResMax; stb_vorbis *v;
// Use whatever stb_vorbis API that is available (either pull or push)
#if !defined(STB_VORBIS_NO_PULLDATA_API) && !defined(STB_VORBIS_NO_FROMMEMORY)
@@ -873,7 +873,7 @@
#else
{ int use, err; v = stb_vorbis_open_pushdata(pSmpl, (int)(pSmplEnd - pSmpl), &use, &err, TSF_NULL); pSmpl += use; }
#endif
- if (v == TSF_NULL) return TSF_FALSE;
+ if (v == TSF_NULL) return 0;
for (;;)
{
@@ -894,14 +894,14 @@
if (resNum > resMax)
{
do { resMax += (resMax ? (resMax < 1048576 ? resMax : 1048576) : resInitial); } while (resNum > resMax);
- res = (float*)TSF_REALLOC(res, resMax * sizeof(float));
- if (!res) { stb_vorbis_close(v); return 0; }
+ res = (float*)TSF_REALLOC((oldres = res), resMax * sizeof(float));
+ if (!res) { TSF_FREE(oldres); stb_vorbis_close(v); return 0; }
}
TSF_MEMCPY(res + resNum - n_samples, outputs[0], n_samples * sizeof(float));
}
stb_vorbis_close(v);
*pRes = res; *pResNum = resNum; *pResMax = resMax;
- return TSF_TRUE;
+ return 1;
}
static int tsf_decode_sf3_samples(const void* rawBuffer, float** pFloatBuffer, unsigned int* pSmplCount, struct tsf_hydra *hydra)
@@ -908,7 +908,7 @@
{
const tsf_u8* smplBuffer = (const tsf_u8*)rawBuffer;
tsf_u32 smplLength = *pSmplCount, resNum = 0, resMax = 0, resInitial = (smplLength > 0x100000 ? (smplLength & ~0xFFFFF) : 65536);
- float *res = TSF_NULL;
+ float *res = TSF_NULL, *oldres;
int i;
for (i = 0; i < hydra->shdrNum; i++)
{
@@ -948,8 +948,8 @@
if (resNum > resMax)
{
do { resMax += (resMax ? (resMax < 1048576 ? resMax : 1048576) : resInitial); } while (resNum > resMax);
- res = (float*)TSF_REALLOC(res, resMax * sizeof(float));
- if (!res) { return 0; }
+ res = (float*)TSF_REALLOC((oldres = res), resMax * sizeof(float));
+ if (!res) { TSF_FREE(oldres); return 0; }
}
// Convert the samples from short to float
@@ -959,7 +959,7 @@
}
// Trim the sample buffer down then return success (unless out of memory)
- res = (float*)TSF_REALLOC(res, resNum * sizeof(float));
+ if (!(*pFloatBuffer = (float*)TSF_REALLOC(res, resNum * sizeof(float)))) *pFloatBuffer = res;
*pFloatBuffer = res;
*pSmplCount = resNum;
return (res ? 1 : 0);
@@ -970,6 +970,7 @@
{
#ifdef STB_VORBIS_INCLUDE_STB_VORBIS_H
// With OGG Vorbis support we cannot pre-allocate the memory for tsf_decode_sf3_samples
+ tsf_u32 resNum, resMax; float* oldres;
*pSmplCount = chunkSmpl->size;
*pRawBuffer = (void*)TSF_MALLOC(*pSmplCount);
if (!*pRawBuffer || !stream->read(stream->data, *pRawBuffer, chunkSmpl->size)) return 0;
@@ -976,9 +977,9 @@
if (chunkSmpl->id[3] != 'o') return 1;
// Decode custom .sfo 'smpo' format where all samples are in a single ogg stream
- tsf_u32 resNum = 0, resMax = 0, resInitial = 65536;
- if (!tsf_decode_ogg((tsf_u8*)*pRawBuffer, (tsf_u8*)*pRawBuffer + chunkSmpl->size, pFloatBuffer, &resNum, &resMax, resInitial)) return 0;
- *pFloatBuffer = (float*)TSF_REALLOC(*pFloatBuffer, resNum * sizeof(float));
+ resNum = resMax = 0;
+ if (!tsf_decode_ogg((tsf_u8*)*pRawBuffer, (tsf_u8*)*pRawBuffer + chunkSmpl->size, pFloatBuffer, &resNum, &resMax, 65536)) return 0;
+ if (!(*pFloatBuffer = (float*)TSF_REALLOC((oldres = *pFloatBuffer), resNum * sizeof(float)))) *pFloatBuffer = oldres;
*pSmplCount = resNum;
return (*pFloatBuffer ? 1 : 0);
#else