Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ fn_to_numeric_cast_any = "warn"
ptr_cast_constness = "warn"

# == Correctness == #
#as_conversions = "warn"
as_conversions = "warn"
cast_lossless = "warn"
cast_possible_truncation = "warn"
cast_possible_wrap = "warn"
Expand Down
5 changes: 3 additions & 2 deletions benches/src/perfenc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ async fn main() -> Result<(), anyhow::Error> {
let mut updates = DisplayUpdates::new(file, DesktopSize { width, height }, fps);
while let Some(up) = updates.next_update().await? {
if let DisplayUpdate::Bitmap(ref up) = up {
total_raw += up.data.len() as u64;
total_raw += u64::try_from(up.data.len())?;
} else {
eprintln!("Invalid update");
break;
Expand All @@ -78,7 +78,7 @@ async fn main() -> Result<(), anyhow::Error> {
let Some(frag) = iter.next().await else {
break;
};
let len = frag?.data.len() as u64;
let len = u64::try_from(frag?.data.len())?;
total_enc += len;
}
n_updates += 1;
Expand All @@ -87,6 +87,7 @@ async fn main() -> Result<(), anyhow::Error> {
}
println!();

#[expect(clippy::as_conversions, reason = "casting u64 to f64")]
let ratio = total_enc as f64 / total_raw as f64;
let percent = 100.0 - ratio * 100.0;
println!("Encoder: {encoder:?}");
Expand Down
11 changes: 9 additions & 2 deletions crates/ironrdp-client/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ impl App {
let Some((window, _)) = self.window.as_mut() else {
return;
};
#[expect(clippy::as_conversions, reason = "casting f64 to u32")]
let scale_factor = (window.scale_factor() * 100.0) as u32;

let width = u16::try_from(size.width).expect("reasonable width");
Expand Down Expand Up @@ -222,8 +223,10 @@ impl ApplicationHandler<RdpOutputEvent> for App {
}
WindowEvent::CursorMoved { position, .. } => {
let win_size = window.inner_size();
let x = (position.x / win_size.width as f64 * self.buffer_size.0 as f64) as u16;
let y = (position.y / win_size.height as f64 * self.buffer_size.1 as f64) as u16;
#[expect(clippy::as_conversions, reason = "casting f64 to u16")]
let x = (position.x / f64::from(win_size.width) * f64::from(self.buffer_size.0)) as u16;
#[expect(clippy::as_conversions, reason = "casting f64 to u16")]
let y = (position.y / f64::from(win_size.height) * f64::from(self.buffer_size.1)) as u16;
let operation = ironrdp::input::Operation::MouseMove(ironrdp::input::MousePosition { x, y });

let input_events = self.input_database.apply(core::iter::once(operation));
Expand All @@ -239,6 +242,7 @@ impl ApplicationHandler<RdpOutputEvent> for App {
operations.push(ironrdp::input::Operation::WheelRotations(
ironrdp::input::WheelRotations {
is_vertical: false,
#[expect(clippy::as_conversions, reason = "casting f32 to i16")]
rotation_units: (delta_x * 100.) as i16,
},
));
Expand All @@ -248,6 +252,7 @@ impl ApplicationHandler<RdpOutputEvent> for App {
operations.push(ironrdp::input::Operation::WheelRotations(
ironrdp::input::WheelRotations {
is_vertical: true,
#[expect(clippy::as_conversions, reason = "casting f32 to i16")]
rotation_units: (delta_y * 100.) as i16,
},
));
Expand All @@ -258,6 +263,7 @@ impl ApplicationHandler<RdpOutputEvent> for App {
operations.push(ironrdp::input::Operation::WheelRotations(
ironrdp::input::WheelRotations {
is_vertical: false,
#[expect(clippy::as_conversions, reason = "casting f64 to i16")]
rotation_units: delta.x as i16,
},
));
Expand All @@ -267,6 +273,7 @@ impl ApplicationHandler<RdpOutputEvent> for App {
operations.push(ironrdp::input::Operation::WheelRotations(
ironrdp::input::WheelRotations {
is_vertical: true,
#[expect(clippy::as_conversions, reason = "casting f64 to i16")]
rotation_units: delta.y as i16,
},
));
Expand Down
4 changes: 2 additions & 2 deletions crates/ironrdp-client/src/rdp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ async fn connect(

let upgraded = ironrdp_tokio::mark_as_upgraded(should_upgrade, &mut connector);

let erased_stream = Box::new(upgraded_stream) as Box<dyn AsyncReadWrite + Unpin + Send + Sync>;
let erased_stream: Box<dyn AsyncReadWrite + Unpin + Send + Sync> = Box::new(upgraded_stream);
let mut upgraded_framed = ironrdp_tokio::TokioFramed::new_with_leftover(erased_stream, leftover_bytes);

let connection_result = ironrdp_tokio::connect_finalize(
Expand Down Expand Up @@ -336,7 +336,7 @@ async fn connect_ws(
.await?;

let (ws, leftover_bytes) = framed.into_inner();
let erased_stream = Box::new(ws) as Box<dyn AsyncReadWrite + Unpin + Send + Sync>;
let erased_stream: Box<dyn AsyncReadWrite + Unpin + Send + Sync> = Box::new(ws);
let upgraded_framed = ironrdp_tokio::TokioFramed::new_with_leftover(erased_stream, leftover_bytes);

Ok((connection_result, upgraded_framed))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl<'a> ClipboardDataRef<'a> {
};

// SAFETY: It is safe to call `GlobalLock` on the valid handle.
let data = unsafe { GlobalLock(handle) } as *const u8;
let data = unsafe { GlobalLock(handle) }.cast::<u8>().cast_const();

if data.is_null() {
// Can't lock data handle, handle is not valid anymore (e.g. clipboard has changed)
Expand Down
14 changes: 9 additions & 5 deletions crates/ironrdp-cliprdr-native/src/windows/clipboard_impl.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use core::ptr::with_exposed_provenance_mut;
use core::time::Duration;
use std::collections::HashSet;
use std::sync::mpsc;
Expand Down Expand Up @@ -320,17 +321,19 @@ pub(crate) unsafe extern "system" fn clipboard_subproc(

// SAFETY: `data` is a valid pointer, returned by `Box::into_raw`, transferred to OS earlier
// via `SetWindowSubclass` call.
let _ = unsafe { Box::from_raw(data as *mut WinClipboardImpl) };
let _ = unsafe { Box::from_raw(with_exposed_provenance_mut::<WinClipboardImpl>(data)) };
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with_exposed_provenance_mut:

Converts an address back to a mutable pointer, picking up some previously ‘exposed’ provenance.
This is fully equivalent to addr as *mut T. The provenance of the returned pointer is that of some pointer that was previously exposed by passing it to expose_provenance, or a ptr as usize cast

return LRESULT(0);
}

// SAFETY: `data` is a valid pointer, returned by `Box::into_raw`, transferred to OS earlier
// via `SetWindowSubclass` call.
let ctx = unsafe { &mut *(data as *mut WinClipboardImpl) };
let ctx = unsafe { &mut *(with_exposed_provenance_mut::<WinClipboardImpl>(data)) };

match msg {
// We need to keep track of window state to distinguish between local and remote copy
WM_ACTIVATE | WM_ACTIVATEAPP => ctx.window_is_active = wparam.0 != WA_INACTIVE as usize, // `as` conversion is fine for constants
WM_ACTIVATE | WM_ACTIVATEAPP => {
ctx.window_is_active = wparam.0 != usize::try_from(WA_INACTIVE).expect("WA_INACTIVE fits into usize")
}
// Sent by the OS when OS clipboard content is changed
WM_CLIPBOARDUPDATE => {
// SAFETY: `GetClipboardOwner` is always safe to call.
Expand All @@ -347,8 +350,9 @@ pub(crate) unsafe extern "system" fn clipboard_subproc(
}
// Sent by the OS when delay-rendered data is requested for rendering.
WM_RENDERFORMAT => {
#[expect(clippy::cast_possible_truncation)] // should never truncate in practice
ctx.handle_event(BackendEvent::RenderFormat(ClipboardFormatId::new(wparam.0 as u32)));
ctx.handle_event(BackendEvent::RenderFormat(ClipboardFormatId::new(
u32::try_from(wparam.0).expect("should never truncate in practice"),
)));
}
// Sent by the OS when all delay-rendered data is requested for rendering.
WM_RENDERALLFORMATS => {
Expand Down
10 changes: 8 additions & 2 deletions crates/ironrdp-cliprdr-native/src/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,14 @@ impl WinClipboard {
//
// SAFETY: `window` is a valid window handle, `clipboard_subproc` is in the static memory,
// `ctx` is valid and its ownership is transferred to the subclass via `into_raw`.
let winapi_result =
unsafe { SetWindowSubclass(window, Some(clipboard_subproc), 0, Box::into_raw(ctx) as usize) };
let winapi_result = unsafe {
SetWindowSubclass(
window,
Some(clipboard_subproc),
0,
Box::into_raw(ctx).expose_provenance(),
)
};

if winapi_result == FALSE {
return Err(WinCliprdrError::WindowSubclass);
Expand Down
2 changes: 1 addition & 1 deletion crates/ironrdp-cliprdr-native/src/windows/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl GlobalMemoryBuffer {
// - `dst` is valid for writes of `data.len()` bytes, we allocated enough above.
// - Both `data` and `dst` are properly aligned: u8 alignment is 1
// - Memory regions are not overlapping, `dst` was allocated by us just above.
unsafe { core::ptr::copy_nonoverlapping(data.as_ptr(), dst as *mut u8, data.len()) };
unsafe { core::ptr::copy_nonoverlapping(data.as_ptr(), dst.cast::<u8>(), data.len()) };

// SAFETY: We called `GlobalLock` on this handle just above.
if let Err(error) = unsafe { GlobalUnlock(handle) } {
Expand Down
4 changes: 0 additions & 4 deletions crates/ironrdp-cliprdr/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
#![cfg_attr(doc, doc = include_str!("../README.md"))]
#![doc(html_logo_url = "https://cdnweb.devolutions.net/images/projects/devolutions/logos/devolutions-icon-shadow.svg")]
#![allow(clippy::arithmetic_side_effects)] // FIXME: remove
#![allow(clippy::cast_lossless)] // FIXME: remove
#![allow(clippy::cast_possible_truncation)] // FIXME: remove
#![allow(clippy::cast_possible_wrap)] // FIXME: remove
#![allow(clippy::cast_sign_loss)] // FIXME: remove

pub mod backend;
pub mod pdu;
Expand Down
4 changes: 2 additions & 2 deletions crates/ironrdp-connector/src/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -699,9 +699,9 @@ fn create_gcc_blocks<'a>(
desktop_physical_width: Some(0), // 0 per FreeRDP
desktop_physical_height: Some(0), // 0 per FreeRDP
desktop_orientation: if config.desktop_size.width > config.desktop_size.height {
Some(MonitorOrientation::Landscape as u16)
Some(MonitorOrientation::Landscape.as_u16())
} else {
Some(MonitorOrientation::Portrait as u16)
Some(MonitorOrientation::Portrait.as_u16())
},
desktop_scale_factor: Some(config.desktop_scale_factor),
device_scale_factor: if config.desktop_scale_factor >= 100 && config.desktop_scale_factor <= 500 {
Expand Down
18 changes: 16 additions & 2 deletions crates/ironrdp-dvc/src/pdu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ impl Header {

fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ensure_fixed_part_size!(in: dst);
dst.write_u8(((self.cmd as u8) << 4) | (Into::<u8>::into(self.sp) << 2) | Into::<u8>::into(self.cb_id));
dst.write_u8(((self.cmd.as_u8()) << 4) | (Into::<u8>::into(self.sp) << 2) | Into::<u8>::into(self.cb_id));
Ok(())
}

Expand Down Expand Up @@ -235,6 +235,16 @@ enum Cmd {
SoftSyncResponse = 0x09,
}

impl Cmd {
#[expect(
clippy::as_conversions,
reason = "guarantees discriminant layout, and as is the only way to cast enum -> primitive"
)]
fn as_u8(self) -> u8 {
self as u8
}
}

impl TryFrom<u8> for Cmd {
type Error = DecodeError;

Expand Down Expand Up @@ -666,7 +676,7 @@ impl CapsVersion {

fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
ensure_size!(in: dst, size: Self::size());
dst.write_u16(*self as u16);
dst.write_u16(u16::from(*self));
Ok(())
}

Expand All @@ -689,6 +699,10 @@ impl TryFrom<u16> for CapsVersion {
}

impl From<CapsVersion> for u16 {
#[expect(
clippy::as_conversions,
reason = "guarantees discriminant layout, and as is the only way to cast enum -> primitive"
)]
fn from(version: CapsVersion) -> Self {
version as u16
}
Expand Down
4 changes: 2 additions & 2 deletions crates/ironrdp-fuzzing/src/oracles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ pub fn rdp6_decode_bitmap_stream_to_rgb24(input: &BitmapInput<'_>) {
let _ = BitmapStreamDecoder::default().decode_bitmap_stream_to_rgb24(
input.src,
&mut out,
input.width as usize,
input.height as usize,
usize::from(input.width),
usize::from(input.height),
);
}

Expand Down
13 changes: 9 additions & 4 deletions crates/ironrdp-graphics/src/color_conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,15 @@ pub fn to_64x64_ycbcr_tile(
/// Convert a 16-bit RDP color to RGB representation. Input value should be represented in
/// little-endian format.
pub fn rdp_16bit_to_rgb(color: u16) -> [u8; 3] {
let r = (((((color >> 11) & 0x1f) * 527) + 23) >> 6) as u8;
let g = (((((color >> 5) & 0x3f) * 259) + 33) >> 6) as u8;
let b = ((((color & 0x1f) * 527) + 23) >> 6) as u8;
[r, g, b]
#[expect(clippy::missing_panics_doc, reason = "unreachable panic (checked integer underflow)")]
let out = {
let r = u8::try_from(((((color >> 11) & 0x1f) * 527) + 23) >> 6).expect("max possible value is 255");
let g = u8::try_from(((((color >> 5) & 0x3f) * 259) + 33) >> 6).expect("max possible value is 255");
let b = u8::try_from((((color & 0x1f) * 527) + 23) >> 6).expect("max possible value is 255");
[r, g, b]
};

out
}

#[derive(Debug)]
Expand Down
Loading
Loading