Skip to content

Validate malformed input packets before decoding#2024

Open
cmuellner wants to merge 6 commits into
mcallegari:masterfrom
cmuellner:pr-1955-fixes-p1
Open

Validate malformed input packets before decoding#2024
cmuellner wants to merge 6 commits into
mcallegari:masterfrom
cmuellner:pr-1955-fixes-p1

Conversation

@cmuellner
Copy link
Copy Markdown
Contributor

Description

Summary of Changes:

This PR fixes malformed-input reliability issues found while reviewing
stale PR #1955 and adjacent parser code.

The affected parsers now reject short or inconsistent input before
reading fixed fields or payload bytes. Well-formed input is handled as
before.

Commit Guide

Commit Origin Reproduction / coverage
Script: reject fixtures outside universe list Reported in PR #1955 Added a regression test in script_test for a fixture whose universe is absent from the runtime universe list.
Art-Net: reject packets with truncated fields Reported in PR #1955 Extended artnet_test with short ArtPollReply, ArtDMX and ArtTOD packets.
E1.31: validate DMX property value count Reported in PR #1955 Added e131packetizer_test coverage for missing start code, zero count, truncated payload and a valid packet.
OSC: reject truncated messages and bundle sizes Reported in PR #1955 Added oscpacketizer_test coverage for unterminated type tags, truncated string arguments, short bundle size fields and a valid bundle.
RDM: validate response length before decoding Derived while validating PR #1955 Extended artnet_test with short RDM headers, oversized or truncated PDL values, too-short PID payloads, and valid ACK responses.
DMX USB: validate Enttec input payload offsets Derived while validating PR #1955 No automated regression test exists for this device input path; a reviewer with compatible hardware can smoke-test normal DMX and MIDI input for regressions.

Testing

Automated Coverage:

The parser paths with in-tree harnesses are covered by:

  • script_test
  • artnet_test
  • e131packetizer_test
  • oscpacketizer_test

Result:

The added and extended tests pass locally.

Manual Testing Gaps

The Enttec DMX USB Pro input-path change is not covered by an
automated regression test because the current tree does not provide a
device-level test harness for that plugin.

A reviewer with compatible hardware can help confirm there is no
behavioral regression by connecting the device, enabling the DMX USB
plugin, and verifying that normal DMX input and MIDI input still work.

Additional Notes

The fixes are split into one commit per issue so individual parser
changes remain easy to review and bisect.

Each commit body contains the full rationale and reproduction details.

Checklist

  • I have read and followed the QLC+ Coding Guidelines.
  • My code adheres to the project's coding style, including:
    • Placing opening braces { on a new line for functions and class definitions.
    • Consistent use of spaces and indentation.
  • I have tested my changes on the following platforms:
    • Linux
    • Windows
    • macOS
  • I have added or updated documentation as necessary.

cmuellner added 6 commits May 14, 2026 08:15
Origin: reported in PR mcallegari#1955.

The regression test creates a fixture on universe 1, then calls
`setfixture` with a runtime universe list that only contains universe
0. Before this fix, `handleSetFixture()` indexed `universes[1]` and
could read past the list.

Reject the command before requesting a fader when the fixture universe
is not present in the runtime universe list. This keeps malformed or
inconsistent projects from crashing script playback.

Added a regression test in `script_test` for a fixture whose universe
is missing from the runtime universe list.

Signed-off-by: Christoph Müllner <christophm30@gmail.com>
Origin: reported in PR mcallegari#1955.

The regression test covers protocol inputs rather than GUI steps: a
186-byte ArtPollReply, a short ArtDMX packet, an ArtDMX packet whose
length field exceeds the datagram, and a TOD packet with `uidCount` 1
but no UID bytes. These inputs previously reached fixed-offset reads or
accepted an incomplete UID list.

Validate the minimum ArtPollReply size, the ArtDMX fixed header and
advertised payload length, and the TOD UID list length before decoding.

Extended `artnet_test` to cover short ArtPollReply, short ArtDMX,
truncated ArtDMX payload, and truncated TOD UID list packets.

Signed-off-by: Christoph Müllner <christophm30@gmail.com>
Origin: reported in PR mcallegari#1955.

The regression test covers protocol inputs rather than GUI steps: a
125-byte packet missing the DMX start code, a zero property value count,
and a packet whose count exceeds the remaining datagram. Before this
fix, `checkPacket()` accepted the missing-start-code packet and
`fillDMXdata()` could read byte 125 or underflow `length - 1`.

Require the start-code byte before accepting an E1.31 DMX packet, then
reject zero, oversized, or truncated property value counts before
copying DMX slots.

Added `e131packetizer_test` to cover a missing start code, zero
property value count, truncated payload, and a valid packet.

Signed-off-by: Christoph Müllner <christophm30@gmail.com>
Origin: reported in PR mcallegari#1955.

The regression test covers protocol inputs rather than GUI steps: an
OSC message whose type-tag list has no NUL terminator, a message whose
string argument is missing its NUL terminator, and a bundle with a valid
first message followed by a trailing 3-byte message-size field. Before
this fix, parseMessage() could scan past the message buffer or accept a
truncated argument, and the bundle parser could read bufPos + 3 past the
packet.

Stop type-tag and string-argument scanning at the buffer end. Reject
fixed-size arguments whose bytes are not fully present, and require four
bytes before reading each bundled message size.

Added oscpacketizer_test to cover unterminated type tags, truncated
string arguments, short bundle size fields, and a valid bundled
message.

Signed-off-by: Christoph Müllner <christophm30@gmail.com>
Origin: derived while validating PR mcallegari#1955.

The regression test uses protocol inputs in artnet_test: a one-byte
RDM start-code packet, a 22-byte fixed header, a packet whose PDL claims
21 bytes without carrying that payload, and a DEVICE_INFO response whose
valid checksum covers a too-short PID payload. Before this fix,
parsePacket() could read the sub-start code, fixed response fields, or
PID-specific payload beyond the reply buffer or beyond the declared
PDL.

Validate the fixed response header before decoding fields, then require
PDL bytes plus the checksum before entering PID-specific parsing. Reject
PID payloads that are too short for fixed-field decoders, and decode the
19-byte DEVICE_INFO sensor-count field at its protocol offset.

Extended artnet_test to cover short RDM headers, truncated PDL payloads,
too-short PID payloads, and valid RDM packets.

Signed-off-by: Christoph Müllner <christophm30@gmail.com>
Origin: derived while validating PR mcallegari#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>
@coveralls
Copy link
Copy Markdown

Coverage Status

coverage: 35.646% (+0.6%) from 35.037% — cmuellner:pr-1955-fixes-p1 into mcallegari:master

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants