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.
This commit is contained in:
Thomas Goyne 2012-11-25 07:45:54 -08:00
parent 4e8e5b597c
commit 59e6a1bef7
2 changed files with 33 additions and 42 deletions

View file

@ -78,58 +78,47 @@ void AudioProvider::GetAudioWithVolume(void *buf, int64_t start, int64_t count,
} }
} }
void AudioProvider::GetAudio(void *buf, int64_t start, int64_t count) const { void AudioProvider::ZeroFill(void *buf, int64_t count) const {
if (start+count > num_samples) { if (bytes_per_sample == 1)
int64_t oldcount = count; // 8 bit formats are usually unsigned with bias 127
count = num_samples-start; memset(buf, 127, count * channels);
if (count < 0) count = 0; else
// While everything else is signed
memset(buf, 0, count * bytes_per_sample * channels);
}
// Fill beyond with zero void AudioProvider::GetAudio(void *buf, int64_t start, int64_t count) const {
if (bytes_per_sample == 1) { if (start < 0) {
char *temp = (char *) buf; ZeroFill(buf, std::min(-start, count));
for (int i=count;i<oldcount;i++) { buf = static_cast<char *>(buf) + -start * bytes_per_sample * channels;
temp[i] = 0; count += start;
} start = 0;
}
if (bytes_per_sample == 2) {
short *temp = (short *) buf;
for (int i=count;i<oldcount;i++) {
temp[i] = 0;
}
}
} }
if (start + count > num_samples) { if (start + count > num_samples) {
int64_t zero_count = std::min(count, start + count - num_samples); int64_t zero_count = std::min(count, start + count - num_samples);
count -= zero_count; count -= zero_count;
char *zero_buf = static_cast<char *>(buf) + count * bytes_per_sample * channels; ZeroFill(static_cast<char *>(buf) + count * bytes_per_sample * channels, zero_count);
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);
} }
if (count > 0) { if (count <= 0) return;
try { try {
FillBuffer(buf, start, count); FillBuffer(buf, start, count);
} }
catch (AudioDecodeError const& e) { catch (AudioDecodeError const& e) {
LOG_E("audio_provider") << e.GetChainedMessage(); LOG_E("audio_provider") << e.GetChainedMessage();
memset(buf, 0, count*bytes_per_sample); ZeroFill(buf, count);
return; return;
} }
catch (...) { catch (...) {
// FIXME: Poor error handling though better than none, to patch issue #800. // FIXME: Poor error handling though better than none, to patch issue #800.
// Just return blank audio if real provider fails. // Just return blank audio if real provider fails.
LOG_E("audio_provider") << "Unknown audio decoding error"; LOG_E("audio_provider") << "Unknown audio decoding error";
memset(buf, 0, count*bytes_per_sample); ZeroFill(buf, count);
return; return;
} }
} }
}
AudioProvider *AudioProviderFactory::GetProvider(wxString const& filename, int cache) { AudioProvider *AudioProviderFactory::GetProvider(wxString const& filename, int cache) {
AudioProvider *provider = 0; AudioProvider *provider = 0;

View file

@ -67,6 +67,8 @@ protected:
virtual void FillBuffer(void *buf, int64_t start, int64_t count) const = 0; virtual void FillBuffer(void *buf, int64_t start, int64_t count) const = 0;
void ZeroFill(void *buf, int64_t count) const;
public: public:
virtual ~AudioProvider() { } virtual ~AudioProvider() { }