Auto merge of #2827 - mojave2:memcpy, r=oli-obk
add `memcpy` and `strcpy` shims
This commit is contained in:
commit
fa8e02f634
@ -744,6 +744,44 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
dest,
|
||||
)?;
|
||||
}
|
||||
"memcpy" => {
|
||||
let [ptr_dest, ptr_src, n] =
|
||||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
let ptr_dest = this.read_pointer(ptr_dest)?;
|
||||
let ptr_src = this.read_pointer(ptr_src)?;
|
||||
let n = this.read_target_usize(n)?;
|
||||
this.mem_copy(
|
||||
ptr_src,
|
||||
Align::ONE,
|
||||
ptr_dest,
|
||||
Align::ONE,
|
||||
Size::from_bytes(n),
|
||||
true,
|
||||
)?;
|
||||
this.write_pointer(ptr_dest, dest)?;
|
||||
}
|
||||
"strcpy" => {
|
||||
let [ptr_dest, ptr_src] =
|
||||
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
|
||||
let ptr_dest = this.read_pointer(ptr_dest)?;
|
||||
let ptr_src = this.read_pointer(ptr_src)?;
|
||||
|
||||
// We use `read_c_str` to determine the amount of data to copy,
|
||||
// and then use `mem_copy` for the actual copy. This means
|
||||
// pointer provenance is preserved by this implementation of `strcpy`.
|
||||
// That is probably overly cautious, but there also is no fundamental
|
||||
// reason to have `strcpy` destroy pointer provenance.
|
||||
let n = this.read_c_str(ptr_src)?.len().checked_add(1).unwrap();
|
||||
this.mem_copy(
|
||||
ptr_src,
|
||||
Align::ONE,
|
||||
ptr_dest,
|
||||
Align::ONE,
|
||||
Size::from_bytes(n),
|
||||
true,
|
||||
)?;
|
||||
this.write_pointer(ptr_dest, dest)?;
|
||||
}
|
||||
|
||||
// math functions (note that there are also intrinsics for some other functions)
|
||||
#[rustfmt::skip]
|
||||
|
@ -302,6 +302,83 @@ fn test_posix_mkstemp() {
|
||||
}
|
||||
}
|
||||
|
||||
fn test_memcpy() {
|
||||
unsafe {
|
||||
let src = [1i8, 2, 3];
|
||||
let dest = libc::calloc(3, 1);
|
||||
libc::memcpy(dest, src.as_ptr() as *const libc::c_void, 3);
|
||||
let slc = std::slice::from_raw_parts(dest as *const i8, 3);
|
||||
assert_eq!(*slc, [1i8, 2, 3]);
|
||||
libc::free(dest);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let src = [1i8, 2, 3];
|
||||
let dest = libc::calloc(4, 1);
|
||||
libc::memcpy(dest, src.as_ptr() as *const libc::c_void, 3);
|
||||
let slc = std::slice::from_raw_parts(dest as *const i8, 4);
|
||||
assert_eq!(*slc, [1i8, 2, 3, 0]);
|
||||
libc::free(dest);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let src = 123_i32;
|
||||
let mut dest = 0_i32;
|
||||
libc::memcpy(
|
||||
&mut dest as *mut i32 as *mut libc::c_void,
|
||||
&src as *const i32 as *const libc::c_void,
|
||||
std::mem::size_of::<i32>(),
|
||||
);
|
||||
assert_eq!(dest, src);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let src = Some(123);
|
||||
let mut dest: Option<i32> = None;
|
||||
libc::memcpy(
|
||||
&mut dest as *mut Option<i32> as *mut libc::c_void,
|
||||
&src as *const Option<i32> as *const libc::c_void,
|
||||
std::mem::size_of::<Option<i32>>(),
|
||||
);
|
||||
assert_eq!(dest, src);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let src = &123;
|
||||
let mut dest = &42;
|
||||
libc::memcpy(
|
||||
&mut dest as *mut &'static i32 as *mut libc::c_void,
|
||||
&src as *const &'static i32 as *const libc::c_void,
|
||||
std::mem::size_of::<&'static i32>(),
|
||||
);
|
||||
assert_eq!(*dest, 123);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_strcpy() {
|
||||
use std::ffi::{CStr, CString};
|
||||
|
||||
// case: src_size equals dest_size
|
||||
unsafe {
|
||||
let src = CString::new("rust").unwrap();
|
||||
let size = src.as_bytes_with_nul().len();
|
||||
let dest = libc::malloc(size);
|
||||
libc::strcpy(dest as *mut libc::c_char, src.as_ptr());
|
||||
assert_eq!(CStr::from_ptr(dest as *const libc::c_char), src.as_ref());
|
||||
libc::free(dest);
|
||||
}
|
||||
|
||||
// case: src_size is less than dest_size
|
||||
unsafe {
|
||||
let src = CString::new("rust").unwrap();
|
||||
let size = src.as_bytes_with_nul().len();
|
||||
let dest = libc::malloc(size + 1);
|
||||
libc::strcpy(dest as *mut libc::c_char, src.as_ptr());
|
||||
assert_eq!(CStr::from_ptr(dest as *const libc::c_char), src.as_ref());
|
||||
libc::free(dest);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_sigrt() {
|
||||
let min = libc::SIGRTMIN();
|
||||
@ -333,6 +410,9 @@ fn main() {
|
||||
test_isatty();
|
||||
test_clocks();
|
||||
|
||||
test_memcpy();
|
||||
test_strcpy();
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
test_posix_fadvise();
|
||||
|
Loading…
x
Reference in New Issue
Block a user