Skip to content

fix(pdu): keep the packed byte of RLEX segments when the palette has a single entry - #1903

Open
Adrien CROS (AdrienAvalon) wants to merge 3 commits into
Devolutions:masterfrom
AdrienAvalon:fix/rlex-single-palette-packed-byte
Open

fix(pdu): keep the packed byte of RLEX segments when the palette has a single entry#1903
Adrien CROS (AdrienAvalon) wants to merge 3 commits into
Devolutions:masterfrom
AdrienAvalon:fix/rlex-single-palette-packed-byte

Conversation

@AdrienAvalon

Copy link
Copy Markdown

Closes #1902.

decode_rlex special-cased a one-entry palette (stop_index_bits = 0, bare run lengths). Per MS-RDPEGFX 2.2.4.6.2.2 and FreeRDP's clear_decompress_subcode_rlex (CLEAR_LOG2_FLOOR[0] == 0), stopIndex still takes one bit in that case and every segment keeps its packed byte. The shortcut read every run length one byte off and rejected the one-colour regions Windows Server uses for the solid corners of its taskbar (14×64, 64×46) with "suite exceeds region pixel count".

This PR gives stopIndex one bit for a single entry, removes the special path, and adds a test decoding such a 14×64 region (a run of 895 on a 16-bit length plus a suite of one). No encoder emitted the old form. cargo test -p ironrdp-pdu rlex: 8 passed.

Shipped in avash's vendored ironrdp-pdu since 0.7.1, verified against Windows Server 2025 with the recorded session that exposed it.

…a single entry

MS-RDPEGFX 2.2.4.6.2.2 gives stopIndex floor(log2(paletteCount - 1)) + 1
bits; with a single palette entry FreeRDP's CLEAR_LOG2_FLOOR table yields
0, so stopIndex still takes one bit and every segment keeps its packed
byte. The single-entry shortcut read bare run lengths instead, one byte
off, and failed with "suite exceeds region pixel count" on the solid
taskbar corners Windows Server encodes this way (14x64, 64x46).

Closes Devolutions#1902
@github-actions github-actions Bot added kind/protocol Affects RDP or related protocol behavior maintainer-required Maintainer review or intervention is required risk/medium Behavioral change that does not substantially alter a core public API scope/core Touches the core architectural tier size/S Size: up to 199 counted lines and 5 files; exceeds XS in either measure labels Sep 4, 2026
@CBenoit
Benoît Cortier (CBenoit) requested a balanced review from Copilot September 4, 2026 20:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The full test suite fails because an existing one-entry RLEX fixture was not updated.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Fixes single-entry RLEX palette decoding by preserving the mandatory packed segment byte.

Changes:

  • Uses one stopIndex bit for single-entry palettes.
  • Removes the obsolete bare-run decoder path.
  • Adds a Windows Server regression test.
File summaries
File Review
crates/ironrdp-pdu/src/codecs/clearcodec/rlex.rs Corrects RLEX parsing. The existing subcodec fixture must include the packed byte and updated bitmap length. Renaming the helper to decode_segments is a non-blocking nit.
Review details

Suppressed comments (1)

crates/ironrdp-pdu/src/codecs/clearcodec/rlex.rs:87

  • Now that this path also handles one-entry palettes, decode_multi_palette_segments no longer describes the helper's responsibility. Rename it to decode_segments so future changes do not mistakenly assume the helper is only valid for multi-entry palettes.
    decode_multi_palette_segments(
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Balanced

&mut segments,
)?;
}
decode_multi_palette_segments(

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking. On this branch cargo test -p ironrdp-pdu passes (423 tests, and the CI checks are green): decode_subcodec_layer only records each region with its codec id and never runs the RLEX decoder on it, so this fixture was not parsed. It did still describe the old encoding, so 399ea8c makes it a valid one-entry RLEX stream (bitmap length 6, a zero packed byte before the run length), as you suggested.

The subcodec layer only records the region and its codec id, so this
fixture is never parsed by the RLEX decoder and the test kept passing.
It still documented the old, incorrect encoding (no packed byte when the
palette has a single entry); make it match what the decoder now expects
so the fixture stays a valid RLEX stream.
Comment thread crates/ironrdp-pdu/src/codecs/clearcodec/subcodec.rs Outdated

@CBenoit Benoît Cortier (CBenoit) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@github-actions

Copy link
Copy Markdown
Contributor

Automated review will not run because this contributor is not yet eligible under the automation policy.

Contributors become eligible after one qualifying IronRDP pull request is merged into master. Maintainer review is required.

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

Labels

kind/protocol Affects RDP or related protocol behavior maintainer-required Maintainer review or intervention is required risk/medium Behavioral change that does not substantially alter a core public API scope/core Touches the core architectural tier size/S Size: up to 199 counted lines and 5 files; exceeds XS in either measure

Development

Successfully merging this pull request may close these issues.

clearcodec: RLEX regions with a single palette entry are parsed without their packed byte

3 participants