aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWohlstand <admin@wohlnet.ru>2017-10-25 15:21:22 +0300
committerWohlstand <admin@wohlnet.ru>2017-10-25 15:21:22 +0300
commit21180b02ab4146c43abc31484ab086b72104d8c5 (patch)
tree55b77e0a99c270ec766a3b2970c6604d1eeeaca4
parent43a4513ec794c2f5619c64f321af3cd0dd47ff4e (diff)
downloadlibADLMIDI-21180b02ab4146c43abc31484ab086b72104d8c5.tar.gz
libADLMIDI-21180b02ab4146c43abc31484ab086b72104d8c5.tar.bz2
libADLMIDI-21180b02ab4146c43abc31484ab086b72104d8c5.zip
Prevent possible going far far away after end of track memory block
This will prevent possible crash on attempt to parse wrong or damaged MIDI file
-rw-r--r--src/adlmidi_midiplay.cpp58
-rw-r--r--src/adlmidi_private.hpp6
2 files changed, 56 insertions, 8 deletions
diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp
index 071497c..84ff275 100644
--- a/src/adlmidi_midiplay.cpp
+++ b/src/adlmidi_midiplay.cpp
@@ -132,6 +132,7 @@ MIDIplay::MidiEvent::MidiEvent() :
type(T_UNKNOWN),
subtype(T_UNKNOWN),
channel(0),
+ isValid(1),
absPosition(0)
{}
@@ -232,7 +233,12 @@ bool MIDIplay::buildTrackData()
MidiTrackPos evtPos;
do
{
- event = parseEvent(&trackPtr, status);
+ event = parseEvent(&trackPtr, end, status);
+ if(!event.isValid)
+ {
+ //TODO: Implement file parsing error here
+ return false;
+ }
evtPos.events.push_back(event);
if(event.type == MidiEvent::T_SPECIAL && event.subtype == MidiEvent::ST_TEMPOCHANGE)
{
@@ -258,7 +264,7 @@ bool MIDIplay::buildTrackData()
trackDataNew[tk].push_back(evtPos);
evtPos.reset();
}
- } while(event.subtype != MidiEvent::ST_ENDTRACK);
+ } while((trackPtr <= end) && (event.subtype != MidiEvent::ST_ENDTRACK));
// Build the chain of events
//for(size_t i = 0, j = 1; i < trackDataNew[tk].size() && j < trackDataNew[tk].size(); i++, j++)
@@ -1420,15 +1426,28 @@ bool MIDIplay::ProcessEventsNew(bool isSeek)
return true;//Has events in queue
}
-MIDIplay::MidiEvent MIDIplay::parseEvent(uint8_t**pptr, int &status)
+MIDIplay::MidiEvent MIDIplay::parseEvent(uint8_t**pptr, uint8_t *end, int &status)
{
uint8_t *&ptr = *pptr;
MIDIplay::MidiEvent evt;
+
+ if(ptr + 1 > end)
+ {
+ evt.isValid = 0;
+ return evt;
+ }
+
unsigned char byte = *(ptr++);
+ bool ok = false;
if(byte == MidiEvent::T_SYSEX || byte == MidiEvent::T_SYSEX2)// Ignore SysEx
{
- uint64_t length = ReadVarLen(pptr);
+ uint64_t length = ReadVarLenEx(pptr, end, ok);
+ if(!ok || (ptr + length > end))
+ {
+ evt.isValid = 0;
+ return evt;
+ }
ptr += (size_t)length;
return evt;
}
@@ -1437,7 +1456,12 @@ MIDIplay::MidiEvent MIDIplay::parseEvent(uint8_t**pptr, int &status)
{
// Special event FF
uint8_t evtype = *(ptr++);
- uint64_t length = ReadVarLen(pptr);
+ uint64_t length = ReadVarLenEx(pptr, end, ok);
+ if(!ok || (ptr + length > end))
+ {
+ evt.isValid = 0;
+ return evt;
+ }
std::string data(length ? (const char *)ptr : 0, (size_t)length);
ptr += (size_t)length;
@@ -1489,6 +1513,11 @@ MIDIplay::MidiEvent MIDIplay::parseEvent(uint8_t**pptr, int &status)
//Sys Com Song Select(Song #) [0-127]
if(byte == MidiEvent::T_SYSCOMSNGSEL)
{
+ if(ptr + 1 > end)
+ {
+ evt.isValid = 0;
+ return evt;
+ }
evt.type = byte;
evt.data.push_back(*(ptr++));
return evt;
@@ -1497,6 +1526,11 @@ MIDIplay::MidiEvent MIDIplay::parseEvent(uint8_t**pptr, int &status)
//Sys Com Song Position Pntr [LSB, MSB]
if(byte == MidiEvent::T_SYSCOMSPOSPTR)
{
+ if(ptr + 2 > end)
+ {
+ evt.isValid = 0;
+ return evt;
+ }
evt.type = byte;
evt.data.push_back(*(ptr++));
evt.data.push_back(*(ptr++));
@@ -1515,9 +1549,21 @@ MIDIplay::MidiEvent MIDIplay::parseEvent(uint8_t**pptr, int &status)
case MidiEvent::T_NOTETOUCH:
case MidiEvent::T_CTRLCHANGE:
case MidiEvent::T_WHEEL:
- evt.data.push_back(*(ptr++)); /* fallthrough */
+ if(ptr + 2 > end)
+ {
+ evt.isValid = 0;
+ return evt;
+ }
+ evt.data.push_back(*(ptr++));
+ evt.data.push_back(*(ptr++));
+ return evt;
case MidiEvent::T_PATCHCHANGE://1 byte length
case MidiEvent::T_CHANAFTTOUCH:
+ if(ptr + 1 > end)
+ {
+ evt.isValid = 0;
+ return evt;
+ }
evt.data.push_back(*(ptr++));
return evt;
}
diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp
index d964e1e..83ac72e 100644
--- a/src/adlmidi_private.hpp
+++ b/src/adlmidi_private.hpp
@@ -356,8 +356,10 @@ private:
uint8_t subtype;
//! Targeted MIDI channel
uint8_t channel;
+ //! Is valid event
+ uint8_t isValid;
//! Reserved 5 bytes padding
- uint8_t __padding[5];
+ uint8_t __padding[4];
//! Absolute tick position (Used for the tempo calculation only)
uint64_t absPosition;
//! Raw data of this event
@@ -430,7 +432,7 @@ private:
std::vector<MidiTrackQueue > trackDataNew;
std::vector<int> trackDataNewStatus;
bool buildTrackData();
- MidiEvent parseEvent(uint8_t **ptr, int &status);
+ MidiEvent parseEvent(uint8_t **ptr, uint8_t *end, int &status);
public:
MIDIplay();