1 #![allow(clippy::redundant_slicing)]
2 
3 use nix::sys::mman::{mmap_anonymous, MapFlags, ProtFlags};
4 use std::num::NonZeroUsize;
5 
6 #[test]
test_mmap_anonymous()7 fn test_mmap_anonymous() {
8     unsafe {
9         let mut ptr = mmap_anonymous(
10             None,
11             NonZeroUsize::new(1).unwrap(),
12             ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
13             MapFlags::MAP_PRIVATE,
14         )
15         .unwrap()
16         .cast::<u8>();
17         assert_eq!(*ptr.as_ref(), 0x00u8);
18         *ptr.as_mut() = 0xffu8;
19         assert_eq!(*ptr.as_ref(), 0xffu8);
20     }
21 }
22 
23 #[test]
24 #[cfg(any(target_os = "linux", target_os = "netbsd"))]
test_mremap_grow()25 fn test_mremap_grow() {
26     use nix::libc::size_t;
27     use nix::sys::mman::{mremap, MRemapFlags};
28     use std::ptr::NonNull;
29 
30     const ONE_K: size_t = 1024;
31     let one_k_non_zero = NonZeroUsize::new(ONE_K).unwrap();
32 
33     let slice: &mut [u8] = unsafe {
34         let mem = mmap_anonymous(
35             None,
36             one_k_non_zero,
37             ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
38             MapFlags::MAP_PRIVATE,
39         )
40         .unwrap();
41         std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
42     };
43     assert_eq!(slice[ONE_K - 1], 0x00);
44     slice[ONE_K - 1] = 0xFF;
45     assert_eq!(slice[ONE_K - 1], 0xFF);
46 
47     let slice: &mut [u8] = unsafe {
48         #[cfg(target_os = "linux")]
49         let mem = mremap(
50             NonNull::from(&mut slice[..]).cast(),
51             ONE_K,
52             10 * ONE_K,
53             MRemapFlags::MREMAP_MAYMOVE,
54             None,
55         )
56         .unwrap();
57         #[cfg(target_os = "netbsd")]
58         let mem = mremap(
59             NonNull::from(&mut slice[..]).cast(),
60             ONE_K,
61             10 * ONE_K,
62             MRemapFlags::MAP_REMAPDUP,
63             None,
64         )
65         .unwrap();
66         std::slice::from_raw_parts_mut(mem.cast().as_ptr(), 10 * ONE_K)
67     };
68 
69     // The first KB should still have the old data in it.
70     assert_eq!(slice[ONE_K - 1], 0xFF);
71 
72     // The additional range should be zero-init'd and accessible.
73     assert_eq!(slice[10 * ONE_K - 1], 0x00);
74     slice[10 * ONE_K - 1] = 0xFF;
75     assert_eq!(slice[10 * ONE_K - 1], 0xFF);
76 }
77 
78 #[test]
79 #[cfg(any(target_os = "linux", target_os = "netbsd"))]
80 // Segfaults for unknown reasons under QEMU for 32-bit targets
81 #[cfg_attr(all(target_pointer_width = "32", qemu), ignore)]
test_mremap_shrink()82 fn test_mremap_shrink() {
83     use nix::libc::size_t;
84     use nix::sys::mman::{mremap, MRemapFlags};
85     use std::num::NonZeroUsize;
86     use std::ptr::NonNull;
87 
88     const ONE_K: size_t = 1024;
89     let ten_one_k = NonZeroUsize::new(10 * ONE_K).unwrap();
90     let slice: &mut [u8] = unsafe {
91         let mem = mmap_anonymous(
92             None,
93             ten_one_k,
94             ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
95             MapFlags::MAP_PRIVATE,
96         )
97         .unwrap();
98         std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
99     };
100     assert_eq!(slice[ONE_K - 1], 0x00);
101     slice[ONE_K - 1] = 0xFF;
102     assert_eq!(slice[ONE_K - 1], 0xFF);
103 
104     let slice: &mut [u8] = unsafe {
105         let mem = mremap(
106             NonNull::from(&mut slice[..]).cast(),
107             ten_one_k.into(),
108             ONE_K,
109             MRemapFlags::empty(),
110             None,
111         )
112         .unwrap();
113         // Since we didn't supply MREMAP_MAYMOVE, the address should be the
114         // same.
115         assert_eq!(mem.as_ptr(), NonNull::from(&mut slice[..]).cast().as_ptr());
116         std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
117     };
118 
119     // The first KB should still be accessible and have the old data in it.
120     assert_eq!(slice[ONE_K - 1], 0xFF);
121 }
122