You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Part of #1120. This issue is an egfx-scoped child of the main fuzzing umbrella, focusing on the codec-pipeline depth specific to MS-RDPEGFX. It sits alongside #1122 (Arbitrary impls) and #1124 (advanced fuzz targets) under the #1120 umbrella, not as a parallel framing.
Why a separate child issue rather than comments on #1120
#1120 is broad and workspace-wide. The egfx-specific fuzz coverage gaps below are six concrete targets across four oracle classes, scoped to one crate's codec pipeline. That is enough scope to warrant its own tracking surface as a child issue rather than getting buried in #1120's comment thread (where our 2026-05-18 issuecomment-4483012331 on the ZGFX + memory-budget question is currently sitting).
Background
PR #1271 (merged 2026-05-25) extended the pdu_decode oracle in crates/ironrdp-fuzzing/src/oracles/mod.rs to include egfx wire-PDU types: GfxPdu, CacheToSurfacePdu, EgfxRawCapabilitySet, Avc420BitmapStream<'_>, Avc444BitmapStream<'_>, QuantQuality, Point, Color, CapabilitiesAdvertisePdu. Two real bugs surfaced and were fixed in-PR (Avc444BitmapStream::decodesplit_at panic on malformed streamLen; Avc420BitmapStream::decodeVec::with_capacity(num_regions) ASan OOM on attacker-controlled u32).
PR #1291 (merged 2026-05-25) added pdu_round_trip for ironrdp-pdu types, but did not extend into ironrdp-egfx's own encoders.
The result is that egfx is fuzzed at the wire-PDU-decode layer but the pipeline below that is not. The unfuzzed areas are below.
Filing per-target PRs will follow as the work lands; this issue tracks the set.
egfx_avc420_decode — fuzz the wrapper layer that takes a decoded Avc420BitmapStream's bitmap_data and feeds it to H264Decoder::decode(&[u8]). OpenH264 itself is fuzzed by OSS-Fuzz; the IronRDP wrapper is not. Target: the input-construction code including any Annex B vs AVC-length-prefix conversion and any frame-header munging. Catches: panics in the wrapper, OOM via attacker-controlled chunking, contract violations in H264Decoder trait callers.
egfx_avc444_decode — same shape, MS-RDPEGFX 2.2.4.4 luma/chroma split. AVC444 has the auxiliary chroma stream and a tagged dispatch that AVC420 does not; merits a separate target.
egfx_zgfx_decompress — ZGFX is distinct from ironrdp-bulk's MPPC/NCRUSH/XCRUSH; lives in crates/ironrdp-graphics/src/zgfx/. No fuzz target today. Raised in our 2026-05-18 issuecomment-4483012331 on Advanced fuzzing with arbitrary #1120 as still-TODO. Decompression bombs and corrupted-history paths are the high-value catches.
egfx_multi_frame — the workspace currently has no multi-frame oracle pattern (per configs/ironrdp.md codec_pr_requirements). H.264 decoding maintains reference-picture state, SPS/PPS context, and decoder configuration across frames. Surface caching, frame acks, and codec state in egfx all carry forward. Single-shot fuzzers cannot find frame-to-frame state corruption. First codec to require it lands the pattern.
The codec memory-budget oracle remains the shape question raised in our 2026-05-18 issuecomment-4483012331 on #1120. Once that shape is settled, targets 3 (ZGFX) and the H.264 wrapper targets (1, 2) gain memory-budget oracles. Landing the targets above does not strictly require the memory-budget oracle answer (the targets work as panic/sanitizer-only oracles in the interim).
egfx_avc420_decode + egfx_avc444_decode (targets 1, 2) target the highest-value attack surface (H.264 wrapper) but require careful design around OpenH264's stateful decoder. Second pass.
egfx_zgfx_decompress (target 3) is closed-form in shape (similar to bulk_* targets) but has the open memory-budget oracle question.
egfx_multi_frame (target 5) establishes the workspace pattern for multi-PDU state-carrying oracles. Largest design work; expected via a dedicated PR with a separate design doc.
We have downstream consumer interest in egfx via lamco-rdp-server and lamco-rdp-wasm. We will drive the per-target PRs ourselves, scoped per the sequencing above. Filing as a child issue under #1120 so the workspace has a public tracking surface and per-target PRs can reference it back.
Open question on parent: our 2026-05-18 issuecomment-4483012331 on Advanced fuzzing with arbitrary #1120 (ZGFX + memory-budget shape, pending response)
Part of #1120. This issue is an egfx-scoped child of the main fuzzing umbrella, focusing on the codec-pipeline depth specific to MS-RDPEGFX. It sits alongside #1122 (Arbitrary impls) and #1124 (advanced fuzz targets) under the #1120 umbrella, not as a parallel framing.
Why a separate child issue rather than comments on #1120
#1120 is broad and workspace-wide. The egfx-specific fuzz coverage gaps below are six concrete targets across four oracle classes, scoped to one crate's codec pipeline. That is enough scope to warrant its own tracking surface as a child issue rather than getting buried in #1120's comment thread (where our 2026-05-18
issuecomment-4483012331on the ZGFX + memory-budget question is currently sitting).Background
PR #1271 (merged 2026-05-25) extended the
pdu_decodeoracle incrates/ironrdp-fuzzing/src/oracles/mod.rsto include egfx wire-PDU types:GfxPdu,CacheToSurfacePdu,EgfxRawCapabilitySet,Avc420BitmapStream<'_>,Avc444BitmapStream<'_>,QuantQuality,Point,Color,CapabilitiesAdvertisePdu. Two real bugs surfaced and were fixed in-PR (Avc444BitmapStream::decodesplit_atpanic on malformedstreamLen;Avc420BitmapStream::decodeVec::with_capacity(num_regions)ASan OOM on attacker-controlled u32).PR #1291 (merged 2026-05-25) added
pdu_round_tripforironrdp-pdutypes, but did not extend intoironrdp-egfx's own encoders.The result is that egfx is fuzzed at the wire-PDU-decode layer but the pipeline below that is not. The unfuzzed areas are below.
Coverage gaps
encode_avc420_bitmap_streametc.)Proposed fuzz targets
Filing per-target PRs will follow as the work lands; this issue tracks the set.
egfx_avc420_decode— fuzz the wrapper layer that takes a decodedAvc420BitmapStream'sbitmap_dataand feeds it toH264Decoder::decode(&[u8]). OpenH264 itself is fuzzed by OSS-Fuzz; the IronRDP wrapper is not. Target: the input-construction code including any Annex B vs AVC-length-prefix conversion and any frame-header munging. Catches: panics in the wrapper, OOM via attacker-controlled chunking, contract violations inH264Decodertrait callers.egfx_avc444_decode— same shape, MS-RDPEGFX 2.2.4.4 luma/chroma split. AVC444 has the auxiliary chroma stream and a tagged dispatch that AVC420 does not; merits a separate target.egfx_zgfx_decompress— ZGFX is distinct fromironrdp-bulk's MPPC/NCRUSH/XCRUSH; lives incrates/ironrdp-graphics/src/zgfx/. No fuzz target today. Raised in our 2026-05-18issuecomment-4483012331on Advanced fuzzing witharbitrary#1120 as still-TODO. Decompression bombs and corrupted-history paths are the high-value catches.egfx_round_trip— encoder/decoder symmetry forironrdp-egfx's own encoders (encode_avc420_bitmap_stream,Avc420Region::encode, the new server-encode paths from PR feat(graphics,egfx): add progressive RFX server encode and mixed-codec frames #1198). Same shape as PR test(fuzz): add pdu_round_trip oracle and target #1291'spdu_round_tripbut scoped to egfx encoders. Maps to Add advanced fuzz targets to verify more invariants (round-trip, framing, state-machine…) #1124's task 1 (round_trip) extended into egfx. Catches the same class of bug PR fix(pdu): cover BitmapCacheV3 in CapabilitySet encoder #1313 fixed inironrdp-pdu'sCapabilitySetencoder (decoder-accepted variant missing from encoder match).egfx_multi_frame— the workspace currently has no multi-frame oracle pattern (perconfigs/ironrdp.mdcodec_pr_requirements). H.264 decoding maintains reference-picture state, SPS/PPS context, and decoder configuration across frames. Surface caching, frame acks, and codec state in egfx all carry forward. Single-shot fuzzers cannot find frame-to-frame state corruption. First codec to require it lands the pattern.egfx_surface_state— state-machine fuzzing for the surface lifecycle (CreateSurface/ResetGraphics/WireToSurface1/MapSurfaceToWindowPdu/DeleteSurfaceorderings + cache state transitions). Maps to Add advanced fuzz targets to verify more invariants (round-trip, framing, state-machine…) #1124's task 3 (connector_state_machine) narrowed to egfx surface state.Memory-budget oracle (cross-cutting)
The codec memory-budget oracle remains the shape question raised in our 2026-05-18
issuecomment-4483012331on #1120. Once that shape is settled, targets 3 (ZGFX) and the H.264 wrapper targets (1, 2) gain memory-budget oracles. Landing the targets above does not strictly require the memory-budget oracle answer (the targets work as panic/sanitizer-only oracles in the interim).Sequencing
egfx_round_trip(target 4) is the smallest and most closed-form (mirrors PR test(fuzz): add pdu_round_trip oracle and target #1291's shape). Best to land first.egfx_avc420_decode+egfx_avc444_decode(targets 1, 2) target the highest-value attack surface (H.264 wrapper) but require careful design around OpenH264's stateful decoder. Second pass.egfx_zgfx_decompress(target 3) is closed-form in shape (similar tobulk_*targets) but has the open memory-budget oracle question.egfx_multi_frame(target 5) establishes the workspace pattern for multi-PDU state-carrying oracles. Largest design work; expected via a dedicated PR with a separate design doc.egfx_surface_state(target 6) maps to Add advanced fuzz targets to verify more invariants (round-trip, framing, state-machine…) #1124 task 3 and may be better tracked there once that task is factored.Lamco-shaped commitment
We have downstream consumer interest in egfx via lamco-rdp-server and lamco-rdp-wasm. We will drive the per-target PRs ourselves, scoped per the sequencing above. Filing as a child issue under #1120 so the workspace has a public tracking surface and per-target PRs can reference it back.
Provenance
arbitrary#1120 (main fuzzing umbrella)Arbitraryfor more PDU structs #1122 (Arbitrary impls), Add advanced fuzz targets to verify more invariants (round-trip, framing, state-machine…) #1124 (advanced fuzz targets), CI: compile/test a feature matrix includingarbitrary(std/no_std) #1123 (CI feature matrix, impl complete via PR ci: addcheck featuresmatrix gate with dynamic CI fan-out #1283)pdu_round_triporacle pattern, the reference shape for target 4 extended to egfx)bulk_*fuzz targets, the reference shape for target 3)CapabilitySetencoder fix; reference for the bug class target 4 catches)issuecomment-4483012331on Advanced fuzzing witharbitrary#1120 (ZGFX + memory-budget shape, pending response)