Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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 @@ -92,7 +92,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