fix(graphics): decode Progressive SRL refinements - #1696
Conversation
Preserve SRL and raw-bit state across Progressive DWT bands. Reject malformed SRL refinement streams instead of decoding invented zero data.
There was a problem hiding this comment.
Pull request overview
Fixes Progressive RemoteFX refinement decoding by preserving SRL and raw-bit state across DWT bands.
Changes:
- Adds stateful, fallible SRL encoding and decoding.
- Preserves component streams across bands and propagates SRL errors.
- Adds malformed-stream and cross-band tests.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
crates/ironrdp-graphics/src/srl.rs |
Implements stateful SRL codecs and validation. |
crates/ironrdp-graphics/src/progressive.rs |
Integrates stateful streams into progressive upgrades. |
There was a problem hiding this comment.
Rewrite of the Progressive codec's SRL entropy coder and TILE_UPGRADE pass into stateful SrlDecoder/SrlEncoder carrying KP and zero-run state across DWT bands, plus fixes to raw-bit continuity, Sign=0 coefficient accumulation, and rejection of malformed/truncated SRL streams via a new SrlError. I independently traced the bit-level logic against the MS-RDPEGFX worked examples cited in the protocol handoff and confirmed each mapped change behaves as claimed; encoder and decoder are symmetric, and has_srl_values gating matches on both sides. The Result-returning signature changes have no other call sites in the workspace beyond the two files reviewed and a single ?-propagating caller, consistent with existing RlgrError handling in this module. No blocking defects found; two minor non-blocking observations below.
Protocol analysis: accepted — Manually re-derived bit sequences for the cited MS-RDPEGFX examples (KP=8 init/escape decoding, unterminated max-magnitude unary decode, cross-band zero-run/KP continuity, cross-band raw-bit continuity, Sign=0 accumulation, LL3 always-raw exclusion) against the code and its own test vectors; all seven change_mappings hold up as conforming. The MAX_ZERO_RUN=4096 potential_discrepancy is accurate but not a functional defect: it is looser than the true eligible-coefficient bound (4096 minus 64 LL3), so it cannot reject conformant data. No additional material protocol concerns found.
Stage component refinements before committing an upgrade pass. Reuse zero counts across SRL decoding bands.
There was a problem hiding this comment.
Well-scoped, protocol-conformant fix. It rewrites the SRL codec as stateful decoder/encoder types that persist zero-run/KP state and bit position across DWT bands, fixes zero-DAS accumulation to add rather than overwrite (matching MS-RDPEGFX 3.3.8.2.1.2), excludes LL3 from SRL entirely, and makes malformed/truncated SRL streams a hard error that leaves TileState untouched (staged local copies committed only after all three components decode). Tests trace the algorithm against the spec's worked examples and cover the new cross-band and rollback behavior. One residual inconsistency (raw-bit truncation still silently zero-fills while SRL truncation now errors) is real but pre-existing/out of scope for this fix.
Protocol analysis: accepted — Independently traced the shared SrlDecoder/RawBitReader across bands, the accumulate-vs-overwrite fix, the new !is_ll3 guard excluding LL3 from SRL, and TileState::decode_upgrade's stage-then-commit rollback, plus the zero-run/unary state machines, against the cited MS-RDPEGFX sections. All match the handoff's conformance calls; the tests exercise exactly the scenarios it flagged as valuable. The flagged RawBitReader-vs-SrlDecoder truncation-handling discrepancy is confirmed still present, but RawBitReader is untouched by this diff so it is reasonably follow-up, not a defect in this change.
- question / low — crates/ironrdp-graphics/src/srl.rs
SrlDecoder::new rejects a stream whose trailing byte is absent or non-zero with MissingTerminator, but MS-RDPEGFX 3.1.8.1.5 states only that a conformant encoder always appends the zero terminator, without explicitly mandating decoder rejection of its absence. Given this crate's public API and that ironrdp is a client decoding server-sent data, was this intentionally chosen as defensive hardening rather than a spec-mandated decoder requirement? The rejects_missing_terminator test only documents the chosen behavior, not the rationale.
7824bc7
into
master
Preserve SRL and raw-bit state across Progressive DWT bands.
Reject malformed SRL refinement streams without decoding invented zero data or partially updating tiles.