Skip to content

Commit 11dd00f

Browse files
committed
DMX USB: validate Enttec input payload offsets
Origin: derived while validating PR #1955. The payload-length guard was found while reviewing the same Enttec input parsing path. Feed the Enttec DMX USB Pro input path a receive-DMX packet with a payload length of 0 or 1, or a MIDI input packet ending with an incomplete command. The DMX branch read the status and start-code bytes without proving they existed, and the MIDI branch read data bytes at i + 1 and i + 2 for a truncated final command. The DMX branch also derived its slot-data slice from packet.size(). That is equivalent for well-formed packets, but using the validated payload offset makes the relationship to the decoded header explicit and keeps the malformed-payload checks localized. Reject malformed DMX payloads before decoding fixed fields, copy DMX data from the validated payload offset, and ignore a trailing incomplete MIDI command. No automated regression test exists for this device input path. Signed-off-by: Christoph Müllner <christophm30@gmail.com>
1 parent 0d4a246 commit 11dd00f

1 file changed

Lines changed: 50 additions & 7 deletions

File tree

plugins/dmxusb/src/enttecdmxusbpro.cpp

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,13 @@ int EnttecDMXUSBPro::readData(QByteArray &payload, bool &isMIDI, int RDM)
526526
isMIDI = false;
527527
int offset = 4;
528528

529+
if (dataLen < 1 || (RDM == None && dataLen < 2))
530+
{
531+
qWarning() << Q_FUNC_INFO << "Malformed DMX packet payload length:" << dataLen;
532+
startIdx = buffer.indexOf(ENTTEC_PRO_START_OF_MSG);
533+
continue;
534+
}
535+
529536
uchar status = static_cast<uchar>(packet[offset++]);
530537
if (status & 0x01)
531538
qWarning() << Q_FUNC_INFO << "Widget receive queue overflowed";
@@ -544,7 +551,7 @@ int EnttecDMXUSBPro::readData(QByteArray &payload, bool &isMIDI, int RDM)
544551
dataLen -= 1;
545552
}
546553

547-
payload = packet.mid(packet.size() - 1 - dataLen, dataLen);
554+
payload = packet.mid(offset, dataLen);
548555
return payload.size();
549556
}
550557

@@ -990,15 +997,51 @@ void EnttecDMXUSBPro::run()
990997

991998
for (int i = 0; i < length;)
992999
{
993-
if (!MIDI_IS_CMD(data[i]))
1000+
uchar midiCmd = data[i];
1001+
if (!MIDI_IS_CMD(midiCmd))
9941002
{
9951003
i++;
9961004
continue;
9971005
}
9981006

999-
uchar midiCmd = data[i];
1000-
uchar midiData1 = data[i + 1];
1001-
uchar midiData2 = data[i + 2];
1007+
if (midiCmd == MIDI_SYSEX)
1008+
break;
1009+
1010+
bool isBeatCommand = midiCmd >= MIDI_BEAT_CLOCK && midiCmd <= MIDI_BEAT_STOP;
1011+
int msgLength = 3;
1012+
if (isBeatCommand)
1013+
msgLength = 1;
1014+
else if (MIDI_CMD(midiCmd) == MIDI_PROGRAM_CHANGE ||
1015+
MIDI_CMD(midiCmd) == MIDI_CHANNEL_AFTERTOUCH)
1016+
msgLength = 2;
1017+
1018+
if (i + msgLength > length)
1019+
break;
1020+
1021+
uchar midiData1 = 0;
1022+
uchar midiData2 = 0;
1023+
if (msgLength > 1)
1024+
{
1025+
if (MIDI_IS_CMD(data[i + 1]))
1026+
{
1027+
i++;
1028+
continue;
1029+
}
1030+
midiData1 = data[i + 1];
1031+
}
1032+
if (msgLength > 2)
1033+
{
1034+
if (MIDI_IS_CMD(data[i + 2]))
1035+
{
1036+
i++;
1037+
continue;
1038+
}
1039+
midiData2 = data[i + 2];
1040+
}
1041+
else if (MIDI_CMD(midiCmd) == MIDI_PROGRAM_CHANGE)
1042+
{
1043+
midiData2 = 127;
1044+
}
10021045

10031046
//qDebug() << "CMD" << midiCmd << "DATA1" << midiData1 << "DATA2" << midiData2;
10041047

@@ -1009,11 +1052,11 @@ void EnttecDMXUSBPro::run()
10091052
{
10101053
emit valueChanged(UINT_MAX, emitLine, channel, value);
10111054

1012-
if (midiCmd >= MIDI_BEAT_CLOCK && midiCmd <= MIDI_BEAT_STOP)
1055+
if (isBeatCommand)
10131056
emit valueChanged(UINT_MAX, emitLine, channel, 0);
10141057
}
10151058

1016-
i += 3;
1059+
i += msgLength;
10171060
}
10181061
}
10191062
}

0 commit comments

Comments
 (0)