|
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