SDL_mixer: Mix_LoadWAV_RW, Mix_FreeChunk: use correct function to free chunk->abuf.

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);
 	}