Merge pull request #4618 from vishruth-thimmaiah/add_memset

feat: add support for libc::memset
This commit is contained in:
Ralf Jung 2025-10-10 10:24:51 +00:00 committed by GitHub
commit 328fec4710
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 82 additions and 0 deletions

View file

@ -827,6 +827,23 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.mem_copy(ptr_src, ptr_dest, Size::from_bytes(n), true)?;
this.write_pointer(ptr_dest, dest)?;
}
"memset" => {
let [ptr_dest, val, n] =
this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
let ptr_dest = this.read_pointer(ptr_dest)?;
let val = this.read_scalar(val)?.to_i32()?;
let n = this.read_target_usize(n)?;
// The docs say val is "interpreted as unsigned char".
#[expect(clippy::as_conversions)]
let val = val as u8;
// C requires that this must always be a valid pointer, even if `n` is zero, so we better check that.
this.ptr_get_alloc_id(ptr_dest, 0)?;
let bytes = std::iter::repeat_n(val, n.try_into().unwrap());
this.write_bytes_ptr(ptr_dest, bytes)?;
this.write_pointer(ptr_dest, dest)?;
}
// LLVM intrinsics
"llvm.prefetch" => {

View file

@ -0,0 +1,8 @@
use std::ptr;
// null is explicitly called out as UB in the C docs for `memset`.
fn main() {
unsafe {
libc::memset(ptr::null_mut(), 0, 0); //~ERROR: null pointer
}
}

View file

@ -0,0 +1,15 @@
error: Undefined Behavior: pointer not dereferenceable: pointer must point to some allocation, but got null pointer
--> tests/fail-dep/libc/memset_null.rs:LL:CC
|
LL | libc::memset(ptr::null_mut(), 0, 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `main` at tests/fail-dep/libc/memset_null.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error

View file

@ -78,6 +78,47 @@ fn test_strcpy() {
}
}
fn test_memset() {
unsafe {
let val = 1;
let dest = libc::calloc(3, 1);
libc::memset(dest, val, 3);
let slc = std::slice::from_raw_parts(dest as *const i8, 3);
assert_eq!(*slc, [1i8, 1, 1]);
libc::free(dest);
}
unsafe {
let val = 1;
let dest = libc::calloc(4, 1);
libc::memset(dest, val, 3);
let slc = std::slice::from_raw_parts(dest as *const i8, 4);
assert_eq!(*slc, [1i8, 1, 1, 0]);
libc::free(dest);
}
unsafe {
let val = 1;
let mut dest = 0_i8;
libc::memset(&mut dest as *mut i8 as *mut libc::c_void, val, mem::size_of::<i8>());
assert_eq!(dest, val as i8);
}
unsafe {
let val = 1;
let mut dest = 0_i16;
libc::memset(&mut dest as *mut i16 as *mut libc::c_void, val, mem::size_of::<i16>());
assert_eq!(dest, 257);
}
unsafe {
let val = 257;
let mut dest = 0_i16;
libc::memset(&mut dest as *mut i16 as *mut libc::c_void, val, mem::size_of::<i16>());
assert_eq!(dest, 257);
}
}
fn test_malloc() {
// Test that small allocations sometimes *are* not very aligned.
let saw_unaligned = (0..64).any(|_| unsafe {
@ -310,4 +351,5 @@ fn main() {
test_memcpy();
test_strcpy();
test_memset();
}