#[cfg(target_os = "macos")]
pub unsafe fn reallocarray(
optr: *mut core::ffi::c_void,
nmemb: usize,
size: usize,
) -> *mut core::ffi::c_void {
const MUL_NO_OVERFLOW: usize = 1usize << (size_of::<usize>() * 4);
unsafe {
if (nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW)
&& nmemb > 0
&& usize::MAX / nmemb < size
{
crate::errno!() = libc::ENOMEM;
return core::ptr::null_mut();
}
libc::realloc(optr, size * nmemb)
}
}
#[cfg(target_os = "linux")]
pub(crate) use libc::reallocarray;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_reallocarray_alloc_usable() {
unsafe {
let p = reallocarray(core::ptr::null_mut(), 4, 4).cast::<u8>();
assert!(!p.is_null());
for i in 0..16usize {
*p.add(i) = i as u8;
}
for i in 0..16usize {
assert_eq!(*p.add(i), i as u8);
}
libc::free(p.cast());
}
}
#[test]
fn test_reallocarray_overflow_returns_null() {
unsafe {
let p = reallocarray(core::ptr::null_mut(), usize::MAX, 2);
assert!(p.is_null());
}
}
}