Skip to content

Commit 78d6f0f

Browse files
authored
Merge pull request #4618 from vishruth-thimmaiah/add_memset
feat: add support for libc::memset
2 parents 64c958c + 7445d17 commit 78d6f0f

File tree

4 files changed

+82
-0
lines changed

4 files changed

+82
-0
lines changed

src/shims/foreign_items.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,23 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
827827
this.mem_copy(ptr_src, ptr_dest, Size::from_bytes(n), true)?;
828828
this.write_pointer(ptr_dest, dest)?;
829829
}
830+
"memset" => {
831+
let [ptr_dest, val, n] =
832+
this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
833+
let ptr_dest = this.read_pointer(ptr_dest)?;
834+
let val = this.read_scalar(val)?.to_i32()?;
835+
let n = this.read_target_usize(n)?;
836+
// The docs say val is "interpreted as unsigned char".
837+
#[expect(clippy::as_conversions)]
838+
let val = val as u8;
839+
840+
// C requires that this must always be a valid pointer, even if `n` is zero, so we better check that.
841+
this.ptr_get_alloc_id(ptr_dest, 0)?;
842+
843+
let bytes = std::iter::repeat_n(val, n.try_into().unwrap());
844+
this.write_bytes_ptr(ptr_dest, bytes)?;
845+
this.write_pointer(ptr_dest, dest)?;
846+
}
830847

831848
// LLVM intrinsics
832849
"llvm.prefetch" => {

tests/fail-dep/libc/memset_null.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use std::ptr;
2+
3+
// null is explicitly called out as UB in the C docs for `memset`.
4+
fn main() {
5+
unsafe {
6+
libc::memset(ptr::null_mut(), 0, 0); //~ERROR: null pointer
7+
}
8+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: Undefined Behavior: pointer not dereferenceable: pointer must point to some allocation, but got null pointer
2+
--> tests/fail-dep/libc/memset_null.rs:LL:CC
3+
|
4+
LL | libc::memset(ptr::null_mut(), 0, 0);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: BACKTRACE:
10+
= note: inside `main` at tests/fail-dep/libc/memset_null.rs:LL:CC
11+
12+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
13+
14+
error: aborting due to 1 previous error
15+

tests/pass-dep/libc/libc-mem.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,47 @@ fn test_strcpy() {
7878
}
7979
}
8080

81+
fn test_memset() {
82+
unsafe {
83+
let val = 1;
84+
let dest = libc::calloc(3, 1);
85+
libc::memset(dest, val, 3);
86+
let slc = std::slice::from_raw_parts(dest as *const i8, 3);
87+
assert_eq!(*slc, [1i8, 1, 1]);
88+
libc::free(dest);
89+
}
90+
91+
unsafe {
92+
let val = 1;
93+
let dest = libc::calloc(4, 1);
94+
libc::memset(dest, val, 3);
95+
let slc = std::slice::from_raw_parts(dest as *const i8, 4);
96+
assert_eq!(*slc, [1i8, 1, 1, 0]);
97+
libc::free(dest);
98+
}
99+
100+
unsafe {
101+
let val = 1;
102+
let mut dest = 0_i8;
103+
libc::memset(&mut dest as *mut i8 as *mut libc::c_void, val, mem::size_of::<i8>());
104+
assert_eq!(dest, val as i8);
105+
}
106+
107+
unsafe {
108+
let val = 1;
109+
let mut dest = 0_i16;
110+
libc::memset(&mut dest as *mut i16 as *mut libc::c_void, val, mem::size_of::<i16>());
111+
assert_eq!(dest, 257);
112+
}
113+
114+
unsafe {
115+
let val = 257;
116+
let mut dest = 0_i16;
117+
libc::memset(&mut dest as *mut i16 as *mut libc::c_void, val, mem::size_of::<i16>());
118+
assert_eq!(dest, 257);
119+
}
120+
}
121+
81122
fn test_malloc() {
82123
// Test that small allocations sometimes *are* not very aligned.
83124
let saw_unaligned = (0..64).any(|_| unsafe {
@@ -310,4 +351,5 @@ fn main() {
310351

311352
test_memcpy();
312353
test_strcpy();
354+
test_memset();
313355
}

0 commit comments

Comments
 (0)