Update to latest DR libs to fix some warnings in MSVC (#5808)

This commit is contained in:
Jeffery Myers
2026-04-26 11:16:35 -07:00
committed by GitHub
parent dff07d020c
commit 8e82249f65
3 changed files with 151 additions and 41 deletions

View File

@ -1,6 +1,6 @@
/* /*
FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file. FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
dr_flac - v0.13.3 - 2026-01-17 dr_flac - v0.13.4 - TBD
David Reid - mackron@gmail.com David Reid - mackron@gmail.com
@ -126,7 +126,7 @@ extern "C" {
#define DRFLAC_VERSION_MAJOR 0 #define DRFLAC_VERSION_MAJOR 0
#define DRFLAC_VERSION_MINOR 13 #define DRFLAC_VERSION_MINOR 13
#define DRFLAC_VERSION_REVISION 3 #define DRFLAC_VERSION_REVISION 4
#define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION) #define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
#include <stddef.h> /* For size_t. */ #include <stddef.h> /* For size_t. */
@ -1547,6 +1547,8 @@ static DRFLAC_INLINE drflac_bool32 drflac_has_sse41(void)
#define DRFLAC_ZERO_OBJECT(p) DRFLAC_ZERO_MEMORY((p), sizeof(*(p))) #define DRFLAC_ZERO_OBJECT(p) DRFLAC_ZERO_MEMORY((p), sizeof(*(p)))
#endif #endif
#define DRFLAC_MIN(a, b) (((a) < (b)) ? (a) : (b))
#define DRFLAC_MAX_SIMD_VECTOR_SIZE 64 /* 64 for AVX-512 in the future. */ #define DRFLAC_MAX_SIMD_VECTOR_SIZE 64 /* 64 for AVX-512 in the future. */
/* Result Codes */ /* Result Codes */
@ -5980,8 +5982,6 @@ static drflac_bool32 drflac__seek_to_pcm_frame__binary_search_internal(drflac* p
break; /* Failed to seek to FLAC frame. */ break; /* Failed to seek to FLAC frame. */
} }
} else { } else {
const float approxCompressionRatio = (drflac_int64)(lastSuccessfulSeekOffset - pFlac->firstFLACFramePosInBytes) / ((drflac_int64)(pcmRangeLo * pFlac->channels * pFlac->bitsPerSample)/8.0f);
if (pcmRangeLo > pcmFrameIndex) { if (pcmRangeLo > pcmFrameIndex) {
/* We seeked too far forward. We need to move our target byte backward and try again. */ /* We seeked too far forward. We need to move our target byte backward and try again. */
byteRangeHi = lastSuccessfulSeekOffset; byteRangeHi = lastSuccessfulSeekOffset;
@ -6004,12 +6004,14 @@ static drflac_bool32 drflac__seek_to_pcm_frame__binary_search_internal(drflac* p
break; /* Failed to seek to FLAC frame. */ break; /* Failed to seek to FLAC frame. */
} }
} else { } else {
const double approxCompressionRatio = (drflac_int64)(lastSuccessfulSeekOffset - pFlac->firstFLACFramePosInBytes) / ((drflac_int64)(pcmRangeLo * pFlac->channels * pFlac->bitsPerSample)/8.0);
byteRangeLo = lastSuccessfulSeekOffset; byteRangeLo = lastSuccessfulSeekOffset;
if (byteRangeHi < byteRangeLo) { if (byteRangeHi < byteRangeLo) {
byteRangeHi = byteRangeLo; byteRangeHi = byteRangeLo;
} }
targetByte = lastSuccessfulSeekOffset + (drflac_uint64)(((drflac_int64)((pcmFrameIndex-pcmRangeLo) * pFlac->channels * pFlac->bitsPerSample)/8.0f) * approxCompressionRatio); targetByte = lastSuccessfulSeekOffset + (drflac_uint64)(((drflac_int64)((pcmFrameIndex-pcmRangeLo) * pFlac->channels * pFlac->bitsPerSample)/8.0) * approxCompressionRatio);
if (targetByte > byteRangeHi) { if (targetByte > byteRangeHi) {
targetByte = byteRangeHi; targetByte = byteRangeHi;
} }
@ -6402,7 +6404,7 @@ static void* drflac__realloc_from_callbacks(void* p, size_t szNew, size_t szOld,
} }
if (p != NULL) { if (p != NULL) {
DRFLAC_COPY_MEMORY(p2, p, szOld); DRFLAC_COPY_MEMORY(p2, p, DRFLAC_MIN(szNew, szOld));
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData); pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
} }
@ -6430,11 +6432,22 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
We want to keep track of the byte position in the stream of the seektable. At the time of calling this function we know that We want to keep track of the byte position in the stream of the seektable. At the time of calling this function we know that
we'll be sitting on byte 42. we'll be sitting on byte 42.
*/ */
drflac_uint64 runningFilePos = 42; drflac_uint64 runningFilePos = 42;
drflac_uint64 seektablePos = 0; drflac_uint64 seektablePos = 0;
drflac_uint32 seektableSize = 0; drflac_uint32 seektableSize = 0;
drflac_int64 fileSize = 0;
drflac_bool32 hasKnownFileSize = DRFLAC_FALSE;
(void)onTell; /* We'll be doing some memory allocations here against untrusted data. We'll do a basic validation check that they don't exceed the size of the file. */
if (onTell != NULL && onSeek != NULL) {
if (onSeek(pUserData, 0, DRFLAC_SEEK_END)) {
if (onTell(pUserData, &fileSize)) {
hasKnownFileSize = DRFLAC_TRUE;
}
onSeek(pUserData, runningFilePos, DRFLAC_SEEK_SET);
}
}
for (;;) { for (;;) {
drflac_metadata metadata; drflac_metadata metadata;
@ -6444,6 +6457,11 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
if (drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize) == DRFLAC_FALSE) { if (drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize) == DRFLAC_FALSE) {
return DRFLAC_FALSE; return DRFLAC_FALSE;
} }
if (hasKnownFileSize && (blockSize > ((drflac_uint64)fileSize - runningFilePos))) {
return DRFLAC_FALSE; /* Block size exceeds the size of the file. */
}
runningFilePos += 4; runningFilePos += 4;
metadata.type = blockType; metadata.type = blockType;
@ -6559,7 +6577,7 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
drflac__free_from_callbacks(pRawData, pAllocationCallbacks); drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
return DRFLAC_FALSE; return DRFLAC_FALSE;
} }
metadata.data.vorbis_comment.vendor = pRunningData; pRunningData += metadata.data.vorbis_comment.vendorLength; metadata.data.vorbis_comment.vendor = pRunningData; pRunningData += metadata.data.vorbis_comment.vendorLength;
metadata.data.vorbis_comment.commentCount = drflac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4; metadata.data.vorbis_comment.commentCount = drflac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
/* Need space for 'commentCount' comments after the block, which at minimum is a drflac_uint32 per comment */ /* Need space for 'commentCount' comments after the block, which at minimum is a drflac_uint32 per comment */
@ -6747,13 +6765,18 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
blockSizeRemaining -= 4; blockSizeRemaining -= 4;
metadata.data.picture.mimeLength = drflac__be2host_32(metadata.data.picture.mimeLength); metadata.data.picture.mimeLength = drflac__be2host_32(metadata.data.picture.mimeLength);
if (blockSizeRemaining < metadata.data.picture.mimeLength) {
result = DRFLAC_FALSE;
goto done_flac;
}
pMime = (char*)drflac__malloc_from_callbacks(metadata.data.picture.mimeLength + 1, pAllocationCallbacks); /* +1 for null terminator. */ pMime = (char*)drflac__malloc_from_callbacks(metadata.data.picture.mimeLength + 1, pAllocationCallbacks); /* +1 for null terminator. */
if (pMime == NULL) { if (pMime == NULL) {
result = DRFLAC_FALSE; result = DRFLAC_FALSE;
goto done_flac; goto done_flac;
} }
if (blockSizeRemaining < metadata.data.picture.mimeLength || onRead(pUserData, pMime, metadata.data.picture.mimeLength) != metadata.data.picture.mimeLength) { if (onRead(pUserData, pMime, metadata.data.picture.mimeLength) != metadata.data.picture.mimeLength) {
result = DRFLAC_FALSE; result = DRFLAC_FALSE;
goto done_flac; goto done_flac;
} }
@ -6769,13 +6792,18 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
blockSizeRemaining -= 4; blockSizeRemaining -= 4;
metadata.data.picture.descriptionLength = drflac__be2host_32(metadata.data.picture.descriptionLength); metadata.data.picture.descriptionLength = drflac__be2host_32(metadata.data.picture.descriptionLength);
if (blockSizeRemaining < metadata.data.picture.descriptionLength) {
result = DRFLAC_FALSE;
goto done_flac;
}
pDescription = (char*)drflac__malloc_from_callbacks(metadata.data.picture.descriptionLength + 1, pAllocationCallbacks); /* +1 for null terminator. */ pDescription = (char*)drflac__malloc_from_callbacks(metadata.data.picture.descriptionLength + 1, pAllocationCallbacks); /* +1 for null terminator. */
if (pDescription == NULL) { if (pDescription == NULL) {
result = DRFLAC_FALSE; result = DRFLAC_FALSE;
goto done_flac; goto done_flac;
} }
if (blockSizeRemaining < metadata.data.picture.descriptionLength || onRead(pUserData, pDescription, metadata.data.picture.descriptionLength) != metadata.data.picture.descriptionLength) { if (onRead(pUserData, pDescription, metadata.data.picture.descriptionLength) != metadata.data.picture.descriptionLength) {
result = DRFLAC_FALSE; result = DRFLAC_FALSE;
goto done_flac; goto done_flac;
} }
@ -8094,11 +8122,17 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
return NULL; return NULL;
} }
if ((0xFFFFFFFF - (seekpointCount * sizeof(drflac_seekpoint))) < allocationSize) {
#ifndef DR_FLAC_NO_OGG
drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
#endif
return NULL;
}
allocationSize += seekpointCount * sizeof(drflac_seekpoint); allocationSize += seekpointCount * sizeof(drflac_seekpoint);
} }
pFlac = (drflac*)drflac__malloc_from_callbacks((size_t)allocationSize, &allocationCallbacks);
pFlac = (drflac*)drflac__malloc_from_callbacks(allocationSize, &allocationCallbacks);
if (pFlac == NULL) { if (pFlac == NULL) {
#ifndef DR_FLAC_NO_OGG #ifndef DR_FLAC_NO_OGG
drflac__free_from_callbacks(pOggbs, &allocationCallbacks); drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
@ -12169,6 +12203,10 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat
/* /*
REVISION HISTORY REVISION HISTORY
================ ================
v0.13.4 - TBD
- Add a bounds check when allocating memory during metadata processing.
- Fix a possible overflow error when parsing picture metadata.
v0.13.3 - 2026-01-17 v0.13.3 - 2026-01-17
- Fix a compiler compatibility issue with some inlined assembly. - Fix a compiler compatibility issue with some inlined assembly.
- Fix a compilation warning. - Fix a compilation warning.

61
src/external/dr_mp3.h vendored
View File

@ -3188,6 +3188,10 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
pTagDataBeg = pFirstFrameData + DRMP3_HDR_SIZE + (bs.pos/8); pTagDataBeg = pFirstFrameData + DRMP3_HDR_SIZE + (bs.pos/8);
pTagData = pTagDataBeg; pTagData = pTagDataBeg;
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 8) {
goto done_xing_info; /* Frame too small for a Xing/Info tag. */
}
/* Check for both "Xing" and "Info" identifiers. */ /* Check for both "Xing" and "Info" identifiers. */
isXing = (pTagData[0] == 'X' && pTagData[1] == 'i' && pTagData[2] == 'n' && pTagData[3] == 'g'); isXing = (pTagData[0] == 'X' && pTagData[1] == 'i' && pTagData[2] == 'n' && pTagData[3] == 'g');
isInfo = (pTagData[0] == 'I' && pTagData[1] == 'n' && pTagData[2] == 'f' && pTagData[3] == 'o'); isInfo = (pTagData[0] == 'I' && pTagData[1] == 'n' && pTagData[2] == 'f' && pTagData[3] == 'o');
@ -3199,42 +3203,60 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
pTagData += 8; /* Skip past the ID and flags. */ pTagData += 8; /* Skip past the ID and flags. */
if (flags & 0x01) { /* FRAMES flag. */ if (flags & 0x01) { /* FRAMES flag. */
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) {
goto done_xing_info; /* Invalid Xing/Info tag. */
}
detectedMP3FrameCount = (drmp3_uint32)pTagData[0] << 24 | (drmp3_uint32)pTagData[1] << 16 | (drmp3_uint32)pTagData[2] << 8 | (drmp3_uint32)pTagData[3]; detectedMP3FrameCount = (drmp3_uint32)pTagData[0] << 24 | (drmp3_uint32)pTagData[1] << 16 | (drmp3_uint32)pTagData[2] << 8 | (drmp3_uint32)pTagData[3];
pTagData += 4; pTagData += 4;
} }
if (flags & 0x02) { /* BYTES flag. */ if (flags & 0x02) { /* BYTES flag. */
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) {
goto done_xing_info; /* Invalid Xing/Info tag. */
}
bytes = (drmp3_uint32)pTagData[0] << 24 | (drmp3_uint32)pTagData[1] << 16 | (drmp3_uint32)pTagData[2] << 8 | (drmp3_uint32)pTagData[3]; bytes = (drmp3_uint32)pTagData[0] << 24 | (drmp3_uint32)pTagData[1] << 16 | (drmp3_uint32)pTagData[2] << 8 | (drmp3_uint32)pTagData[3];
(void)bytes; /* <-- Just to silence a warning about `bytes` being assigned but unused. Want to leave this here in case I want to make use of it later. */ (void)bytes; /* <-- Just to silence a warning about `bytes` being assigned but unused. Want to leave this here in case I want to make use of it later. */
pTagData += 4; pTagData += 4;
} }
if (flags & 0x04) { /* TOC flag. */ if (flags & 0x04) { /* TOC flag. */
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 100) {
goto done_xing_info; /* Invalid Xing/Info tag. */
}
/* TODO: Extract and bind seek points. */ /* TODO: Extract and bind seek points. */
pTagData += 100; pTagData += 100;
} }
if (flags & 0x08) { /* SCALE flag. */ if (flags & 0x08) { /* SCALE flag. */
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) {
goto done_xing_info; /* Invalid Xing/Info tag. */
}
pTagData += 4; pTagData += 4;
} }
/* At this point we're done with the Xing/Info header. Now we can look at the LAME data. */ /* At this point we're done with the Xing/Info header. Now we can look at the LAME data. */
if (pTagData[0]) { if (pTagData[0]) {
int delayInPCMFrames;
int paddingInPCMFrames;
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 36) {
goto done_xing_info; /* Invalid Xing/Info tag. */
}
pTagData += 21; pTagData += 21;
if (pTagData - pFirstFrameData + 14 < firstFrameInfo.frame_bytes) { delayInPCMFrames = (( (drmp3_uint32)pTagData[0] << 4) | ((drmp3_uint32)pTagData[1] >> 4)) + (528 + 1);
int delayInPCMFrames; paddingInPCMFrames = ((((drmp3_uint32)pTagData[1] & 0xF) << 8) | ((drmp3_uint32)pTagData[2] )) - (528 + 1);
int paddingInPCMFrames; if (paddingInPCMFrames < 0) {
paddingInPCMFrames = 0; /* Padding cannot be negative. Probably a malformed file. Ignore. */
delayInPCMFrames = (( (drmp3_uint32)pTagData[0] << 4) | ((drmp3_uint32)pTagData[1] >> 4)) + (528 + 1);
paddingInPCMFrames = ((((drmp3_uint32)pTagData[1] & 0xF) << 8) | ((drmp3_uint32)pTagData[2] )) - (528 + 1);
if (paddingInPCMFrames < 0) {
paddingInPCMFrames = 0; /* Padding cannot be negative. Probably a malformed file. Ignore. */
}
pMP3->delayInPCMFrames = (drmp3_uint32)delayInPCMFrames;
pMP3->paddingInPCMFrames = (drmp3_uint32)paddingInPCMFrames;
} }
pMP3->delayInPCMFrames = (drmp3_uint32)delayInPCMFrames;
pMP3->paddingInPCMFrames = (drmp3_uint32)paddingInPCMFrames;
} }
/* /*
@ -3273,6 +3295,8 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
*/ */
drmp3dec_init(&pMP3->decoder); drmp3dec_init(&pMP3->decoder);
} }
done_xing_info:;
} else { } else {
/* Failed to read the side info. */ /* Failed to read the side info. */
} }
@ -3285,7 +3309,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
} }
if (detectedMP3FrameCount != 0xFFFFFFFF) { if (detectedMP3FrameCount != 0xFFFFFFFF) {
pMP3->totalPCMFrameCount = detectedMP3FrameCount * firstFramePCMFrameCount; pMP3->totalPCMFrameCount = (drmp3_uint64)detectedMP3FrameCount * firstFramePCMFrameCount;
} }
pMP3->channels = pMP3->mp3FrameChannels; pMP3->channels = pMP3->mp3FrameChannels;
@ -4247,7 +4271,7 @@ DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3* pMP3, drmp3_uint64 frame
#else #else
/* Slow path. Convert from s16 to f32. */ /* Slow path. Convert from s16 to f32. */
{ {
drmp3_int16 pTempS16[8192]; drmp3_int16 pTempS16[1152*2]; /* MP3 frames have a maximum per-channel sample count of 1152. Times 2 to account for stereo. */
drmp3_uint64 totalPCMFramesRead = 0; drmp3_uint64 totalPCMFramesRead = 0;
while (totalPCMFramesRead < framesToRead) { while (totalPCMFramesRead < framesToRead) {
@ -4284,7 +4308,7 @@ DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_s16(drmp3* pMP3, drmp3_uint64 frame
#else #else
/* Slow path. Convert from f32 to s16. */ /* Slow path. Convert from f32 to s16. */
{ {
float pTempF32[4096]; float pTempF32[1152*2]; /* MP3 frames have a maximum per-channel sample count of 1152. Times 2 to account for stereo. */
drmp3_uint64 totalPCMFramesRead = 0; drmp3_uint64 totalPCMFramesRead = 0;
while (totalPCMFramesRead < framesToRead) { while (totalPCMFramesRead < framesToRead) {
@ -4772,7 +4796,7 @@ static float* drmp3__full_read_and_close_f32(drmp3* pMP3, drmp3_config* pConfig,
drmp3_uint64 totalFramesRead = 0; drmp3_uint64 totalFramesRead = 0;
drmp3_uint64 framesCapacity = 0; drmp3_uint64 framesCapacity = 0;
float* pFrames = NULL; float* pFrames = NULL;
float temp[4096]; float temp[1152*2]; /* MP3 frames have a maximum per-channel sample count of 1152. Times 2 to account for stereo. */
DRMP3_ASSERT(pMP3 != NULL); DRMP3_ASSERT(pMP3 != NULL);
@ -4841,7 +4865,7 @@ static drmp3_int16* drmp3__full_read_and_close_s16(drmp3* pMP3, drmp3_config* pC
drmp3_uint64 totalFramesRead = 0; drmp3_uint64 totalFramesRead = 0;
drmp3_uint64 framesCapacity = 0; drmp3_uint64 framesCapacity = 0;
drmp3_int16* pFrames = NULL; drmp3_int16* pFrames = NULL;
drmp3_int16 temp[4096]; drmp3_int16 temp[1152*2]; /* MP3 frames have a maximum per-channel sample count of 1152. Times 2 to account for stereo. */
DRMP3_ASSERT(pMP3 != NULL); DRMP3_ASSERT(pMP3 != NULL);
@ -5010,6 +5034,9 @@ DIFFERENCES BETWEEN minimp3 AND dr_mp3
REVISION HISTORY REVISION HISTORY
================ ================
v0.7.4 - TBD v0.7.4 - TBD
- Fix an overflow error with "Xing" and "Info" tag parsing.
- Add some validation checks for "Xing" and "Info" tag parsing.
- Reduce size of some stack allocations.
- Improvements to SIMD detection. - Improvements to SIMD detection.
v0.7.3 - 2026-01-17 v0.7.3 - 2026-01-17

63
src/external/dr_wav.h vendored
View File

@ -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. WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
dr_wav - v0.14.5 - 2026-03-03 dr_wav - v0.14.6 - TBD
David Reid - mackron@gmail.com David Reid - mackron@gmail.com
@ -147,7 +147,7 @@ extern "C" {
#define DRWAV_VERSION_MAJOR 0 #define DRWAV_VERSION_MAJOR 0
#define DRWAV_VERSION_MINOR 14 #define DRWAV_VERSION_MINOR 14
#define DRWAV_VERSION_REVISION 5 #define DRWAV_VERSION_REVISION 6
#define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION) #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. */ #include <stddef.h> /* For size_t. */
@ -1971,7 +1971,15 @@ DRWAV_PRIVATE drwav_result drwav__read_chunk_header(drwav_read_proc onRead, void
return DRWAV_INVALID_FILE; return DRWAV_INVALID_FILE;
} }
pHeaderOut->sizeInBytes = drwav_bytes_to_u64(sizeInBytes) - 24; /* <-- Subtract 24 because w64 includes the size of the header. */ pHeaderOut->sizeInBytes = drwav_bytes_to_u64(sizeInBytes);
/* Subtract 24 from the size because with w64 the reported chunk size includes the size of the header itself. */
if (pHeaderOut->sizeInBytes >= 24) {
pHeaderOut->sizeInBytes -= 24;
} else {
return DRWAV_INVALID_FILE;
}
pHeaderOut->paddingSize = drwav__chunk_padding_size_w64(pHeaderOut->sizeInBytes); pHeaderOut->paddingSize = drwav__chunk_padding_size_w64(pHeaderOut->sizeInBytes);
*pRunningBytesReadOut += 24; *pRunningBytesReadOut += 24;
} else { } else {
@ -2201,7 +2209,7 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
so it's consistent with how we do it in the first stage. so it's consistent with how we do it in the first stage.
*/ */
loopCount = drwav_bytes_to_u32(smplHeaderData + 28); loopCount = drwav_bytes_to_u32(smplHeaderData + 28);
calculatedLoopCount = (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES; calculatedLoopCount = (drwav_uint32)((pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES);
if (loopCount != calculatedLoopCount) { if (loopCount != calculatedLoopCount) {
return totalBytesRead; return totalBytesRead;
} }
@ -2580,8 +2588,10 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_bext_to_metadata_obj(drwav__metadata_pars
pMetadata->data.bext.pCodingHistory = (char*)drwav__metadata_get_memory(pParser, extraBytes + 1, 1); pMetadata->data.bext.pCodingHistory = (char*)drwav__metadata_get_memory(pParser, extraBytes + 1, 1);
DRWAV_ASSERT(pMetadata->data.bext.pCodingHistory != NULL); 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)drwav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL);
pMetadata->data.bext.codingHistorySize = (drwav_uint32)drwav__strlen(pMetadata->data.bext.pCodingHistory); pMetadata->data.bext.pCodingHistory[pMetadata->data.bext.codingHistorySize] = '\0'; /* <-- Explicit null terminator in case of a badly formed file. */
bytesRead += pMetadata->data.bext.codingHistorySize;
} else { } else {
pMetadata->data.bext.pCodingHistory = NULL; pMetadata->data.bext.pCodingHistory = NULL;
pMetadata->data.bext.codingHistorySize = 0; pMetadata->data.bext.codingHistorySize = 0;
@ -2755,10 +2765,10 @@ DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser*
bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead); bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
if (bytesJustRead == sizeof(buffer)) { if (bytesJustRead == sizeof(buffer)) {
drwav_uint32 loopCount = drwav_bytes_to_u32(buffer); drwav_uint32 loopCount = drwav_bytes_to_u32(buffer);
drwav_uint64 calculatedLoopCount; drwav_uint32 calculatedLoopCount;
/* The loop count must be validated against the size of the chunk. */ /* The loop count must be validated against the size of the chunk. */
calculatedLoopCount = (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES; calculatedLoopCount = (drwav_uint32)((pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES);
if (calculatedLoopCount == loopCount) { if (calculatedLoopCount == loopCount) {
bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead); bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
if (bytesJustRead == sizeof(buffer)) { if (bytesJustRead == sizeof(buffer)) {
@ -2860,7 +2870,9 @@ DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser*
return bytesRead; return bytesRead;
} }
allocSizeNeeded += drwav__strlen(buffer) + 1; allocSizeNeeded += drwav__strlen(buffer) + 1;
allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - DRWAV_BEXT_BYTES + 1; /* Coding history. */
/* Coding history. */
allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - DRWAV_BEXT_BYTES + 1;
drwav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1); drwav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1);
@ -3321,6 +3333,10 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
((pWav->container == drwav_container_w64) && drwav_guid_equal(header.id.guid, drwavGUID_W64_FMT))) { ((pWav->container == drwav_container_w64) && drwav_guid_equal(header.id.guid, drwavGUID_W64_FMT))) {
drwav_uint8 fmtData[16]; drwav_uint8 fmtData[16];
if (header.sizeInBytes < sizeof(fmtData)) {
return DRWAV_FALSE; /* Invalid fmt chunk. */
}
foundChunk_fmt = DRWAV_TRUE; foundChunk_fmt = DRWAV_TRUE;
if (pWav->onRead(pWav->pUserData, fmtData, sizeof(fmtData)) != sizeof(fmtData)) { if (pWav->onRead(pWav->pUserData, fmtData, sizeof(fmtData)) != sizeof(fmtData)) {
@ -3833,6 +3849,11 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
/* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */ /* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */
totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels); totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels);
if (totalBlockHeaderSizeInBytes >= dataChunkSize) { /* <-- We'll be subtracting totalBlockHeaderSizeInBytes from dataChunkSize next so it must be validated. */
drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
return DRWAV_FALSE; /* Invalid file. */
}
pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels; pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
} }
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) { if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
@ -3846,6 +3867,11 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
/* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */ /* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */
totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels); totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels);
if (totalBlockHeaderSizeInBytes >= dataChunkSize) { /* <-- We'll be subtracting totalBlockHeaderSizeInBytes from dataChunkSize next so it must be validated. */
drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
return DRWAV_FALSE; /* Invalid file. */
}
pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels; pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
/* The header includes a decoded sample for each channel which acts as the initial predictor sample. */ /* The header includes a decoded sample for each channel which acts as the initial predictor sample. */
@ -6725,6 +6751,10 @@ DRWAV_PRIVATE void drwav__pcm_to_s16(drwav_int16* pOut, const drwav_uint8* pIn,
shift += 8; shift += 8;
} }
if (!drwav__is_little_endian()) {
sample = drwav__bswap64(sample);
}
pIn += j; pIn += j;
*pOut++ = (drwav_int16)((drwav_int64)sample >> 48); *pOut++ = (drwav_int16)((drwav_int64)sample >> 48);
} }
@ -7166,6 +7196,10 @@ DRWAV_PRIVATE void drwav__pcm_to_f32(float* pOut, const drwav_uint8* pIn, size_t
shift += 8; shift += 8;
} }
if (!drwav__is_little_endian()) {
sample = drwav__bswap64(sample);
}
pIn += j; pIn += j;
*pOut++ = (float)((drwav_int64)sample / 9223372036854775807.0); *pOut++ = (float)((drwav_int64)sample / 9223372036854775807.0);
} }
@ -7650,6 +7684,10 @@ DRWAV_PRIVATE void drwav__pcm_to_s32(drwav_int32* pOut, const drwav_uint8* pIn,
shift += 8; shift += 8;
} }
if (!drwav__is_little_endian()) {
sample = drwav__bswap64(sample);
}
pIn += j; pIn += j;
*pOut++ = (drwav_int32)((drwav_int64)sample >> 32); *pOut++ = (drwav_int32)((drwav_int64)sample >> 32);
} }
@ -8557,6 +8595,13 @@ DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b)
/* /*
REVISION HISTORY REVISION HISTORY
================ ================
v0.14.6 - TBD
- Fix an error when loading files with a malformed "bext" chunk.
- Fix an error when loading files with a malformed "fmt" chunk.
- Fix an underflow error with badly formed ADPCM encoded files.
- Fix an underflow error with badly formed W64 files.
- Fix an error when converting from >32 bit samples to s16/f32/s32 on big-endian architectures.
v0.14.5 - 2026-03-03 v0.14.5 - 2026-03-03
- Fix a crash when loading files with a malformed "smpl" chunk. - Fix a crash when loading files with a malformed "smpl" chunk.
- Fix a signed overflow bug with the MS-ADPCM decoder. - Fix a signed overflow bug with the MS-ADPCM decoder.