Skip to content

Commit 82dbb64

Browse files
refactor(ironrdp-pdu)!: fix as_conversions clippy lint warnings (#967)
Co-authored-by: Benoît CORTIER <git.divisible626@passmail.com>
1 parent af8ebdc commit 82dbb64

File tree

49 files changed

+458
-292
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+458
-292
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ fn_to_numeric_cast_any = "warn"
9393
ptr_cast_constness = "warn"
9494

9595
# == Correctness == #
96+
#as_conversions = "warn"
9697
cast_lossless = "warn"
9798
cast_possible_truncation = "warn"
9899
cast_possible_wrap = "warn"

crates/ironrdp-pdu/src/basic_output/bitmap/mod.rs

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use core::fmt::{self, Debug};
77

88
use bitflags::bitflags;
99
use ironrdp_core::{
10-
ensure_fixed_part_size, ensure_size, invalid_field_err, Decode, DecodeResult, Encode, EncodeResult, ReadCursor,
11-
WriteCursor,
10+
cast_length, ensure_fixed_part_size, ensure_size, invalid_field_err, Decode, DecodeResult, Encode, EncodeResult,
11+
ReadCursor, WriteCursor,
1212
};
1313

1414
use crate::geometry::InclusiveRectangle;
@@ -41,11 +41,9 @@ impl Encode for BitmapUpdateData<'_> {
4141
fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
4242
ensure_size!(in: dst, size: self.size());
4343

44-
if self.rectangles.len() > u16::MAX as usize {
45-
return Err(invalid_field_err!("numberRectangles", "rectangle count is too big"));
46-
}
44+
let rectangle_count = cast_length!("number of rectangles", self.rectangles.len())?;
4745

48-
Self::encode_header(self.rectangles.len() as u16, dst)?;
46+
Self::encode_header(rectangle_count, dst)?;
4947

5048
for bitmap_data in self.rectangles.iter() {
5149
bitmap_data.encode(dst)?;
@@ -74,10 +72,10 @@ impl<'de> Decode<'de> for BitmapUpdateData<'de> {
7472
return Err(invalid_field_err!("updateType", "invalid update type"));
7573
}
7674

77-
let rectangles_number = src.read_u16() as usize;
78-
let mut rectangles = Vec::with_capacity(rectangles_number);
75+
let rectangle_count = usize::from(src.read_u16());
76+
let mut rectangles = Vec::with_capacity(rectangle_count);
7977

80-
for _ in 0..rectangles_number {
78+
for _ in 0..rectangle_count {
8179
rectangles.push(BitmapData::decode(src)?);
8280
}
8381

@@ -111,16 +109,14 @@ impl Encode for BitmapData<'_> {
111109
ensure_size!(in: dst, size: self.size());
112110

113111
let encoded_bitmap_data_length = self.encoded_bitmap_data_length();
114-
if encoded_bitmap_data_length > u16::MAX as usize {
115-
return Err(invalid_field_err!("bitmapLength", "bitmap data length is too big"));
116-
}
112+
let encoded_bitmap_data_length = cast_length!("bitmap data length", encoded_bitmap_data_length)?;
117113

118114
self.rectangle.encode(dst)?;
119115
dst.write_u16(self.width);
120116
dst.write_u16(self.height);
121117
dst.write_u16(self.bits_per_pixel);
122118
dst.write_u16(self.compression_flags.bits());
123-
dst.write_u16(encoded_bitmap_data_length as u16);
119+
dst.write_u16(encoded_bitmap_data_length);
124120
if let Some(compressed_data_header) = &self.compressed_data_header {
125121
compressed_data_header.encode(dst)?;
126122
};
@@ -150,25 +146,25 @@ impl<'de> Decode<'de> for BitmapData<'de> {
150146

151147
// A 16-bit, unsigned integer. The size in bytes of the data in the bitmapComprHdr
152148
// and bitmapDataStream fields.
153-
let encoded_bitmap_data_length = src.read_u16();
149+
let encoded_bitmap_data_length = usize::from(src.read_u16());
154150

155-
ensure_size!(in: src, size: encoded_bitmap_data_length as usize);
151+
ensure_size!(in: src, size: encoded_bitmap_data_length);
156152

157153
let (compressed_data_header, buffer_length) = if compression_flags.contains(Compression::BITMAP_COMPRESSION)
158154
&& !compression_flags.contains(Compression::NO_BITMAP_COMPRESSION_HDR)
159155
{
160156
// Check if encoded_bitmap_data_length is at least CompressedDataHeader::ENCODED_SIZE
161-
if encoded_bitmap_data_length < CompressedDataHeader::ENCODED_SIZE as u16 {
157+
if encoded_bitmap_data_length < CompressedDataHeader::ENCODED_SIZE {
162158
return Err(invalid_field_err!(
163159
"cbCompEncodedBitmapDataLength",
164160
"length is less than CompressedDataHeader::ENCODED_SIZE"
165161
));
166162
}
167163

168-
let buffer_length = encoded_bitmap_data_length as usize - CompressedDataHeader::ENCODED_SIZE;
164+
let buffer_length = encoded_bitmap_data_length - CompressedDataHeader::ENCODED_SIZE;
169165
(Some(CompressedDataHeader::decode(src)?), buffer_length)
170166
} else {
171-
(None, encoded_bitmap_data_length as usize)
167+
(None, encoded_bitmap_data_length)
172168
};
173169

174170
let bitmap_data = src.read_slice(buffer_length);

crates/ironrdp-pdu/src/basic_output/bitmap/rdp6.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ impl Encode for BitmapStreamHeader {
5656
fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
5757
ensure_size!(in: dst, size: self.size());
5858

59-
let mut header = ((self.enable_rle_compression as u8) << 4) | ((!self.use_alpha as u8) << 5);
59+
let mut header = (u8::from(self.enable_rle_compression) << 4) | (u8::from(!self.use_alpha) << 5);
6060

6161
match self.color_plane_definition {
6262
ColorPlaneDefinition::Argb => {
@@ -68,7 +68,7 @@ impl Encode for BitmapStreamHeader {
6868
..
6969
} => {
7070
// Add cll and cs flags to header
71-
header |= (color_loss_level & 0x07) | ((use_chroma_subsampling as u8) << 3);
71+
header |= (color_loss_level & 0x07) | (u8::from(use_chroma_subsampling) << 3);
7272
}
7373
}
7474

crates/ironrdp-pdu/src/basic_output/fast_path/mod.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ mod tests;
44
use bit_field::BitField as _;
55
use bitflags::bitflags;
66
use ironrdp_core::{
7-
decode_cursor, ensure_fixed_part_size, ensure_size, invalid_field_err, Decode, DecodeError, DecodeResult, Encode,
8-
EncodeResult, InvalidFieldErr as _, ReadCursor, WriteCursor,
7+
cast_length, decode_cursor, ensure_fixed_part_size, ensure_size, invalid_field_err, Decode, DecodeError,
8+
DecodeResult, Encode, EncodeResult, InvalidFieldErr as _, ReadCursor, WriteCursor,
99
};
1010
use num_derive::FromPrimitive;
1111
use num_traits::FromPrimitive as _;
@@ -42,7 +42,7 @@ impl FastPathHeader {
4242
// it may then be +2 if > 0x7f
4343
let len = self.data_length + Self::FIXED_PART_SIZE + 1;
4444

45-
Self::FIXED_PART_SIZE + per::sizeof_length(len as u16)
45+
Self::FIXED_PART_SIZE + per::sizeof_length(len)
4646
}
4747
}
4848

@@ -56,15 +56,13 @@ impl Encode for FastPathHeader {
5656
dst.write_u8(header);
5757

5858
let length = self.data_length + self.size();
59-
if length > u16::MAX as usize {
60-
return Err(invalid_field_err!("length", "fastpath PDU length is too big"));
61-
}
59+
let length = cast_length!("length", length)?;
6260

6361
if self.forced_long_length {
6462
// Preserve same layout for header as received
65-
per::write_long_length(dst, length as u16);
63+
per::write_long_length(dst, length);
6664
} else {
67-
per::write_length(dst, length as u16);
65+
per::write_length(dst, length);
6866
}
6967

7068
Ok(())
@@ -93,14 +91,15 @@ impl<'de> Decode<'de> for FastPathHeader {
9391
let (length, sizeof_length) = per::read_length(src).map_err(|e| {
9492
DecodeError::invalid_field("", "length", "Invalid encoded fast path PDU length").with_source(e)
9593
})?;
96-
if (length as usize) < sizeof_length + Self::FIXED_PART_SIZE {
94+
let length = usize::from(length);
95+
if length < sizeof_length + Self::FIXED_PART_SIZE {
9796
return Err(invalid_field_err!(
9897
"length",
9998
"received fastpath PDU length is smaller than header size"
10099
));
101100
}
102-
let data_length = length as usize - sizeof_length - Self::FIXED_PART_SIZE;
103-
// Detect case, when received packet has non-optimal packet length packing
101+
let data_length = length - sizeof_length - Self::FIXED_PART_SIZE;
102+
// Detect case, when received packet has non-optimal packet length packing.
104103
let forced_long_length = per::sizeof_length(length) != sizeof_length;
105104

106105
Ok(FastPathHeader {
@@ -131,9 +130,7 @@ impl Encode for FastPathUpdatePdu<'_> {
131130
fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
132131
ensure_size!(in: dst, size: self.size());
133132

134-
if self.data.len() > u16::MAX as usize {
135-
return Err(invalid_field_err!("data", "fastpath PDU data is too big"));
136-
}
133+
let data_len = cast_length!("data length", self.data.len())?;
137134

138135
let mut header = 0u8;
139136
header.set_bits(0..4, self.update_code.as_u8());
@@ -148,7 +145,7 @@ impl Encode for FastPathUpdatePdu<'_> {
148145
dst.write_u8(compression_flags_with_type);
149146
}
150147

151-
dst.write_u16(self.data.len() as u16);
148+
dst.write_u16(data_len);
152149
dst.write_slice(self.data);
153150

154151
Ok(())
@@ -200,7 +197,7 @@ impl<'de> Decode<'de> for FastPathUpdatePdu<'de> {
200197
(None, None)
201198
};
202199

203-
let data_length = src.read_u16() as usize;
200+
let data_length = usize::from(src.read_u16());
204201
ensure_size!(in: src, size: data_length);
205202
let data = src.read_slice(data_length);
206203

crates/ironrdp-pdu/src/basic_output/pointer/mod.rs

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use ironrdp_core::{
2-
ensure_fixed_part_size, ensure_size, invalid_field_err, Decode, DecodeResult, Encode, EncodeResult, ReadCursor,
3-
WriteCursor,
2+
cast_int, cast_length, ensure_fixed_part_size, ensure_size, invalid_field_err, Decode, DecodeResult, Encode,
3+
EncodeResult, ReadCursor, WriteCursor,
44
};
55

66
// Represents `TS_POINT16` described in [MS-RDPBCGR] 2.2.9.1.1.4.1
@@ -69,21 +69,24 @@ macro_rules! check_masks_alignment {
6969
($and_mask:expr, $xor_mask:expr, $pointer_height:expr, $large_ptr:expr) => {{
7070
const AND_MASK_SIZE_FIELD: &str = "lengthAndMask";
7171
const XOR_MASK_SIZE_FIELD: &str = "lengthXorMask";
72+
const U32_MAX: usize = 0xFFFFFFFF;
73+
74+
let pointer_height: usize = cast_int!("pointer height", $pointer_height)?;
7275

7376
let check_mask = |mask: &[u8], field: &'static str| {
7477
if $pointer_height == 0 {
7578
return Err(invalid_field_err!(field, "pointer height cannot be zero"));
7679
}
77-
if $large_ptr && (mask.len() > u32::MAX as usize) {
80+
if $large_ptr && (mask.len() > U32_MAX) {
7881
return Err(invalid_field_err!(field, "pointer mask is too big for u32 size"));
7982
}
80-
if !$large_ptr && (mask.len() > u16::MAX as usize) {
83+
if !$large_ptr && (mask.len() > usize::from(u16::MAX)) {
8184
return Err(invalid_field_err!(field, "pointer mask is too big for u16 size"));
8285
}
83-
if (mask.len() % $pointer_height as usize) != 0 {
86+
if (mask.len() % pointer_height) != 0 {
8487
return Err(invalid_field_err!(field, "pointer mask have incomplete scanlines"));
8588
}
86-
if (mask.len() / $pointer_height as usize) % 2 != 0 {
89+
if (mask.len() / pointer_height) % 2 != 0 {
8790
return Err(invalid_field_err!(
8891
field,
8992
"pointer mask scanlines should be aligned to 16 bits"
@@ -108,8 +111,8 @@ impl Encode for ColorPointerAttribute<'_> {
108111
dst.write_u16(self.width);
109112
dst.write_u16(self.height);
110113

111-
dst.write_u16(self.and_mask.len() as u16);
112-
dst.write_u16(self.xor_mask.len() as u16);
114+
dst.write_u16(cast_length!("and mask length", self.and_mask.len())?);
115+
dst.write_u16(cast_length!("xor mask length", self.xor_mask.len())?);
113116
// Note that masks are written in reverse order. It is not a mistake, that is how the
114117
// message is defined in [MS-RDPBCGR]
115118
dst.write_slice(self.xor_mask);
@@ -135,15 +138,15 @@ impl<'a> Decode<'a> for ColorPointerAttribute<'a> {
135138
let hot_spot = Point16::decode(src)?;
136139
let width = src.read_u16();
137140
let height = src.read_u16();
138-
let length_and_mask = src.read_u16();
139-
let length_xor_mask = src.read_u16();
140-
141141
// Convert to usize during the addition to prevent overflow and match expected type
142-
let expected_masks_size = (length_and_mask as usize) + (length_xor_mask as usize);
142+
let length_and_mask = usize::from(src.read_u16());
143+
let length_xor_mask = usize::from(src.read_u16());
144+
145+
let expected_masks_size = length_and_mask + length_xor_mask;
143146
ensure_size!(in: src, size: expected_masks_size);
144147

145-
let xor_mask = src.read_slice(length_xor_mask as usize);
146-
let and_mask = src.read_slice(length_and_mask as usize);
148+
let xor_mask = src.read_slice(length_xor_mask);
149+
let and_mask = src.read_slice(length_and_mask);
147150

148151
check_masks_alignment!(and_mask, xor_mask, height, false)?;
149152

@@ -270,8 +273,8 @@ impl Encode for LargePointerAttribute<'_> {
270273
dst.write_u16(self.width);
271274
dst.write_u16(self.height);
272275

273-
dst.write_u32(self.and_mask.len() as u32);
274-
dst.write_u32(self.xor_mask.len() as u32);
276+
dst.write_u32(cast_length!("and mask length", self.and_mask.len())?);
277+
dst.write_u32(cast_length!("xor mask length", self.xor_mask.len())?);
275278
// See comment in `ColorPointerAttribute::encode` about encoding order
276279
dst.write_slice(self.xor_mask);
277280
dst.write_slice(self.and_mask);
@@ -298,8 +301,8 @@ impl<'a> Decode<'a> for LargePointerAttribute<'a> {
298301
let width = src.read_u16();
299302
let height = src.read_u16();
300303
// Convert to usize to prevent overflow during addition
301-
let length_and_mask = src.read_u32() as usize;
302-
let length_xor_mask = src.read_u32() as usize;
304+
let length_and_mask = cast_length!("and mask length", src.read_u32())?;
305+
let length_xor_mask = cast_length!("xor mask length", src.read_u32())?;
303306

304307
let expected_masks_size = length_and_mask + length_xor_mask;
305308
ensure_size!(in: src, size: expected_masks_size);

crates/ironrdp-pdu/src/basic_output/surface_commands/mod.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ mod tests;
33

44
use bitflags::bitflags;
55
use ironrdp_core::{
6-
ensure_fixed_part_size, ensure_size, invalid_field_err, Decode, DecodeResult, Encode, EncodeResult, ReadCursor,
7-
WriteCursor,
6+
cast_length, ensure_fixed_part_size, ensure_size, invalid_field_err, Decode, DecodeResult, Encode, EncodeResult,
7+
ReadCursor, WriteCursor,
88
};
9-
use num_derive::{FromPrimitive, ToPrimitive};
9+
use num_derive::FromPrimitive;
1010
use num_traits::FromPrimitive as _;
1111

1212
use crate::geometry::ExclusiveRectangle;
@@ -126,7 +126,7 @@ impl Encode for FrameMarkerPdu {
126126
fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
127127
ensure_fixed_part_size!(in: dst);
128128

129-
dst.write_u16(self.frame_action as u16);
129+
dst.write_u16(self.frame_action.as_u16());
130130
dst.write_u32(self.frame_id.unwrap_or(0));
131131

132132
Ok(())
@@ -197,9 +197,7 @@ impl Encode for ExtendedBitmapDataPdu<'_> {
197197
fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
198198
ensure_size!(in: dst, size: self.size());
199199

200-
if self.data.len() > u32::MAX as usize {
201-
return Err(invalid_field_err!("bitmapDataLength", "bitmap data is too big"));
202-
}
200+
let data_len = cast_length!("bitmap data length", self.data.len())?;
203201

204202
dst.write_u8(self.bpp);
205203
let flags = if self.header.is_some() {
@@ -212,7 +210,7 @@ impl Encode for ExtendedBitmapDataPdu<'_> {
212210
dst.write_u8(self.codec_id);
213211
dst.write_u16(self.width);
214212
dst.write_u16(self.height);
215-
dst.write_u32(self.data.len() as u32);
213+
dst.write_u32(data_len);
216214
if let Some(header) = &self.header {
217215
header.encode(dst)?;
218216
}
@@ -240,7 +238,7 @@ impl<'de> Decode<'de> for ExtendedBitmapDataPdu<'de> {
240238
let codec_id = src.read_u8();
241239
let width = src.read_u16();
242240
let height = src.read_u16();
243-
let data_length = src.read_u32() as usize;
241+
let data_length = cast_length!("bitmap data length", src.read_u32())?;
244242

245243
let expected_remaining_size = if flags.contains(BitmapDataFlags::COMPRESSED_BITMAP_HEADER_PRESENT) {
246244
data_length + BitmapDataHeader::ENCODED_SIZE
@@ -352,13 +350,23 @@ impl From<&SurfaceCommand<'_>> for SurfaceCommandType {
352350
}
353351
}
354352

355-
#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
353+
#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive)]
356354
#[repr(u16)]
357355
pub enum FrameAction {
358356
Begin = 0x00,
359357
End = 0x01,
360358
}
361359

360+
impl FrameAction {
361+
#[expect(
362+
clippy::as_conversions,
363+
reason = "guarantees discriminant layout, and as is the only way to cast enum -> primitive"
364+
)]
365+
pub fn as_u16(self) -> u16 {
366+
self as u16
367+
}
368+
}
369+
362370
bitflags! {
363371
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
364372
struct BitmapDataFlags: u8 {

0 commit comments

Comments
 (0)