|
20 | 20 | use alloc::{alloc::alloc_zeroed, sync::Arc}; |
21 | 21 | use core::{alloc::Layout, any::Any, cell::UnsafeCell, mem, ptr::Unique}; |
22 | 22 |
|
23 | | -use crate::{apic::get_cpu_count, mem::paging::align_down}; |
| 23 | +use crate::{ |
| 24 | + apic::get_cpu_count, |
| 25 | + mem::paging::{align_down, VirtAddr}, |
| 26 | +}; |
24 | 27 |
|
25 | 28 | pub mod buffer; |
26 | 29 | pub mod io; |
27 | 30 | pub mod linker; |
28 | 31 | pub mod sync; |
29 | 32 |
|
30 | | -pub fn validate_ptr<T>(ptr: *const T) -> Option<&'static T> { |
31 | | - if ptr.is_null() { |
32 | | - None |
33 | | - } else { |
34 | | - unsafe { Some(&*ptr) } |
35 | | - } |
36 | | -} |
37 | | - |
38 | 33 | pub fn validate_mut_ptr<T>(ptr: *mut T) -> Option<&'static mut T> { |
39 | | - if ptr.is_null() { |
40 | | - None |
41 | | - } else { |
42 | | - unsafe { Some(&mut *ptr) } |
43 | | - } |
| 34 | + VirtAddr::new(ptr as _).read_mut::<T>() |
44 | 35 | } |
45 | 36 |
|
46 | | -pub fn validate_slice<T>(ptr: *const T, len: usize) -> Option<&'static [T]> { |
47 | | - if len == 0 { |
48 | | - Some(&[]) |
49 | | - } else { |
50 | | - Some(unsafe { core::slice::from_raw_parts(ptr, len) }) |
51 | | - } |
| 37 | +pub fn validate_ptr<T>(ptr: *const T) -> Option<&'static T> { |
| 38 | + // SAFETY: Safe to cast const pointer to mutable since the pointer is not |
| 39 | + // mutated and the returned reference is immutable. |
| 40 | + validate_mut_ptr(ptr as *mut T).map(|e| &*e) |
52 | 41 | } |
53 | 42 |
|
54 | 43 | pub fn validate_slice_mut<T>(ptr: *mut T, len: usize) -> Option<&'static mut [T]> { |
55 | 44 | if len == 0 { |
56 | 45 | Some(&mut []) |
57 | 46 | } else { |
| 47 | + let _ = validate_ptr(ptr)?; // ensure non-null and in-range |
| 48 | + let _ = validate_ptr(unsafe { ptr.add(len) })?; // ensure in-range |
| 49 | + |
| 50 | + // SAFETY: We have validated the pointer above. |
58 | 51 | Some(unsafe { core::slice::from_raw_parts_mut(ptr, len) }) |
59 | 52 | } |
60 | 53 | } |
61 | 54 |
|
| 55 | +pub fn validate_slice<T>(ptr: *const T, len: usize) -> Option<&'static [T]> { |
| 56 | + // SAFETY: Safe to cast const pointer to mutable since the pointer is not |
| 57 | + // mutated and the returned reference is immutable. |
| 58 | + validate_slice_mut(ptr as *mut T, len).map(|e| &*e) |
| 59 | +} |
| 60 | + |
62 | 61 | pub fn validate_str(ptr: *const u8, len: usize) -> Option<&'static str> { |
63 | 62 | let slice = validate_slice(ptr, len)?; |
64 | | - |
65 | | - match core::str::from_utf8(slice) { |
66 | | - Ok(string) => Some(string), |
67 | | - Err(_) => None, |
68 | | - } |
| 63 | + core::str::from_utf8(slice).ok() |
69 | 64 | } |
70 | 65 |
|
71 | 66 | pub fn validate_array_mut<T, const COUNT: usize>(ptr: *mut T) -> Option<&'static mut [T; COUNT]> { |
72 | | - // We use the `validate_slice_mut` function to validate if it safe to read `COUNT` amount |
73 | | - // of memory from `ptr`. Then we convert the slice to an array. |
74 | 67 | let slice = validate_slice_mut::<T>(ptr, COUNT); |
| 68 | + // Convert the validated slice to an array. |
| 69 | + // |
75 | 70 | // SAFETY: We know that `slice` is a valid slice of `COUNT` elements. |
76 | 71 | slice.map(|e| unsafe { &mut *(e.as_ptr() as *mut [T; COUNT]) }) |
77 | 72 | } |
|
0 commit comments