mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-18 02:10:59 +03:00
Validate cursor source metadata before UI dispatch
This commit is contained in:
@@ -3494,21 +3494,22 @@ class CursorModel with ChangeNotifier {
|
|||||||
final hoty = double.parse(evt['hoty']);
|
final hoty = double.parse(evt['hoty']);
|
||||||
final width = int.parse(evt['width']);
|
final width = int.parse(evt['width']);
|
||||||
final height = int.parse(evt['height']);
|
final height = int.parse(evt['height']);
|
||||||
// Bound physical allocation before density normalization or image decoding.
|
// Rust validates native packets; Web receives them directly from JavaScript.
|
||||||
if (!_validCursorRasterSize(width.toDouble(), height.toDouble())) {
|
if (isWeb && !_validCursorRasterSize(width.toDouble(), height.toDouble())) {
|
||||||
debugPrint('Rejected cursor $id: invalid source size ${width}x$height');
|
debugPrint('Rejected cursor $id: invalid source size ${width}x$height');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final pixelRatio = double.tryParse(evt['scale'] ?? '0');
|
final pixelRatio = double.tryParse(evt['scale'] ?? '0');
|
||||||
if (pixelRatio == null || !pixelRatio.isFinite || pixelRatio < 0 ||
|
if (pixelRatio == null ||
|
||||||
(pixelRatio > 0 &&
|
(isWeb && (!pixelRatio.isFinite || pixelRatio < 0 ||
|
||||||
!_validCursorRasterSize(width / pixelRatio, height / pixelRatio))) {
|
(pixelRatio > 0 &&
|
||||||
|
!_validCursorRasterSize(width / pixelRatio, height / pixelRatio))))) {
|
||||||
debugPrint('Rejected cursor $id: invalid pixel ratio ${evt['scale']}');
|
debugPrint('Rejected cursor $id: invalid pixel ratio ${evt['scale']}');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
List<dynamic> colors = json.decode(evt['colors']);
|
List<dynamic> colors = json.decode(evt['colors']);
|
||||||
const bytesPerPixel = 4;
|
const bytesPerPixel = 4;
|
||||||
if (colors.length != width * height * bytesPerPixel) {
|
if (isWeb && colors.length != width * height * bytesPerPixel) {
|
||||||
debugPrint('Rejected cursor $id: invalid RGBA length ${colors.length}');
|
debugPrint('Rejected cursor $id: invalid RGBA length ${colors.length}');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2562,6 +2562,22 @@ fn decode_cursor_data(data: CursorData) -> hbb_common::ResultType<CursorData> {
|
|||||||
if !(1..=MAX_CURSOR_SIZE).contains(&cd.width) || !(1..=MAX_CURSOR_SIZE).contains(&cd.height) {
|
if !(1..=MAX_CURSOR_SIZE).contains(&cd.width) || !(1..=MAX_CURSOR_SIZE).contains(&cd.height) {
|
||||||
bail!("invalid source size {}x{}", cd.width, cd.height);
|
bail!("invalid source size {}x{}", cd.width, cd.height);
|
||||||
}
|
}
|
||||||
|
if !(0..cd.width).contains(&cd.hotx) || !(0..cd.height).contains(&cd.hoty) {
|
||||||
|
bail!(
|
||||||
|
"hotspot ({},{}) is outside the cursor image",
|
||||||
|
cd.hotx,
|
||||||
|
cd.hoty
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Zero preserves legacy sizing; positive density must bound the logical image too.
|
||||||
|
if !cd.scale.is_finite()
|
||||||
|
|| cd.scale < 0.0
|
||||||
|
|| (cd.scale > 0.0
|
||||||
|
&& (f64::from(cd.width) / cd.scale > f64::from(MAX_CURSOR_SIZE)
|
||||||
|
|| f64::from(cd.height) / cd.scale > f64::from(MAX_CURSOR_SIZE)))
|
||||||
|
{
|
||||||
|
bail!("invalid cursor density {}", cd.scale);
|
||||||
|
}
|
||||||
let expected = (cd.width as usize)
|
let expected = (cd.width as usize)
|
||||||
.checked_mul(cd.height as usize)
|
.checked_mul(cd.height as usize)
|
||||||
.and_then(|pixels| pixels.checked_mul(RGBA_CHANNELS))
|
.and_then(|pixels| pixels.checked_mul(RGBA_CHANNELS))
|
||||||
|
|||||||
Reference in New Issue
Block a user