mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-08 05:20:59 +03:00
drm: validate cursor body length and coalesce _drm frames to latest-wins (review 4.1, 4.8)
4.1: the DrmCursor consumer handed the wire body straight to the client, which renders width*height*4 RGBA bytes. Reject a body shorter than that so a truncated cursor cannot make the client read past the buffer. The hidden-cursor sentinel is 0x0 with an empty body, for which the bound is 0 and the check is a no-op. 4.8: the _drm socket is a FIFO, so a consumer that drains slower than we produce (a 4K convert on a modest GPU) fell seconds behind stale frames. Drain the producer channel without blocking each tick and forward only the newest frame; replaced frames drop in place, closing the zero-copy OwnedFd and freeing the CPU-path pixel buffer. Cursor updates stay in order and are never coalesced away.
This commit is contained in:
@@ -375,20 +375,37 @@ async fn recv_thread(
|
||||
height,
|
||||
hotx,
|
||||
hoty,
|
||||
} => match conn.next_raw().await {
|
||||
Ok(raw) => set_drm_cursor(
|
||||
display,
|
||||
DrmCursorData {
|
||||
id,
|
||||
width: width as i32,
|
||||
height: height as i32,
|
||||
hotx,
|
||||
hoty,
|
||||
colors: raw.to_vec(),
|
||||
},
|
||||
),
|
||||
Err(err) => break format!("cursor body: {err}"),
|
||||
},
|
||||
} => {
|
||||
// get_cursor_data() hands `colors` straight to the client, which renders
|
||||
// width*height*4 RGBA bytes. Require the body to carry at least that many so a short
|
||||
// body cannot make the client read past the buffer. A hidden-cursor sentinel arrives
|
||||
// as 0x0 with an empty body, for which `need` is 0 and this check is a no-op.
|
||||
let need = (width as usize)
|
||||
.saturating_mul(height as usize)
|
||||
.saturating_mul(4);
|
||||
match conn.next_raw().await {
|
||||
Ok(raw) => {
|
||||
if raw.len() < need {
|
||||
break format!(
|
||||
"cursor body {} bytes < {need} for {width}x{height}",
|
||||
raw.len()
|
||||
);
|
||||
}
|
||||
set_drm_cursor(
|
||||
display,
|
||||
DrmCursorData {
|
||||
id,
|
||||
width: width as i32,
|
||||
height: height as i32,
|
||||
hotx,
|
||||
hoty,
|
||||
colors: raw.to_vec(),
|
||||
},
|
||||
);
|
||||
}
|
||||
Err(err) => break format!("cursor body: {err}"),
|
||||
}
|
||||
}
|
||||
// Live hotplug: the service pushed a fresh display list after a connector-topology change.
|
||||
// Swap it into the sticky positive availability cache directly (no re-probe over `_drm`, so
|
||||
// this never trips the wayland::clear() re-probe restart loop). A subsequent
|
||||
|
||||
Reference in New Issue
Block a user