SDL_mixer: update dr_flac and dr_mp3 from mainstream (Jul.15, 2026)

From 71c8837e461da3818a98e64e793929b0719712c8 Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Tue, 21 Jul 2026 14:28:10 +0300
Subject: [PATCH] update dr_flac and dr_mp3 from mainstream (Jul.15, 2026)

(cherry picked from commit 4cc1fb51ae00ffdf970f64db61af8842b4db0a3a)
---
 src/dr_libs/dr_flac.h | 31 ++++++++++++++++++++++---------
 src/dr_libs/dr_mp3.h  | 26 ++++++++++++++++++++------
 2 files changed, 42 insertions(+), 15 deletions(-)

diff --git a/src/dr_libs/dr_flac.h b/src/dr_libs/dr_flac.h
index 72bc6b76..3a234ed2 100644
--- a/src/dr_libs/dr_flac.h
+++ b/src/dr_libs/dr_flac.h
@@ -709,6 +709,9 @@ onRead (in)
 onSeek (in)
     The function to call when the read position of the client data needs to move.
 
+onTell (in)
+    The function to call when the read position of the client needs to be queried.
+
 pUserData (in, optional)
     A pointer to application defined data that will be passed to onRead and onSeek.
 
@@ -759,6 +762,9 @@ onRead (in)
 onSeek (in)
     The function to call when the read position of the client data needs to move.
 
+onTell (in)
+    The function to call when the read position of the client needs to be queried.
+
 container (in)
     Whether or not the FLAC stream is encapsulated using standard FLAC encapsulation or Ogg encapsulation.
 
@@ -800,6 +806,9 @@ onRead (in)
 onSeek (in)
     The function to call when the read position of the client data needs to move.
 
+onTell (in)
+    The function to call when the read position of the client needs to be queried.
+
 onMeta (in)
     The function to call for every metadata block.
 
@@ -5369,6 +5378,7 @@ static drflac_bool32 drflac__decode_subframe(drflac_bs* bs, drflac_frame* frame,
 {
     drflac_subframe* pSubframe;
     drflac_uint32 subframeBitsPerSample;
+    drflac_bool32 decodeResult;
 
     DRFLAC_ASSERT(bs != NULL);
     DRFLAC_ASSERT(frame != NULL);
@@ -5415,28 +5425,28 @@ static drflac_bool32 drflac__decode_subframe(drflac_bs* bs, drflac_frame* frame,
     {
         case DRFLAC_SUBFRAME_CONSTANT:
         {
-            drflac__decode_samples__constant(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->pSamplesS32);
+            decodeResult = drflac__decode_samples__constant(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->pSamplesS32);
         } break;
 
         case DRFLAC_SUBFRAME_VERBATIM:
         {
-            drflac__decode_samples__verbatim(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->pSamplesS32);
+            decodeResult = drflac__decode_samples__verbatim(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->pSamplesS32);
         } break;
 
         case DRFLAC_SUBFRAME_FIXED:
         {
-            drflac__decode_samples__fixed(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->lpcOrder, pSubframe->pSamplesS32);
+            decodeResult = drflac__decode_samples__fixed(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->lpcOrder, pSubframe->pSamplesS32);
         } break;
 
         case DRFLAC_SUBFRAME_LPC:
         {
-            drflac__decode_samples__lpc(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->lpcOrder, pSubframe->pSamplesS32);
+            decodeResult = drflac__decode_samples__lpc(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->lpcOrder, pSubframe->pSamplesS32);
         } break;
 
-        default: return DRFLAC_FALSE;
+        default: decodeResult = DRFLAC_FALSE;
     }
 
-    return DRFLAC_TRUE;
+    return decodeResult;
 }
 
 static drflac_bool32 drflac__seek_subframe(drflac_bs* bs, drflac_frame* frame, int subframeIndex)
@@ -6445,7 +6455,7 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
                 hasKnownFileSize = DRFLAC_TRUE;
             }
 
-            onSeek(pUserData, runningFilePos, DRFLAC_SEEK_SET);
+            onSeek(pUserData, (int)runningFilePos, DRFLAC_SEEK_SET);    /* Safe cast because runningFilePos should always be 42 at this point. */
         }
     }
 
@@ -6508,10 +6518,12 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
                     drflac_uint32 seekpointCount;
                     drflac_uint32 iSeekpoint;
                     void* pRawData;
+                    size_t rawDataSize;
 
                     seekpointCount = blockSize/DRFLAC_SEEKPOINT_SIZE_IN_BYTES;
+                    rawDataSize = seekpointCount * sizeof(drflac_seekpoint);
 
-                    pRawData = drflac__malloc_from_callbacks(seekpointCount * sizeof(drflac_seekpoint), pAllocationCallbacks);
+                    pRawData = drflac__malloc_from_callbacks(rawDataSize, pAllocationCallbacks);
                     if (pRawData == NULL) {
                         return DRFLAC_FALSE;
                     }
@@ -6532,7 +6544,7 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
                     }
 
                     metadata.pRawData = pRawData;
-                    metadata.rawDataSize = blockSize;
+                    metadata.rawDataSize = rawDataSize;
                     metadata.data.seektable.seekpointCount = seekpointCount;
                     metadata.data.seektable.pSeekpoints = (const drflac_seekpoint*)pRawData;
 
@@ -12206,6 +12218,7 @@ 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.
+  - Fix an with seek point parsing.
 
 v0.13.3 - 2026-01-17
   - Fix a compiler compatibility issue with some inlined assembly.
diff --git a/src/dr_libs/dr_mp3.h b/src/dr_libs/dr_mp3.h
index a458d86c..01a0f6e1 100644
--- a/src/dr_libs/dr_mp3.h
+++ b/src/dr_libs/dr_mp3.h
@@ -3184,11 +3184,25 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
                 drmp3_bool32 isInfo = DRMP3_FALSE;
                 const drmp3_uint8* pTagData;
                 const drmp3_uint8* pTagDataBeg;
+                const void* pDataBufferEnd = NULL;
+                size_t frameBytes;
 
                 pTagDataBeg = pFirstFrameData + DRMP3_HDR_SIZE + (bs.pos/8);
                 pTagData    = pTagDataBeg;
 
-                if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 8) {
+                /*
+                We need to determine how many bytes are actually available in pTagData. Unfortunately this is different depending on
+                whether or not it's being decoded from memory or callbacks.
+                */
+                if (pMP3->memory.pData != NULL && pMP3->memory.dataSize > 0) {
+                    pDataBufferEnd = pMP3->memory.pData + pMP3->memory.dataSize;
+                } else {
+                    pDataBufferEnd = pMP3->pData + pMP3->dataCapacity;
+                }
+
+                frameBytes = DRMP3_MIN((size_t)firstFrameInfo.frame_bytes, (size_t)((drmp3_uint8*)pDataBufferEnd - pTagDataBeg));
+
+                if (frameBytes - (size_t)(pTagData - pFirstFrameData) < 8) {
                     goto done_xing_info;    /* Frame too small for a Xing/Info tag. */
                 }
 
@@ -3203,7 +3217,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
                     pTagData += 8;  /* Skip past the ID and flags. */
 
                     if (flags & 0x01) { /* FRAMES flag. */
-                        if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) {
+                        if (frameBytes - (size_t)(pTagData - pFirstFrameData) < 4) {
                             goto done_xing_info;    /* Invalid Xing/Info tag. */
                         }
 
@@ -3212,7 +3226,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
                     }
 
                     if (flags & 0x02) { /* BYTES flag. */
-                        if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) {
+                        if (frameBytes - (size_t)(pTagData - pFirstFrameData) < 4) {
                             goto done_xing_info;    /* Invalid Xing/Info tag. */
                         }
 
@@ -3222,7 +3236,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
                     }
 
                     if (flags & 0x04) { /* TOC flag. */
-                        if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 100) {
+                        if (frameBytes - (size_t)(pTagData - pFirstFrameData) < 100) {
                             goto done_xing_info;    /* Invalid Xing/Info tag. */
                         }
 
@@ -3231,7 +3245,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
                     }
 
                     if (flags & 0x08) { /* SCALE flag. */
-                        if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) {
+                        if (frameBytes - (size_t)(pTagData - pFirstFrameData) < 4) {
                             goto done_xing_info;    /* Invalid Xing/Info tag. */
                         }
                         
@@ -3243,7 +3257,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
                         int delayInPCMFrames;
                         int paddingInPCMFrames;
 
-                        if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 36) {
+                        if (frameBytes - (size_t)(pTagData - pFirstFrameData) < 36) {
                             goto done_xing_info;    /* Invalid Xing/Info tag. */
                         }