From 4c47f6f3eb2fe180c9acefea91cc02ae9ba20e68 Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Fri, 7 Oct 2022 14:01:02 +0300
Subject: [PATCH] Mix_LoadWAV_RW, Mix_FreeChunk: use correct function to free
chunk->abuf.
Otherwise, if SDL and SDL_mixer use different C libraries, using free()
on a buffer allocated by SDL_LoadWAV_RW will result in a crash, which is
what happens on windows when SDL_mixer is running against sdl12-compat.
NOTE: SDL2_mixer actually inherited the same mismatch, but it does not
have the issue because, unlike SDL-1.2, SDL_malloc and SDL_free aren't
macros in SDL2.
Reference issue: https://github.com/libsdl-org/sdl12-compat/issues/215
---
CHANGES | 1 +
mixer.c | 22 +++++++++++++++++-----
2 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/CHANGES b/CHANGES
index fd3f8ade..40e40950 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,5 @@
1.2.13:
+- Mix_LoadWAV_RW: Fixed an incompatibility with sdl12-compat.
- MP3: Added playback support using libmpg123 and removed deprecated
smpeg support.
- MP3, mad decoder: skip tags, which otherwise would lead to crashes
diff --git a/mixer.c b/mixer.c
index 431f6e69..317f482c 100644
--- a/mixer.c
+++ b/mixer.c
@@ -560,6 +560,7 @@ Mix_Chunk *Mix_LoadWAV_RW(SDL_RWops *src, int freesrc)
SDL_AudioSpec wavespec, *loaded;
SDL_AudioCVT wavecvt;
int samplesize;
+ int wavfree; /* to decide how to free chunk->abuf. */
/* rcg06012001 Make sure src is valid */
if ( ! src ) {
@@ -591,9 +592,11 @@ Mix_Chunk *Mix_LoadWAV_RW(SDL_RWops *src, int freesrc)
/* Seek backwards for compatibility with older loaders */
SDL_RWseek(src, -(int)sizeof(Uint32), RW_SEEK_CUR);
+ wavfree = 0;
switch (magic) {
case WAVE:
case RIFF:
+ wavfree = 1;
loaded = SDL_LoadWAV_RW(src, freesrc, &wavespec,
(Uint8 **)&chunk->abuf, &chunk->alen);
break;
@@ -643,7 +646,8 @@ Mix_Chunk *Mix_LoadWAV_RW(SDL_RWops *src, int freesrc)
if ( SDL_BuildAudioCVT(&wavecvt,
wavespec.format, wavespec.channels, wavespec.freq,
mixer.format, mixer.channels, mixer.freq) < 0 ) {
- SDL_free(chunk->abuf);
+ if (!wavfree)SDL_free(chunk->abuf);
+ else SDL_FreeWAV(chunk->abuf);
SDL_free(chunk);
return(NULL);
}
@@ -652,12 +656,14 @@ Mix_Chunk *Mix_LoadWAV_RW(SDL_RWops *src, int freesrc)
wavecvt.buf = (Uint8 *)SDL_calloc(1, wavecvt.len*wavecvt.len_mult);
if ( wavecvt.buf == NULL ) {
SDL_SetError("Out of memory");
- SDL_free(chunk->abuf);
+ if (!wavfree) SDL_free(chunk->abuf);
+ else SDL_FreeWAV(chunk->abuf);
SDL_free(chunk);
return(NULL);
}
memcpy(wavecvt.buf, chunk->abuf, wavecvt.len);
- SDL_free(chunk->abuf);
+ if (!wavfree) SDL_free(chunk->abuf);
+ else SDL_FreeWAV(chunk->abuf);
/* Run the audio converter */
if ( SDL_ConvertAudio(&wavecvt) < 0 ) {
@@ -668,9 +674,10 @@ Mix_Chunk *Mix_LoadWAV_RW(SDL_RWops *src, int freesrc)
chunk->abuf = wavecvt.buf;
chunk->alen = wavecvt.len_cvt;
+ wavfree = 0;
}
- chunk->allocated = 1;
+ chunk->allocated = (wavfree == 0) ? 1 : 2; /* see Mix_FreeChunk() */
chunk->volume = MIX_MAX_VOLUME;
return(chunk);
@@ -757,8 +764,13 @@ void Mix_FreeChunk(Mix_Chunk *chunk)
}
SDL_UnlockAudio();
/* Actually free the chunk */
- if ( chunk->allocated ) {
+ switch ( chunk->allocated ) {
+ case 1:
SDL_free(chunk->abuf);
+ break;
+ case 2:
+ SDL_FreeWAV(chunk->abuf);
+ break;
}
SDL_free(chunk);
}