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
#![cfg_attr(not(feature = "use_os"), no_std)]
#[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(any(target_os = "macos", target_os = "ios"), 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 = ptr::read_volatile(b1.offset(i)) as i32
- ptr::read_volatile(b2.offset(i)) as i32;
res = (res & (((diff - 1) & !diff) >> 8)) | diff;
}
((res - 1) >> 8) + (res >> 8) + 1
}
#[cfg(any(
not(any(target_os = "macos", target_os = "ios")),
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 as isize {
ptr::write_volatile(s.offset(i), c);
}
}
#[cfg(all(
any(target_os = "macos", target_os = "ios"),
feature = "use_os"
))]
pub unsafe fn memset<T>(s: *mut T, c: i32, n: usize) {
use mach_o_sys::ranlib::{ rsize_t, errno_t };
extern {
fn memset_s(s: *mut libc::c_void, smax: rsize_t, c: libc::c_int, n: rsize_t) -> errno_t;
}
if n > 0 {
match memset_s(s as *mut libc::c_void, n as rsize_t, c, n as rsize_t) {
0 => (),
ret => panic!("memset_s return with error value {}", ret)
}
}
}
#[cfg(any(
not(any(
all(windows, not(target_env = "msvc")),
target_os = "freebsd",
target_os = "openbsd"
)),
not(feature = "use_os")
))]
#[inline]
pub unsafe fn memzero<T>(dest: *mut T, n: usize) {
memset(dest, 0, n);
}
#[cfg(all(
any(target_os = "freebsd", target_os = "openbsd"),
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);
}