Devolutions / Devolutions/IronRDP
ironrdp-session: Bitmap rendering crashes and diagonal distortion when connecting to xRDP
- Dominant language
- Rust
- Stars
- 3.2k
- Forks
- 275
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 189
Description
### Description
When using IronRDP as a client to connect to [xRDP](https://github.com/neutrinolabs/xrdp) servers, two related issues occur in `ironrdp-session`:
1. **Diagonal bitmap distortion** — The rendered desktop appears as diagonally-shifted pixel rows, making the display unusable.
2. **Panic on out-of-bounds framebuffer writes** — `index out of bounds` panics occur during bitmap updates, particularly near framebuffer edges or during resolution changes.
Both issues are specific to the slow-path bitmap update code path (`fast_path.rs` bitmap handling + `image.rs` apply methods). RFX/progressive codec updates are unaffected.
### Root Cause
#### 1. Bitmap stride mismatch in `fast_path.rs`
xRDP (and other servers) commonly send `BitmapData` updates where the bitmap data dimensions (`bitmapWidth` × `bitmapHeight`) differ from the destination rectangle dimensions (`destRight - destLeft + 1` × `destBottom - destTop + 1`). Per [MS-RDPBCGR §2.2.9.1.1.3.1.2.2](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/84b2ec7a-7e0c-4261-b3c5-1d51afee9920), these are distinct fields:
- `bitmapWidth` / `bitmapHeight`: dimensions of the bitmap data (may include padding for alignment)
- `destLeft` / `destTop` / `destRight` / `destBottom`: destination rectangle on the framebuffer
Currently, `update.rectangle` (derived from the dest fields) is passed directly to the `apply_*` methods, which use the rectangle's width as the row stride for iterating over pixel data. When the bitmap data width differs from the rectangle width, pixels are read at incorrect offsets, producing a diagonal shearing artifact.
#### 2. Missing bounds checks in `image.rs`
Multiple `apply_*` methods (`apply_rgb16_bitmap`, `apply_rgb15_bitmap`, `apply_bgr24_bitmap`, `apply_rgb8_with_palette`, `apply_rgb24_iter`, `apply_rgb32_bitmap`) compute `dst_idx` from the update rectangle coordinates and write directly to `self.data[dst_idx..]` without verifying that `dst_idx` is within `self.data.len()`. When xRDP sends bitmap updates that extend beyond the framebuffer boundary (common during session startup or resize), this causes:
`panicked at ironrdp-session/src/image.rs:784:30: index out of bounds: the len is 8294400 but the index is 8300760`
### Reproduction
1. Set up an xRDP server (e.g., on Ubuntu with `xrdp` + `xfce4-session`)
2. Connect using any IronRDP-based client
3. Observe diagonal distortion on the login screen and subsequent desktop
4. Occasionally observe panics during initial bitmap updates
_Tested with xRDP 0.10.x on Ubuntu 22.04, IronRDP at commit [3fe6d15](https://github.com/amartyaa/IronRDP/commit/3fe6d157e0b55bddfdac20af290a6cfa6e550576)._
### Environment
- **IronRDP version**: `3fe6d15` (master)
- **RDP Server**: xRDP 0.10.x (Ubuntu 22.04)
- **Client platform**: WASM (wasm32-unknown-unknown) via `ironrdp-session`
- **Color depths affected**: 8bpp, 15bpp, 16bpp, 24bpp, 32bpp (all slow-path bitmap paths)
### Proposed Fix
[Fix bitmap stride mismatch and out-of-bounds writes for xRDP compatibility](https://github.com/Devolutions/IronRDP/pull/1252) #1252
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.