Add bounds checking to SoundMacro execution loop

This commit is contained in:
Jack Andersen 2016-12-07 18:54:45 -10:00
parent c886bfd7d2
commit eb948dfd63
4 changed files with 51 additions and 19 deletions

View File

@ -103,7 +103,7 @@ if (APPLE AND (NOT CMAKE_OSX_DEPLOYMENT_TARGET OR CMAKE_OSX_DEPLOYMENT_TARGET VE
) )
else() else()
message(WARNING "Unable to find developer provision profile; skipping Amuse-AU") message(WARNING "Unable to find developer provisioning profile; skipping Amuse-AU")
endif() endif()
endif() endif()
endif() endif()

View File

@ -5,6 +5,7 @@
#include <vector> #include <vector>
#include <list> #include <list>
#include "Entity.hpp" #include "Entity.hpp"
#include "Common.hpp"
namespace amuse namespace amuse
{ {
@ -119,6 +120,17 @@ class SoundMacroState
/** 'program counter' stack for the active SoundMacro */ /** 'program counter' stack for the active SoundMacro */
std::vector<std::pair<const unsigned char*, int>> m_pc; std::vector<std::pair<const unsigned char*, int>> m_pc;
static int _assertPC(int pc, uint32_t size);
static int _assertPC(int pc, uint32_t size, bool swapSize)
{
return _assertPC(pc, swapSize ? SBig(size) : size);
}
void _setPC(int pc)
{
m_pc.back().second = _assertPC(pc, m_header.m_size);
}
double m_ticksPerSec; /**< ratio for resolving ticks in commands that use them */ double m_ticksPerSec; /**< ratio for resolving ticks in commands that use them */
uint8_t m_initVel; /**< Velocity played for this macro invocation */ uint8_t m_initVel; /**< Velocity played for this macro invocation */
uint8_t m_initMod; /**< Modulation played for this macro invocation */ uint8_t m_initMod; /**< Modulation played for this macro invocation */

View File

@ -13,6 +13,19 @@
namespace amuse namespace amuse
{ {
int SoundMacroState::_assertPC(int pc, uint32_t size)
{
if (pc == -1)
return -1;
int cmdCount = (size - sizeof(Header)) / sizeof(Command);
if (pc >= cmdCount)
{
fprintf(stderr, "SoundMacro PC bounds exceeded [%d/%d]\n", pc, cmdCount);
abort();
}
return pc;
}
void SoundMacroState::Header::swapBig() void SoundMacroState::Header::swapBig()
{ {
m_size = SBig(m_size); m_size = SBig(m_size);
@ -133,7 +146,8 @@ void SoundMacroState::initialize(const unsigned char* ptr, int step, double tick
m_curMod = midiMod; m_curMod = midiMod;
m_curPitch = midiKey * 100; m_curPitch = midiKey * 100;
m_pc.clear(); m_pc.clear();
m_pc.push_back({ptr, step}); const Header& header = reinterpret_cast<const Header&>(ptr);
m_pc.push_back({ptr, _assertPC(step, header.m_size, swapData)});
m_inWait = false; m_inWait = false;
m_execTime = 0.f; m_execTime = 0.f;
m_keyoff = false; m_keyoff = false;
@ -143,7 +157,7 @@ void SoundMacroState::initialize(const unsigned char* ptr, int step, double tick
m_useAdsrControllers = false; m_useAdsrControllers = false;
m_portamentoMode = 2; m_portamentoMode = 2;
m_portamentoTime = 0.5f; m_portamentoTime = 0.5f;
m_header = *reinterpret_cast<const Header*>(ptr); m_header = header;
if (swapData) if (swapData)
m_header.swapBig(); m_header.swapBig();
} }
@ -180,6 +194,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
/* Load next command based on counter */ /* Load next command based on counter */
const Command* commands = reinterpret_cast<const Command*>(m_pc.back().first + sizeof(Header)); const Command* commands = reinterpret_cast<const Command*>(m_pc.back().first + sizeof(Header));
_assertPC(m_pc.back().second, m_header.m_size);
Command cmd = commands[m_pc.back().second++]; Command cmd = commands[m_pc.back().second++];
if (vox.getAudioGroup().getDataFormat() != DataFormat::PC) if (vox.getAudioGroup().getDataFormat() != DataFormat::PC)
cmd.swapBig(); cmd.swapBig();
@ -189,7 +204,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
{ {
case Op::End: case Op::End:
case Op::Stop: case Op::Stop:
m_pc.back().second = -1; _setPC(-1);
return true; return true;
case Op::SplitKey: case Op::SplitKey:
{ {
@ -201,7 +216,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
{ {
/* Do Branch */ /* Do Branch */
if (macroId == m_header.m_macroId) if (macroId == m_header.m_macroId)
m_pc.back().second = macroStep; _setPC(macroStep);
else else
vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod); vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod);
} }
@ -218,7 +233,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
{ {
/* Do Branch */ /* Do Branch */
if (macroId == m_header.m_macroId) if (macroId == m_header.m_macroId)
m_pc.back().second = macroStep; _setPC(macroStep);
else else
vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod); vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod);
} }
@ -287,7 +302,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
{ {
/* Loop back to step */ /* Loop back to step */
--m_loopCountdown; --m_loopCountdown;
m_pc.back().second = step; _setPC(step);
} }
else /* Break out of loop */ else /* Break out of loop */
m_loopCountdown = -1; m_loopCountdown = -1;
@ -301,7 +316,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
/* Do Branch */ /* Do Branch */
if (macroId == m_header.m_macroId) if (macroId == m_header.m_macroId)
m_pc.back().second = macroStep; _setPC(macroStep);
else else
vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod); vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod);
@ -389,7 +404,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
{ {
/* Do Branch */ /* Do Branch */
if (macroId == m_header.m_macroId) if (macroId == m_header.m_macroId)
m_pc.back().second = macroStep; _setPC(macroStep);
else else
vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod); vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod);
} }
@ -511,7 +526,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
{ {
/* Do branch */ /* Do branch */
if (macroId == m_header.m_macroId) if (macroId == m_header.m_macroId)
m_pc.back().second = macroStep; _setPC(macroStep);
else else
vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod); vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod);
} }
@ -776,7 +791,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
int16_t macroStep = *reinterpret_cast<int16_t*>(&cmd.m_data[3]); int16_t macroStep = *reinterpret_cast<int16_t*>(&cmd.m_data[3]);
if (macroId == m_header.m_macroId) if (macroId == m_header.m_macroId)
m_pc.push_back({m_pc.back().first, macroStep}); m_pc.push_back({m_pc.back().first, _assertPC(macroStep, m_header.m_size)});
else else
vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod, true); vox.loadSoundObject(macroId, macroStep, m_ticksPerSec, m_initKey, m_initVel, m_initMod, true);
@ -1205,7 +1220,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
b = m_variables[b]; b = m_variables[b];
if ((a == b) ^ lnot) if ((a == b) ^ lnot)
m_pc.back().second = macroStep; _setPC(macroStep);
break; break;
} }
@ -1229,7 +1244,7 @@ bool SoundMacroState::advance(Voice& vox, double dt)
b = m_variables[b]; b = m_variables[b];
if ((a < b) ^ lnot) if ((a < b) ^ lnot)
m_pc.back().second = macroStep; _setPC(macroStep);
break; break;
} }

View File

@ -46,7 +46,8 @@ void Voice::_macroSampleEnd()
{ {
if (m_sampleEndTrap.macroId == m_state.m_header.m_macroId) if (m_sampleEndTrap.macroId == m_state.m_header.m_macroId)
{ {
m_state.m_pc.back().second = m_sampleEndTrap.macroStep; m_state.m_pc.back().second = SoundMacroState::_assertPC(m_sampleEndTrap.macroStep,
m_state.m_header.m_size);
m_state.m_inWait = false; m_state.m_inWait = false;
} }
else else
@ -751,9 +752,11 @@ bool Voice::_loadSoundMacro(const unsigned char* macroData, int macroStep, doubl
{ {
if (!pushPc) if (!pushPc)
m_state.m_pc.clear(); m_state.m_pc.clear();
m_state.m_pc.push_back({macroData, macroStep}); const SoundMacroState::Header& header = reinterpret_cast<const SoundMacroState::Header&>(macroData);
m_state.m_header = *reinterpret_cast<const SoundMacroState::Header*>(macroData); const bool swapData = m_audioGroup.getDataFormat() != DataFormat::PC;
if (m_audioGroup.getDataFormat() != DataFormat::PC) m_state.m_pc.push_back({macroData, SoundMacroState::_assertPC(macroStep, header.m_size, swapData)});
m_state.m_header = header;
if (swapData)
m_state.m_header.swapBig(); m_state.m_header.swapBig();
} }
@ -846,7 +849,8 @@ void Voice::keyOff()
{ {
if (m_keyoffTrap.macroId == m_state.m_header.m_macroId) if (m_keyoffTrap.macroId == m_state.m_header.m_macroId)
{ {
m_state.m_pc.back().second = m_keyoffTrap.macroStep; m_state.m_pc.back().second = SoundMacroState::_assertPC(m_keyoffTrap.macroStep,
m_state.m_header.m_size);
m_state.m_inWait = false; m_state.m_inWait = false;
} }
else else
@ -867,7 +871,8 @@ void Voice::message(int32_t val)
if (m_messageTrap.macroId != 0xffff) if (m_messageTrap.macroId != 0xffff)
{ {
if (m_messageTrap.macroId == m_state.m_header.m_macroId) if (m_messageTrap.macroId == m_state.m_header.m_macroId)
m_state.m_pc.back().second = m_messageTrap.macroStep; m_state.m_pc.back().second = SoundMacroState::_assertPC(m_messageTrap.macroStep,
m_state.m_header.m_size);
else else
loadSoundObject(m_messageTrap.macroId, m_messageTrap.macroStep, m_state.m_ticksPerSec, m_state.m_initKey, loadSoundObject(m_messageTrap.macroId, m_messageTrap.macroStep, m_state.m_ticksPerSec, m_state.m_initKey,
m_state.m_initVel, m_state.m_initMod); m_state.m_initVel, m_state.m_initMod);