From 27afeb0085db8f066636a512241ed8e2003a3fe2 Mon Sep 17 00:00:00 2001 From: vishruth-thimmaiah Date: Wed, 8 Oct 2025 01:59:44 +0530 Subject: [PATCH] feat: add support for libc::memset Signed-off-by: vishruth-thimmaiah --- src/tools/miri/src/shims/foreign_items.rs | 16 +++++++ .../miri/tests/pass-dep/libc/libc-mem.rs | 42 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 1d086906e7a5..3fd57d3c8db2 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -827,6 +827,22 @@ 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; + + 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" => { diff --git a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs index 727533a9de61..531d637d1f24 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs @@ -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::()); + 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::()); + 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::()); + 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(); }