summaryrefslogtreecommitdiffhomepage
path: root/src/external
diff options
context:
space:
mode:
Diffstat (limited to 'src/external')
-rw-r--r--src/external/dr_wav.h712
1 files changed, 487 insertions, 225 deletions
diff --git a/src/external/dr_wav.h b/src/external/dr_wav.h
index ef1f803e..a119d66a 100644
--- a/src/external/dr_wav.h
+++ b/src/external/dr_wav.h
@@ -1,6 +1,6 @@
/*
WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
-dr_wav - v0.13.3 - TBD
+dr_wav - v0.13.4 - 2021-12-08
David Reid - [email protected]
@@ -125,7 +125,7 @@ extern "C" {
#define DRWAV_VERSION_MAJOR 0
#define DRWAV_VERSION_MINOR 13
-#define DRWAV_VERSION_REVISION 2
+#define DRWAV_VERSION_REVISION 4
#define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
#include <stddef.h> /* For size_t. */
@@ -1335,6 +1335,7 @@ DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b);
#define drwav_min(a, b) (((a) < (b)) ? (a) : (b))
#define drwav_max(a, b) (((a) > (b)) ? (a) : (b))
#define drwav_clamp(x, lo, hi) (drwav_max((lo), drwav_min((hi), (x))))
+#define drwav_offset_ptr(p, offset) (((drwav_uint8*)(p)) + (offset))
#define DRWAV_MAX_SIMD_VECTOR_SIZE 64 /* 64 for AVX-512 in the future. */
@@ -2166,13 +2167,14 @@ DRWAV_PRIVATE size_t drwav__metadata_parser_read(drwav__metadata_parser* pParser
}
}
-DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata)
+DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_parser* pParser, const drwav_chunk_header* pChunkHeader, drwav_metadata* pMetadata)
{
drwav_uint8 smplHeaderData[DRWAV_SMPL_BYTES];
drwav_uint64 totalBytesRead = 0;
size_t bytesJustRead = drwav__metadata_parser_read(pParser, smplHeaderData, sizeof(smplHeaderData), &totalBytesRead);
DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
+ DRWAV_ASSERT(pChunkHeader != NULL);
if (bytesJustRead == sizeof(smplHeaderData)) {
drwav_uint32 iSampleLoop;
@@ -2187,36 +2189,43 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
pMetadata->data.smpl.smpteOffset = drwav_bytes_to_u32(smplHeaderData + 24);
pMetadata->data.smpl.sampleLoopCount = drwav_bytes_to_u32(smplHeaderData + 28);
pMetadata->data.smpl.samplerSpecificDataSizeInBytes = drwav_bytes_to_u32(smplHeaderData + 32);
- pMetadata->data.smpl.pLoops = (drwav_smpl_loop*)drwav__metadata_get_memory(pParser, sizeof(drwav_smpl_loop) * pMetadata->data.smpl.sampleLoopCount, DRWAV_METADATA_ALIGNMENT);
-
- for (iSampleLoop = 0; iSampleLoop < pMetadata->data.smpl.sampleLoopCount; ++iSampleLoop) {
- drwav_uint8 smplLoopData[DRWAV_SMPL_LOOP_BYTES];
- bytesJustRead = drwav__metadata_parser_read(pParser, smplLoopData, sizeof(smplLoopData), &totalBytesRead);
-
- if (bytesJustRead == sizeof(smplLoopData)) {
- pMetadata->data.smpl.pLoops[iSampleLoop].cuePointId = drwav_bytes_to_u32(smplLoopData + 0);
- pMetadata->data.smpl.pLoops[iSampleLoop].type = drwav_bytes_to_u32(smplLoopData + 4);
- pMetadata->data.smpl.pLoops[iSampleLoop].firstSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 8);
- pMetadata->data.smpl.pLoops[iSampleLoop].lastSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 12);
- pMetadata->data.smpl.pLoops[iSampleLoop].sampleFraction = drwav_bytes_to_u32(smplLoopData + 16);
- pMetadata->data.smpl.pLoops[iSampleLoop].playCount = drwav_bytes_to_u32(smplLoopData + 20);
- } else {
- break;
+
+ /*
+ The loop count needs to be validated against the size of the chunk for safety so we don't
+ attempt to read over the boundary of the chunk.
+ */
+ if (pMetadata->data.smpl.sampleLoopCount == (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES) {
+ pMetadata->data.smpl.pLoops = (drwav_smpl_loop*)drwav__metadata_get_memory(pParser, sizeof(drwav_smpl_loop) * pMetadata->data.smpl.sampleLoopCount, DRWAV_METADATA_ALIGNMENT);
+
+ for (iSampleLoop = 0; iSampleLoop < pMetadata->data.smpl.sampleLoopCount; ++iSampleLoop) {
+ drwav_uint8 smplLoopData[DRWAV_SMPL_LOOP_BYTES];
+ bytesJustRead = drwav__metadata_parser_read(pParser, smplLoopData, sizeof(smplLoopData), &totalBytesRead);
+
+ if (bytesJustRead == sizeof(smplLoopData)) {
+ pMetadata->data.smpl.pLoops[iSampleLoop].cuePointId = drwav_bytes_to_u32(smplLoopData + 0);
+ pMetadata->data.smpl.pLoops[iSampleLoop].type = drwav_bytes_to_u32(smplLoopData + 4);
+ pMetadata->data.smpl.pLoops[iSampleLoop].firstSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 8);
+ pMetadata->data.smpl.pLoops[iSampleLoop].lastSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 12);
+ pMetadata->data.smpl.pLoops[iSampleLoop].sampleFraction = drwav_bytes_to_u32(smplLoopData + 16);
+ pMetadata->data.smpl.pLoops[iSampleLoop].playCount = drwav_bytes_to_u32(smplLoopData + 20);
+ } else {
+ break;
+ }
}
- }
- if (pMetadata->data.smpl.samplerSpecificDataSizeInBytes > 0) {
- pMetadata->data.smpl.pSamplerSpecificData = drwav__metadata_get_memory(pParser, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, 1);
- DRWAV_ASSERT(pMetadata->data.smpl.pSamplerSpecificData != NULL);
+ if (pMetadata->data.smpl.samplerSpecificDataSizeInBytes > 0) {
+ pMetadata->data.smpl.pSamplerSpecificData = drwav__metadata_get_memory(pParser, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, 1);
+ DRWAV_ASSERT(pMetadata->data.smpl.pSamplerSpecificData != NULL);
- drwav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead);
+ drwav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead);
+ }
}
}
return totalBytesRead;
}
-DRWAV_PRIVATE drwav_uint64 drwav__read_cue_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata)
+DRWAV_PRIVATE drwav_uint64 drwav__read_cue_to_metadata_obj(drwav__metadata_parser* pParser, const drwav_chunk_header* pChunkHeader, drwav_metadata* pMetadata)
{
drwav_uint8 cueHeaderSectionData[DRWAV_CUE_BYTES];
drwav_uint64 totalBytesRead = 0;
@@ -2227,28 +2236,35 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_cue_to_metadata_obj(drwav__metadata_parse
if (bytesJustRead == sizeof(cueHeaderSectionData)) {
pMetadata->type = drwav_metadata_type_cue;
pMetadata->data.cue.cuePointCount = drwav_bytes_to_u32(cueHeaderSectionData);
- pMetadata->data.cue.pCuePoints = (drwav_cue_point*)drwav__metadata_get_memory(pParser, sizeof(drwav_cue_point) * pMetadata->data.cue.cuePointCount, DRWAV_METADATA_ALIGNMENT);
- DRWAV_ASSERT(pMetadata->data.cue.pCuePoints != NULL);
-
- if (pMetadata->data.cue.cuePointCount > 0) {
- drwav_uint32 iCuePoint;
-
- for (iCuePoint = 0; iCuePoint < pMetadata->data.cue.cuePointCount; ++iCuePoint) {
- drwav_uint8 cuePointData[DRWAV_CUE_POINT_BYTES];
- bytesJustRead = drwav__metadata_parser_read(pParser, cuePointData, sizeof(cuePointData), &totalBytesRead);
-
- if (bytesJustRead == sizeof(cuePointData)) {
- pMetadata->data.cue.pCuePoints[iCuePoint].id = drwav_bytes_to_u32(cuePointData + 0);
- pMetadata->data.cue.pCuePoints[iCuePoint].playOrderPosition = drwav_bytes_to_u32(cuePointData + 4);
- pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[0] = cuePointData[8];
- pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[1] = cuePointData[9];
- pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[2] = cuePointData[10];
- pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[3] = cuePointData[11];
- pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart = drwav_bytes_to_u32(cuePointData + 12);
- pMetadata->data.cue.pCuePoints[iCuePoint].blockStart = drwav_bytes_to_u32(cuePointData + 16);
- pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset = drwav_bytes_to_u32(cuePointData + 20);
- } else {
- break;
+
+ /*
+ We need to validate the cue point count against the size of the chunk so we don't read
+ beyond the chunk.
+ */
+ if (pMetadata->data.cue.cuePointCount == (pChunkHeader->sizeInBytes - DRWAV_CUE_BYTES) / DRWAV_CUE_POINT_BYTES) {
+ pMetadata->data.cue.pCuePoints = (drwav_cue_point*)drwav__metadata_get_memory(pParser, sizeof(drwav_cue_point) * pMetadata->data.cue.cuePointCount, DRWAV_METADATA_ALIGNMENT);
+ DRWAV_ASSERT(pMetadata->data.cue.pCuePoints != NULL);
+
+ if (pMetadata->data.cue.cuePointCount > 0) {
+ drwav_uint32 iCuePoint;
+
+ for (iCuePoint = 0; iCuePoint < pMetadata->data.cue.cuePointCount; ++iCuePoint) {
+ drwav_uint8 cuePointData[DRWAV_CUE_POINT_BYTES];
+ bytesJustRead = drwav__metadata_parser_read(pParser, cuePointData, sizeof(cuePointData), &totalBytesRead);
+
+ if (bytesJustRead == sizeof(cuePointData)) {
+ pMetadata->data.cue.pCuePoints[iCuePoint].id = drwav_bytes_to_u32(cuePointData + 0);
+ pMetadata->data.cue.pCuePoints[iCuePoint].playOrderPosition = drwav_bytes_to_u32(cuePointData + 4);
+ pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[0] = cuePointData[8];
+ pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[1] = cuePointData[9];
+ pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[2] = cuePointData[10];
+ pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[3] = cuePointData[11];
+ pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart = drwav_bytes_to_u32(cuePointData + 12);
+ pMetadata->data.cue.pCuePoints[iCuePoint].blockStart = drwav_bytes_to_u32(cuePointData + 16);
+ pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset = drwav_bytes_to_u32(cuePointData + 20);
+ } else {
+ break;
+ }
}
}
}
@@ -2300,7 +2316,7 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_acid_to_metadata_obj(drwav__metadata_pars
return bytesRead;
}
-DRWAV_PRIVATE size_t drwav__strlen_clamped(char* str, size_t maxToRead)
+DRWAV_PRIVATE size_t drwav__strlen_clamped(const char* str, size_t maxToRead)
{
size_t result = 0;
@@ -2311,7 +2327,7 @@ DRWAV_PRIVATE size_t drwav__strlen_clamped(char* str, size_t maxToRead)
return result;
}
-DRWAV_PRIVATE char* drwav__metadata_copy_string(drwav__metadata_parser* pParser, char* str, size_t maxToRead)
+DRWAV_PRIVATE char* drwav__metadata_copy_string(drwav__metadata_parser* pParser, const char* str, size_t maxToRead)
{
size_t len = drwav__strlen_clamped(str, maxToRead);
@@ -2328,77 +2344,183 @@ DRWAV_PRIVATE char* drwav__metadata_copy_string(drwav__metadata_parser* pParser,
}
}
+typedef struct
+{
+ const void* pBuffer;
+ size_t sizeInBytes;
+ size_t cursor;
+} drwav_buffer_reader;
+
+DRWAV_PRIVATE drwav_result drwav_buffer_reader_init(const void* pBuffer, size_t sizeInBytes, drwav_buffer_reader* pReader)
+{
+ DRWAV_ASSERT(pBuffer != NULL);
+ DRWAV_ASSERT(pReader != NULL);
+
+ DRWAV_ZERO_OBJECT(pReader);
+
+ pReader->pBuffer = pBuffer;
+ pReader->sizeInBytes = sizeInBytes;
+ pReader->cursor = 0;
+
+ return DRWAV_SUCCESS;
+}
+
+DRWAV_PRIVATE const void* drwav_buffer_reader_ptr(const drwav_buffer_reader* pReader)
+{
+ DRWAV_ASSERT(pReader != NULL);
+
+ return drwav_offset_ptr(pReader->pBuffer, pReader->cursor);
+}
+
+DRWAV_PRIVATE drwav_result drwav_buffer_reader_seek(drwav_buffer_reader* pReader, size_t bytesToSeek)
+{
+ DRWAV_ASSERT(pReader != NULL);
+
+ if (pReader->cursor + bytesToSeek > pReader->sizeInBytes) {
+ return DRWAV_BAD_SEEK; /* Seeking too far forward. */
+ }
+
+ pReader->cursor += bytesToSeek;
+
+ return DRWAV_SUCCESS;
+}
+
+DRWAV_PRIVATE drwav_result drwav_buffer_reader_read(drwav_buffer_reader* pReader, void* pDst, size_t bytesToRead, size_t* pBytesRead)
+{
+ drwav_result result = DRWAV_SUCCESS;
+ size_t bytesRemaining;
+
+ DRWAV_ASSERT(pReader != NULL);
+
+ if (pBytesRead != NULL) {
+ *pBytesRead = 0;
+ }
+
+ bytesRemaining = (pReader->sizeInBytes - pReader->cursor);
+ if (bytesToRead > bytesRemaining) {
+ bytesToRead = bytesRemaining;
+ }
+
+ if (pDst == NULL) {
+ /* Seek. */
+ result = drwav_buffer_reader_seek(pReader, bytesToRead);
+ } else {
+ /* Read. */
+ DRWAV_COPY_MEMORY(pDst, drwav_buffer_reader_ptr(pReader), bytesToRead);
+ pReader->cursor += bytesToRead;
+ }
+
+ DRWAV_ASSERT(pReader->cursor <= pReader->sizeInBytes);
+
+ if (result == DRWAV_SUCCESS) {
+ if (pBytesRead != NULL) {
+ *pBytesRead = bytesToRead;
+ }
+ }
+
+ return DRWAV_SUCCESS;
+}
+
+DRWAV_PRIVATE drwav_result drwav_buffer_reader_read_u16(drwav_buffer_reader* pReader, drwav_uint16* pDst)
+{
+ drwav_result result;
+ size_t bytesRead;
+ drwav_uint8 data[2];
+
+ DRWAV_ASSERT(pReader != NULL);
+ DRWAV_ASSERT(pDst != NULL);
+
+ *pDst = 0; /* Safety. */
+
+ result = drwav_buffer_reader_read(pReader, data, sizeof(*pDst), &bytesRead);
+ if (result != DRWAV_SUCCESS || bytesRead != sizeof(*pDst)) {
+ return result;
+ }
+
+ *pDst = drwav_bytes_to_u16(data);
+
+ return DRWAV_SUCCESS;
+}
+
+DRWAV_PRIVATE drwav_result drwav_buffer_reader_read_u32(drwav_buffer_reader* pReader, drwav_uint32* pDst)
+{
+ drwav_result result;
+ size_t bytesRead;
+ drwav_uint8 data[4];
+
+ DRWAV_ASSERT(pReader != NULL);
+ DRWAV_ASSERT(pDst != NULL);
+
+ *pDst = 0; /* Safety. */
+
+ result = drwav_buffer_reader_read(pReader, data, sizeof(*pDst), &bytesRead);
+ if (result != DRWAV_SUCCESS || bytesRead != sizeof(*pDst)) {
+ return result;
+ }
+
+ *pDst = drwav_bytes_to_u32(data);
+
+ return DRWAV_SUCCESS;
+}
+
+
+
DRWAV_PRIVATE drwav_uint64 drwav__read_bext_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata, drwav_uint64 chunkSize)
{
drwav_uint8 bextData[DRWAV_BEXT_BYTES];
- drwav_uint64 bytesRead = drwav__metadata_parser_read(pParser, bextData, sizeof(bextData), NULL);
+ size_t bytesRead = drwav__metadata_parser_read(pParser, bextData, sizeof(bextData), NULL);
DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
if (bytesRead == sizeof(bextData)) {
- drwav_uint8* pReadPointer;
+ drwav_buffer_reader reader;
drwav_uint32 timeReferenceLow;
drwav_uint32 timeReferenceHigh;
size_t extraBytes;
pMetadata->type = drwav_metadata_type_bext;
- pReadPointer = bextData;
- pMetadata->data.bext.pDescription = drwav__metadata_copy_string(pParser, (char*)(pReadPointer), DRWAV_BEXT_DESCRIPTION_BYTES);
- pReadPointer += DRWAV_BEXT_DESCRIPTION_BYTES;
-
- pMetadata->data.bext.pOriginatorName = drwav__metadata_copy_string(pParser, (char*)(pReadPointer), DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
- pReadPointer += DRWAV_BEXT_ORIGINATOR_NAME_BYTES;
-
- pMetadata->data.bext.pOriginatorReference = drwav__metadata_copy_string(pParser, (char*)(pReadPointer), DRWAV_BEXT_ORIGINATOR_REF_BYTES);
- pReadPointer += DRWAV_BEXT_ORIGINATOR_REF_BYTES;
+ if (drwav_buffer_reader_init(bextData, bytesRead, &reader) == DRWAV_SUCCESS) {
+ pMetadata->data.bext.pDescription = drwav__metadata_copy_string(pParser, (const char*)drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_DESCRIPTION_BYTES);
+ drwav_buffer_reader_seek(&reader, DRWAV_BEXT_DESCRIPTION_BYTES);
- memcpy(pMetadata->data.bext.pOriginationDate, pReadPointer, sizeof(pMetadata->data.bext.pOriginationDate));
- pReadPointer += sizeof(pMetadata->data.bext.pOriginationDate);
+ pMetadata->data.bext.pOriginatorName = drwav__metadata_copy_string(pParser, (const char*)drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
+ drwav_buffer_reader_seek(&reader, DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
- memcpy(pMetadata->data.bext.pOriginationTime, pReadPointer, sizeof(pMetadata->data.bext.pOriginationTime));
- pReadPointer += sizeof(pMetadata->data.bext.pOriginationTime);
+ pMetadata->data.bext.pOriginatorReference = drwav__metadata_copy_string(pParser, (const char*)drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_ORIGINATOR_REF_BYTES);
+ drwav_buffer_reader_seek(&reader, DRWAV_BEXT_ORIGINATOR_REF_BYTES);
- timeReferenceLow = drwav_bytes_to_u32(pReadPointer);
- pReadPointer += sizeof(drwav_uint32);
- timeReferenceHigh = drwav_bytes_to_u32(pReadPointer);
- pReadPointer += sizeof(drwav_uint32);
- pMetadata->data.bext.timeReference = ((drwav_uint64)timeReferenceHigh << 32) + timeReferenceLow;
+ drwav_buffer_reader_read(&reader, pMetadata->data.bext.pOriginationDate, sizeof(pMetadata->data.bext.pOriginationDate), NULL);
+ drwav_buffer_reader_read(&reader, pMetadata->data.bext.pOriginationTime, sizeof(pMetadata->data.bext.pOriginationTime), NULL);
- pMetadata->data.bext.version = drwav_bytes_to_u16(pReadPointer);
- pReadPointer += sizeof(drwav_uint16);
+ drwav_buffer_reader_read_u32(&reader, &timeReferenceLow);
+ drwav_buffer_reader_read_u32(&reader, &timeReferenceHigh);
+ pMetadata->data.bext.timeReference = ((drwav_uint64)timeReferenceHigh << 32) + timeReferenceLow;
- pMetadata->data.bext.pUMID = drwav__metadata_get_memory(pParser, DRWAV_BEXT_UMID_BYTES, 1);
- memcpy(pMetadata->data.bext.pUMID, pReadPointer, DRWAV_BEXT_UMID_BYTES);
- pReadPointer += DRWAV_BEXT_UMID_BYTES;
+ drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.version);
- pMetadata->data.bext.loudnessValue = drwav_bytes_to_u16(pReadPointer);
- pReadPointer += sizeof(drwav_uint16);
+ pMetadata->data.bext.pUMID = drwav__metadata_get_memory(pParser, DRWAV_BEXT_UMID_BYTES, 1);
+ drwav_buffer_reader_read(&reader, pMetadata->data.bext.pUMID, DRWAV_BEXT_UMID_BYTES, NULL);
- pMetadata->data.bext.loudnessRange = drwav_bytes_to_u16(pReadPointer);
- pReadPointer += sizeof(drwav_uint16);
+ drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.loudnessValue);
+ drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.loudnessRange);
+ drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.maxTruePeakLevel);
+ drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.maxMomentaryLoudness);
+ drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.maxShortTermLoudness);
- pMetadata->data.bext.maxTruePeakLevel = drwav_bytes_to_u16(pReadPointer);
- pReadPointer += sizeof(drwav_uint16);
+ DRWAV_ASSERT((drwav_offset_ptr(drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_RESERVED_BYTES)) == (bextData + DRWAV_BEXT_BYTES));
- pMetadata->data.bext.maxMomentaryLoudness = drwav_bytes_to_u16(pReadPointer);
- pReadPointer += sizeof(drwav_uint16);
+ extraBytes = (size_t)(chunkSize - DRWAV_BEXT_BYTES);
+ if (extraBytes > 0) {
+ pMetadata->data.bext.pCodingHistory = (char*)drwav__metadata_get_memory(pParser, extraBytes + 1, 1);
+ DRWAV_ASSERT(pMetadata->data.bext.pCodingHistory != NULL);
- pMetadata->data.bext.maxShortTermLoudness = drwav_bytes_to_u16(pReadPointer);
- pReadPointer += sizeof(drwav_uint16);
-
- DRWAV_ASSERT((pReadPointer + DRWAV_BEXT_RESERVED_BYTES) == (bextData + DRWAV_BEXT_BYTES));
-
- extraBytes = (size_t)(chunkSize - DRWAV_BEXT_BYTES);
- if (extraBytes > 0) {
- pMetadata->data.bext.pCodingHistory = (char*)drwav__metadata_get_memory(pParser, extraBytes + 1, 1);
- DRWAV_ASSERT(pMetadata->data.bext.pCodingHistory != NULL);
-
- bytesRead += drwav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL);
- pMetadata->data.bext.codingHistorySize = (drwav_uint32)strlen(pMetadata->data.bext.pCodingHistory);
- } else {
- pMetadata->data.bext.pCodingHistory = NULL;
- pMetadata->data.bext.codingHistorySize = 0;
+ bytesRead += drwav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL);
+ pMetadata->data.bext.codingHistorySize = (drwav_uint32)strlen(pMetadata->data.bext.pCodingHistory);
+ } else {
+ pMetadata->data.bext.pCodingHistory = NULL;
+ pMetadata->data.bext.codingHistorySize = 0;
+ }
}
}
@@ -2568,18 +2690,25 @@ DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser*
bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
if (bytesJustRead == sizeof(buffer)) {
drwav_uint32 loopCount = drwav_bytes_to_u32(buffer);
-
- bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
- if (bytesJustRead == sizeof(buffer)) {
- drwav_uint32 samplerSpecificDataSizeInBytes = drwav_bytes_to_u32(buffer);
-
- pParser->metadataCount += 1;
- drwav__metadata_request_extra_memory_for_stage_2(pParser, sizeof(drwav_smpl_loop) * loopCount, DRWAV_METADATA_ALIGNMENT);
- drwav__metadata_request_extra_memory_for_stage_2(pParser, samplerSpecificDataSizeInBytes, 1);
- }
+ drwav_uint64 calculatedLoopCount;
+
+ /* The loop count must be validated against the size of the chunk. */
+ calculatedLoopCount = (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES;
+ if (calculatedLoopCount == loopCount) {
+ bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
+ if (bytesJustRead == sizeof(buffer)) {
+ drwav_uint32 samplerSpecificDataSizeInBytes = drwav_bytes_to_u32(buffer);
+
+ pParser->metadataCount += 1;
+ drwav__metadata_request_extra_memory_for_stage_2(pParser, sizeof(drwav_smpl_loop) * loopCount, DRWAV_METADATA_ALIGNMENT);
+ drwav__metadata_request_extra_memory_for_stage_2(pParser, samplerSpecificDataSizeInBytes, 1);
+ }
+ } else {
+ /* Loop count in header does not match the size of the chunk. */
+ }
}
} else {
- bytesRead = drwav__read_smpl_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor]);
+ bytesRead = drwav__read_smpl_to_metadata_obj(pParser, pChunkHeader, &pParser->pMetadata[pParser->metadataCursor]);
if (bytesRead == pChunkHeader->sizeInBytes) {
pParser->metadataCursor += 1;
} else {
@@ -2628,7 +2757,7 @@ DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser*
cueCount = (size_t)(pChunkHeader->sizeInBytes - DRWAV_CUE_BYTES) / DRWAV_CUE_POINT_BYTES;
drwav__metadata_request_extra_memory_for_stage_2(pParser, sizeof(drwav_cue_point) * cueCount, DRWAV_METADATA_ALIGNMENT);
} else {
- bytesRead = drwav__read_cue_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor]);
+ bytesRead = drwav__read_cue_to_metadata_obj(pParser, pChunkHeader, &pParser->pMetadata[pParser->metadataCursor]);
if (bytesRead == pChunkHeader->sizeInBytes) {
pParser->metadataCursor += 1;
} else {
@@ -3222,7 +3351,12 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
if (sampleCountFromFactChunk != 0) {
pWav->totalPCMFrameCount = sampleCountFromFactChunk;
} else {
- pWav->totalPCMFrameCount = dataChunkSize / drwav_get_bytes_per_pcm_frame(pWav);
+ drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return DRWAV_FALSE; /* Invalid file. */
+ }
+
+ pWav->totalPCMFrameCount = dataChunkSize / bytesPerFrame;
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
drwav_uint64 totalBlockHeaderSizeInBytes;
@@ -5135,6 +5269,7 @@ DRWAV_API drwav_result drwav_uninit(drwav* pWav)
DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOut)
{
size_t bytesRead;
+ drwav_uint32 bytesPerFrame;
if (pWav == NULL || bytesToRead == 0) {
return 0; /* Invalid args. */
@@ -5148,6 +5283,11 @@ DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOu
return 0; /* At end. */
}
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0; /* Could not determine the bytes per frame. */
+ }
+
if (pBufferOut != NULL) {
bytesRead = pWav->onRead(pWav->pUserData, pBufferOut, bytesToRead);
} else {
@@ -5184,7 +5324,7 @@ DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOu
}
}
- pWav->readCursorInPCMFrames += bytesRead / drwav_get_bytes_per_pcm_frame(pWav);
+ pWav->readCursorInPCMFrames += bytesRead / bytesPerFrame;
pWav->bytesRemaining -= bytesRead;
return bytesRead;
@@ -5233,7 +5373,12 @@ DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(drwav* pWav, drwav_uint64 frames
drwav_uint64 framesRead = drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
if (pBufferOut != NULL) {
- drwav__bswap_samples(pBufferOut, framesRead*pWav->channels, drwav_get_bytes_per_pcm_frame(pWav)/pWav->channels, pWav->translatedFormatTag);
+ drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0; /* Could not get the bytes per frame which means bytes per sample cannot be determined and we don't know how to byte swap. */
+ }
+
+ drwav__bswap_samples(pBufferOut, framesRead*pWav->channels, bytesPerFrame/pWav->channels, pWav->translatedFormatTag);
}
return framesRead;
@@ -5348,12 +5493,18 @@ DRWAV_API drwav_bool32 drwav_seek_to_pcm_frame(drwav* pWav, drwav_uint64 targetF
drwav_uint64 currentBytePos;
drwav_uint64 targetBytePos;
drwav_uint64 offset;
+ drwav_uint32 bytesPerFrame;
- totalSizeInBytes = pWav->totalPCMFrameCount * drwav_get_bytes_per_pcm_frame(pWav);
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return DRWAV_FALSE; /* Not able to calculate offset. */
+ }
+
+ totalSizeInBytes = pWav->totalPCMFrameCount * bytesPerFrame;
DRWAV_ASSERT(totalSizeInBytes >= pWav->bytesRemaining);
currentBytePos = totalSizeInBytes - pWav->bytesRemaining;
- targetBytePos = targetFrameIndex * drwav_get_bytes_per_pcm_frame(pWav);
+ targetBytePos = targetFrameIndex * bytesPerFrame;
if (currentBytePos < targetBytePos) {
/* Offset forwards. */
@@ -5372,7 +5523,7 @@ DRWAV_API drwav_bool32 drwav_seek_to_pcm_frame(drwav* pWav, drwav_uint64 targetF
return DRWAV_FALSE;
}
- pWav->readCursorInPCMFrames += offset32 / drwav_get_bytes_per_pcm_frame(pWav);
+ pWav->readCursorInPCMFrames += offset32 / bytesPerFrame;
pWav->bytesRemaining -= offset32;
offset -= offset32;
}
@@ -5488,6 +5639,9 @@ DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 frame
pRunningData = (const drwav_uint8*)pData;
bytesPerSample = drwav_get_bytes_per_pcm_frame(pWav) / pWav->channels;
+ if (bytesPerSample == 0) {
+ return 0; /* Cannot determine bytes per sample, or bytes per sample is less than one byte. */
+ }
while (bytesToWrite > 0) {
drwav_uint8 temp[4096];
@@ -5763,7 +5917,7 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uin
}
pWav->ima.predictor[0] = drwav_bytes_to_s16(header + 0);
- pWav->ima.stepIndex[0] = header[2];
+ pWav->ima.stepIndex[0] = drwav_clamp(header[2], 0, (drwav_int32)drwav_countof(stepTable)-1); /* Clamp not necessary because we checked above, but adding here to silence a static analysis warning. */
pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 1] = pWav->ima.predictor[0];
pWav->ima.cachedFrameCount = 1;
} else {
@@ -5781,9 +5935,9 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uin
}
pWav->ima.predictor[0] = drwav_bytes_to_s16(header + 0);
- pWav->ima.stepIndex[0] = header[2];
+ pWav->ima.stepIndex[0] = drwav_clamp(header[2], 0, (drwav_int32)drwav_countof(stepTable)-1); /* Clamp not necessary because we checked above, but adding here to silence a static analysis warning. */
pWav->ima.predictor[1] = drwav_bytes_to_s16(header + 4);
- pWav->ima.stepIndex[1] = header[6];
+ pWav->ima.stepIndex[1] = drwav_clamp(header[6], 0, (drwav_int32)drwav_countof(stepTable)-1); /* Clamp not necessary because we checked above, but adding here to silence a static analysis warning. */
pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 2] = pWav->ima.predictor[0];
pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 1] = pWav->ima.predictor[1];
@@ -5928,7 +6082,7 @@ static DRWAV_INLINE drwav_int16 drwav__mulaw_to_s16(drwav_uint8 sampleIn)
DRWAV_PRIVATE void drwav__pcm_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
{
- unsigned int i;
+ size_t i;
/* Special case for 8-bit sample data because it's treated as unsigned. */
if (bytesPerSample == 1) {
@@ -5996,8 +6150,10 @@ DRWAV_PRIVATE void drwav__ieee_to_s16(drwav_int16* pOut, const drwav_uint8* pIn,
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__pcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
{
drwav_uint64 totalFramesRead;
- drwav_uint8 sampleData[4096];
+ drwav_uint8 sampleData[4096] = {0};
drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
/* Fast path. */
if ((pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM && pWav->bitsPerSample == 16) || pBufferOut == NULL) {
@@ -6009,6 +6165,11 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__pcm(drwav* pWav, drwav_uin
return 0;
}
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
totalFramesRead = 0;
while (framesToRead > 0) {
@@ -6020,9 +6181,16 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__pcm(drwav* pWav, drwav_uin
DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
- drwav__pcm_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
- pBufferOut += framesRead*pWav->channels;
+ drwav__pcm_to_s16(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample);
+
+ pBufferOut += samplesRead;
framesToRead -= framesRead;
totalFramesRead += framesRead;
}
@@ -6033,8 +6201,10 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__pcm(drwav* pWav, drwav_uin
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ieee(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
{
drwav_uint64 totalFramesRead;
- drwav_uint8 sampleData[4096];
+ drwav_uint8 sampleData[4096] = {0};
drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
if (pBufferOut == NULL) {
return drwav_read_pcm_frames(pWav, framesToRead, NULL);
@@ -6045,6 +6215,11 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ieee(drwav* pWav, drwav_ui
return 0;
}
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
totalFramesRead = 0;
while (framesToRead > 0) {
@@ -6056,9 +6231,16 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ieee(drwav* pWav, drwav_ui
DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
- drwav__ieee_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
+
+ drwav__ieee_to_s16(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample); /* Safe cast. */
- pBufferOut += framesRead*pWav->channels;
+ pBufferOut += samplesRead;
framesToRead -= framesRead;
totalFramesRead += framesRead;
}
@@ -6069,8 +6251,10 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ieee(drwav* pWav, drwav_ui
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__alaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
{
drwav_uint64 totalFramesRead;
- drwav_uint8 sampleData[4096];
+ drwav_uint8 sampleData[4096] = {0};
drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
if (pBufferOut == NULL) {
return drwav_read_pcm_frames(pWav, framesToRead, NULL);
@@ -6081,6 +6265,11 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__alaw(drwav* pWav, drwav_ui
return 0;
}
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
totalFramesRead = 0;
while (framesToRead > 0) {
@@ -6092,9 +6281,16 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__alaw(drwav* pWav, drwav_ui
DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
- drwav_alaw_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
- pBufferOut += framesRead*pWav->channels;
+ drwav_alaw_to_s16(pBufferOut, sampleData, (size_t)samplesRead);
+
+ pBufferOut += samplesRead;
framesToRead -= framesRead;
totalFramesRead += framesRead;
}
@@ -6105,8 +6301,10 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__alaw(drwav* pWav, drwav_ui
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__mulaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
{
drwav_uint64 totalFramesRead;
- drwav_uint8 sampleData[4096];
+ drwav_uint8 sampleData[4096] = {0};
drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
if (pBufferOut == NULL) {
return drwav_read_pcm_frames(pWav, framesToRead, NULL);
@@ -6117,6 +6315,11 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__mulaw(drwav* pWav, drwav_u
return 0;
}
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
totalFramesRead = 0;
while (framesToRead > 0) {
@@ -6128,9 +6331,16 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__mulaw(drwav* pWav, drwav_u
DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
- drwav_mulaw_to_s16(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
- pBufferOut += framesRead*pWav->channels;
+ drwav_mulaw_to_s16(pBufferOut, sampleData, (size_t)samplesRead);
+
+ pBufferOut += samplesRead;
framesToRead -= framesRead;
totalFramesRead += framesRead;
}
@@ -6354,14 +6564,21 @@ DRWAV_PRIVATE void drwav__ieee_to_f32(float* pOut, const drwav_uint8* pIn, size_
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__pcm(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
{
drwav_uint64 totalFramesRead;
- drwav_uint8 sampleData[4096];
+ drwav_uint8 sampleData[4096] = {0};
drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
if (bytesPerFrame == 0) {
return 0;
}
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
totalFramesRead = 0;
while (framesToRead > 0) {
@@ -6373,39 +6590,16 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__pcm(drwav* pWav, drwav_uin
DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
- drwav__pcm_to_f32(pBufferOut, sampleData, (size_t)framesRead*pWav->channels, bytesPerFrame/pWav->channels);
-
- pBufferOut += framesRead*pWav->channels;
- framesToRead -= framesRead;
- totalFramesRead += framesRead;
- }
-
- return totalFramesRead;
-}
-
-DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__msadpcm(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
-{
- /*
- We're just going to borrow the implementation from the drwav_read_s16() since ADPCM is a little bit more complicated than other formats and I don't
- want to duplicate that code.
- */
- drwav_uint64 totalFramesRead;
- drwav_int16 samples16[2048];
-
- totalFramesRead = 0;
-
- while (framesToRead > 0) {
- drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels);
- drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToReadThisIteration, samples16);
- if (framesRead == 0) {
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
break;
}
- DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
-
- drwav_s16_to_f32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels)); /* <-- Safe cast because we're clamping to 2048. */
+ drwav__pcm_to_f32(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample);
- pBufferOut += framesRead*pWav->channels;
+ pBufferOut += samplesRead;
framesToRead -= framesRead;
totalFramesRead += framesRead;
}
@@ -6413,10 +6607,10 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__msadpcm(drwav* pWav, drwav
return totalFramesRead;
}
-DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__ima(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__msadpcm_ima(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
{
/*
- We're just going to borrow the implementation from the drwav_read_s16() since IMA-ADPCM is a little bit more complicated than other formats and I don't
+ We're just going to borrow the implementation from the drwav_read_s16() since ADPCM is a little bit more complicated than other formats and I don't
want to duplicate that code.
*/
drwav_uint64 totalFramesRead;
@@ -6446,8 +6640,10 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__ima(drwav* pWav, drwav_uin
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__ieee(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
{
drwav_uint64 totalFramesRead;
- drwav_uint8 sampleData[4096];
+ drwav_uint8 sampleData[4096] = {0};
drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
/* Fast path. */
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT && pWav->bitsPerSample == 32) {
@@ -6459,6 +6655,11 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__ieee(drwav* pWav, drwav_ui
return 0;
}
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
totalFramesRead = 0;
while (framesToRead > 0) {
@@ -6470,9 +6671,16 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__ieee(drwav* pWav, drwav_ui
DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
- drwav__ieee_to_f32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
- pBufferOut += framesRead*pWav->channels;
+ drwav__ieee_to_f32(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample);
+
+ pBufferOut += samplesRead;
framesToRead -= framesRead;
totalFramesRead += framesRead;
}
@@ -6483,14 +6691,21 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__ieee(drwav* pWav, drwav_ui
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__alaw(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
{
drwav_uint64 totalFramesRead;
- drwav_uint8 sampleData[4096];
+ drwav_uint8 sampleData[4096] = {0};
drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
if (bytesPerFrame == 0) {
return 0;
}
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
totalFramesRead = 0;
while (framesToRead > 0) {
@@ -6502,9 +6717,16 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__alaw(drwav* pWav, drwav_ui
DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
- drwav_alaw_to_f32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
+
+ drwav_alaw_to_f32(pBufferOut, sampleData, (size_t)samplesRead);
- pBufferOut += framesRead*pWav->channels;
+ pBufferOut += samplesRead;
framesToRead -= framesRead;
totalFramesRead += framesRead;
}
@@ -6515,14 +6737,21 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__alaw(drwav* pWav, drwav_ui
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__mulaw(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
{
drwav_uint64 totalFramesRead;
- drwav_uint8 sampleData[4096];
+ drwav_uint8 sampleData[4096] = {0};
drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
if (bytesPerFrame == 0) {
return 0;
}
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
totalFramesRead = 0;
while (framesToRead > 0) {
@@ -6534,9 +6763,16 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__mulaw(drwav* pWav, drwav_u
DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
- drwav_mulaw_to_f32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
+
+ drwav_mulaw_to_f32(pBufferOut, sampleData, (size_t)samplesRead);
- pBufferOut += framesRead*pWav->channels;
+ pBufferOut += samplesRead;
framesToRead -= framesRead;
totalFramesRead += framesRead;
}
@@ -6563,8 +6799,8 @@ DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav* pWav, drwav_uint64 frame
return drwav_read_pcm_frames_f32__pcm(pWav, framesToRead, pBufferOut);
}
- if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
- return drwav_read_pcm_frames_f32__msadpcm(pWav, framesToRead, pBufferOut);
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM || pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
+ return drwav_read_pcm_frames_f32__msadpcm_ima(pWav, framesToRead, pBufferOut);
}
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
@@ -6579,10 +6815,6 @@ DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav* pWav, drwav_uint64 frame
return drwav_read_pcm_frames_f32__mulaw(pWav, framesToRead, pBufferOut);
}
- if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
- return drwav_read_pcm_frames_f32__ima(pWav, framesToRead, pBufferOut);
- }
-
return 0;
}
@@ -6791,8 +7023,10 @@ DRWAV_PRIVATE void drwav__ieee_to_s32(drwav_int32* pOut, const drwav_uint8* pIn,
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__pcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
{
drwav_uint64 totalFramesRead;
- drwav_uint8 sampleData[4096];
+ drwav_uint8 sampleData[4096] = {0};
drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
/* Fast path. */
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM && pWav->bitsPerSample == 32) {
@@ -6804,6 +7038,11 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__pcm(drwav* pWav, drwav_uin
return 0;
}
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
totalFramesRead = 0;
while (framesToRead > 0) {
@@ -6815,37 +7054,16 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__pcm(drwav* pWav, drwav_uin
DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
- drwav__pcm_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
-
- pBufferOut += framesRead*pWav->channels;
- framesToRead -= framesRead;
- totalFramesRead += framesRead;
- }
-
- return totalFramesRead;
-}
-
-DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__msadpcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
-{
- /*
- We're just going to borrow the implementation from the drwav_read_s16() since ADPCM is a little bit more complicated than other formats and I don't
- want to duplicate that code.
- */
- drwav_uint64 totalFramesRead = 0;
- drwav_int16 samples16[2048];
-
- while (framesToRead > 0) {
- drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels);
- drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToReadThisIteration, samples16);
- if (framesRead == 0) {
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
break;
}
- DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
-
- drwav_s16_to_s32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels)); /* <-- Safe cast because we're clamping to 2048. */
+ drwav__pcm_to_s32(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample);
- pBufferOut += framesRead*pWav->channels;
+ pBufferOut += samplesRead;
framesToRead -= framesRead;
totalFramesRead += framesRead;
}
@@ -6853,10 +7071,10 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__msadpcm(drwav* pWav, drwav
return totalFramesRead;
}
-DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__ima(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__msadpcm_ima(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
{
/*
- We're just going to borrow the implementation from the drwav_read_s16() since IMA-ADPCM is a little bit more complicated than other formats and I don't
+ We're just going to borrow the implementation from the drwav_read_s16() since ADPCM is a little bit more complicated than other formats and I don't
want to duplicate that code.
*/
drwav_uint64 totalFramesRead = 0;
@@ -6884,13 +7102,21 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__ima(drwav* pWav, drwav_uin
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__ieee(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
{
drwav_uint64 totalFramesRead;
- drwav_uint8 sampleData[4096];
- drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ drwav_uint8 sampleData[4096] = {0};
+ drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
if (bytesPerFrame == 0) {
return 0;
}
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
totalFramesRead = 0;
while (framesToRead > 0) {
@@ -6902,9 +7128,16 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__ieee(drwav* pWav, drwav_ui
DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
- drwav__ieee_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels), bytesPerFrame/pWav->channels);
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
- pBufferOut += framesRead*pWav->channels;
+ drwav__ieee_to_s32(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample);
+
+ pBufferOut += samplesRead;
framesToRead -= framesRead;
totalFramesRead += framesRead;
}
@@ -6915,13 +7148,21 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__ieee(drwav* pWav, drwav_ui
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__alaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
{
drwav_uint64 totalFramesRead;
- drwav_uint8 sampleData[4096];
- drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ drwav_uint8 sampleData[4096] = {0};
+ drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
if (bytesPerFrame == 0) {
return 0;
}
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
totalFramesRead = 0;
while (framesToRead > 0) {
@@ -6933,9 +7174,16 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__alaw(drwav* pWav, drwav_ui
DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
- drwav_alaw_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
- pBufferOut += framesRead*pWav->channels;
+ drwav_alaw_to_s32(pBufferOut, sampleData, (size_t)samplesRead);
+
+ pBufferOut += samplesRead;
framesToRead -= framesRead;
totalFramesRead += framesRead;
}
@@ -6946,13 +7194,21 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__alaw(drwav* pWav, drwav_ui
DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__mulaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
{
drwav_uint64 totalFramesRead;
- drwav_uint8 sampleData[4096];
- drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ drwav_uint8 sampleData[4096] = {0};
+ drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
if (bytesPerFrame == 0) {
return 0;
}
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
totalFramesRead = 0;
while (framesToRead > 0) {
@@ -6964,9 +7220,16 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__mulaw(drwav* pWav, drwav_u
DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
- drwav_mulaw_to_s32(pBufferOut, sampleData, (size_t)(framesRead*pWav->channels));
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
- pBufferOut += framesRead*pWav->channels;
+ drwav_mulaw_to_s32(pBufferOut, sampleData, (size_t)samplesRead);
+
+ pBufferOut += samplesRead;
framesToRead -= framesRead;
totalFramesRead += framesRead;
}
@@ -6993,8 +7256,8 @@ DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32(drwav* pWav, drwav_uint64 frame
return drwav_read_pcm_frames_s32__pcm(pWav, framesToRead, pBufferOut);
}
- if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
- return drwav_read_pcm_frames_s32__msadpcm(pWav, framesToRead, pBufferOut);
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM || pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
+ return drwav_read_pcm_frames_s32__msadpcm_ima(pWav, framesToRead, pBufferOut);
}
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
@@ -7009,10 +7272,6 @@ DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32(drwav* pWav, drwav_uint64 frame
return drwav_read_pcm_frames_s32__mulaw(pWav, framesToRead, pBufferOut);
}
- if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
- return drwav_read_pcm_frames_s32__ima(pWav, framesToRead, pBufferOut);
- }
-
return 0;
}
@@ -7600,7 +7859,10 @@ DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b)
/*
REVISION HISTORY
================
-v0.13.3 - TBD
+v0.13.4 - 2021-12-08
+ - Fix some static analysis warnings.
+
+v0.13.3 - 2021-11-24
- Fix an incorrect assertion when trying to endian swap 1-byte sample formats. This is now a no-op
rather than a failed assertion.
- Fix a bug with parsing of the bext chunk.