diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index b4098ca0750c..0932f2a3910e 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -1017,7 +1017,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } /// Check that the given `caller_fn_abi` matches the expected ABI described by - /// `callee_abi`, `callee_input_tys`, `callee_output_ty`, and the return the list of + /// `callee_abi`, `callee_input_tys`, `callee_output_ty`, and then returns the list of /// arguments. fn check_shim_abi<'a, const N: usize>( &mut self, diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index fb80a36af9fc..c98d6e2b408a 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -21,7 +21,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &mut self, clk_id_op: &OpTy<'tcx>, tp_op: &OpTy<'tcx>, - ) -> InterpResult<'tcx, Scalar> { + dest: &MPlaceTy<'tcx>, + ) -> InterpResult<'tcx> { // This clock support is deliberately minimal because a lot of clock types have fiddly // properties (is it possible for Miri to be suspended independently of the host?). If you // have a use for another clock type, please open an issue. @@ -29,8 +30,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); this.assert_target_os_is_unix("clock_gettime"); + let clockid_t_size = this.libc_ty_layout("clockid_t").size; - let clk_id = this.read_scalar(clk_id_op)?.to_i32()?; + let clk_id = this.read_scalar(clk_id_op)?.to_int(clockid_t_size)?; let tp = this.deref_pointer_as(tp_op, this.libc_ty_layout("timespec"))?; let absolute_clocks; @@ -43,34 +45,34 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Linux further distinguishes regular and "coarse" clocks, but the "coarse" version // is just specified to be "faster and less precise", so we implement both the same way. absolute_clocks = vec![ - this.eval_libc_i32("CLOCK_REALTIME"), - this.eval_libc_i32("CLOCK_REALTIME_COARSE"), + this.eval_libc("CLOCK_REALTIME").to_int(clockid_t_size)?, + this.eval_libc("CLOCK_REALTIME_COARSE").to_int(clockid_t_size)?, ]; // The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are // never allowed to go backwards. We don't need to do any additional monotonicity // enforcement because std::time::Instant already guarantees that it is monotonic. relative_clocks = vec![ - this.eval_libc_i32("CLOCK_MONOTONIC"), - this.eval_libc_i32("CLOCK_MONOTONIC_COARSE"), + this.eval_libc("CLOCK_MONOTONIC").to_int(clockid_t_size)?, + this.eval_libc("CLOCK_MONOTONIC_COARSE").to_int(clockid_t_size)?, ]; } "macos" => { - absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")]; - relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")]; + absolute_clocks = vec![this.eval_libc("CLOCK_REALTIME").to_int(clockid_t_size)?]; + relative_clocks = vec![this.eval_libc("CLOCK_MONOTONIC").to_int(clockid_t_size)?]; // `CLOCK_UPTIME_RAW` supposed to not increment while the system is asleep... but // that's not really something a program running inside Miri can tell, anyway. // We need to support it because std uses it. - relative_clocks.push(this.eval_libc_i32("CLOCK_UPTIME_RAW")); + relative_clocks.push(this.eval_libc("CLOCK_UPTIME_RAW").to_int(clockid_t_size)?); } "solaris" | "illumos" => { // The REALTIME clock returns the actual time since the Unix epoch. - absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")]; + absolute_clocks = vec![this.eval_libc("CLOCK_REALTIME").to_int(clockid_t_size)?]; // MONOTONIC, in the other hand, is the high resolution, non-adjustable // clock from an arbitrary time in the past. // Note that the man page mentions HIGHRES but it is just // an alias of MONOTONIC and the libc crate does not expose it anyway. // https://docs.oracle.com/cd/E23824_01/html/821-1465/clock-gettime-3c.html - relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")]; + relative_clocks = vec![this.eval_libc("CLOCK_MONOTONIC").to_int(clockid_t_size)?]; } target => throw_unsup_format!("`clock_gettime` is not supported on target OS {target}"), } @@ -81,15 +83,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } else if relative_clocks.contains(&clk_id) { this.machine.monotonic_clock.now().duration_since(this.machine.monotonic_clock.epoch()) } else { - return this.set_last_error_and_return_i32(LibcError("EINVAL")); + return this.set_last_error_and_return(LibcError("EINVAL"), dest); }; let tv_sec = duration.as_secs(); let tv_nsec = duration.subsec_nanos(); this.write_int_fields(&[tv_sec.into(), tv_nsec.into()], &tp)?; + this.write_int(0, dest)?; - interp_ok(Scalar::from_i32(0)) + interp_ok(()) } fn gettimeofday( diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 5e6259c35744..026aa1f95039 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -112,51 +112,122 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // Environment related shims "getenv" => { - let [name] = this.check_shim(abi, Conv::C, link_name, args)?; + let [name] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty], + this.machine.layouts.mut_raw_ptr.ty, + args, + )?; let result = this.getenv(name)?; this.write_pointer(result, dest)?; } "unsetenv" => { - let [name] = this.check_shim(abi, Conv::C, link_name, args)?; + let [name] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.unsetenv(name)?; this.write_scalar(result, dest)?; } "setenv" => { - let [name, value, overwrite] = this.check_shim(abi, Conv::C, link_name, args)?; + let [name, value, overwrite] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [ + this.machine.layouts.const_raw_ptr.ty, + this.machine.layouts.const_raw_ptr.ty, + this.tcx.types.i32, + ], + this.tcx.types.i32, + args, + )?; this.read_scalar(overwrite)?.to_i32()?; let result = this.setenv(name, value)?; this.write_scalar(result, dest)?; } "getcwd" => { - let [buf, size] = this.check_shim(abi, Conv::C, link_name, args)?; + let [buf, size] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.mut_raw_ptr.ty, this.tcx.types.usize], + this.machine.layouts.mut_raw_ptr.ty, + args, + )?; let result = this.getcwd(buf, size)?; this.write_pointer(result, dest)?; } "chdir" => { - let [path] = this.check_shim(abi, Conv::C, link_name, args)?; + let [path] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.chdir(path)?; this.write_scalar(result, dest)?; } "getpid" => { - let [] = this.check_shim(abi, Conv::C, link_name, args)?; + let [] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [], + this.libc_ty_layout("pid_t").ty, + args, + )?; let result = this.getpid()?; this.write_scalar(result, dest)?; } "sysconf" => { - let [val] = this.check_shim(abi, Conv::C, link_name, args)?; + let [val] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32], + this.tcx.types.isize, + args, + )?; let result = this.sysconf(val)?; this.write_scalar(result, dest)?; } // File descriptors "read" => { - let [fd, buf, count] = this.check_shim(abi, Conv::C, link_name, args)?; + let [fd, buf, count] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32, this.machine.layouts.mut_raw_ptr.ty, this.tcx.types.usize], + this.tcx.types.isize, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_pointer(buf)?; let count = this.read_target_usize(count)?; this.read(fd, buf, count, None, dest)?; } "write" => { - let [fd, buf, n] = this.check_shim(abi, Conv::C, link_name, args)?; + let [fd, buf, n] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [ + this.tcx.types.i32, + this.machine.layouts.const_raw_ptr.ty, + this.tcx.types.usize, + ], + this.tcx.types.isize, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_pointer(buf)?; let count = this.read_target_usize(n)?; @@ -164,38 +235,88 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write(fd, buf, count, None, dest)?; } "pread" => { - let [fd, buf, count, offset] = this.check_shim(abi, Conv::C, link_name, args)?; + let off_t = this.libc_ty_layout("off_t"); + let [fd, buf, count, offset] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [ + this.tcx.types.i32, + this.machine.layouts.mut_raw_ptr.ty, + this.tcx.types.usize, + off_t.ty, + ], + this.tcx.types.isize, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_pointer(buf)?; let count = this.read_target_usize(count)?; - let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; + let offset = this.read_scalar(offset)?.to_int(off_t.size)?; this.read(fd, buf, count, Some(offset), dest)?; } "pwrite" => { - let [fd, buf, n, offset] = this.check_shim(abi, Conv::C, link_name, args)?; + let off_t = this.libc_ty_layout("off_t"); + let [fd, buf, n, offset] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [ + this.tcx.types.i32, + this.machine.layouts.const_raw_ptr.ty, + this.tcx.types.usize, + off_t.ty, + ], + this.tcx.types.isize, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_pointer(buf)?; let count = this.read_target_usize(n)?; - let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; + let offset = this.read_scalar(offset)?.to_int(off_t.size)?; trace!("Called pwrite({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset); this.write(fd, buf, count, Some(offset), dest)?; } "pread64" => { - let [fd, buf, count, offset] = this.check_shim(abi, Conv::C, link_name, args)?; + let off64_t = this.libc_ty_layout("off64_t"); + let [fd, buf, count, offset] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [ + this.tcx.types.i32, + this.machine.layouts.mut_raw_ptr.ty, + this.tcx.types.usize, + off64_t.ty, + ], + this.tcx.types.isize, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_pointer(buf)?; let count = this.read_target_usize(count)?; - let offset = - this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?; + let offset = this.read_scalar(offset)?.to_int(off64_t.size)?; this.read(fd, buf, count, Some(offset), dest)?; } "pwrite64" => { - let [fd, buf, n, offset] = this.check_shim(abi, Conv::C, link_name, args)?; + let off64_t = this.libc_ty_layout("off64_t"); + let [fd, buf, n, offset] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [ + this.tcx.types.i32, + this.machine.layouts.const_raw_ptr.ty, + this.tcx.types.usize, + off64_t.ty, + ], + this.tcx.types.isize, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_pointer(buf)?; let count = this.read_target_usize(n)?; - let offset = - this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?; + let offset = this.read_scalar(offset)?.to_int(off64_t.size)?; trace!("Called pwrite64({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset); this.write(fd, buf, count, Some(offset), dest)?; } @@ -218,13 +339,27 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } "dup" => { - let [old_fd] = this.check_shim(abi, Conv::C, link_name, args)?; + let [old_fd] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32], + this.tcx.types.i32, + args, + )?; let old_fd = this.read_scalar(old_fd)?.to_i32()?; let new_fd = this.dup(old_fd)?; this.write_scalar(new_fd, dest)?; } "dup2" => { - let [old_fd, new_fd] = this.check_shim(abi, Conv::C, link_name, args)?; + let [old_fd, new_fd] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32, this.tcx.types.i32], + this.tcx.types.i32, + args, + )?; let old_fd = this.read_scalar(old_fd)?.to_i32()?; let new_fd = this.read_scalar(new_fd)?.to_i32()?; let result = this.dup2(old_fd, new_fd)?; @@ -233,7 +368,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "flock" => { // Currently this function does not exist on all Unixes, e.g. on Solaris. this.check_target_os(&["linux", "freebsd", "macos", "illumos"], link_name)?; - let [fd, op] = this.check_shim(abi, Conv::C, link_name, args)?; + let [fd, op] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32, this.tcx.types.i32], + this.tcx.types.i32, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; let op = this.read_scalar(op)?.to_i32()?; let result = this.flock(fd, op)?; @@ -250,140 +392,311 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } "unlink" => { - let [path] = this.check_shim(abi, Conv::C, link_name, args)?; + let [path] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.unlink(path)?; this.write_scalar(result, dest)?; } "symlink" => { - let [target, linkpath] = this.check_shim(abi, Conv::C, link_name, args)?; + let [target, linkpath] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty, this.machine.layouts.const_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.symlink(target, linkpath)?; this.write_scalar(result, dest)?; } "rename" => { - let [oldpath, newpath] = this.check_shim(abi, Conv::C, link_name, args)?; + let [oldpath, newpath] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty, this.machine.layouts.const_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.rename(oldpath, newpath)?; this.write_scalar(result, dest)?; } "mkdir" => { - let [path, mode] = this.check_shim(abi, Conv::C, link_name, args)?; + let [path, mode] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty, this.libc_ty_layout("mode_t").ty], + this.tcx.types.i32, + args, + )?; let result = this.mkdir(path, mode)?; this.write_scalar(result, dest)?; } "rmdir" => { - let [path] = this.check_shim(abi, Conv::C, link_name, args)?; + let [path] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.rmdir(path)?; this.write_scalar(result, dest)?; } "opendir" => { - let [name] = this.check_shim(abi, Conv::C, link_name, args)?; + let [name] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty], + this.machine.layouts.mut_raw_ptr.ty, + args, + )?; let result = this.opendir(name)?; this.write_scalar(result, dest)?; } "closedir" => { - let [dirp] = this.check_shim(abi, Conv::C, link_name, args)?; + let [dirp] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.mut_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.closedir(dirp)?; this.write_scalar(result, dest)?; } "lseek64" => { - let [fd, offset, whence] = this.check_shim(abi, Conv::C, link_name, args)?; + let off64_t = this.libc_ty_layout("off64_t"); + let [fd, offset, whence] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32, off64_t.ty, this.tcx.types.i32], + off64_t.ty, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; - let offset = this.read_scalar(offset)?.to_i64()?; + let offset = this.read_scalar(offset)?.to_int(off64_t.size)?; let whence = this.read_scalar(whence)?.to_i32()?; - let result = this.lseek64(fd, offset.into(), whence)?; - this.write_scalar(result, dest)?; + this.lseek64(fd, offset, whence, dest)?; } "lseek" => { - let [fd, offset, whence] = this.check_shim(abi, Conv::C, link_name, args)?; + let off_t = this.libc_ty_layout("off_t"); + let [fd, offset, whence] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32, off_t.ty, this.tcx.types.i32], + off_t.ty, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; - let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; + let offset = this.read_scalar(offset)?.to_int(off_t.size)?; let whence = this.read_scalar(whence)?.to_i32()?; - let result = this.lseek64(fd, offset, whence)?; - this.write_scalar(result, dest)?; + this.lseek64(fd, offset, whence, dest)?; } "ftruncate64" => { - let [fd, length] = this.check_shim(abi, Conv::C, link_name, args)?; + let off64_t = this.libc_ty_layout("off64_t"); + let [fd, length] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32, off64_t.ty], + this.tcx.types.i32, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; - let length = this.read_scalar(length)?.to_i64()?; - let result = this.ftruncate64(fd, length.into())?; + let length = this.read_scalar(length)?.to_int(off64_t.size)?; + let result = this.ftruncate64(fd, length)?; this.write_scalar(result, dest)?; } "ftruncate" => { - let [fd, length] = this.check_shim(abi, Conv::C, link_name, args)?; + let off_t = this.libc_ty_layout("off_t"); + let [fd, length] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32, off_t.ty], + this.tcx.types.i32, + args, + )?; let fd = this.read_scalar(fd)?.to_i32()?; - let length = this.read_scalar(length)?.to_int(this.libc_ty_layout("off_t").size)?; + let length = this.read_scalar(length)?.to_int(off_t.size)?; let result = this.ftruncate64(fd, length)?; this.write_scalar(result, dest)?; } "fsync" => { - let [fd] = this.check_shim(abi, Conv::C, link_name, args)?; + let [fd] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32], + this.tcx.types.i32, + args, + )?; let result = this.fsync(fd)?; this.write_scalar(result, dest)?; } "fdatasync" => { - let [fd] = this.check_shim(abi, Conv::C, link_name, args)?; + let [fd] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32], + this.tcx.types.i32, + args, + )?; let result = this.fdatasync(fd)?; this.write_scalar(result, dest)?; } "readlink" => { - let [pathname, buf, bufsize] = this.check_shim(abi, Conv::C, link_name, args)?; + let [pathname, buf, bufsize] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [ + this.machine.layouts.const_raw_ptr.ty, + this.machine.layouts.mut_raw_ptr.ty, + this.tcx.types.usize, + ], + this.tcx.types.isize, + args, + )?; let result = this.readlink(pathname, buf, bufsize)?; this.write_scalar(Scalar::from_target_isize(result, this), dest)?; } "posix_fadvise" => { - let [fd, offset, len, advice] = this.check_shim(abi, Conv::C, link_name, args)?; + let off_t = this.libc_ty_layout("off_t"); + let [fd, offset, len, advice] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.tcx.types.i32, off_t.ty, off_t.ty, this.tcx.types.i32], + this.tcx.types.i32, + args, + )?; this.read_scalar(fd)?.to_i32()?; - this.read_target_isize(offset)?; - this.read_target_isize(len)?; + this.read_scalar(offset)?.to_int(off_t.size)?; + this.read_scalar(len)?.to_int(off_t.size)?; this.read_scalar(advice)?.to_i32()?; // fadvise is only informational, we can ignore it. this.write_null(dest)?; } "realpath" => { - let [path, resolved_path] = this.check_shim(abi, Conv::C, link_name, args)?; + let [path, resolved_path] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty, this.machine.layouts.mut_raw_ptr.ty], + this.machine.layouts.mut_raw_ptr.ty, + args, + )?; let result = this.realpath(path, resolved_path)?; this.write_scalar(result, dest)?; } "mkstemp" => { - let [template] = this.check_shim(abi, Conv::C, link_name, args)?; + let [template] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.mut_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.mkstemp(template)?; this.write_scalar(result, dest)?; } // Unnamed sockets and pipes "socketpair" => { - let [domain, type_, protocol, sv] = - this.check_shim(abi, Conv::C, link_name, args)?; + let [domain, type_, protocol, sv] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [ + this.tcx.types.i32, + this.tcx.types.i32, + this.tcx.types.i32, + this.machine.layouts.mut_raw_ptr.ty, + ], + this.tcx.types.i32, + args, + )?; let result = this.socketpair(domain, type_, protocol, sv)?; this.write_scalar(result, dest)?; } "pipe" => { - let [pipefd] = this.check_shim(abi, Conv::C, link_name, args)?; + let [pipefd] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.mut_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.pipe2(pipefd, /*flags*/ None)?; this.write_scalar(result, dest)?; } "pipe2" => { // Currently this function does not exist on all Unixes, e.g. on macOS. this.check_target_os(&["linux", "freebsd", "solaris", "illumos"], link_name)?; - let [pipefd, flags] = this.check_shim(abi, Conv::C, link_name, args)?; + let [pipefd, flags] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.mut_raw_ptr.ty, this.tcx.types.i32], + this.tcx.types.i32, + args, + )?; let result = this.pipe2(pipefd, Some(flags))?; this.write_scalar(result, dest)?; } // Time "gettimeofday" => { - let [tv, tz] = this.check_shim(abi, Conv::C, link_name, args)?; + let [tv, tz] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.mut_raw_ptr.ty, this.machine.layouts.mut_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; let result = this.gettimeofday(tv, tz)?; this.write_scalar(result, dest)?; } "localtime_r" => { - let [timep, result_op] = this.check_shim(abi, Conv::C, link_name, args)?; + let [timep, result_op] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.machine.layouts.const_raw_ptr.ty, this.machine.layouts.mut_raw_ptr.ty], + this.machine.layouts.mut_raw_ptr.ty, + args, + )?; let result = this.localtime_r(timep, result_op)?; this.write_pointer(result, dest)?; } "clock_gettime" => { - let [clk_id, tp] = this.check_shim(abi, Conv::C, link_name, args)?; - let result = this.clock_gettime(clk_id, tp)?; - this.write_scalar(result, dest)?; + let [clk_id, tp] = this.check_shim_abi( + link_name, + abi, + ExternAbi::C { unwind: false }, + [this.libc_ty_layout("clockid_t").ty, this.machine.layouts.mut_raw_ptr.ty], + this.tcx.types.i32, + args, + )?; + this.clock_gettime(clk_id, tp, dest)?; } // Allocation @@ -834,7 +1147,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // These shims are enabled only when the caller is in the standard library. "pthread_attr_getguardsize" if this.frame_in_std() => { let [_attr, guard_size] = this.check_shim(abi, Conv::C, link_name, args)?; - let guard_size_layout = this.libc_ty_layout("size_t"); + let guard_size_layout = this.machine.layouts.usize; let guard_size = this.deref_pointer_as(guard_size, guard_size_layout)?; this.write_scalar( Scalar::from_uint(this.machine.page_size, guard_size_layout.size), diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index fc0f57694a71..1f6acff0787a 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -502,7 +502,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(Scalar::from_i32(this.try_unwrap_io_result(fd)?)) } - fn lseek64(&mut self, fd_num: i32, offset: i128, whence: i32) -> InterpResult<'tcx, Scalar> { + fn lseek64( + &mut self, + fd_num: i32, + offset: i128, + whence: i32, + dest: &MPlaceTy<'tcx>, + ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); // Isolation check is done via `FileDescription` trait. @@ -510,7 +516,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let seek_from = if whence == this.eval_libc_i32("SEEK_SET") { if offset < 0 { // Negative offsets return `EINVAL`. - return this.set_last_error_and_return_i64(LibcError("EINVAL")); + return this.set_last_error_and_return(LibcError("EINVAL"), dest); } else { SeekFrom::Start(u64::try_from(offset).unwrap()) } @@ -519,19 +525,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } else if whence == this.eval_libc_i32("SEEK_END") { SeekFrom::End(i64::try_from(offset).unwrap()) } else { - return this.set_last_error_and_return_i64(LibcError("EINVAL")); + return this.set_last_error_and_return(LibcError("EINVAL"), dest); }; let communicate = this.machine.communicate(); let Some(fd) = this.machine.fds.get(fd_num) else { - return this.set_last_error_and_return_i64(LibcError("EBADF")); + return this.set_last_error_and_return(LibcError("EBADF"), dest); }; let result = fd.seek(communicate, seek_from)?.map(|offset| i64::try_from(offset).unwrap()); drop(fd); let result = this.try_unwrap_io_result(result)?; - interp_ok(Scalar::from_i64(result)) + this.write_int(result, dest)?; + interp_ok(()) } fn unlink(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { diff --git a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs index 515e467fb54d..ac6e221fcd8d 100644 --- a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs +++ b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.rs @@ -9,6 +9,6 @@ extern "C" { fn main() { let mut fds = [-1, -1]; let res = unsafe { pipe(fds.as_mut_ptr()) }; - //~^ ERROR: calling a non-variadic function with a variadic caller-side signature + //~^ ERROR: ABI mismatch: calling a non-variadic function with a variadic caller-side signature assert_eq!(res, 0); } diff --git a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr index 2782f3b3269c..0f642aca322a 100644 --- a/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr +++ b/src/tools/miri/tests/fail/shims/vararg_caller_signature_mismatch.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: calling a non-variadic function with a variadic caller-side signature +error: Undefined Behavior: ABI mismatch: calling a non-variadic function with a variadic caller-side signature --> tests/fail/shims/vararg_caller_signature_mismatch.rs:LL:CC | LL | let res = unsafe { pipe(fds.as_mut_ptr()) }; - | ^^^^^^^^^^^^^^^^^^^^^^ calling a non-variadic function with a variadic caller-side signature + | ^^^^^^^^^^^^^^^^^^^^^^ ABI mismatch: calling a non-variadic function with a variadic caller-side signature | = 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