Validate and decode cursor packets at the Rust receive boundary

This commit is contained in:
fufesou
2026-09-14 10:00:54 +08:00
parent c142cba450
commit f6c89aa06c
3 changed files with 38 additions and 4 deletions

View File

@@ -1508,7 +1508,11 @@ impl<T: InvokeUiSession> Remote<T> {
_ => {}
},
Some(message::Union::CursorData(cd)) => {
self.handler.set_cursor_data(cd);
let id = cd.id;
match decode_cursor_data(cd) {
Ok(cd) => self.handler.set_cursor_data(cd),
Err(err) => log::warn!("Rejected cursor {id}: {err}"),
}
}
Some(message::Union::CursorId(id)) => {
self.handler.set_cursor_id(id.to_string());
@@ -2542,6 +2546,37 @@ impl<T: InvokeUiSession> Remote<T> {
}
}
// Both UI handlers receive validated, uncompressed RGBA from the receive loop.
fn decode_cursor_data(data: CursorData) -> hbb_common::ResultType<CursorData> {
use hbb_common::{anyhow::anyhow, bail};
const MAX_CURSOR_SIZE: i32 = 4096;
const RGBA_CHANNELS: usize = 4;
let mut cd = data;
// Sciter keeps the legacy outer image; Flutter uses the physical variant.
#[cfg(feature = "flutter")]
if let Some(physical) = cd.high_resolution.take() {
cd = physical;
}
if !(1..=MAX_CURSOR_SIZE).contains(&cd.width) || !(1..=MAX_CURSOR_SIZE).contains(&cd.height) {
bail!("invalid source size {}x{}", cd.width, cd.height);
}
let expected = (cd.width as usize)
.checked_mul(cd.height as usize)
.and_then(|pixels| pixels.checked_mul(RGBA_CHANNELS))
.ok_or_else(|| anyhow!("cursor RGBA size overflow"))?;
let colors = zstd::bulk::decompress(&cd.colors, expected)?;
if colors.len() != expected {
bail!(
"invalid RGBA length: expected {expected}, got {}",
colors.len()
);
}
cd.colors = colors.into();
Ok(cd)
}
struct RemoveJob {
files: Vec<FileEntry>,
path: String,

View File

@@ -642,8 +642,7 @@ impl FlutterHandler {
impl InvokeUiSession for FlutterHandler {
fn set_cursor_data(&self, cd: CursorData) {
let cd = cd.high_resolution.as_ref().unwrap_or(&cd);
let colors = hbb_common::compress::decompress(&cd.colors);
let colors = &cd.colors;
self.push_event(
"cursor_data",
&[

View File

@@ -122,7 +122,7 @@ impl SciterHandler {
impl InvokeUiSession for SciterHandler {
fn set_cursor_data(&self, cd: CursorData) {
let mut colors = hbb_common::compress::decompress(&cd.colors);
let mut colors: Vec<u8> = cd.colors.into();
if colors.iter().filter(|x| **x != 0).next().is_none() {
log::info!("Fix transparent");
// somehow all 0 images shows black rect, here is a workaround