Hi!
We had some problems with malformed sysex messages hanging our midi-thread. After some snooping around, it seems that a malformed sysex message causes juce to perpetually parse the incoming midi stream as a mesage, until the sysex finished byte (0xf7) is received.
Looking at the midi specification, any data bytes in the sysex message should not have it's 7th bit set. This is checked in Juce_MidiDataConcenator.h: (from juce git, starting from line 124)
if (pendingBytes > 0 && *d >= 0x80)
{
if (*d >= 0xfa || *d == 0xf8)
{
callback.handleIncomingMidiMessage (input, MidiMessage (*d, time));
++d;
--numBytes;
}
else
{
if (*d == 0xf7)
{
*dest++ = *d++;
pendingBytes++;
--numBytes;
}
break;
}
}
else
{
*dest++ = *d++;
pendingBytes++;
--numBytes;
}
There are checks for midi start and midi clock (0xfa and 0xf8), but other other midi messages don't stop the parsing of the sysex.
To solve this, i added an else statement for these other bytes. Here is my code (it's not really from the tip, a bit behind):
if (pendingBytes > 0 && *d >= 0x80)
{
if (*d >= 0xfa || *d == 0xf8)
{
callback.handleIncomingMidiMessage (input, MidiMessage (*d, time));
++d;
--numBytes;
pendingBytes = 0; // don't process sysex after wierdness.
}
else
{
if (*d == 0xf7)
{
*dest++ = *d++;
pendingBytes++;
--numBytes;
}
#pragma MODIFIED_BY_RESOLUME // added else statement: data bytes with bit 7 are malformed, quit parsing
else
{
Logger::writeToLog("Illegal sysex data with bit 7 set, stopping parse..");
int used = 0;
const MidiMessage m (d, numBytes, used, 0, time);
if (used <= 0)
break; // malformed message..
callback.handleIncomingMidiMessage (input, m);
numBytes -= used;
d += used;
pendingBytes = 0; // don't process sysex after wierdness.
}
}
}
I hope it is of use to someone.
Cheers,
Tim
