From abc014c0fe94e5e7ca0ac8d8a9d021e8142ec41f Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Mon, 22 Dec 2025 09:57:47 -0500
Subject: [PATCH] wav: Don't fail to load if data is appended to an
otherwise-valid WAV file.
Fixes #747.
---
src/decoder_wav.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/src/decoder_wav.c b/src/decoder_wav.c
index 2a6b32de..9b6fa2a7 100644
--- a/src/decoder_wav.c
+++ b/src/decoder_wav.c
@@ -1205,7 +1205,7 @@ static bool BuildSeekBlocks(WAV_AudioData *adata)
static bool WAV_init_audio_internal(WAV_AudioData *adata, SDL_IOStream *io, SDL_AudioSpec *spec, SDL_PropertiesID props)
{
- const Sint64 flen = SDL_GetIOSize(io);
+ Sint64 flen = SDL_GetIOSize(io);
bool found_FMT = false;
bool found_DATA = false;
@@ -1217,6 +1217,8 @@ static bool WAV_init_audio_internal(WAV_AudioData *adata, SDL_IOStream *io, SDL_
return SDL_SetError("Corrupt WAV file (wavlength goes past EOF)");
}
+ flen = wavelen; // clamp the believed file length, in case there's something appended to the WAV file.
+
if (WAVEmagic == RIFF) {
// there's a 4-byte "form type" that must be WAVE, and then the first chunk follows directly after.
if (!SDL_ReadU32LE(io, &WAVEmagic)) {
@@ -1245,7 +1247,7 @@ static bool WAV_init_audio_internal(WAV_AudioData *adata, SDL_IOStream *io, SDL_
if (chunk_length == 0) {
break;
- } else if ((chunk_start_position + chunk_length) > flen) {
+ } else if (((chunk_start_position + chunk_length) - (sizeof (Uint32) * 2)) > flen) {
return SDL_SetError("Corrupt WAV file (chunk goes past EOF)");
}
@@ -1278,12 +1280,16 @@ static bool WAV_init_audio_internal(WAV_AudioData *adata, SDL_IOStream *io, SDL_
return false;
}
+ // move to start of next chunk.
+ Sint64 next_chunk = chunk_start_position + chunk_length;
// RIFF chunks have a 2-byte alignment. Skip padding byte.
if (chunk_length & 1) {
- chunk_length++;
+ next_chunk++;
}
- // move to start of next chunk.
- if (SDL_SeekIO(io, chunk_start_position + chunk_length, SDL_IO_SEEK_SET) < 0) {
+
+ if (next_chunk >= flen) {
+ break; // we're done.
+ } else if (SDL_SeekIO(io, next_chunk, SDL_IO_SEEK_SET) < 0) {
return false;
}
}