From 99b5c26592269b0113deda644be1c74465c272f3 Mon Sep 17 00:00:00 2001 From: Thomas Goyne <plorkyeran@aegisub.org> Date: Sun, 25 Nov 2012 07:45:54 -0800 Subject: [PATCH] Fix crash when playing audio before time 0 There were two checks for reads past the end rather than checks for before start and after end. Closes #1556. --- aegisub/src/audio_provider.cpp | 73 +++++++++----------- aegisub/src/include/aegisub/audio_provider.h | 2 + 2 files changed, 33 insertions(+), 42 deletions(-) diff --git a/aegisub/src/audio_provider.cpp b/aegisub/src/audio_provider.cpp index 1482a56d6..9fb06e715 100644 --- a/aegisub/src/audio_provider.cpp +++ b/aegisub/src/audio_provider.cpp @@ -80,56 +80,45 @@ void AudioProvider::GetAudioWithVolume(void *buf, int64_t start, int64_t count, } } +void AudioProvider::ZeroFill(void *buf, int64_t count) const { + if (bytes_per_sample == 1) + // 8 bit formats are usually unsigned with bias 127 + memset(buf, 127, count * channels); + else + // While everything else is signed + memset(buf, 0, count * bytes_per_sample * channels); +} + void AudioProvider::GetAudio(void *buf, int64_t start, int64_t count) const { - if (start+count > num_samples) { - int64_t oldcount = count; - count = num_samples-start; - if (count < 0) count = 0; - - // Fill beyond with zero - if (bytes_per_sample == 1) { - char *temp = (char *) buf; - for (int i=count;i<oldcount;i++) { - temp[i] = 0; - } - } - if (bytes_per_sample == 2) { - short *temp = (short *) buf; - for (int i=count;i<oldcount;i++) { - temp[i] = 0; - } - } + if (start < 0) { + ZeroFill(buf, std::min(-start, count)); + buf = static_cast<char *>(buf) + -start * bytes_per_sample * channels; + count += start; + start = 0; } if (start + count > num_samples) { int64_t zero_count = std::min(count, start + count - num_samples); count -= zero_count; - char *zero_buf = static_cast<char *>(buf) + count * bytes_per_sample * channels; - - if (bytes_per_sample == 1) - // 8 bit formats are usually unsigned with bias 127 - memset(zero_buf, 127, zero_count * channels); - else - // While everything else is signed - memset(zero_buf, 0, zero_count * bytes_per_sample * channels); + ZeroFill(static_cast<char *>(buf) + count * bytes_per_sample * channels, zero_count); } - if (count > 0) { - try { - FillBuffer(buf, start, count); - } - catch (AudioDecodeError const& e) { - LOG_E("audio_provider") << e.GetChainedMessage(); - memset(buf, 0, count*bytes_per_sample); - return; - } - catch (...) { - // FIXME: Poor error handling though better than none, to patch issue #800. - // Just return blank audio if real provider fails. - LOG_E("audio_provider") << "Unknown audio decoding error"; - memset(buf, 0, count*bytes_per_sample); - return; - } + if (count <= 0) return; + + try { + FillBuffer(buf, start, count); + } + catch (AudioDecodeError const& e) { + LOG_E("audio_provider") << e.GetChainedMessage(); + ZeroFill(buf, count); + return; + } + catch (...) { + // FIXME: Poor error handling though better than none, to patch issue #800. + // Just return blank audio if real provider fails. + LOG_E("audio_provider") << "Unknown audio decoding error"; + ZeroFill(buf, count); + return; } } diff --git a/aegisub/src/include/aegisub/audio_provider.h b/aegisub/src/include/aegisub/audio_provider.h index fa7e67191..e029c6620 100644 --- a/aegisub/src/include/aegisub/audio_provider.h +++ b/aegisub/src/include/aegisub/audio_provider.h @@ -69,6 +69,8 @@ protected: virtual void FillBuffer(void *buf, int64_t start, int64_t count) const = 0; + void ZeroFill(void *buf, int64_t count) const; + public: virtual ~AudioProvider() { } -- GitLab