Skip to content

Commit c956ff8

Browse files
committed
feat: Remove dangerous FromMemoryView blanket impl for all Copy types. Instead, provide explicit implementations only for primitive types.
1 parent 15acac7 commit c956ff8

File tree

6 files changed

+103
-16
lines changed

6 files changed

+103
-16
lines changed

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/dyn_memory/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use raw_struct::{
88
raw_struct,
99
Copy,
1010
CopyMemory,
11+
FromMemoryView,
1112
SizedViewable,
1213
};
1314

@@ -26,7 +27,7 @@ fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
2627
}
2728

2829
#[raw_struct(memory = "([u8; 0x10], T)")]
29-
struct Container<T: marker::Copy + Send + Sync + 'static> {
30+
struct Container<T: marker::Copy + FromMemoryView + Send + Sync + 'static> {
3031
#[field(offset = 0x00)]
3132
pub var_a: u64,
3233

raw_struct/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ description.workspace = true
1010
readme = "../README.MD"
1111

1212
[dependencies]
13-
raw_struct_derive = { version = "0.1", path = "../raw_struct_derive" }
13+
raw_struct_derive = { version = "*", path = "../raw_struct_derive" }
1414

1515
[features]
1616
no_std = []

raw_struct/src/builtins/ptr.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,20 @@ impl<T: ?Sized> Clone for Ptr64<T> {
3030
}
3131
impl<T: ?Sized> marker::Copy for Ptr64<T> {}
3232

33+
impl<T: ?Sized> FromMemoryView for Ptr64<T> {
34+
type DecodeError = <u64 as FromMemoryView>::DecodeError;
35+
36+
fn read_object<M: MemoryView>(
37+
view: &M,
38+
offset: u64,
39+
) -> Result<Self, MemoryDecodeError<M::AccessError, Self::DecodeError>> {
40+
Ok(Self {
41+
address: u64::read_object(view, offset)?,
42+
_type: Default::default(),
43+
})
44+
}
45+
}
46+
3347
impl<T: ?Sized> Ptr64<T> {
3448
pub fn is_null(&self) -> bool {
3549
self.address == 0

raw_struct/src/copy.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::{
2+
convert::Infallible,
23
marker,
34
mem::{
45
self,
@@ -9,6 +10,8 @@ use core::{
910
};
1011

1112
use crate::{
13+
FromMemoryView,
14+
MemoryDecodeError,
1215
MemoryView,
1316
OutOfBoundsViolation,
1417
Reference,
@@ -70,6 +73,17 @@ impl<T: SizedViewable> Copy<T> {
7073
}
7174
}
7275

76+
impl<T: SizedViewable> FromMemoryView for Copy<T> {
77+
type DecodeError = Infallible;
78+
79+
fn read_object<M: MemoryView>(
80+
view: &M,
81+
offset: u64,
82+
) -> Result<Self, MemoryDecodeError<M::AccessError, Self::DecodeError>> {
83+
Self::read_from_memory(view, offset).map_err(MemoryDecodeError::MemoryAccess)
84+
}
85+
}
86+
7387
impl<T> Clone for Copy<T>
7488
where
7589
T: SizedViewable,

raw_struct/src/memory.rs

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,23 +58,81 @@ pub trait FromMemoryView: Sized {
5858
// fn read_boxed(view: &dyn MemoryView, offset: u64) -> Result<Box<Self>, Box<dyn error::ErrorType>>;
5959
}
6060

61-
/// By default all copy traits are decodeable from memory.
62-
// FIXME: Remove this as it's ub for invalid values. Explicitly implement this trait for certain types instead!
63-
impl<T: Copy> FromMemoryView for T {
61+
macro_rules! impl_from_memory_copy {
62+
($type:ty) => {
63+
impl FromMemoryView for $type {
64+
type DecodeError = Infallible;
65+
66+
fn read_object<M: MemoryView>(
67+
view: &M,
68+
offset: u64,
69+
) -> Result<Self, MemoryDecodeError<M::AccessError, Self::DecodeError>> {
70+
let mut result = MaybeUninit::uninit();
71+
72+
{
73+
let result_memory = unsafe {
74+
slice::from_raw_parts_mut(
75+
result.as_mut_ptr() as *mut u8,
76+
mem::size_of::<$type>(),
77+
)
78+
};
79+
80+
view.read_memory(offset, result_memory)
81+
.map_err(MemoryDecodeError::MemoryAccess)?;
82+
}
83+
84+
Ok(unsafe { result.assume_init() })
85+
}
86+
}
87+
88+
impl<const N: usize> FromMemoryView for [$type; N] {
89+
type DecodeError = Infallible;
90+
91+
fn read_object<M: MemoryView>(
92+
view: &M,
93+
offset: u64,
94+
) -> Result<Self, MemoryDecodeError<M::AccessError, Self::DecodeError>> {
95+
let mut result = MaybeUninit::uninit();
96+
97+
{
98+
let result_memory = unsafe {
99+
slice::from_raw_parts_mut(
100+
result.as_mut_ptr() as *mut u8,
101+
mem::size_of::<$type>() * N,
102+
)
103+
};
104+
105+
view.read_memory(offset, result_memory)
106+
.map_err(MemoryDecodeError::MemoryAccess)?;
107+
}
108+
109+
Ok(unsafe { result.assume_init() })
110+
}
111+
}
112+
};
113+
}
114+
115+
impl_from_memory_copy!(i8);
116+
impl_from_memory_copy!(u8);
117+
impl_from_memory_copy!(i16);
118+
impl_from_memory_copy!(u16);
119+
impl_from_memory_copy!(i32);
120+
impl_from_memory_copy!(u32);
121+
impl_from_memory_copy!(i64);
122+
impl_from_memory_copy!(u64);
123+
124+
impl_from_memory_copy!(f32);
125+
impl_from_memory_copy!(f64);
126+
127+
impl FromMemoryView for bool {
64128
type DecodeError = Infallible;
65129

66130
fn read_object<M: MemoryView>(
67131
view: &M,
68132
offset: u64,
69133
) -> Result<Self, MemoryDecodeError<M::AccessError, Self::DecodeError>> {
70-
let mut result = MaybeUninit::uninit();
71-
let size = mem::size_of::<T>();
72-
73-
let buffer = unsafe { slice::from_raw_parts_mut(&mut result as *mut _ as *mut u8, size) };
74-
view.read_memory(offset, buffer)
75-
.map_err(MemoryDecodeError::MemoryAccess)?;
76-
77-
Ok(unsafe { result.assume_init() })
134+
let value = u8::read_object(view, offset)?;
135+
Ok(value > 0)
78136
}
79137
}
80138

0 commit comments

Comments
 (0)