diff --git a/src/shims/unix/foreign_items.rs b/src/shims/unix/foreign_items.rs index 35036ce078..87cfe2907b 100644 --- a/src/shims/unix/foreign_items.rs +++ b/src/shims/unix/foreign_items.rs @@ -262,6 +262,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "mmap" => { let [addr, length, prot, flags, fd, offset] = this.check_shim(abi, Abi::C {unwind: false}, link_name, args)?; + let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; let ptr = this.mmap(addr, length, prot, flags, fd, offset)?; this.write_scalar(ptr, dest)?; } diff --git a/src/shims/unix/linux/foreign_items.rs b/src/shims/unix/linux/foreign_items.rs index 6937e0f089..a05a6470a5 100644 --- a/src/shims/unix/linux/foreign_items.rs +++ b/src/shims/unix/linux/foreign_items.rs @@ -9,6 +9,7 @@ use shims::unix::fs::EvalContextExt as _; use shims::unix::linux::fd::EvalContextExt as _; use shims::unix::linux::mem::EvalContextExt as _; use shims::unix::linux::sync::futex; +use shims::unix::mem::EvalContextExt as _; use shims::unix::sync::EvalContextExt as _; use shims::unix::thread::EvalContextExt as _; @@ -43,6 +44,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let result = this.linux_readdir64(dirp)?; this.write_scalar(result, dest)?; } + "mmap64" => { + let [addr, length, prot, flags, fd, offset] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let offset = this.read_scalar(offset)?.to_i64()?; + let ptr = this.mmap(addr, length, prot, flags, fd, offset.into())?; + this.write_scalar(ptr, dest)?; + } + // Linux-only "sync_file_range" => { let [fd, offset, nbytes, flags] = diff --git a/src/shims/unix/mem.rs b/src/shims/unix/mem.rs index d7dc17fa89..d3470893db 100644 --- a/src/shims/unix/mem.rs +++ b/src/shims/unix/mem.rs @@ -26,7 +26,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { prot: &OpTy<'tcx, Provenance>, flags: &OpTy<'tcx, Provenance>, fd: &OpTy<'tcx, Provenance>, - offset: &OpTy<'tcx, Provenance>, + offset: i128, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); @@ -36,7 +36,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let prot = this.read_scalar(prot)?.to_i32()?; let flags = this.read_scalar(flags)?.to_i32()?; let fd = this.read_scalar(fd)?.to_i32()?; - let offset = this.read_target_usize(offset)?; let map_private = this.eval_libc_i32("MAP_PRIVATE"); let map_anonymous = this.eval_libc_i32("MAP_ANONYMOUS"); diff --git a/tests/pass-dep/shims/mmap.rs b/tests/pass-dep/shims/mmap.rs index e19f54d068..7bbb9dd53c 100644 --- a/tests/pass-dep/shims/mmap.rs +++ b/tests/pass-dep/shims/mmap.rs @@ -5,16 +5,25 @@ use std::io::Error; use std::{ptr, slice}; -fn test_mmap() { +fn test_mmap( + mmap: unsafe extern "C" fn( + *mut libc::c_void, + libc::size_t, + libc::c_int, + libc::c_int, + libc::c_int, + Offset, + ) -> *mut libc::c_void, +) { let page_size = page_size::get(); let ptr = unsafe { - libc::mmap( + mmap( ptr::null_mut(), page_size, libc::PROT_READ | libc::PROT_WRITE, libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, -1, - 0, + Default::default(), ) }; assert!(!ptr.is_null()); @@ -35,40 +44,40 @@ fn test_mmap() { // Test all of our error conditions let ptr = unsafe { - libc::mmap( + mmap( ptr::null_mut(), page_size, libc::PROT_READ | libc::PROT_WRITE, libc::MAP_PRIVATE | libc::MAP_SHARED, // Can't be both private and shared -1, - 0, + Default::default(), ) }; assert_eq!(ptr, libc::MAP_FAILED); assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::EINVAL); let ptr = unsafe { - libc::mmap( + mmap( ptr::null_mut(), 0, // Can't map no memory libc::PROT_READ | libc::PROT_WRITE, libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, -1, - 0, + Default::default(), ) }; assert_eq!(ptr, libc::MAP_FAILED); assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::EINVAL); let ptr = unsafe { - libc::mmap( + mmap( ptr::invalid_mut(page_size * 64), page_size, libc::PROT_READ | libc::PROT_WRITE, // We don't support MAP_FIXED libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | libc::MAP_FIXED, -1, - 0, + Default::default(), ) }; assert_eq!(ptr, libc::MAP_FAILED); @@ -77,13 +86,13 @@ fn test_mmap() { // We don't support protections other than read+write for prot in [libc::PROT_NONE, libc::PROT_EXEC, libc::PROT_READ, libc::PROT_WRITE] { let ptr = unsafe { - libc::mmap( + mmap( ptr::null_mut(), page_size, prot, libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, -1, - 0, + Default::default(), ) }; assert_eq!(ptr, libc::MAP_FAILED); @@ -93,13 +102,13 @@ fn test_mmap() { // We report an error for mappings whose length cannot be rounded up to a multiple of // the page size. let ptr = unsafe { - libc::mmap( + mmap( ptr::null_mut(), usize::MAX - 1, libc::PROT_READ | libc::PROT_WRITE, libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, -1, - 0, + Default::default(), ) }; assert_eq!(ptr, libc::MAP_FAILED); @@ -163,7 +172,9 @@ fn test_mremap() { } fn main() { - test_mmap(); + test_mmap(libc::mmap); + #[cfg(target_os = "linux")] + test_mmap(libc::mmap64); #[cfg(target_os = "linux")] test_mremap(); }