1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#![cfg_attr(not(feature = "use_os"), no_std)]
#![cfg_attr(feature = "nightly", feature(core_intrinsics))]
#[cfg(feature = "alloc")] extern crate rand;
#[cfg(all(unix, feature = "use_os"))] extern crate libc;
#[cfg(all(windows, feature = "use_os"))] extern crate winapi;
#[cfg(all(windows, feature = "use_os"))] extern crate kernel32;
#[cfg(all(apple, feature = "use_os"))]
extern crate mach_o_sys;
mod mlock;
mod alloc;
#[cfg(feature = "use_os")] use std::ptr;
#[cfg(not(feature = "use_os"))] use core::ptr;
#[cfg(feature = "use_os")] pub use mlock::{ mlock, munlock };
#[cfg(feature = "alloc")] pub use alloc::{ Prot, mprotect, malloc, allocarray, free };
#[inline(never)]
pub unsafe fn memeq<T>(b1: *const T, b2: *const T, len: usize) -> bool {
let b1 = b1 as *const u8;
let b2 = b2 as *const u8;
(0..len as isize)
.map(|i| ptr::read_volatile(b1.offset(i)) ^ ptr::read_volatile(b2.offset(i)))
.fold(0, |sum, next| sum | next)
.eq(&0)
}
#[inline(never)]
pub unsafe fn memcmp<T>(b1: *const T, b2: *const T, len: usize) -> i32 {
let b1 = b1 as *const u8;
let b2 = b2 as *const u8;
let mut res = 0;
for i in (0..len as isize).rev() {
let diff = i32::from(ptr::read_volatile(b1.offset(i)))
- i32::from(ptr::read_volatile(b2.offset(i)));
res = (res & (((diff - 1) & !diff) >> 8)) | diff;
}
((res - 1) >> 8) + (res >> 8) + 1
}
#[cfg(feature = "nightly")]
#[cfg(any(not(apple), not(feature = "use_os")))]
#[inline(never)]
pub unsafe fn memset<T>(s: *mut T, c: i32, n: usize) {
#[cfg(feature = "use_os")]
use std::intrinsics;
#[cfg(not(feature = "use_os"))]
use core::intrinsics;
intrinsics::volatile_set_memory(s as *mut u8, c as u8, n);
}
#[cfg(not(feature = "nightly"))]
#[cfg(any(not(apple), not(feature = "use_os")))]
#[inline(never)]
pub unsafe fn memset<T>(s: *mut T, c: i32, n: usize) {
let s = s as *mut u8;
let c = c as u8;
for i in 0..n {
ptr::write_volatile(s.offset(i as isize), c);
}
}
#[cfg(all(apple, feature = "use_os"))]
pub unsafe fn memset<T>(s: *mut T, c: i32, n: usize) {
use libc::{ c_void, c_int };
use mach_o_sys::ranlib::{ rsize_t, errno_t };
extern {
fn memset_s(s: *mut c_void, smax: rsize_t, c: c_int, n: rsize_t) -> errno_t;
}
if n > 0 && memset_s(s as *mut c_void, n as rsize_t, c, n as rsize_t) != 0 {
std::process::abort()
}
}
#[cfg(any(
not(any(
all(windows, not(target_env = "msvc")),
freebsdlike, netbsdlike
)),
not(feature = "use_os")
))]
#[inline]
pub unsafe fn memzero<T>(dest: *mut T, n: usize) {
memset(dest, 0, n);
}
#[cfg(all(any(freebsdlike, netbsdlike), feature = "use_os"))]
pub unsafe fn memzero<T>(dest: *mut T, n: usize) {
extern {
fn explicit_bzero(s: *mut libc::c_void, n: libc::size_t);
}
explicit_bzero(dest as *mut libc::c_void, n);
}
#[cfg(all(windows, not(target_env = "msvc"), feature = "use_os"))]
pub unsafe fn memzero<T>(s: *mut T, n: usize) {
extern "system" {
fn RtlSecureZeroMemory(ptr: winapi::PVOID, cnt: winapi::SIZE_T);
}
RtlSecureZeroMemory(s as winapi::PVOID, n as winapi::SIZE_T);
}