xref: /aosp_15_r20/external/crosvm/base/src/sys/windows/mmap.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use libc::c_void;
6*bb4ee6a4SAndroid Build Coastguard Worker use win_util::create_file_mapping;
7*bb4ee6a4SAndroid Build Coastguard Worker use win_util::duplicate_handle;
8*bb4ee6a4SAndroid Build Coastguard Worker use winapi::um::winnt::PAGE_READWRITE;
9*bb4ee6a4SAndroid Build Coastguard Worker 
10*bb4ee6a4SAndroid Build Coastguard Worker pub use super::mmap_platform::MemoryMappingArena;
11*bb4ee6a4SAndroid Build Coastguard Worker use crate::AsRawDescriptor;
12*bb4ee6a4SAndroid Build Coastguard Worker use crate::Descriptor;
13*bb4ee6a4SAndroid Build Coastguard Worker use crate::FromRawDescriptor;
14*bb4ee6a4SAndroid Build Coastguard Worker use crate::MappedRegion;
15*bb4ee6a4SAndroid Build Coastguard Worker use crate::MemoryMapping as CrateMemoryMapping;
16*bb4ee6a4SAndroid Build Coastguard Worker use crate::MemoryMappingBuilder;
17*bb4ee6a4SAndroid Build Coastguard Worker use crate::MmapError as Error;
18*bb4ee6a4SAndroid Build Coastguard Worker use crate::MmapResult as Result;
19*bb4ee6a4SAndroid Build Coastguard Worker use crate::Protection;
20*bb4ee6a4SAndroid Build Coastguard Worker use crate::RawDescriptor;
21*bb4ee6a4SAndroid Build Coastguard Worker use crate::SafeDescriptor;
22*bb4ee6a4SAndroid Build Coastguard Worker 
23*bb4ee6a4SAndroid Build Coastguard Worker /// Validates that `offset`..`offset+range_size` lies within the bounds of a memory mapping of
24*bb4ee6a4SAndroid Build Coastguard Worker /// `mmap_size` bytes.  Also checks for any overflow.
validate_includes_range(mmap_size: usize, offset: usize, range_size: usize) -> Result<()>25*bb4ee6a4SAndroid Build Coastguard Worker fn validate_includes_range(mmap_size: usize, offset: usize, range_size: usize) -> Result<()> {
26*bb4ee6a4SAndroid Build Coastguard Worker     // Ensure offset + size doesn't overflow
27*bb4ee6a4SAndroid Build Coastguard Worker     let end_offset = offset
28*bb4ee6a4SAndroid Build Coastguard Worker         .checked_add(range_size)
29*bb4ee6a4SAndroid Build Coastguard Worker         .ok_or(Error::InvalidAddress)?;
30*bb4ee6a4SAndroid Build Coastguard Worker     // Ensure offset + size are within the mapping bounds
31*bb4ee6a4SAndroid Build Coastguard Worker     if end_offset <= mmap_size {
32*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
33*bb4ee6a4SAndroid Build Coastguard Worker     } else {
34*bb4ee6a4SAndroid Build Coastguard Worker         Err(Error::InvalidAddress)
35*bb4ee6a4SAndroid Build Coastguard Worker     }
36*bb4ee6a4SAndroid Build Coastguard Worker }
37*bb4ee6a4SAndroid Build Coastguard Worker 
38*bb4ee6a4SAndroid Build Coastguard Worker impl dyn MappedRegion {
39*bb4ee6a4SAndroid Build Coastguard Worker     /// Calls msync with MS_SYNC on a mapping of `size` bytes starting at `offset` from the start of
40*bb4ee6a4SAndroid Build Coastguard Worker     /// the region.  `offset`..`offset+size` must be contained within the `MappedRegion`.
msync(&self, offset: usize, size: usize) -> Result<()>41*bb4ee6a4SAndroid Build Coastguard Worker     pub fn msync(&self, offset: usize, size: usize) -> Result<()> {
42*bb4ee6a4SAndroid Build Coastguard Worker         validate_includes_range(self.size(), offset, size)?;
43*bb4ee6a4SAndroid Build Coastguard Worker 
44*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY:
45*bb4ee6a4SAndroid Build Coastguard Worker         // Safe because the MemoryMapping/MemoryMappingArena interface ensures our pointer and size
46*bb4ee6a4SAndroid Build Coastguard Worker         // are correct, and we've validated that `offset`..`offset+size` is in the range owned by
47*bb4ee6a4SAndroid Build Coastguard Worker         // this `MappedRegion`.
48*bb4ee6a4SAndroid Build Coastguard Worker         let ret = unsafe {
49*bb4ee6a4SAndroid Build Coastguard Worker             use winapi::um::memoryapi::FlushViewOfFile;
50*bb4ee6a4SAndroid Build Coastguard Worker             if FlushViewOfFile((self.as_ptr() as usize + offset) as *mut libc::c_void, size) == 0 {
51*bb4ee6a4SAndroid Build Coastguard Worker                 -1
52*bb4ee6a4SAndroid Build Coastguard Worker             } else {
53*bb4ee6a4SAndroid Build Coastguard Worker                 0
54*bb4ee6a4SAndroid Build Coastguard Worker             }
55*bb4ee6a4SAndroid Build Coastguard Worker         };
56*bb4ee6a4SAndroid Build Coastguard Worker         if ret != -1 {
57*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
58*bb4ee6a4SAndroid Build Coastguard Worker         } else {
59*bb4ee6a4SAndroid Build Coastguard Worker             Err(Error::SystemCallFailed(super::Error::last()))
60*bb4ee6a4SAndroid Build Coastguard Worker         }
61*bb4ee6a4SAndroid Build Coastguard Worker     }
62*bb4ee6a4SAndroid Build Coastguard Worker }
63*bb4ee6a4SAndroid Build Coastguard Worker 
64*bb4ee6a4SAndroid Build Coastguard Worker /// Wraps an anonymous shared memory mapping in the current process. Provides
65*bb4ee6a4SAndroid Build Coastguard Worker /// RAII semantics including munmap when no longer needed.
66*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)]
67*bb4ee6a4SAndroid Build Coastguard Worker pub struct MemoryMapping {
68*bb4ee6a4SAndroid Build Coastguard Worker     pub(crate) addr: *mut c_void,
69*bb4ee6a4SAndroid Build Coastguard Worker     pub(crate) size: usize,
70*bb4ee6a4SAndroid Build Coastguard Worker }
71*bb4ee6a4SAndroid Build Coastguard Worker 
72*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
73*bb4ee6a4SAndroid Build Coastguard Worker // Send and Sync aren't automatically inherited for the raw address pointer.
74*bb4ee6a4SAndroid Build Coastguard Worker // Accessing that pointer is only done through the stateless interface which
75*bb4ee6a4SAndroid Build Coastguard Worker // allows the object to be shared by multiple threads without a decrease in
76*bb4ee6a4SAndroid Build Coastguard Worker // safety.
77*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl Send for MemoryMapping {}
78*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: See comments for impl Send
79*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl Sync for MemoryMapping {}
80*bb4ee6a4SAndroid Build Coastguard Worker 
81*bb4ee6a4SAndroid Build Coastguard Worker impl MemoryMapping {
82*bb4ee6a4SAndroid Build Coastguard Worker     /// Creates an anonymous shared, read/write mapping of `size` bytes.
83*bb4ee6a4SAndroid Build Coastguard Worker     ///
84*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
85*bb4ee6a4SAndroid Build Coastguard Worker     /// * `size` - Size of memory region in bytes.
new(size: usize) -> Result<MemoryMapping>86*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(size: usize) -> Result<MemoryMapping> {
87*bb4ee6a4SAndroid Build Coastguard Worker         MemoryMapping::new_protection(size, Protection::read_write())
88*bb4ee6a4SAndroid Build Coastguard Worker     }
89*bb4ee6a4SAndroid Build Coastguard Worker 
90*bb4ee6a4SAndroid Build Coastguard Worker     /// Maps the first `size` bytes of the given `descriptor` as read/write.
91*bb4ee6a4SAndroid Build Coastguard Worker     ///
92*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
93*bb4ee6a4SAndroid Build Coastguard Worker     /// * `file_handle` - File handle to map from.
94*bb4ee6a4SAndroid Build Coastguard Worker     /// * `size` - Size of memory region in bytes.
from_descriptor( file_handle: &dyn AsRawDescriptor, size: usize, ) -> Result<MemoryMapping>95*bb4ee6a4SAndroid Build Coastguard Worker     pub fn from_descriptor(
96*bb4ee6a4SAndroid Build Coastguard Worker         file_handle: &dyn AsRawDescriptor,
97*bb4ee6a4SAndroid Build Coastguard Worker         size: usize,
98*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<MemoryMapping> {
99*bb4ee6a4SAndroid Build Coastguard Worker         MemoryMapping::from_descriptor_offset(file_handle, size, 0)
100*bb4ee6a4SAndroid Build Coastguard Worker     }
101*bb4ee6a4SAndroid Build Coastguard Worker 
from_raw_descriptor(file_handle: RawDescriptor, size: usize) -> Result<MemoryMapping>102*bb4ee6a4SAndroid Build Coastguard Worker     pub fn from_raw_descriptor(file_handle: RawDescriptor, size: usize) -> Result<MemoryMapping> {
103*bb4ee6a4SAndroid Build Coastguard Worker         MemoryMapping::from_descriptor_offset(&Descriptor(file_handle), size, 0)
104*bb4ee6a4SAndroid Build Coastguard Worker     }
105*bb4ee6a4SAndroid Build Coastguard Worker 
from_descriptor_offset( file_handle: &dyn AsRawDescriptor, size: usize, offset: u64, ) -> Result<MemoryMapping>106*bb4ee6a4SAndroid Build Coastguard Worker     pub fn from_descriptor_offset(
107*bb4ee6a4SAndroid Build Coastguard Worker         file_handle: &dyn AsRawDescriptor,
108*bb4ee6a4SAndroid Build Coastguard Worker         size: usize,
109*bb4ee6a4SAndroid Build Coastguard Worker         offset: u64,
110*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<MemoryMapping> {
111*bb4ee6a4SAndroid Build Coastguard Worker         MemoryMapping::from_descriptor_offset_protection(
112*bb4ee6a4SAndroid Build Coastguard Worker             file_handle,
113*bb4ee6a4SAndroid Build Coastguard Worker             size,
114*bb4ee6a4SAndroid Build Coastguard Worker             offset,
115*bb4ee6a4SAndroid Build Coastguard Worker             Protection::read_write(),
116*bb4ee6a4SAndroid Build Coastguard Worker         )
117*bb4ee6a4SAndroid Build Coastguard Worker     }
118*bb4ee6a4SAndroid Build Coastguard Worker 
119*bb4ee6a4SAndroid Build Coastguard Worker     // Check that offset+count is valid and return the sum.
range_end(&self, offset: usize, count: usize) -> Result<usize>120*bb4ee6a4SAndroid Build Coastguard Worker     pub(crate) fn range_end(&self, offset: usize, count: usize) -> Result<usize> {
121*bb4ee6a4SAndroid Build Coastguard Worker         let mem_end = offset.checked_add(count).ok_or(Error::InvalidAddress)?;
122*bb4ee6a4SAndroid Build Coastguard Worker         if mem_end > self.size() {
123*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::InvalidAddress);
124*bb4ee6a4SAndroid Build Coastguard Worker         }
125*bb4ee6a4SAndroid Build Coastguard Worker         Ok(mem_end)
126*bb4ee6a4SAndroid Build Coastguard Worker     }
127*bb4ee6a4SAndroid Build Coastguard Worker }
128*bb4ee6a4SAndroid Build Coastguard Worker 
129*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
130*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the pointer and size point to a memory range owned by this MemoryMapping that won't
131*bb4ee6a4SAndroid Build Coastguard Worker // be unmapped until it's Dropped.
132*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl MappedRegion for MemoryMapping {
as_ptr(&self) -> *mut u8133*bb4ee6a4SAndroid Build Coastguard Worker     fn as_ptr(&self) -> *mut u8 {
134*bb4ee6a4SAndroid Build Coastguard Worker         self.addr as *mut u8
135*bb4ee6a4SAndroid Build Coastguard Worker     }
136*bb4ee6a4SAndroid Build Coastguard Worker 
size(&self) -> usize137*bb4ee6a4SAndroid Build Coastguard Worker     fn size(&self) -> usize {
138*bb4ee6a4SAndroid Build Coastguard Worker         self.size
139*bb4ee6a4SAndroid Build Coastguard Worker     }
140*bb4ee6a4SAndroid Build Coastguard Worker }
141*bb4ee6a4SAndroid Build Coastguard Worker 
142*bb4ee6a4SAndroid Build Coastguard Worker impl CrateMemoryMapping {
from_raw_ptr(addr: RawDescriptor, size: usize) -> Result<CrateMemoryMapping>143*bb4ee6a4SAndroid Build Coastguard Worker     pub fn from_raw_ptr(addr: RawDescriptor, size: usize) -> Result<CrateMemoryMapping> {
144*bb4ee6a4SAndroid Build Coastguard Worker         MemoryMapping::from_raw_ptr(addr, size).map(|mapping| CrateMemoryMapping {
145*bb4ee6a4SAndroid Build Coastguard Worker             mapping,
146*bb4ee6a4SAndroid Build Coastguard Worker             _file_descriptor: None,
147*bb4ee6a4SAndroid Build Coastguard Worker         })
148*bb4ee6a4SAndroid Build Coastguard Worker     }
149*bb4ee6a4SAndroid Build Coastguard Worker }
150*bb4ee6a4SAndroid Build Coastguard Worker 
151*bb4ee6a4SAndroid Build Coastguard Worker pub trait MemoryMappingBuilderWindows<'a> {
152*bb4ee6a4SAndroid Build Coastguard Worker     /// Build the memory mapping given the specified descriptor to mapped memory
153*bb4ee6a4SAndroid Build Coastguard Worker     ///
154*bb4ee6a4SAndroid Build Coastguard Worker     /// Default: Create a new memory mapping.
155*bb4ee6a4SAndroid Build Coastguard Worker     ///
156*bb4ee6a4SAndroid Build Coastguard Worker     /// descriptor MUST be a mapping handle. Files MUST use `MemoryMappingBuilder::from_file`
157*bb4ee6a4SAndroid Build Coastguard Worker     /// instead.
158*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(clippy::wrong_self_convention)]
from_descriptor(self, descriptor: &'a dyn AsRawDescriptor) -> MemoryMappingBuilder159*bb4ee6a4SAndroid Build Coastguard Worker     fn from_descriptor(self, descriptor: &'a dyn AsRawDescriptor) -> MemoryMappingBuilder;
160*bb4ee6a4SAndroid Build Coastguard Worker }
161*bb4ee6a4SAndroid Build Coastguard Worker 
162*bb4ee6a4SAndroid Build Coastguard Worker impl<'a> MemoryMappingBuilderWindows<'a> for MemoryMappingBuilder<'a> {
163*bb4ee6a4SAndroid Build Coastguard Worker     /// See MemoryMappingBuilderWindows.
from_descriptor(mut self, descriptor: &'a dyn AsRawDescriptor) -> MemoryMappingBuilder164*bb4ee6a4SAndroid Build Coastguard Worker     fn from_descriptor(mut self, descriptor: &'a dyn AsRawDescriptor) -> MemoryMappingBuilder {
165*bb4ee6a4SAndroid Build Coastguard Worker         self.descriptor = Some(descriptor);
166*bb4ee6a4SAndroid Build Coastguard Worker         self
167*bb4ee6a4SAndroid Build Coastguard Worker     }
168*bb4ee6a4SAndroid Build Coastguard Worker }
169*bb4ee6a4SAndroid Build Coastguard Worker 
170*bb4ee6a4SAndroid Build Coastguard Worker impl<'a> MemoryMappingBuilder<'a> {
171*bb4ee6a4SAndroid Build Coastguard Worker     /// Build a MemoryMapping from the provided options.
build(self) -> Result<CrateMemoryMapping>172*bb4ee6a4SAndroid Build Coastguard Worker     pub fn build(self) -> Result<CrateMemoryMapping> {
173*bb4ee6a4SAndroid Build Coastguard Worker         match self.descriptor {
174*bb4ee6a4SAndroid Build Coastguard Worker             Some(descriptor) => {
175*bb4ee6a4SAndroid Build Coastguard Worker                 let mapping_descriptor = if self.is_file_descriptor {
176*bb4ee6a4SAndroid Build Coastguard Worker                     // On Windows, a file cannot be mmapped directly. We have to create a mapping
177*bb4ee6a4SAndroid Build Coastguard Worker                     // handle for it first. That handle is then provided to Self::wrap, which
178*bb4ee6a4SAndroid Build Coastguard Worker                     // performs the actual mmap (creating a mapped view).
179*bb4ee6a4SAndroid Build Coastguard Worker                     //
180*bb4ee6a4SAndroid Build Coastguard Worker                     // SAFETY:
181*bb4ee6a4SAndroid Build Coastguard Worker                     // Safe because self.descriptor is guaranteed to be a valid handle.
182*bb4ee6a4SAndroid Build Coastguard Worker                     let mapping_handle = unsafe {
183*bb4ee6a4SAndroid Build Coastguard Worker                         create_file_mapping(
184*bb4ee6a4SAndroid Build Coastguard Worker                             Some(descriptor.as_raw_descriptor()),
185*bb4ee6a4SAndroid Build Coastguard Worker                             self.size as u64,
186*bb4ee6a4SAndroid Build Coastguard Worker                             PAGE_READWRITE,
187*bb4ee6a4SAndroid Build Coastguard Worker                             None,
188*bb4ee6a4SAndroid Build Coastguard Worker                         )
189*bb4ee6a4SAndroid Build Coastguard Worker                     }
190*bb4ee6a4SAndroid Build Coastguard Worker                     .map_err(Error::StdSyscallFailed)?;
191*bb4ee6a4SAndroid Build Coastguard Worker 
192*bb4ee6a4SAndroid Build Coastguard Worker                     // SAFETY:
193*bb4ee6a4SAndroid Build Coastguard Worker                     // The above comment block is why the SafeDescriptor wrap is safe.
194*bb4ee6a4SAndroid Build Coastguard Worker                     Some(unsafe { SafeDescriptor::from_raw_descriptor(mapping_handle) })
195*bb4ee6a4SAndroid Build Coastguard Worker                 } else {
196*bb4ee6a4SAndroid Build Coastguard Worker                     None
197*bb4ee6a4SAndroid Build Coastguard Worker                 };
198*bb4ee6a4SAndroid Build Coastguard Worker 
199*bb4ee6a4SAndroid Build Coastguard Worker                 MemoryMappingBuilder::wrap(
200*bb4ee6a4SAndroid Build Coastguard Worker                     MemoryMapping::from_descriptor_offset_protection(
201*bb4ee6a4SAndroid Build Coastguard Worker                         match mapping_descriptor.as_ref() {
202*bb4ee6a4SAndroid Build Coastguard Worker                             Some(descriptor) => descriptor as &dyn AsRawDescriptor,
203*bb4ee6a4SAndroid Build Coastguard Worker                             None => descriptor,
204*bb4ee6a4SAndroid Build Coastguard Worker                         },
205*bb4ee6a4SAndroid Build Coastguard Worker                         self.size,
206*bb4ee6a4SAndroid Build Coastguard Worker                         self.offset.unwrap_or(0),
207*bb4ee6a4SAndroid Build Coastguard Worker                         self.protection.unwrap_or_else(Protection::read_write),
208*bb4ee6a4SAndroid Build Coastguard Worker                     )?,
209*bb4ee6a4SAndroid Build Coastguard Worker                     if self.is_file_descriptor {
210*bb4ee6a4SAndroid Build Coastguard Worker                         self.descriptor
211*bb4ee6a4SAndroid Build Coastguard Worker                     } else {
212*bb4ee6a4SAndroid Build Coastguard Worker                         None
213*bb4ee6a4SAndroid Build Coastguard Worker                     },
214*bb4ee6a4SAndroid Build Coastguard Worker                 )
215*bb4ee6a4SAndroid Build Coastguard Worker             }
216*bb4ee6a4SAndroid Build Coastguard Worker             None => MemoryMappingBuilder::wrap(
217*bb4ee6a4SAndroid Build Coastguard Worker                 MemoryMapping::new_protection(
218*bb4ee6a4SAndroid Build Coastguard Worker                     self.size,
219*bb4ee6a4SAndroid Build Coastguard Worker                     self.protection.unwrap_or_else(Protection::read_write),
220*bb4ee6a4SAndroid Build Coastguard Worker                 )?,
221*bb4ee6a4SAndroid Build Coastguard Worker                 None,
222*bb4ee6a4SAndroid Build Coastguard Worker             ),
223*bb4ee6a4SAndroid Build Coastguard Worker         }
224*bb4ee6a4SAndroid Build Coastguard Worker     }
wrap( mapping: MemoryMapping, file_descriptor: Option<&'a dyn AsRawDescriptor>, ) -> Result<CrateMemoryMapping>225*bb4ee6a4SAndroid Build Coastguard Worker     pub fn wrap(
226*bb4ee6a4SAndroid Build Coastguard Worker         mapping: MemoryMapping,
227*bb4ee6a4SAndroid Build Coastguard Worker         file_descriptor: Option<&'a dyn AsRawDescriptor>,
228*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<CrateMemoryMapping> {
229*bb4ee6a4SAndroid Build Coastguard Worker         let file_descriptor = match file_descriptor {
230*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY:
231*bb4ee6a4SAndroid Build Coastguard Worker             // Safe because `duplicate_handle` will return a handle or at least error out.
232*bb4ee6a4SAndroid Build Coastguard Worker             Some(descriptor) => unsafe {
233*bb4ee6a4SAndroid Build Coastguard Worker                 Some(SafeDescriptor::from_raw_descriptor(
234*bb4ee6a4SAndroid Build Coastguard Worker                     duplicate_handle(descriptor.as_raw_descriptor())
235*bb4ee6a4SAndroid Build Coastguard Worker                         .map_err(Error::StdSyscallFailed)?,
236*bb4ee6a4SAndroid Build Coastguard Worker                 ))
237*bb4ee6a4SAndroid Build Coastguard Worker             },
238*bb4ee6a4SAndroid Build Coastguard Worker             None => None,
239*bb4ee6a4SAndroid Build Coastguard Worker         };
240*bb4ee6a4SAndroid Build Coastguard Worker 
241*bb4ee6a4SAndroid Build Coastguard Worker         Ok(CrateMemoryMapping {
242*bb4ee6a4SAndroid Build Coastguard Worker             mapping,
243*bb4ee6a4SAndroid Build Coastguard Worker             _file_descriptor: file_descriptor,
244*bb4ee6a4SAndroid Build Coastguard Worker         })
245*bb4ee6a4SAndroid Build Coastguard Worker     }
246*bb4ee6a4SAndroid Build Coastguard Worker }
247*bb4ee6a4SAndroid Build Coastguard Worker 
248*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
249*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
250*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
251*bb4ee6a4SAndroid Build Coastguard Worker     use crate::SharedMemory;
252*bb4ee6a4SAndroid Build Coastguard Worker     use crate::VolatileMemory;
253*bb4ee6a4SAndroid Build Coastguard Worker     use crate::VolatileMemoryError;
254*bb4ee6a4SAndroid Build Coastguard Worker 
255*bb4ee6a4SAndroid Build Coastguard Worker     // get_slice() and other methods are only available on crate::MemoryMapping.
to_crate_mmap(mapping: MemoryMapping) -> crate::MemoryMapping256*bb4ee6a4SAndroid Build Coastguard Worker     fn to_crate_mmap(mapping: MemoryMapping) -> crate::MemoryMapping {
257*bb4ee6a4SAndroid Build Coastguard Worker         crate::MemoryMapping {
258*bb4ee6a4SAndroid Build Coastguard Worker             mapping,
259*bb4ee6a4SAndroid Build Coastguard Worker             _file_descriptor: None,
260*bb4ee6a4SAndroid Build Coastguard Worker         }
261*bb4ee6a4SAndroid Build Coastguard Worker     }
262*bb4ee6a4SAndroid Build Coastguard Worker 
263*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
basic_map()264*bb4ee6a4SAndroid Build Coastguard Worker     fn basic_map() {
265*bb4ee6a4SAndroid Build Coastguard Worker         let shm = SharedMemory::new("test", 1028).unwrap();
266*bb4ee6a4SAndroid Build Coastguard Worker         let m = to_crate_mmap(MemoryMapping::from_descriptor(&shm, 1024).unwrap());
267*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(1024, m.size());
268*bb4ee6a4SAndroid Build Coastguard Worker     }
269*bb4ee6a4SAndroid Build Coastguard Worker 
270*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
test_write_past_end()271*bb4ee6a4SAndroid Build Coastguard Worker     fn test_write_past_end() {
272*bb4ee6a4SAndroid Build Coastguard Worker         let shm = SharedMemory::new("test", 1028).unwrap();
273*bb4ee6a4SAndroid Build Coastguard Worker         let m = to_crate_mmap(MemoryMapping::from_descriptor(&shm, 5).unwrap());
274*bb4ee6a4SAndroid Build Coastguard Worker         let res = m.write_slice(&[1, 2, 3, 4, 5, 6], 0);
275*bb4ee6a4SAndroid Build Coastguard Worker         assert!(res.is_ok());
276*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(res.unwrap(), 5);
277*bb4ee6a4SAndroid Build Coastguard Worker     }
278*bb4ee6a4SAndroid Build Coastguard Worker 
279*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
slice_size()280*bb4ee6a4SAndroid Build Coastguard Worker     fn slice_size() {
281*bb4ee6a4SAndroid Build Coastguard Worker         let shm = SharedMemory::new("test", 1028).unwrap();
282*bb4ee6a4SAndroid Build Coastguard Worker         let m = to_crate_mmap(MemoryMapping::from_descriptor(&shm, 5).unwrap());
283*bb4ee6a4SAndroid Build Coastguard Worker         let s = m.get_slice(2, 3).unwrap();
284*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(s.size(), 3);
285*bb4ee6a4SAndroid Build Coastguard Worker     }
286*bb4ee6a4SAndroid Build Coastguard Worker 
287*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
slice_addr()288*bb4ee6a4SAndroid Build Coastguard Worker     fn slice_addr() {
289*bb4ee6a4SAndroid Build Coastguard Worker         let shm = SharedMemory::new("test", 1028).unwrap();
290*bb4ee6a4SAndroid Build Coastguard Worker         let m = to_crate_mmap(MemoryMapping::from_descriptor(&shm, 5).unwrap());
291*bb4ee6a4SAndroid Build Coastguard Worker         let s = m.get_slice(2, 3).unwrap();
292*bb4ee6a4SAndroid Build Coastguard Worker         // SAFETY: trivially safe
293*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(s.as_ptr(), unsafe { m.as_ptr().offset(2) });
294*bb4ee6a4SAndroid Build Coastguard Worker     }
295*bb4ee6a4SAndroid Build Coastguard Worker 
296*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
slice_overflow_error()297*bb4ee6a4SAndroid Build Coastguard Worker     fn slice_overflow_error() {
298*bb4ee6a4SAndroid Build Coastguard Worker         let shm = SharedMemory::new("test", 1028).unwrap();
299*bb4ee6a4SAndroid Build Coastguard Worker         let m = to_crate_mmap(MemoryMapping::from_descriptor(&shm, 5).unwrap());
300*bb4ee6a4SAndroid Build Coastguard Worker         let res = m.get_slice(usize::MAX, 3).unwrap_err();
301*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
302*bb4ee6a4SAndroid Build Coastguard Worker             res,
303*bb4ee6a4SAndroid Build Coastguard Worker             VolatileMemoryError::Overflow {
304*bb4ee6a4SAndroid Build Coastguard Worker                 base: usize::MAX,
305*bb4ee6a4SAndroid Build Coastguard Worker                 offset: 3,
306*bb4ee6a4SAndroid Build Coastguard Worker             }
307*bb4ee6a4SAndroid Build Coastguard Worker         );
308*bb4ee6a4SAndroid Build Coastguard Worker     }
309*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
slice_oob_error()310*bb4ee6a4SAndroid Build Coastguard Worker     fn slice_oob_error() {
311*bb4ee6a4SAndroid Build Coastguard Worker         let shm = SharedMemory::new("test", 1028).unwrap();
312*bb4ee6a4SAndroid Build Coastguard Worker         let m = to_crate_mmap(MemoryMapping::from_descriptor(&shm, 5).unwrap());
313*bb4ee6a4SAndroid Build Coastguard Worker         let res = m.get_slice(3, 3).unwrap_err();
314*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(res, VolatileMemoryError::OutOfBounds { addr: 6 });
315*bb4ee6a4SAndroid Build Coastguard Worker     }
316*bb4ee6a4SAndroid Build Coastguard Worker }
317