fix(session): Fix bitmap stride mismatch and out-of-bounds writes for xRDP compatibility#1252
fix(session): Fix bitmap stride mismatch and out-of-bounds writes for xRDP compatibility#1252Amartya Anshuman (amartyaa) wants to merge 4 commits into
Conversation
|
Thanks for the report and the fix Amartya Anshuman (@amartyaa). The stride insight is correct: MS-RDPBCGR §2.2.9.1.1.3.1.2.2 does distinguish A few suggestions a reviewer is likely to raise: 1. Horizontal over-paint when 2. Tests. A regression test for the stride case (construct a known-pattern bitmap whose data width differs from the destination width, call 3. Inconsistent bounds-check operators. Five sites use 4. Silent clipping vs Downstream context: this is relevant to Lamco's xRDP interop testing. Our test fleet uses xRDP 0.10.x on Ubuntu as a non-Windows comparison server, and IronRDP clients connecting there hit the diagonal-distortion symptom you describe. A version of this fix landing upstream would resolve a recurring noise item in our fleet runs. If a revised version lands, I can run it through our xRDP test fleet to confirm. |
|
Hello Greg Lamberson (@glamberson) !!
Happy to iterate further. Looking forward to Lamco's xRDP fleet results once this lands! |
There was a problem hiding this comment.
Pull request overview
Fixes diagonal bitmap shearing and out-of-bounds panics observed when ironrdp-session connects to xRDP servers, which send BitmapData whose pixel dimensions (update.width/update.height) don't match the destination rectangle. The fix derives a blit_rect whose size is the per-spec clip of bitmap-data vs. destination-rect dimensions and routes all apply_* calls through it, plus adds per-pixel/per-slice bounds guards in image.rs and enables unit tests for the crate.
Changes:
- In
fast_path.rs::process_bitmap_update, build ablit_rectfrommin(update.width, rect.width)/min(update.height, rect.height)and pass it to everyapply_*path instead ofupdate.rectangle. - In
image.rs, adddebug_assert!+if dst_idx + DST_COLOR_DEPTH <= self.data.len()per-pixel guards to all slow-path apply methods, amax_rowsclamp inapply_rgb24_iter, and a silent clamp indata_for_rect; also add atestsmodule covering rgb32 placement, rgb16 in-bounds writes, oversize rect rejection, anddata_for_rectclamping. - In
ironrdp-session/Cargo.toml, comment outtest = falseto enable the new unit tests.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
crates/ironrdp-session/src/fast_path.rs |
Introduces clipped blit_rect and routes all apply_* calls through it to fix stride/shearing. |
crates/ironrdp-session/src/image.rs |
Adds redundant-with-rect_fits per-pixel guards, clamps data_for_rect, and adds a unit-test module. |
crates/ironrdp-session/Cargo.toml |
Comments out test = false to allow the new tests to run. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -844,7 +863,9 @@ impl DecodedImage { | |||
| .for_each(|(col_idx, src_pixel)| { | |||
| let dst_idx = ((top + row_idx) * image_width + left + col_idx) * DST_COLOR_DEPTH; | |||
|
|
|||
|
Hi Amartya Anshuman (@amartyaa), your four points are addressed cleanly. The Copilot's follow-up review has some substantive items worth working through. In particular, the asymmetric-clipping note at I'll run the patched version against our xRDP 0.10.x test fleet once you've worked through Copilot's review; running against an in-flight revision wouldn't tell us much about the final shape. Should take 1-2 days from your next push. |
e0e2d0a to
b7fdb8e
Compare
* fix: minor code quality changes * fix: formatting fixed * fix: Lint Issues fixed
|
Hello Greg Lamberson (@glamberson)! I think all the points are covered now. |
Fixes #1251
Summary
This PR fixes two related issues in
ironrdp-sessionthat cause diagonal bitmap distortion and index-out-of-bounds panics when connecting to xRDP servers.Changes
crates/ironrdp-session/src/fast_path.rsxRDP sends bitmap updates where the data dimensions (
update.width×update.height) differ from the destination rectangle (update.rectangle). Per MS-RDPBCGR §2.2.9.1.1.3.1.2.2,bitmapWidth/bitmapHeightdefine the pixel data layout whiledestLeft/destTop/destRight/destBottomdefine the screen placement.The
apply_*methods use the rectangle's width as the row stride. Passingupdate.rectanglewhen it's wider/narrower than the actual data causes diagonal shearing.Fix: Construct a
blit_rectwhose dimensions match the actual bitmap data, positioned at the destination's top-left corner:crates/ironrdp-session/src/image.rsAdded bounds checks to all apply_* bitmap methods that were missing them:
Each pixel write is now guarded with
if dst_idx + bytes_per_pixel < self.data.len().This is consistent with how other parts of the codebase handle edge-of-framebuffer updates — pixels beyond the buffer are silently clipped rather than panicking.
Also added a
max_rowsclamp inapply_rgb24_iterto prevent iterating beyond the framebuffer height.Testing