aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorWillem Jan Palenstijn2017-12-03 12:49:11 +0100
committerWillem Jan Palenstijn2017-12-03 12:49:11 +0100
commit3a933138ce9273724726efc0df051b8dcf92b7d8 (patch)
treea0e9ed1f8ed7091aaef4ce44dce21cd39e0fc2f5 /engines/sci
parentc78fa86860f55ab28554327f0da310a825041655 (diff)
downloadscummvm-rg350-3a933138ce9273724726efc0df051b8dcf92b7d8.tar.gz
scummvm-rg350-3a933138ce9273724726efc0df051b8dcf92b7d8.tar.bz2
scummvm-rg350-3a933138ce9273724726efc0df051b8dcf92b7d8.zip
SCI: Avoid buffer overflow in amigamac sound driver
By default, frac_t is interpreted as signed. The resulting range isn't large enough to store offsets, so we interpret it as unsigned here instead. Fixes a crash in QfG1/Mac where instrument->loop_size is 49457.
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/sound/drivers/amigamac.cpp9
1 files changed, 7 insertions, 2 deletions
diff --git a/engines/sci/sound/drivers/amigamac.cpp b/engines/sci/sound/drivers/amigamac.cpp
index b8b6a32214..22950cb2e7 100644
--- a/engines/sci/sound/drivers/amigamac.cpp
+++ b/engines/sci/sound/drivers/amigamac.cpp
@@ -34,6 +34,11 @@
namespace Sci {
+// We use frac_t to store non-negative offsets that can be larger than 32767
+static uint fracToUInt(frac_t value) {
+ return ((uint32)value) / (1 << FRAC_BITS);
+}
+
class MidiDriver_AmigaMac : public MidiDriver_Emulated {
public:
enum {
@@ -170,7 +175,7 @@ void MidiDriver_AmigaMac::setEnvelope(Voice *channel, Envelope *envelope, int ph
}
int MidiDriver_AmigaMac::interpolate(int8 *samples, frac_t offset, uint32 maxOffset, bool isUnsigned) {
- uint x = fracToInt(offset);
+ uint x = fracToUInt(offset);
uint x2 = x == maxOffset ? 0 : x + 1;
if (isUnsigned) {
@@ -272,7 +277,7 @@ void MidiDriver_AmigaMac::playInstrument(int16 *dest, Voice *channel, int count)
if (index == count)
break;
- if ((uint32)fracToInt(channel->offset) >= seg_end) {
+ if (fracToUInt(channel->offset) >= seg_end) {
if (instrument->mode & kModeLoop) {
/* Loop the samples */
channel->offset -= intToFrac(seg_end);