From 49153ebfc4cd857769777aa5a2edd3aa5bbd8304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20=C3=85stholm?= Date: Sat, 28 Dec 2024 00:18:16 +0100 Subject: [PATCH] audio: Add NULL check to SDL_UnbindAudioStreams --- include/SDL3/SDL_audio.h | 4 ++-- src/audio/SDL_audio.c | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/SDL3/SDL_audio.h b/include/SDL3/SDL_audio.h index 9082ac3b8f..71f34c87af 100644 --- a/include/SDL3/SDL_audio.h +++ b/include/SDL3/SDL_audio.h @@ -990,7 +990,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_BindAudioStream(SDL_AudioDeviceID devid, SD * * Unbinding a stream that isn't bound to a device is a legal no-op. * - * \param streams an array of audio streams to unbind. + * \param streams an array of audio streams to unbind. Can be NULL or contain NULL. * \param num_streams number streams listed in the `streams` array. * * \threadsafety It is safe to call this function from any thread. @@ -1007,7 +1007,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnbindAudioStreams(SDL_AudioStream * const * This is a convenience function, equivalent to calling * `SDL_UnbindAudioStreams(&stream, 1)`. * - * \param stream an audio stream to unbind from a device. + * \param stream an audio stream to unbind from a device. Can be NULL. * * \threadsafety It is safe to call this function from any thread. * diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 51e1ad2871..b3652ee911 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -1949,6 +1949,10 @@ bool SDL_BindAudioStream(SDL_AudioDeviceID devid, SDL_AudioStream *stream) // !!! FIXME: this and BindAudioStreams are mutex nightmares. :/ void SDL_UnbindAudioStreams(SDL_AudioStream * const *streams, int num_streams) { + if (num_streams <= 0 || !streams) { + return; // nothing to do + } + /* to prevent deadlock when holding both locks, we _must_ lock the device first, and the stream second, as that is the order the audio thread will do it. But this means we have an unlikely, pathological case where a stream could change its binding between when we lookup its bound device and when we lock everything, so we double-check here. */