Skip to content

Commit 1ea59c7

Browse files
feat: mman NonNull (#2000)
* feat: mmap `NonNull` * feat: munmap `NonNull` * feat: mremap `NonNull` * feat: madvise `NonNull` * feat: msync `NonNull` * feat: mprotect `NonNull` * feat: munlock `NonNull` * feat mlock `NonNull`
1 parent 7c1045e commit 1ea59c7

File tree

3 files changed

+54
-43
lines changed

3 files changed

+54
-43
lines changed

changelog/2000.changed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
`mmap`, `mmap_anonymous`, `munmap`, `mremap`, `madvise`, `msync`, `mprotect`, `munlock` and `mlock` updated to use `NonNull`.

src/sys/mman.rs

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@ use crate::Result;
88
#[cfg(feature = "fs")]
99
use crate::{fcntl::OFlag, sys::stat::Mode};
1010
use libc::{self, c_int, c_void, off_t, size_t};
11-
use std::{
12-
num::NonZeroUsize,
13-
os::unix::io::{AsFd, AsRawFd},
14-
};
11+
use std::{num::NonZeroUsize, os::unix::io::{AsRawFd, AsFd}};
12+
use std::ptr::NonNull;
1513

1614
libc_bitflags! {
1715
/// Desired memory protection of a memory mapping.
@@ -377,8 +375,8 @@ libc_bitflags! {
377375
/// `addr` must meet all the requirements described in the [`mlock(2)`] man page.
378376
///
379377
/// [`mlock(2)`]: https://man7.org/linux/man-pages/man2/mlock.2.html
380-
pub unsafe fn mlock(addr: *const c_void, length: size_t) -> Result<()> {
381-
Errno::result(libc::mlock(addr, length)).map(drop)
378+
pub unsafe fn mlock(addr: NonNull<c_void>, length: size_t) -> Result<()> {
379+
Errno::result(libc::mlock(addr.as_ptr(), length)).map(drop)
382380
}
383381

384382
/// Unlocks all memory pages that contain part of the address range with
@@ -390,8 +388,8 @@ pub unsafe fn mlock(addr: *const c_void, length: size_t) -> Result<()> {
390388
/// page.
391389
///
392390
/// [`munlock(2)`]: https://man7.org/linux/man-pages/man2/munlock.2.html
393-
pub unsafe fn munlock(addr: *const c_void, length: size_t) -> Result<()> {
394-
Errno::result(libc::munlock(addr, length)).map(drop)
391+
pub unsafe fn munlock(addr: NonNull<c_void>, length: size_t) -> Result<()> {
392+
Errno::result(libc::munlock(addr.as_ptr(), length)).map(drop)
395393
}
396394

397395
/// Locks all memory pages mapped into this process' address space.
@@ -430,7 +428,7 @@ pub unsafe fn mmap<F: AsFd>(
430428
flags: MapFlags,
431429
f: F,
432430
offset: off_t,
433-
) -> Result<*mut c_void> {
431+
) -> Result<NonNull<c_void>> {
434432
let ptr = addr.map_or(std::ptr::null_mut(), |a| a.get() as *mut c_void);
435433

436434
let fd = f.as_fd().as_raw_fd();
@@ -439,9 +437,12 @@ pub unsafe fn mmap<F: AsFd>(
439437

440438
if ret == libc::MAP_FAILED {
441439
Err(Errno::last())
442-
} else {
443-
Ok(ret)
444440
}
441+
else {
442+
// SAFETY: `libc::mmap` returns a valid non-null pointer or `libc::MAP_FAILED`, thus `ret`
443+
// will be non-null here.
444+
Ok(unsafe { NonNull::new_unchecked(ret) })
445+
}
445446
}
446447

447448
/// Create an anonymous memory mapping.
@@ -459,7 +460,7 @@ pub unsafe fn mmap_anonymous(
459460
length: NonZeroUsize,
460461
prot: ProtFlags,
461462
flags: MapFlags,
462-
) -> Result<*mut c_void> {
463+
) -> Result<NonNull<c_void>> {
463464
let ptr = addr.map_or(std::ptr::null_mut(), |a| a.get() as *mut c_void);
464465

465466
let flags = MapFlags::MAP_ANONYMOUS | flags;
@@ -468,7 +469,9 @@ pub unsafe fn mmap_anonymous(
468469
if ret == libc::MAP_FAILED {
469470
Err(Errno::last())
470471
} else {
471-
Ok(ret)
472+
// SAFETY: `libc::mmap` returns a valid non-null pointer or `libc::MAP_FAILED`, thus `ret`
473+
// will be non-null here.
474+
Ok(unsafe { NonNull::new_unchecked(ret) })
472475
}
473476
}
474477

@@ -481,33 +484,35 @@ pub unsafe fn mmap_anonymous(
481484
/// detailed requirements.
482485
#[cfg(any(target_os = "linux", target_os = "netbsd"))]
483486
pub unsafe fn mremap(
484-
addr: *mut c_void,
487+
addr: NonNull<c_void>,
485488
old_size: size_t,
486489
new_size: size_t,
487490
flags: MRemapFlags,
488-
new_address: Option<*mut c_void>,
489-
) -> Result<*mut c_void> {
491+
new_address: Option<NonNull<c_void>>,
492+
) -> Result<NonNull<c_void>> {
490493
#[cfg(target_os = "linux")]
491494
let ret = libc::mremap(
492-
addr,
495+
addr.as_ptr(),
493496
old_size,
494497
new_size,
495498
flags.bits(),
496-
new_address.unwrap_or(std::ptr::null_mut()),
499+
new_address.map(NonNull::as_ptr).unwrap_or(std::ptr::null_mut()),
497500
);
498501
#[cfg(target_os = "netbsd")]
499502
let ret = libc::mremap(
500-
addr,
503+
addr.as_ptr(),
501504
old_size,
502-
new_address.unwrap_or(std::ptr::null_mut()),
505+
new_address.map(NonNull::as_ptr).unwrap_or(std::ptr::null_mut()),
503506
new_size,
504507
flags.bits(),
505508
);
506509

507510
if ret == libc::MAP_FAILED {
508511
Err(Errno::last())
509512
} else {
510-
Ok(ret)
513+
// SAFETY: `libc::mremap` returns a valid non-null pointer or `libc::MAP_FAILED`, thus `ret`
514+
// will be non-null here.
515+
Ok(unsafe { NonNull::new_unchecked(ret) })
511516
}
512517
}
513518

@@ -519,8 +524,8 @@ pub unsafe fn mremap(
519524
/// page.
520525
///
521526
/// [`munmap(2)`]: https://man7.org/linux/man-pages/man2/munmap.2.html
522-
pub unsafe fn munmap(addr: *mut c_void, len: size_t) -> Result<()> {
523-
Errno::result(libc::munmap(addr, len)).map(drop)
527+
pub unsafe fn munmap(addr: NonNull<c_void>, len: size_t) -> Result<()> {
528+
Errno::result(libc::munmap(addr.as_ptr(), len)).map(drop)
524529
}
525530

526531
/// give advice about use of memory
@@ -532,11 +537,11 @@ pub unsafe fn munmap(addr: *mut c_void, len: size_t) -> Result<()> {
532537
///
533538
/// [`madvise(2)`]: https://man7.org/linux/man-pages/man2/madvise.2.html
534539
pub unsafe fn madvise(
535-
addr: *mut c_void,
540+
addr: NonNull<c_void>,
536541
length: size_t,
537542
advise: MmapAdvise,
538543
) -> Result<()> {
539-
Errno::result(libc::madvise(addr, length, advise as i32)).map(drop)
544+
Errno::result(libc::madvise(addr.as_ptr(), length, advise as i32)).map(drop)
540545
}
541546

542547
/// Set protection of memory mapping.
@@ -560,18 +565,18 @@ pub unsafe fn madvise(
560565
/// let mem = mmap_anonymous(None, one_k_non_zero, ProtFlags::PROT_NONE, MapFlags::MAP_PRIVATE)
561566
/// .unwrap();
562567
/// mprotect(mem, ONE_K, ProtFlags::PROT_READ | ProtFlags::PROT_WRITE).unwrap();
563-
/// std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
568+
/// std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
564569
/// };
565570
/// assert_eq!(slice[0], 0x00);
566571
/// slice[0] = 0xFF;
567572
/// assert_eq!(slice[0], 0xFF);
568573
/// ```
569574
pub unsafe fn mprotect(
570-
addr: *mut c_void,
575+
addr: NonNull<c_void>,
571576
length: size_t,
572577
prot: ProtFlags,
573578
) -> Result<()> {
574-
Errno::result(libc::mprotect(addr, length, prot.bits())).map(drop)
579+
Errno::result(libc::mprotect(addr.as_ptr(), length, prot.bits())).map(drop)
575580
}
576581

577582
/// synchronize a mapped region
@@ -583,11 +588,11 @@ pub unsafe fn mprotect(
583588
///
584589
/// [`msync(2)`]: https://man7.org/linux/man-pages/man2/msync.2.html
585590
pub unsafe fn msync(
586-
addr: *mut c_void,
591+
addr: NonNull<c_void>,
587592
length: size_t,
588593
flags: MsFlags,
589594
) -> Result<()> {
590-
Errno::result(libc::msync(addr, length, flags.bits())).map(drop)
595+
Errno::result(libc::msync(addr.as_ptr(), length, flags.bits())).map(drop)
591596
}
592597

593598
#[cfg(not(target_os = "android"))]

test/sys/test_mman.rs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
1+
#![allow(clippy::redundant_slicing)]
2+
13
use nix::sys::mman::{mmap_anonymous, MapFlags, ProtFlags};
24
use std::num::NonZeroUsize;
35

46
#[test]
57
fn test_mmap_anonymous() {
68
unsafe {
7-
let ptr = mmap_anonymous(
9+
let mut ptr = mmap_anonymous(
810
None,
911
NonZeroUsize::new(1).unwrap(),
1012
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
1113
MapFlags::MAP_PRIVATE,
1214
)
13-
.unwrap() as *mut u8;
14-
assert_eq!(*ptr, 0x00u8);
15-
*ptr = 0xffu8;
16-
assert_eq!(*ptr, 0xffu8);
15+
.unwrap()
16+
.cast::<u8>();
17+
assert_eq!(*ptr.as_ref(), 0x00u8);
18+
*ptr.as_mut() = 0xffu8;
19+
assert_eq!(*ptr.as_ref(), 0xffu8);
1720
}
1821
}
1922

@@ -22,6 +25,7 @@ fn test_mmap_anonymous() {
2225
fn test_mremap_grow() {
2326
use nix::libc::size_t;
2427
use nix::sys::mman::{mremap, MRemapFlags};
28+
use std::ptr::NonNull;
2529

2630
const ONE_K: size_t = 1024;
2731
let one_k_non_zero = NonZeroUsize::new(ONE_K).unwrap();
@@ -34,7 +38,7 @@ fn test_mremap_grow() {
3438
MapFlags::MAP_PRIVATE,
3539
)
3640
.unwrap();
37-
std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
41+
std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
3842
};
3943
assert_eq!(slice[ONE_K - 1], 0x00);
4044
slice[ONE_K - 1] = 0xFF;
@@ -43,7 +47,7 @@ fn test_mremap_grow() {
4347
let slice: &mut [u8] = unsafe {
4448
#[cfg(target_os = "linux")]
4549
let mem = mremap(
46-
slice.as_mut_ptr().cast(),
50+
NonNull::from(&mut slice[..]).cast(),
4751
ONE_K,
4852
10 * ONE_K,
4953
MRemapFlags::MREMAP_MAYMOVE,
@@ -52,14 +56,14 @@ fn test_mremap_grow() {
5256
.unwrap();
5357
#[cfg(target_os = "netbsd")]
5458
let mem = mremap(
55-
slice.as_mut_ptr().cast(),
59+
NonNull::from(&mut slice[..]).cast(),
5660
ONE_K,
5761
10 * ONE_K,
5862
MRemapFlags::MAP_REMAPDUP,
5963
None,
6064
)
6165
.unwrap();
62-
std::slice::from_raw_parts_mut(mem as *mut u8, 10 * ONE_K)
66+
std::slice::from_raw_parts_mut(mem.cast().as_ptr(), 10 * ONE_K)
6367
};
6468

6569
// The first KB should still have the old data in it.
@@ -79,6 +83,7 @@ fn test_mremap_shrink() {
7983
use nix::libc::size_t;
8084
use nix::sys::mman::{mremap, MRemapFlags};
8185
use std::num::NonZeroUsize;
86+
use std::ptr::NonNull;
8287

8388
const ONE_K: size_t = 1024;
8489
let ten_one_k = NonZeroUsize::new(10 * ONE_K).unwrap();
@@ -90,15 +95,15 @@ fn test_mremap_shrink() {
9095
MapFlags::MAP_PRIVATE,
9196
)
9297
.unwrap();
93-
std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
98+
std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
9499
};
95100
assert_eq!(slice[ONE_K - 1], 0x00);
96101
slice[ONE_K - 1] = 0xFF;
97102
assert_eq!(slice[ONE_K - 1], 0xFF);
98103

99104
let slice: &mut [u8] = unsafe {
100105
let mem = mremap(
101-
slice.as_mut_ptr().cast(),
106+
NonNull::from(&mut slice[..]).cast(),
102107
ten_one_k.into(),
103108
ONE_K,
104109
MRemapFlags::empty(),
@@ -107,8 +112,8 @@ fn test_mremap_shrink() {
107112
.unwrap();
108113
// Since we didn't supply MREMAP_MAYMOVE, the address should be the
109114
// same.
110-
assert_eq!(mem, slice.as_mut_ptr().cast());
111-
std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
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)
112117
};
113118

114119
// The first KB should still be accessible and have the old data in it.

0 commit comments

Comments
 (0)