diff options
author | Evgeny Grechnikov | 2018-10-16 00:49:07 +0300 |
---|---|---|
committer | Evgeny Grechnikov | 2018-10-16 00:49:07 +0300 |
commit | 8162309212bbc287632fc375d1740a64733019fb (patch) | |
tree | 0b78997549fd0de4ad18dbf09fbb7b2e886eb770 | |
parent | 45641f3de5c598b534b36d4ba0f30ac6b41d9bac (diff) | |
download | scummvm-rg350-8162309212bbc287632fc375d1740a64733019fb.tar.gz scummvm-rg350-8162309212bbc287632fc375d1740a64733019fb.tar.bz2 scummvm-rg350-8162309212bbc287632fc375d1740a64733019fb.zip |
LASTEXPRESS: fix race condition in sound code
SoundEntry::play() calls StreamedSound::setFilterId(),
StreamSound::setFilterId() requires the underlying reference to be alive.
SoundQueue::handleTimer() checks that the stream is still alive
by calling SoundEntry::isFinished(). However, if the stream is finalized
just between calls to SoundEntry::isFinished() and SoundEntry::play(),
the sound mixer frees the stream leading to use-after-free in setFilterId().
Turn off the automatical disposing, delete the stream in SoundEntry::~SoundEntry().
-rw-r--r-- | engines/lastexpress/data/snd.cpp | 14 | ||||
-rw-r--r-- | engines/lastexpress/data/snd.h | 2 |
2 files changed, 11 insertions, 5 deletions
diff --git a/engines/lastexpress/data/snd.cpp b/engines/lastexpress/data/snd.cpp index e310bafd18..4cff837193 100644 --- a/engines/lastexpress/data/snd.cpp +++ b/engines/lastexpress/data/snd.cpp @@ -446,8 +446,9 @@ LastExpress_ADPCMStream *SimpleSound::makeDecoder(Common::SeekableReadStream *in return new LastExpress_ADPCMStream(in, DisposeAfterUse::YES, size, _blockSize, filterId); } -void SimpleSound::play(Audio::AudioStream *as) { - g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_handle, as); +void SimpleSound::play(Audio::AudioStream *as, DisposeAfterUse::Flag autofreeStream) { + g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_handle, as, + -1, Audio::Mixer::kMaxChannelVolume, 0, autofreeStream); } ////////////////////////////////////////////////////////////////////////// @@ -456,6 +457,7 @@ void SimpleSound::play(Audio::AudioStream *as) { StreamedSound::StreamedSound() : _as(NULL), _loaded(false) {} StreamedSound::~StreamedSound() { + delete _as; _as = NULL; } @@ -467,11 +469,15 @@ bool StreamedSound::load(Common::SeekableReadStream *stream, int32 filterId) { loadHeader(stream); + if (_as) { + stop(); + delete _as; + } // Start decoding the input stream _as = makeDecoder(stream, _size, filterId); // Start playing the decoded audio stream - play(_as); + play(_as, DisposeAfterUse::NO); _loaded = true; @@ -501,7 +507,7 @@ AppendableSound::AppendableSound() : SimpleSound() { _finished = false; // Start playing the decoded audio stream - play(_as); + play(_as, DisposeAfterUse::YES); // Initialize the block size // TODO: get it as an argument? diff --git a/engines/lastexpress/data/snd.h b/engines/lastexpress/data/snd.h index 19e5fda9c9..23aae905ac 100644 --- a/engines/lastexpress/data/snd.h +++ b/engines/lastexpress/data/snd.h @@ -62,7 +62,7 @@ public: protected: void loadHeader(Common::SeekableReadStream *in); LastExpress_ADPCMStream *makeDecoder(Common::SeekableReadStream *in, uint32 size, int32 filterId = -1) const; - void play(Audio::AudioStream *as); + void play(Audio::AudioStream *as, DisposeAfterUse::Flag autofreeStream); uint32 _size; ///< data size ///< - NIS: size of all blocks, including those located in the matching LNK file |