From cc27f3d6361342cb461cc45be52ec4e1b2f839d1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 27 Jul 2025 13:34:55 +0200 Subject: [PATCH] introduce a macro for shim signature checking Co-Authored-By: geetanshjuneja --- src/helpers.rs | 213 +---------- src/intrinsics/atomic.rs | 2 +- src/intrinsics/mod.rs | 22 +- src/intrinsics/simd.rs | 5 +- src/lib.rs | 2 + src/shims/aarch64.rs | 5 +- src/shims/backtrace.rs | 8 +- src/shims/foreign_items.rs | 90 +++-- src/shims/mod.rs | 1 + src/shims/sig.rs | 265 +++++++++++++ src/shims/unix/android/foreign_items.rs | 11 +- src/shims/unix/android/thread.rs | 4 +- src/shims/unix/fd.rs | 2 +- src/shims/unix/foreign_items.rs | 451 +++++++++-------------- src/shims/unix/freebsd/foreign_items.rs | 26 +- src/shims/unix/fs.rs | 2 +- src/shims/unix/linux/foreign_items.rs | 39 +- src/shims/unix/linux_like/sync.rs | 2 +- src/shims/unix/linux_like/syscall.rs | 4 +- src/shims/unix/macos/foreign_items.rs | 71 ++-- src/shims/unix/solarish/foreign_items.rs | 34 +- src/shims/unwind.rs | 6 +- src/shims/wasi/foreign_items.rs | 6 +- src/shims/windows/foreign_items.rs | 147 ++++---- src/shims/x86/aesni.rs | 14 +- src/shims/x86/avx.rs | 50 ++- src/shims/x86/avx2.rs | 57 ++- src/shims/x86/bmi.rs | 2 +- src/shims/x86/gfni.rs | 9 +- src/shims/x86/mod.rs | 11 +- src/shims/x86/sha.rs | 6 +- src/shims/x86/sse.rs | 24 +- src/shims/x86/sse2.rs | 40 +- src/shims/x86/sse3.rs | 5 +- src/shims/x86/sse41.rs | 28 +- src/shims/x86/sse42.rs | 14 +- src/shims/x86/ssse3.rs | 17 +- 37 files changed, 900 insertions(+), 795 deletions(-) create mode 100644 src/shims/sig.rs diff --git a/src/helpers.rs b/src/helpers.rs index 6e80bc5da9..0c96ddf00d 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -3,7 +3,7 @@ use std::time::Duration; use std::{cmp, iter}; use rand::RngCore; -use rustc_abi::{Align, CanonAbi, ExternAbi, FieldIdx, FieldsShape, Size, Variants}; +use rustc_abi::{Align, ExternAbi, FieldIdx, FieldsShape, Size, Variants}; use rustc_apfloat::Float; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_hir::Safety; @@ -14,11 +14,10 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::ExportedSymbol; use rustc_middle::ty::layout::{LayoutOf, MaybeResult, TyAndLayout}; -use rustc_middle::ty::{self, Binder, FloatTy, FnSig, IntTy, Ty, TyCtxt, UintTy}; +use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, UintTy}; use rustc_session::config::CrateType; use rustc_span::{Span, Symbol}; use rustc_symbol_mangling::mangle_internal_symbol; -use rustc_target::callconv::FnAbi; use crate::*; @@ -437,7 +436,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// For now, arguments must be scalars (so that the caller does not have to know the layout). /// /// If you do not provide a return place, a dangling zero-sized place will be created - /// for your convenience. + /// for your convenience. This is only valid if the return type is `()`. fn call_function( &mut self, f: ty::Instance<'tcx>, @@ -452,7 +451,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let mir = this.load_mir(f.def, None)?; let dest = match dest { Some(dest) => dest.clone(), - None => MPlaceTy::fake_alloc_zst(this.layout_of(mir.return_ty())?), + None => MPlaceTy::fake_alloc_zst(this.machine.layouts.unit), }; // Construct a function pointer type representing the caller perspective. @@ -465,6 +464,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ); let caller_fn_abi = this.fn_abi_of_fn_ptr(ty::Binder::dummy(sig), ty::List::empty())?; + // This will also show proper errors if there is any ABI mismatch. this.init_stack_frame( f, mir, @@ -929,21 +929,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { self.read_c_str_with_char_size(ptr, wchar_t.size, wchar_t.align.abi) } - /// Check that the calling convention is what we expect. - fn check_callconv<'a>( - &self, - fn_abi: &FnAbi<'tcx, Ty<'tcx>>, - exp_abi: CanonAbi, - ) -> InterpResult<'a, ()> { - if fn_abi.conv != exp_abi { - throw_ub_format!( - r#"calling a function with calling convention "{exp_abi}" using caller calling convention "{}""#, - fn_abi.conv - ); - } - interp_ok(()) - } - fn frame_in_std(&self) -> bool { let this = self.eval_context_ref(); let frame = this.frame(); @@ -967,161 +952,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { crate_name == "std" || crate_name == "std_miri_test" } - fn check_abi_and_shim_symbol_clash( - &mut self, - abi: &FnAbi<'tcx, Ty<'tcx>>, - exp_abi: CanonAbi, - link_name: Symbol, - ) -> InterpResult<'tcx, ()> { - self.check_callconv(abi, exp_abi)?; - if let Some((body, instance)) = self.eval_context_mut().lookup_exported_symbol(link_name)? { - // If compiler-builtins is providing the symbol, then don't treat it as a clash. - // We'll use our built-in implementation in `emulate_foreign_item_inner` for increased - // performance. Note that this means we won't catch any undefined behavior in - // compiler-builtins when running other crates, but Miri can still be run on - // compiler-builtins itself (or any crate that uses it as a normal dependency) - if self.eval_context_ref().tcx.is_compiler_builtins(instance.def_id().krate) { - return interp_ok(()); - } - - throw_machine_stop!(TerminationInfo::SymbolShimClashing { - link_name, - span: body.span.data(), - }) - } - interp_ok(()) - } - - fn check_shim<'a, const N: usize>( - &mut self, - abi: &FnAbi<'tcx, Ty<'tcx>>, - exp_abi: CanonAbi, - link_name: Symbol, - args: &'a [OpTy<'tcx>], - ) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> { - self.check_abi_and_shim_symbol_clash(abi, exp_abi, link_name)?; - - if abi.c_variadic { - throw_ub_format!( - "calling a non-variadic function with a variadic caller-side signature" - ); - } - if let Ok(ops) = args.try_into() { - return interp_ok(ops); - } - throw_ub_format!( - "incorrect number of arguments for `{link_name}`: got {}, expected {}", - args.len(), - N - ) - } - - /// Check that the given `caller_fn_abi` matches the expected ABI described by - /// `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, - link_name: Symbol, - caller_fn_abi: &FnAbi<'tcx, Ty<'tcx>>, - callee_abi: ExternAbi, - callee_input_tys: [Ty<'tcx>; N], - callee_output_ty: Ty<'tcx>, - caller_args: &'a [OpTy<'tcx>], - ) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> { - let this = self.eval_context_mut(); - let mut inputs_and_output = callee_input_tys.to_vec(); - inputs_and_output.push(callee_output_ty); - let fn_sig_binder = Binder::dummy(FnSig { - inputs_and_output: this.machine.tcx.mk_type_list(&inputs_and_output), - c_variadic: false, - // This does not matter for the ABI. - safety: Safety::Safe, - abi: callee_abi, - }); - let callee_fn_abi = this.fn_abi_of_fn_ptr(fn_sig_binder, Default::default())?; - - this.check_abi_and_shim_symbol_clash(caller_fn_abi, callee_fn_abi.conv, link_name)?; - - if caller_fn_abi.c_variadic { - throw_ub_format!( - "ABI mismatch: calling a non-variadic function with a variadic caller-side signature" - ); - } - - if callee_fn_abi.fixed_count != caller_fn_abi.fixed_count { - throw_ub_format!( - "ABI mismatch: expected {} arguments, found {} arguments ", - callee_fn_abi.fixed_count, - caller_fn_abi.fixed_count - ); - } - - if callee_fn_abi.can_unwind && !caller_fn_abi.can_unwind { - throw_ub_format!( - "ABI mismatch: callee may unwind, but caller-side signature prohibits unwinding", - ); - } - - if !this.check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret)? { - throw_ub!(AbiMismatchReturn { - caller_ty: caller_fn_abi.ret.layout.ty, - callee_ty: callee_fn_abi.ret.layout.ty - }); - } - - if let Some(index) = caller_fn_abi - .args - .iter() - .zip(callee_fn_abi.args.iter()) - .map(|(caller_arg, callee_arg)| this.check_argument_compat(caller_arg, callee_arg)) - .collect::>>()? - .into_iter() - .position(|b| !b) - { - throw_ub!(AbiMismatchArgument { - caller_ty: caller_fn_abi.args[index].layout.ty, - callee_ty: callee_fn_abi.args[index].layout.ty - }); - } - - if let Ok(ops) = caller_args.try_into() { - return interp_ok(ops); - } - unreachable!() - } - - /// Check shim for variadic function. - /// Returns a tuple that consisting of an array of fixed args, and a slice of varargs. - fn check_shim_variadic<'a, const N: usize>( - &mut self, - abi: &FnAbi<'tcx, Ty<'tcx>>, - exp_abi: CanonAbi, - link_name: Symbol, - args: &'a [OpTy<'tcx>], - ) -> InterpResult<'tcx, (&'a [OpTy<'tcx>; N], &'a [OpTy<'tcx>])> - where - &'a [OpTy<'tcx>; N]: TryFrom<&'a [OpTy<'tcx>]>, - { - self.check_abi_and_shim_symbol_clash(abi, exp_abi, link_name)?; - - if !abi.c_variadic { - throw_ub_format!( - "calling a variadic function with a non-variadic caller-side signature" - ); - } - if abi.fixed_count != u32::try_from(N).unwrap() { - throw_ub_format!( - "incorrect number of fixed arguments for variadic function `{}`: got {}, expected {N}", - link_name.as_str(), - abi.fixed_count - ) - } - if let Some(args) = args.split_first_chunk() { - return interp_ok(args); - } - panic!("mismatch between signature and `args` slice"); - } - /// Mark a machine allocation that was just created as immutable. fn mark_immutable(&mut self, mplace: &MPlaceTy<'tcx>) { let this = self.eval_context_mut(); @@ -1317,39 +1147,6 @@ impl<'tcx> MiriMachine<'tcx> { } } -/// Check that the number of args is what we expect. -pub fn check_intrinsic_arg_count<'a, 'tcx, const N: usize>( - args: &'a [OpTy<'tcx>], -) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> -where - &'a [OpTy<'tcx>; N]: TryFrom<&'a [OpTy<'tcx>]>, -{ - if let Ok(ops) = args.try_into() { - return interp_ok(ops); - } - throw_ub_format!( - "incorrect number of arguments for intrinsic: got {}, expected {}", - args.len(), - N - ) -} - -/// Check that the number of varargs is at least the minimum what we expect. -/// Fixed args should not be included. -pub fn check_min_vararg_count<'a, 'tcx, const N: usize>( - name: &'a str, - args: &'a [OpTy<'tcx>], -) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> { - if let Some((ops, _)) = args.split_first_chunk() { - return interp_ok(ops); - } - throw_ub_format!( - "not enough variadic arguments for `{name}`: got {}, expected at least {}", - args.len(), - N - ) -} - pub fn isolation_abort_error<'tcx>(name: &str) -> InterpResult<'tcx> { throw_machine_stop!(TerminationInfo::UnsupportedInIsolation(format!( "{name} not available when isolation is enabled", diff --git a/src/intrinsics/atomic.rs b/src/intrinsics/atomic.rs index 0a59a707a1..bcc3e9ec88 100644 --- a/src/intrinsics/atomic.rs +++ b/src/intrinsics/atomic.rs @@ -2,7 +2,7 @@ use rustc_middle::mir::BinOp; use rustc_middle::ty::AtomicOrdering; use rustc_middle::{mir, ty}; -use self::helpers::check_intrinsic_arg_count; +use super::check_intrinsic_arg_count; use crate::*; pub enum AtomicOp { diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 4efa7dd4dc..b5e8146077 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -14,11 +14,28 @@ use rustc_middle::ty::{self, FloatTy, ScalarInt}; use rustc_span::{Symbol, sym}; use self::atomic::EvalContextExt as _; -use self::helpers::{ToHost, ToSoft, check_intrinsic_arg_count}; +use self::helpers::{ToHost, ToSoft}; use self::simd::EvalContextExt as _; use crate::math::{IeeeExt, apply_random_float_error_ulp}; use crate::*; +/// Check that the number of args is what we expect. +fn check_intrinsic_arg_count<'a, 'tcx, const N: usize>( + args: &'a [OpTy<'tcx>], +) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> +where + &'a [OpTy<'tcx>; N]: TryFrom<&'a [OpTy<'tcx>]>, +{ + if let Ok(ops) = args.try_into() { + return interp_ok(ops); + } + throw_ub_format!( + "incorrect number of arguments for intrinsic: got {}, expected {}", + args.len(), + N + ) +} + impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn call_intrinsic( @@ -114,7 +131,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )); } "catch_unwind" => { - this.handle_catch_unwind(args, dest, ret)?; + let [try_fn, data, catch_fn] = check_intrinsic_arg_count(args)?; + this.handle_catch_unwind(try_fn, data, catch_fn, dest, ret)?; // This pushed a stack frame, don't jump to `ret`. return interp_ok(EmulateItemResult::AlreadyJumped); } diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index e63992aa95..b26516c0ff 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -6,9 +6,8 @@ use rustc_middle::ty::FloatTy; use rustc_middle::{mir, ty}; use rustc_span::{Symbol, sym}; -use crate::helpers::{ - ToHost, ToSoft, bool_to_simd_element, check_intrinsic_arg_count, simd_element_to_bool, -}; +use super::check_intrinsic_arg_count; +use crate::helpers::{ToHost, ToSoft, bool_to_simd_element, simd_element_to_bool}; use crate::*; #[derive(Copy, Clone)] diff --git a/src/lib.rs b/src/lib.rs index ae70257653..507d4f7b42 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ #![feature(never_type)] #![feature(try_blocks)] #![feature(io_error_more)] +#![feature(if_let_guard)] #![feature(variant_count)] #![feature(yeet_expr)] #![feature(nonzero_ops)] @@ -158,6 +159,7 @@ pub use crate::shims::foreign_items::{DynSym, EvalContextExt as _}; pub use crate::shims::io_error::{EvalContextExt as _, IoError, LibcError}; pub use crate::shims::os_str::EvalContextExt as _; pub use crate::shims::panic::EvalContextExt as _; +pub use crate::shims::sig::EvalContextExt as _; pub use crate::shims::time::EvalContextExt as _; pub use crate::shims::tls::TlsData; pub use crate::shims::unwind::{CatchUnwindData, EvalContextExt as _}; diff --git a/src/shims/aarch64.rs b/src/shims/aarch64.rs index 44ad5081ad..6e422b4ab7 100644 --- a/src/shims/aarch64.rs +++ b/src/shims/aarch64.rs @@ -20,7 +20,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let unprefixed_name = link_name.as_str().strip_prefix("llvm.aarch64.").unwrap(); match unprefixed_name { "isb" => { - let [arg] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [arg] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let arg = this.read_scalar(arg)?.to_i32()?; match arg { // SY ("full system scope") @@ -38,7 +38,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `left` input, the second half of the output from the `right` input. // https://developer.arm.com/architectures/instruction-sets/intrinsics/vpmaxq_u8 "neon.umaxp.v16i8" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; diff --git a/src/shims/backtrace.rs b/src/shims/backtrace.rs index 18d60915d2..bd3914b652 100644 --- a/src/shims/backtrace.rs +++ b/src/shims/backtrace.rs @@ -15,7 +15,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let [flags] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + let [flags] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; let flags = this.read_scalar(flags)?.to_u64()?; if flags != 0 { @@ -37,7 +37,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let ptr_ty = this.machine.layouts.mut_raw_ptr.ty; let ptr_layout = this.layout_of(ptr_ty)?; - let [flags, buf] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + let [flags, buf] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; let flags = this.read_scalar(flags)?.to_u64()?; let buf_place = this.deref_pointer_as(buf, ptr_layout)?; @@ -117,7 +117,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let [ptr, flags] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + let [ptr, flags] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; let flags = this.read_scalar(flags)?.to_u64()?; @@ -195,7 +195,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let [ptr, flags, name_ptr, filename_ptr] = - this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; let flags = this.read_scalar(flags)?.to_u64()?; if flags != 0 { diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index 94cda57658..21545b6802 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -288,16 +288,17 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // Miri-specific extern functions "miri_start_unwind" => { - let [payload] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + let [payload] = + this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; this.handle_miri_start_unwind(payload)?; return interp_ok(EmulateItemResult::NeedsUnwind); } "miri_run_provenance_gc" => { - let [] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; this.run_provenance_gc(); } "miri_get_alloc_id" => { - let [ptr] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + let [ptr] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr, 0).map_err_kind(|_e| { err_machine_stop!(TerminationInfo::Abort(format!( @@ -307,7 +308,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(Scalar::from_u64(alloc_id.0.get()), dest)?; } "miri_print_borrow_state" => { - let [id, show_unnamed] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + let [id, show_unnamed] = + this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; let id = this.read_scalar(id)?.to_u64()?; let show_unnamed = this.read_scalar(show_unnamed)?.to_bool()?; if let Some(id) = std::num::NonZero::new(id).map(AllocId) @@ -322,7 +324,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // This associates a name to a tag. Very useful for debugging, and also makes // tests more strict. let [ptr, nth_parent, name] = - this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; let nth_parent = this.read_scalar(nth_parent)?.to_u8()?; let name = this.read_immediate(name)?; @@ -335,7 +337,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.give_pointer_debug_name(ptr, nth_parent, &name)?; } "miri_static_root" => { - let [ptr] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + let [ptr] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; let (alloc_id, offset, _) = this.ptr_get_alloc_id(ptr, 0)?; if offset != Size::ZERO { @@ -346,7 +348,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.machine.static_roots.push(alloc_id); } "miri_host_to_target_path" => { - let [ptr, out, out_size] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + let [ptr, out, out_size] = + this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; let out = this.read_pointer(out)?; let out_size = this.read_scalar(out_size)?.to_target_usize(this)?; @@ -382,7 +385,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // Writes some bytes to the interpreter's stdout/stderr. See the // README for details. "miri_write_to_stdout" | "miri_write_to_stderr" => { - let [msg] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + let [msg] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; let msg = this.read_immediate(msg)?; let msg = this.read_byte_slice(&msg)?; // Note: we're ignoring errors writing to host stdout/stderr. @@ -396,7 +399,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { "miri_promise_symbolic_alignment" => { use rustc_abi::AlignFromBytesError; - let [ptr, align] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + let [ptr, align] = + this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; let align = this.read_target_usize(align)?; if !align.is_power_of_two() { @@ -437,12 +441,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // Aborting the process. "exit" => { - let [code] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [code] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let code = this.read_scalar(code)?.to_i32()?; throw_machine_stop!(TerminationInfo::Exit { code, leak_check: false }); } "abort" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; throw_machine_stop!(TerminationInfo::Abort( "the program aborted execution".to_owned() )) @@ -450,7 +454,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // Standard C allocation "malloc" => { - let [size] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [size] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let size = this.read_target_usize(size)?; if size <= this.max_size_of_val().bytes() { let res = this.malloc(size, AllocInit::Uninit)?; @@ -464,7 +468,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } } "calloc" => { - let [items, elem_size] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [items, elem_size] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let items = this.read_target_usize(items)?; let elem_size = this.read_target_usize(elem_size)?; if let Some(size) = this.compute_size_in_bytes(Size::from_bytes(elem_size), items) { @@ -479,12 +484,13 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } } "free" => { - let [ptr] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [ptr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let ptr = this.read_pointer(ptr)?; this.free(ptr)?; } "realloc" => { - let [old_ptr, new_size] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [old_ptr, new_size] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let old_ptr = this.read_pointer(old_ptr)?; let new_size = this.read_target_usize(new_size)?; if new_size <= this.max_size_of_val().bytes() { @@ -504,7 +510,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let default = |ecx: &mut MiriInterpCx<'tcx>| { // Only call `check_shim` when `#[global_allocator]` isn't used. When that // macro is used, we act like no shim exists, so that the exported function can run. - let [size, align] = ecx.check_shim(abi, CanonAbi::Rust, link_name, args)?; + let [size, align] = + ecx.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; let size = ecx.read_target_usize(size)?; let align = ecx.read_target_usize(align)?; @@ -537,7 +544,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.emulate_allocator(|this| { // See the comment for `__rust_alloc` why `check_shim` is only called in the // default case. - let [size, align] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + let [size, align] = + this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; let size = this.read_target_usize(size)?; let align = this.read_target_usize(align)?; @@ -559,7 +567,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // See the comment for `__rust_alloc` why `check_shim` is only called in the // default case. let [ptr, old_size, align] = - ecx.check_shim(abi, CanonAbi::Rust, link_name, args)?; + ecx.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; let ptr = ecx.read_pointer(ptr)?; let old_size = ecx.read_target_usize(old_size)?; let align = ecx.read_target_usize(align)?; @@ -590,7 +598,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // See the comment for `__rust_alloc` why `check_shim` is only called in the // default case. let [ptr, old_size, align, new_size] = - this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; let old_size = this.read_target_usize(old_size)?; let align = this.read_target_usize(align)?; @@ -613,20 +621,21 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } name if name == this.mangle_internal_symbol("__rust_no_alloc_shim_is_unstable_v2") => { // This is a no-op shim that only exists to prevent making the allocator shims instantly stable. - let [] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; } name if name == this.mangle_internal_symbol("__rust_alloc_error_handler_should_panic_v2") => { // Gets the value of the `oom` option. - let [] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; let val = this.tcx.sess.opts.unstable_opts.oom.should_panic(); this.write_int(val, dest)?; } // C memory handling functions "memcmp" => { - let [left, right, n] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, n] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let left = this.read_pointer(left)?; let right = this.read_pointer(right)?; let n = Size::from_bytes(this.read_target_usize(n)?); @@ -650,7 +659,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(Scalar::from_i32(result), dest)?; } "memrchr" => { - let [ptr, val, num] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [ptr, val, num] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let ptr = this.read_pointer(ptr)?; let val = this.read_scalar(val)?.to_i32()?; let num = this.read_target_usize(num)?; @@ -676,7 +686,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } } "memchr" => { - let [ptr, val, num] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [ptr, val, num] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let ptr = this.read_pointer(ptr)?; let val = this.read_scalar(val)?.to_i32()?; let num = this.read_target_usize(num)?; @@ -699,7 +710,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } } "strlen" => { - let [ptr] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [ptr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let ptr = this.read_pointer(ptr)?; // This reads at least 1 byte, so we are already enforcing that this is a valid pointer. let n = this.read_c_str(ptr)?.len(); @@ -709,7 +720,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; } "wcslen" => { - let [ptr] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [ptr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let ptr = this.read_pointer(ptr)?; // This reads at least 1 byte, so we are already enforcing that this is a valid pointer. let n = this.read_wchar_t_str(ptr)?.len(); @@ -719,7 +730,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; } "memcpy" => { - let [ptr_dest, ptr_src, n] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [ptr_dest, ptr_src, n] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let ptr_dest = this.read_pointer(ptr_dest)?; let ptr_src = this.read_pointer(ptr_src)?; let n = this.read_target_usize(n)?; @@ -733,7 +745,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_pointer(ptr_dest, dest)?; } "strcpy" => { - let [ptr_dest, ptr_src] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [ptr_dest, ptr_src] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let ptr_dest = this.read_pointer(ptr_dest)?; let ptr_src = this.read_pointer(ptr_src)?; @@ -764,7 +777,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { | "erff" | "erfcf" => { - let [f] = this.check_shim(abi, CanonAbi::C , link_name, args)?; + let [f] = this.check_shim_sig_lenient(abi, CanonAbi::C , link_name, args)?; let f = this.read_scalar(f)?.to_f32()?; // Using host floats (but it's fine, these operations do not have guaranteed precision). let f_host = f.to_host(); @@ -802,7 +815,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { | "atan2f" | "fdimf" => { - let [f1, f2] = this.check_shim(abi, CanonAbi::C , link_name, args)?; + let [f1, f2] = this.check_shim_sig_lenient(abi, CanonAbi::C , link_name, args)?; let f1 = this.read_scalar(f1)?.to_f32()?; let f2 = this.read_scalar(f2)?.to_f32()?; // underscore case for windows, here and below @@ -841,7 +854,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { | "erf" | "erfc" => { - let [f] = this.check_shim(abi, CanonAbi::C , link_name, args)?; + let [f] = this.check_shim_sig_lenient(abi, CanonAbi::C , link_name, args)?; let f = this.read_scalar(f)?.to_f64()?; // Using host floats (but it's fine, these operations do not have guaranteed precision). let f_host = f.to_host(); @@ -879,7 +892,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { | "atan2" | "fdim" => { - let [f1, f2] = this.check_shim(abi, CanonAbi::C , link_name, args)?; + let [f1, f2] = this.check_shim_sig_lenient(abi, CanonAbi::C , link_name, args)?; let f1 = this.read_scalar(f1)?.to_f64()?; let f2 = this.read_scalar(f2)?.to_f64()?; // underscore case for windows, here and below @@ -908,7 +921,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { | "ldexp" | "scalbn" => { - let [x, exp] = this.check_shim(abi, CanonAbi::C , link_name, args)?; + let [x, exp] = this.check_shim_sig_lenient(abi, CanonAbi::C , link_name, args)?; // For radix-2 (binary) systems, `ldexp` and `scalbn` are the same. let x = this.read_scalar(x)?.to_f64()?; let exp = this.read_scalar(exp)?.to_i32()?; @@ -918,7 +931,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "lgammaf_r" => { - let [x, signp] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [x, signp] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let x = this.read_scalar(x)?.to_f32()?; let signp = this.deref_pointer_as(signp, this.machine.layouts.i32)?; @@ -934,7 +947,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "lgamma_r" => { - let [x, signp] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [x, signp] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let x = this.read_scalar(x)?.to_f64()?; let signp = this.deref_pointer_as(signp, this.machine.layouts.i32)?; @@ -952,7 +965,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // LLVM intrinsics "llvm.prefetch" => { - let [p, rw, loc, ty] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [p, rw, loc, ty] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let _ = this.read_pointer(p)?; let rw = this.read_scalar(rw)?.to_i32()?; @@ -979,7 +993,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // Used to implement the x86 `_mm{,256,512}_popcnt_epi{8,16,32,64}` and wasm // `{i,u}8x16_popcnt` functions. name if name.starts_with("llvm.ctpop.v") => { - let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (op, op_len) = this.project_to_simd(op)?; let (dest, dest_len) = this.project_to_simd(dest)?; @@ -1015,7 +1029,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } // FIXME: Move this to an `arm` submodule. "llvm.arm.hint" if this.tcx.sess.target.arch == "arm" => { - let [arg] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [arg] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let arg = this.read_scalar(arg)?.to_i32()?; // Note that different arguments might have different target feature requirements. match arg { diff --git a/src/shims/mod.rs b/src/shims/mod.rs index 2a7709829e..7f594d4fdd 100644 --- a/src/shims/mod.rs +++ b/src/shims/mod.rs @@ -18,6 +18,7 @@ pub mod global_ctor; pub mod io_error; pub mod os_str; pub mod panic; +pub mod sig; pub mod time; pub mod tls; pub mod unwind; diff --git a/src/shims/sig.rs b/src/shims/sig.rs new file mode 100644 index 0000000000..8dd08055c7 --- /dev/null +++ b/src/shims/sig.rs @@ -0,0 +1,265 @@ +//! Everything related to checking the signature of shim invocations. + +use rustc_abi::{CanonAbi, ExternAbi}; +use rustc_hir::Safety; +use rustc_middle::ty::{Binder, FnSig, Ty}; +use rustc_span::Symbol; +use rustc_target::callconv::FnAbi; + +use crate::*; + +/// Describes the expected signature of a shim. +pub struct ShimSig<'tcx, const ARGS: usize> { + pub abi: ExternAbi, + pub args: [Ty<'tcx>; ARGS], + pub ret: Ty<'tcx>, +} + +/// Construct a `ShimSig` with convenient syntax: +/// ```rust,ignore +/// shim_sig!(this, extern "C" fn (*const T, i32) -> usize) +/// ``` +#[macro_export] +macro_rules! shim_sig { + (extern $abi:literal fn($($arg:ty),*) -> $ret:ty) => { + |this| $crate::shims::sig::ShimSig { + abi: std::str::FromStr::from_str($abi).expect("incorrect abi specified"), + args: [$(shim_sig_arg!(this, $arg)),*], + ret: shim_sig_arg!(this, $ret), + } + }; +} + +/// Helper for `shim_sig!`. +#[macro_export] +macro_rules! shim_sig_arg { + // Unfortuantely we cannot take apart a `ty`-typed token at compile time, + // so we have to stringify it and match at runtime. + ($this:ident, $x:ty) => {{ + match stringify!($x) { + "i8" => $this.tcx.types.i8, + "i16" => $this.tcx.types.i16, + "i32" => $this.tcx.types.i32, + "i64" => $this.tcx.types.i64, + "i128" => $this.tcx.types.i128, + "isize" => $this.tcx.types.isize, + "u8" => $this.tcx.types.u8, + "u16" => $this.tcx.types.u16, + "u32" => $this.tcx.types.u32, + "u64" => $this.tcx.types.u64, + "u128" => $this.tcx.types.u128, + "usize" => $this.tcx.types.usize, + "()" => $this.tcx.types.unit, + "*const _" => $this.machine.layouts.const_raw_ptr.ty, + "*mut _" => $this.machine.layouts.mut_raw_ptr.ty, + ty if let Some(libc_ty) = ty.strip_prefix("libc::") => $this.libc_ty_layout(libc_ty).ty, + ty => panic!("unsupported signature type {ty:?}"), + } + }}; +} + +/// Helper function to compare two ABIs. +fn check_shim_abi<'tcx>( + this: &MiriInterpCx<'tcx>, + callee_abi: &FnAbi<'tcx, Ty<'tcx>>, + caller_abi: &FnAbi<'tcx, Ty<'tcx>>, +) -> InterpResult<'tcx> { + if callee_abi.conv != caller_abi.conv { + throw_ub_format!( + r#"calling a function with calling convention "{callee}" using caller calling convention "{caller}""#, + callee = callee_abi.conv, + caller = caller_abi.conv, + ); + } + if callee_abi.can_unwind && !caller_abi.can_unwind { + throw_ub_format!( + "ABI mismatch: callee may unwind, but caller-side signature prohibits unwinding", + ); + } + if caller_abi.c_variadic && !callee_abi.c_variadic { + throw_ub_format!( + "ABI mismatch: calling a non-variadic function with a variadic caller-side signature" + ); + } + if !caller_abi.c_variadic && callee_abi.c_variadic { + throw_ub_format!( + "ABI mismatch: calling a variadic function with a non-variadic caller-side signature" + ); + } + + if callee_abi.fixed_count != caller_abi.fixed_count { + throw_ub_format!( + "ABI mismatch: expected {} arguments, found {} arguments ", + callee_abi.fixed_count, + caller_abi.fixed_count + ); + } + + if !this.check_argument_compat(&caller_abi.ret, &callee_abi.ret)? { + throw_ub!(AbiMismatchReturn { + caller_ty: caller_abi.ret.layout.ty, + callee_ty: callee_abi.ret.layout.ty + }); + } + + for (idx, (caller_arg, callee_arg)) in + caller_abi.args.iter().zip(callee_abi.args.iter()).enumerate() + { + if !this.check_argument_compat(caller_arg, callee_arg)? { + throw_ub!(AbiMismatchArgument { + caller_ty: caller_abi.args[idx].layout.ty, + callee_ty: callee_abi.args[idx].layout.ty + }); + } + } + + interp_ok(()) +} + +fn check_shim_symbol_clash<'tcx>( + this: &mut MiriInterpCx<'tcx>, + link_name: Symbol, +) -> InterpResult<'tcx, ()> { + if let Some((body, instance)) = this.lookup_exported_symbol(link_name)? { + // If compiler-builtins is providing the symbol, then don't treat it as a clash. + // We'll use our built-in implementation in `emulate_foreign_item_inner` for increased + // performance. Note that this means we won't catch any undefined behavior in + // compiler-builtins when running other crates, but Miri can still be run on + // compiler-builtins itself (or any crate that uses it as a normal dependency) + if this.tcx.is_compiler_builtins(instance.def_id().krate) { + return interp_ok(()); + } + + throw_machine_stop!(TerminationInfo::SymbolShimClashing { + link_name, + span: body.span.data(), + }) + } + interp_ok(()) +} + +impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} +pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + fn check_shim_sig_lenient<'a, const N: usize>( + &mut self, + abi: &FnAbi<'tcx, Ty<'tcx>>, + exp_abi: CanonAbi, + link_name: Symbol, + args: &'a [OpTy<'tcx>], + ) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> { + let this = self.eval_context_mut(); + check_shim_symbol_clash(this, link_name)?; + + if abi.conv != exp_abi { + throw_ub_format!( + r#"calling a function with calling convention "{exp_abi}" using caller calling convention "{}""#, + abi.conv + ); + } + if abi.c_variadic { + throw_ub_format!( + "calling a non-variadic function with a variadic caller-side signature" + ); + } + + if let Ok(ops) = args.try_into() { + return interp_ok(ops); + } + throw_ub_format!( + "incorrect number of arguments for `{link_name}`: got {}, expected {}", + args.len(), + N + ) + } + + /// Check that the given `caller_fn_abi` matches the expected ABI described by `shim_sig`, and + /// then returns the list of arguments. + fn check_shim_sig<'a, const N: usize>( + &mut self, + shim_sig: fn(&MiriInterpCx<'tcx>) -> ShimSig<'tcx, N>, + link_name: Symbol, + caller_fn_abi: &FnAbi<'tcx, Ty<'tcx>>, + caller_args: &'a [OpTy<'tcx>], + ) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> { + let this = self.eval_context_mut(); + let shim_sig = shim_sig(this); + + // Compute full callee ABI. + let mut inputs_and_output = Vec::with_capacity(N.strict_add(1)); + inputs_and_output.extend(&shim_sig.args); + inputs_and_output.push(shim_sig.ret); + let fn_sig_binder = Binder::dummy(FnSig { + inputs_and_output: this.machine.tcx.mk_type_list(&inputs_and_output), + c_variadic: false, + // This does not matter for the ABI. + safety: Safety::Safe, + abi: shim_sig.abi, + }); + let callee_fn_abi = this.fn_abi_of_fn_ptr(fn_sig_binder, Default::default())?; + + // Check everything. + check_shim_abi(this, callee_fn_abi, caller_fn_abi)?; + check_shim_symbol_clash(this, link_name)?; + + // Return arguments. + if let Ok(ops) = caller_args.try_into() { + return interp_ok(ops); + } + unreachable!() + } + + /// Check shim for variadic function. + /// Returns a tuple that consisting of an array of fixed args, and a slice of varargs. + fn check_shim_sig_variadic_lenient<'a, const N: usize>( + &mut self, + abi: &FnAbi<'tcx, Ty<'tcx>>, + exp_abi: CanonAbi, + link_name: Symbol, + args: &'a [OpTy<'tcx>], + ) -> InterpResult<'tcx, (&'a [OpTy<'tcx>; N], &'a [OpTy<'tcx>])> + where + &'a [OpTy<'tcx>; N]: TryFrom<&'a [OpTy<'tcx>]>, + { + let this = self.eval_context_mut(); + check_shim_symbol_clash(this, link_name)?; + + if abi.conv != exp_abi { + throw_ub_format!( + r#"calling a function with calling convention "{exp_abi}" using caller calling convention "{}""#, + abi.conv + ); + } + if !abi.c_variadic { + throw_ub_format!( + "calling a variadic function with a non-variadic caller-side signature" + ); + } + if abi.fixed_count != u32::try_from(N).unwrap() { + throw_ub_format!( + "incorrect number of fixed arguments for variadic function `{}`: got {}, expected {N}", + link_name.as_str(), + abi.fixed_count + ) + } + if let Some(args) = args.split_first_chunk() { + return interp_ok(args); + } + panic!("mismatch between signature and `args` slice"); + } +} + +/// Check that the number of varargs is at least the minimum what we expect. +/// Fixed args should not be included. +pub fn check_min_vararg_count<'a, 'tcx, const N: usize>( + name: &'a str, + args: &'a [OpTy<'tcx>], +) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> { + if let Some((ops, _)) = args.split_first_chunk() { + return interp_ok(ops); + } + throw_ub_format!( + "not enough variadic arguments for `{name}`: got {}, expected at least {}", + args.len(), + N + ) +} diff --git a/src/shims/unix/android/foreign_items.rs b/src/shims/unix/android/foreign_items.rs index 690b529568..04c5d28838 100644 --- a/src/shims/unix/android/foreign_items.rs +++ b/src/shims/unix/android/foreign_items.rs @@ -26,29 +26,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // epoll, eventfd "epoll_create1" => { - let [flag] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [flag] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.epoll_create1(flag)?; this.write_scalar(result, dest)?; } "epoll_ctl" => { - let [epfd, op, fd, event] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [epfd, op, fd, event] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.epoll_ctl(epfd, op, fd, event)?; this.write_scalar(result, dest)?; } "epoll_wait" => { let [epfd, events, maxevents, timeout] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.epoll_wait(epfd, events, maxevents, timeout, dest)?; } "eventfd" => { - let [val, flag] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [val, flag] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.eventfd(val, flag)?; this.write_scalar(result, dest)?; } // Miscellaneous "__errno" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let errno_place = this.last_error_place()?; this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } diff --git a/src/shims/unix/android/thread.rs b/src/shims/unix/android/thread.rs index 5d17d6c851..4e7b21d7d9 100644 --- a/src/shims/unix/android/thread.rs +++ b/src/shims/unix/android/thread.rs @@ -3,7 +3,7 @@ use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::callconv::FnAbi; -use crate::helpers::check_min_vararg_count; +use crate::shims::sig::check_min_vararg_count; use crate::shims::unix::thread::{EvalContextExt as _, ThreadNameResult}; use crate::*; @@ -16,7 +16,7 @@ pub fn prctl<'tcx>( args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx> { - let ([op], varargs) = ecx.check_shim_variadic(abi, CanonAbi::C, link_name, args)?; + let ([op], varargs) = ecx.check_shim_sig_variadic_lenient(abi, CanonAbi::C, link_name, args)?; // FIXME: Use constants once https://github.com/rust-lang/libc/pull/3941 backported to the 0.2 branch. let pr_set_name = 15; diff --git a/src/shims/unix/fd.rs b/src/shims/unix/fd.rs index b420955501..e226a55d8b 100644 --- a/src/shims/unix/fd.rs +++ b/src/shims/unix/fd.rs @@ -7,8 +7,8 @@ use std::io::ErrorKind; use rand::Rng; use rustc_abi::Size; -use crate::helpers::check_min_vararg_count; use crate::shims::files::FileDescription; +use crate::shims::sig::check_min_vararg_count; use crate::shims::unix::linux_like::epoll::EpollReadyEvents; use crate::shims::unix::*; use crate::*; diff --git a/src/shims/unix/foreign_items.rs b/src/shims/unix/foreign_items.rs index 548eabb1b9..55906f4eb9 100644 --- a/src/shims/unix/foreign_items.rs +++ b/src/shims/unix/foreign_items.rs @@ -1,7 +1,7 @@ use std::ffi::OsStr; use std::str; -use rustc_abi::{CanonAbi, ExternAbi, Size}; +use rustc_abi::{CanonAbi, Size}; use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::callconv::FnAbi; @@ -14,7 +14,7 @@ use self::shims::unix::solarish::foreign_items as solarish; use crate::concurrency::cpu_affinity::CpuAffinityMask; use crate::shims::alloc::EvalContextExt as _; use crate::shims::unix::*; -use crate::*; +use crate::{shim_sig, *}; pub fn is_dyn_sym(name: &str, target_os: &str) -> bool { match name { @@ -111,40 +111,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // Environment related shims "getenv" => { - let [name] = this.check_shim_abi( + let [name] = this.check_shim_sig( + shim_sig!(extern "C" fn(*const _) -> *mut _), 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( + let [name] = this.check_shim_sig( + shim_sig!(extern "C" fn(*const _) -> i32), 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( + let [name, value, overwrite] = this.check_shim_sig( + shim_sig!(extern "C" fn(*const _, *const _, i32) -> i32), 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()?; @@ -152,48 +142,40 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } "getcwd" => { - let [buf, size] = this.check_shim_abi( + let [buf, size] = this.check_shim_sig( + shim_sig!(extern "C" fn(*mut _, usize) -> *mut _), 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( + let [path] = this.check_shim_sig( + shim_sig!(extern "C" fn(*const _) -> i32), 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( + let [] = this.check_shim_sig( + shim_sig!(extern "C" fn() -> libc::pid_t), 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( + let [val] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32) -> isize), link_name, abi, - ExternAbi::C { unwind: false }, - [this.tcx.types.i32], - this.tcx.types.isize, args, )?; let result = this.sysconf(val)?; @@ -201,12 +183,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // File descriptors "read" => { - let [fd, buf, count] = this.check_shim_abi( + let [fd, buf, count] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, *mut _, usize) -> isize), 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()?; @@ -215,16 +195,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.read(fd, buf, count, None, dest)?; } "write" => { - let [fd, buf, n] = this.check_shim_abi( + let [fd, buf, n] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, *const _, usize) -> isize), 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()?; @@ -234,98 +208,64 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write(fd, buf, count, None, dest)?; } "pread" => { - let off_t = this.libc_ty_layout("off_t"); - let [fd, buf, count, offset] = this.check_shim_abi( + let [fd, buf, count, offset] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, *mut _, usize, libc::off_t) -> isize), 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(off_t.size)?; + let offset = this.read_scalar(offset)?.to_int(offset.layout.size)?; this.read(fd, buf, count, Some(offset), dest)?; } "pwrite" => { - let off_t = this.libc_ty_layout("off_t"); - let [fd, buf, n, offset] = this.check_shim_abi( + let [fd, buf, n, offset] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, *const _, usize, libc::off_t) -> isize), 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(off_t.size)?; + let offset = this.read_scalar(offset)?.to_int(offset.layout.size)?; trace!("Called pwrite({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset); this.write(fd, buf, count, Some(offset), dest)?; } "pread64" => { - let off64_t = this.libc_ty_layout("off64_t"); - let [fd, buf, count, offset] = this.check_shim_abi( + let [fd, buf, count, offset] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, *mut _, usize, libc::off64_t) -> isize), 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(off64_t.size)?; + let offset = this.read_scalar(offset)?.to_int(offset.layout.size)?; this.read(fd, buf, count, Some(offset), dest)?; } "pwrite64" => { - let off64_t = this.libc_ty_layout("off64_t"); - let [fd, buf, n, offset] = this.check_shim_abi( + let [fd, buf, n, offset] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, *const _, usize, libc::off64_t) -> isize), 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(off64_t.size)?; + let offset = this.read_scalar(offset)?.to_int(offset.layout.size)?; trace!("Called pwrite64({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset); this.write(fd, buf, count, Some(offset), dest)?; } "close" => { - let [fd] = this.check_shim_abi( + let [fd] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32) -> i32), link_name, abi, - ExternAbi::C { unwind: false }, - [this.tcx.types.i32], - this.tcx.types.i32, args, )?; let result = this.close(fd)?; @@ -333,17 +273,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "fcntl" => { let ([fd_num, cmd], varargs) = - this.check_shim_variadic(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_variadic_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.fcntl(fd_num, cmd, varargs)?; this.write_scalar(result, dest)?; } "dup" => { - let [old_fd] = this.check_shim_abi( + let [old_fd] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32) -> i32), 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()?; @@ -351,12 +289,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(new_fd, dest)?; } "dup2" => { - let [old_fd, new_fd] = this.check_shim_abi( + let [old_fd, new_fd] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, i32) -> i32), 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()?; @@ -367,12 +303,10 @@ 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( + let [fd, op] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, i32) -> i32), 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()?; @@ -386,230 +320,187 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `open` is variadic, the third argument is only present when the second argument // has O_CREAT (or on linux O_TMPFILE, but miri doesn't support that) set let ([path_raw, flag], varargs) = - this.check_shim_variadic(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_variadic_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.open(path_raw, flag, varargs)?; this.write_scalar(result, dest)?; } "unlink" => { - let [path] = this.check_shim_abi( + let [path] = this.check_shim_sig( + shim_sig!(extern "C" fn(*const _) -> i32), 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( + let [target, linkpath] = this.check_shim_sig( + shim_sig!(extern "C" fn(*const _, *const _) -> i32), 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( + let [oldpath, newpath] = this.check_shim_sig( + shim_sig!(extern "C" fn(*const _, *const _) -> i32), 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( + let [path, mode] = this.check_shim_sig( + shim_sig!(extern "C" fn(*const _, libc::mode_t) -> i32), 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( + let [path] = this.check_shim_sig( + shim_sig!(extern "C" fn(*const _) -> i32), 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( + let [name] = this.check_shim_sig( + shim_sig!(extern "C" fn(*const _) -> *mut _), 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( + let [dirp] = this.check_shim_sig( + shim_sig!(extern "C" fn(*mut _) -> i32), 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 off64_t = this.libc_ty_layout("off64_t"); - let [fd, offset, whence] = this.check_shim_abi( + let [fd, offset, whence] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, libc::off64_t, i32) -> libc::off64_t), 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_int(off64_t.size)?; + let offset = this.read_scalar(offset)?.to_int(offset.layout.size)?; let whence = this.read_scalar(whence)?.to_i32()?; this.lseek64(fd, offset, whence, dest)?; } "lseek" => { - let off_t = this.libc_ty_layout("off_t"); - let [fd, offset, whence] = this.check_shim_abi( + let [fd, offset, whence] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, libc::off_t, i32) -> libc::off_t), 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(off_t.size)?; + let offset = this.read_scalar(offset)?.to_int(offset.layout.size)?; let whence = this.read_scalar(whence)?.to_i32()?; this.lseek64(fd, offset, whence, dest)?; } "ftruncate64" => { - let off64_t = this.libc_ty_layout("off64_t"); - let [fd, length] = this.check_shim_abi( + let [fd, length] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, libc::off64_t) -> i32), 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_int(off64_t.size)?; + let length = this.read_scalar(length)?.to_int(length.layout.size)?; let result = this.ftruncate64(fd, length)?; this.write_scalar(result, dest)?; } "ftruncate" => { - let off_t = this.libc_ty_layout("off_t"); - let [fd, length] = this.check_shim_abi( + let [fd, length] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, libc::off_t) -> i32), 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(off_t.size)?; + let length = this.read_scalar(length)?.to_int(length.layout.size)?; let result = this.ftruncate64(fd, length)?; this.write_scalar(result, dest)?; } "fsync" => { - let [fd] = this.check_shim_abi( + let [fd] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32) -> i32), 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( + let [fd] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32) -> i32), 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( + let [pathname, buf, bufsize] = this.check_shim_sig( + shim_sig!(extern "C" fn(*const _, *mut _, usize) -> isize), 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 off_t = this.libc_ty_layout("off_t"); - let [fd, offset, len, advice] = this.check_shim_abi( + let [fd, offset, len, advice] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, libc::off_t, libc::off_t, i32) -> i32), 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_scalar(offset)?.to_int(off_t.size)?; - this.read_scalar(len)?.to_int(off_t.size)?; + this.read_scalar(offset)?.to_int(offset.layout.size)?; + this.read_scalar(len)?.to_int(len.layout.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( + let [path, resolved_path] = this.check_shim_sig( + shim_sig!(extern "C" fn(*const _, *mut _) -> *mut _), 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( + let [template] = this.check_shim_sig( + shim_sig!(extern "C" fn(*mut _) -> i32), link_name, abi, - ExternAbi::C { unwind: false }, - [this.machine.layouts.mut_raw_ptr.ty], - this.tcx.types.i32, args, )?; let result = this.mkstemp(template)?; @@ -618,29 +509,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Unnamed sockets and pipes "socketpair" => { - let [domain, type_, protocol, sv] = this.check_shim_abi( + let [domain, type_, protocol, sv] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, i32, i32, *mut _) -> i32), 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( + let [pipefd] = this.check_shim_sig( + shim_sig!(extern "C" fn(*mut _) -> i32), 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)?; @@ -649,12 +531,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "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( + let [pipefd, flags] = this.check_shim_sig( + shim_sig!(extern "C" fn(*mut _, i32) -> i32), 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))?; @@ -663,36 +543,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Time "gettimeofday" => { - let [tv, tz] = this.check_shim_abi( + let [tv, tz] = this.check_shim_sig( + shim_sig!(extern "C" fn(*mut _, *mut _) -> i32), 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( + let [timep, result_op] = this.check_shim_sig( + shim_sig!(extern "C" fn(*const _, *mut _) -> *mut _), 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( + let [clk_id, tp] = this.check_shim_sig( + shim_sig!(extern "C" fn(libc::clockid_t, *mut _) -> i32), 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)?; @@ -700,20 +574,22 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Allocation "posix_memalign" => { - let [memptr, align, size] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [memptr, align, size] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.posix_memalign(memptr, align, size)?; this.write_scalar(result, dest)?; } "mmap" => { let [addr, length, prot, flags, fd, offset] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, 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)?; } "munmap" => { - let [addr, length] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [addr, length] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.munmap(addr, length)?; this.write_scalar(result, dest)?; } @@ -721,7 +597,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "reallocarray" => { // Currently this function does not exist on all Unixes, e.g. on macOS. this.check_target_os(&["linux", "freebsd", "android"], link_name)?; - let [ptr, nmemb, size] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [ptr, nmemb, size] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let ptr = this.read_pointer(ptr)?; let nmemb = this.read_target_usize(nmemb)?; let size = this.read_target_usize(size)?; @@ -744,14 +621,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "aligned_alloc" => { // This is a C11 function, we assume all Unixes have it. // (MSVC explicitly does not support this.) - let [align, size] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [align, size] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let res = this.aligned_alloc(align, size)?; this.write_pointer(res, dest)?; } // Dynamic symbol loading "dlsym" => { - let [handle, symbol] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [handle, symbol] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.read_target_usize(handle)?; let symbol = this.read_pointer(symbol)?; let name = this.read_c_str(symbol)?; @@ -767,7 +646,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Thread-local storage "pthread_key_create" => { - let [key, dtor] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [key, dtor] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let key_place = this.deref_pointer_as(key, this.libc_ty_layout("pthread_key_t"))?; let dtor = this.read_pointer(dtor)?; @@ -795,21 +674,22 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_null(dest)?; } "pthread_key_delete" => { - let [key] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [key] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let key = this.read_scalar(key)?.to_bits(key.layout.size)?; this.machine.tls.delete_tls_key(key)?; // Return success (0) this.write_null(dest)?; } "pthread_getspecific" => { - let [key] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [key] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let key = this.read_scalar(key)?.to_bits(key.layout.size)?; let active_thread = this.active_thread(); let ptr = this.machine.tls.load_tls(key, active_thread, this)?; this.write_scalar(ptr, dest)?; } "pthread_setspecific" => { - let [key, new_ptr] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [key, new_ptr] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let key = this.read_scalar(key)?.to_bits(key.layout.size)?; let active_thread = this.active_thread(); let new_data = this.read_scalar(new_ptr)?; @@ -821,117 +701,124 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Synchronization primitives "pthread_mutexattr_init" => { - let [attr] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [attr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_mutexattr_init(attr)?; this.write_null(dest)?; } "pthread_mutexattr_settype" => { - let [attr, kind] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [attr, kind] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.pthread_mutexattr_settype(attr, kind)?; this.write_scalar(result, dest)?; } "pthread_mutexattr_destroy" => { - let [attr] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [attr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_mutexattr_destroy(attr)?; this.write_null(dest)?; } "pthread_mutex_init" => { - let [mutex, attr] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [mutex, attr] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_mutex_init(mutex, attr)?; this.write_null(dest)?; } "pthread_mutex_lock" => { - let [mutex] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [mutex] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_mutex_lock(mutex, dest)?; } "pthread_mutex_trylock" => { - let [mutex] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [mutex] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.pthread_mutex_trylock(mutex)?; this.write_scalar(result, dest)?; } "pthread_mutex_unlock" => { - let [mutex] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [mutex] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.pthread_mutex_unlock(mutex)?; this.write_scalar(result, dest)?; } "pthread_mutex_destroy" => { - let [mutex] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [mutex] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_mutex_destroy(mutex)?; this.write_int(0, dest)?; } "pthread_rwlock_rdlock" => { - let [rwlock] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_rwlock_rdlock(rwlock, dest)?; } "pthread_rwlock_tryrdlock" => { - let [rwlock] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.pthread_rwlock_tryrdlock(rwlock)?; this.write_scalar(result, dest)?; } "pthread_rwlock_wrlock" => { - let [rwlock] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_rwlock_wrlock(rwlock, dest)?; } "pthread_rwlock_trywrlock" => { - let [rwlock] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.pthread_rwlock_trywrlock(rwlock)?; this.write_scalar(result, dest)?; } "pthread_rwlock_unlock" => { - let [rwlock] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_rwlock_unlock(rwlock)?; this.write_null(dest)?; } "pthread_rwlock_destroy" => { - let [rwlock] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [rwlock] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_rwlock_destroy(rwlock)?; this.write_null(dest)?; } "pthread_condattr_init" => { - let [attr] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [attr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_condattr_init(attr)?; this.write_null(dest)?; } "pthread_condattr_setclock" => { - let [attr, clock_id] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [attr, clock_id] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.pthread_condattr_setclock(attr, clock_id)?; this.write_scalar(result, dest)?; } "pthread_condattr_getclock" => { - let [attr, clock_id] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [attr, clock_id] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_condattr_getclock(attr, clock_id)?; this.write_null(dest)?; } "pthread_condattr_destroy" => { - let [attr] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [attr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_condattr_destroy(attr)?; this.write_null(dest)?; } "pthread_cond_init" => { - let [cond, attr] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [cond, attr] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_cond_init(cond, attr)?; this.write_null(dest)?; } "pthread_cond_signal" => { - let [cond] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [cond] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_cond_signal(cond)?; this.write_null(dest)?; } "pthread_cond_broadcast" => { - let [cond] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [cond] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_cond_broadcast(cond)?; this.write_null(dest)?; } "pthread_cond_wait" => { - let [cond, mutex] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [cond, mutex] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_cond_wait(cond, mutex, dest)?; } "pthread_cond_timedwait" => { - let [cond, mutex, abstime] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [cond, mutex, abstime] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_cond_timedwait(cond, mutex, abstime, dest)?; } "pthread_cond_destroy" => { - let [cond] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [cond] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_cond_destroy(cond)?; this.write_null(dest)?; } @@ -939,31 +826,33 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Threading "pthread_create" => { let [thread, attr, start, arg] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_create(thread, attr, start, arg)?; this.write_null(dest)?; } "pthread_join" => { - let [thread, retval] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [thread, retval] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.pthread_join(thread, retval, dest)?; } "pthread_detach" => { - let [thread] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [thread] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let res = this.pthread_detach(thread)?; this.write_scalar(res, dest)?; } "pthread_self" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let res = this.pthread_self()?; this.write_scalar(res, dest)?; } "sched_yield" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.sched_yield()?; this.write_null(dest)?; } "nanosleep" => { - let [duration, rem] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [duration, rem] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.nanosleep(duration, rem)?; this.write_scalar(result, dest)?; } @@ -974,14 +863,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { link_name, )?; let [clock_id, flags, req, rem] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.clock_nanosleep(clock_id, flags, req, rem)?; this.write_scalar(result, dest)?; } "sched_getaffinity" => { // Currently this function does not exist on all Unixes, e.g. on macOS. this.check_target_os(&["linux", "freebsd", "android"], link_name)?; - let [pid, cpusetsize, mask] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [pid, cpusetsize, mask] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let pid = this.read_scalar(pid)?.to_u32()?; let cpusetsize = this.read_target_usize(cpusetsize)?; let mask = this.read_pointer(mask)?; @@ -1018,7 +908,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "sched_setaffinity" => { // Currently this function does not exist on all Unixes, e.g. on macOS. this.check_target_os(&["linux", "freebsd", "android"], link_name)?; - let [pid, cpusetsize, mask] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [pid, cpusetsize, mask] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let pid = this.read_scalar(pid)?.to_u32()?; let cpusetsize = this.read_target_usize(cpusetsize)?; let mask = this.read_pointer(mask)?; @@ -1058,13 +949,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Miscellaneous "isatty" => { - let [fd] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [fd] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.isatty(fd)?; this.write_scalar(result, dest)?; } "pthread_atfork" => { let [prepare, parent, child] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.read_pointer(prepare)?; this.read_pointer(parent)?; this.read_pointer(child)?; @@ -1078,7 +969,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &["linux", "macos", "freebsd", "illumos", "solaris", "android"], link_name, )?; - let [buf, bufsize] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [buf, bufsize] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let buf = this.read_pointer(buf)?; let bufsize = this.read_target_usize(bufsize)?; @@ -1096,7 +988,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "strerror_r" => { - let [errnum, buf, buflen] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [errnum, buf, buflen] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.strerror_r(errnum, buf, buflen)?; this.write_scalar(result, dest)?; } @@ -1108,7 +1001,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &["linux", "freebsd", "illumos", "solaris", "android"], link_name, )?; - let [ptr, len, flags] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [ptr, len, flags] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let ptr = this.read_pointer(ptr)?; let len = this.read_target_usize(len)?; let _flags = this.read_scalar(flags)?.to_i32()?; @@ -1120,7 +1014,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // This function is non-standard but exists with the same signature and // same behavior (eg never fails) on FreeBSD and Solaris/Illumos. this.check_target_os(&["freebsd", "illumos", "solaris"], link_name)?; - let [ptr, len] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [ptr, len] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let ptr = this.read_pointer(ptr)?; let len = this.read_target_usize(len)?; this.gen_random(ptr, len)?; @@ -1144,12 +1038,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { link_name, )?; // This function looks and behaves excatly like miri_start_unwind. - let [payload] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [payload] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.handle_miri_start_unwind(payload)?; return interp_ok(EmulateItemResult::NeedsUnwind); } "getuid" | "geteuid" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; // For now, just pretend we always have this fixed UID. this.write_int(UID, dest)?; } @@ -1157,7 +1051,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Incomplete shims that we "stub out" just to get pre-main initialization code to work. // 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, CanonAbi::C, link_name, args)?; + let [_attr, guard_size] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let guard_size_layout = this.machine.layouts.usize; let guard_size = this.deref_pointer_as(guard_size, guard_size_layout)?; this.write_scalar( @@ -1170,11 +1065,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "pthread_attr_init" | "pthread_attr_destroy" if this.frame_in_std() => { - let [_] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [_] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.write_null(dest)?; } "pthread_attr_setstacksize" if this.frame_in_std() => { - let [_, _] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [_, _] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.write_null(dest)?; } @@ -1182,7 +1077,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // We don't support "pthread_attr_setstack", so we just pretend all stacks have the same values here. // Hence we can mostly ignore the input `attr_place`. let [attr_place, addr_place, size_place] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let _attr_place = this.deref_pointer_as(attr_place, this.libc_ty_layout("pthread_attr_t"))?; let addr_place = this.deref_pointer_as(addr_place, this.machine.layouts.usize)?; @@ -1202,18 +1097,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "signal" | "sigaltstack" if this.frame_in_std() => { - let [_, _] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [_, _] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.write_null(dest)?; } "sigaction" | "mprotect" if this.frame_in_std() => { - let [_, _, _] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [_, _, _] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.write_null(dest)?; } "getpwuid_r" | "__posix_getpwuid_r" if this.frame_in_std() => { // getpwuid_r is the standard name, __posix_getpwuid_r is used on solarish let [uid, pwd, buf, buflen, result] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.check_no_isolation("`getpwuid_r`")?; let uid = this.read_scalar(uid)?.to_u32()?; diff --git a/src/shims/unix/freebsd/foreign_items.rs b/src/shims/unix/freebsd/foreign_items.rs index 33564a2f84..9e247053fb 100644 --- a/src/shims/unix/freebsd/foreign_items.rs +++ b/src/shims/unix/freebsd/foreign_items.rs @@ -24,7 +24,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // Threading "pthread_setname_np" => { - let [thread, name] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [thread, name] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let max_len = u64::MAX; // FreeBSD does not seem to have a limit. let res = match this.pthread_setname_np( this.read_scalar(thread)?, @@ -39,7 +40,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "pthread_getname_np" => { - let [thread, name, len] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [thread, name, len] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; // FreeBSD's pthread_getname_np uses strlcpy, which truncates the resulting value, // but always adds a null terminator (except for zero-sized buffers). // https://github.com/freebsd/freebsd-src/blob/c2d93a803acef634bd0eede6673aeea59e90c277/lib/libthr/thread/thr_info.c#L119-L144 @@ -57,7 +59,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "pthread_getthreadid_np" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.unix_gettid(link_name.as_str())?; this.write_scalar(result, dest)?; } @@ -65,7 +67,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "cpuset_getaffinity" => { // The "same" kind of api as `sched_getaffinity` but more fine grained control for FreeBSD specifically. let [level, which, id, set_size, mask] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let level = this.read_scalar(level)?.to_i32()?; let which = this.read_scalar(which)?.to_i32()?; @@ -129,7 +131,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Synchronization primitives "_umtx_op" => { let [obj, op, val, uaddr, uaddr2] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this._umtx_op(obj, op, val, uaddr, uaddr2, dest)?; } @@ -137,29 +139,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // For those, we both intercept `func` and `call@FBSD_1.0` symbols cases // since freebsd 12 the former form can be expected. "stat" | "stat@FBSD_1.0" => { - let [path, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.macos_fbsd_solarish_stat(path, buf)?; this.write_scalar(result, dest)?; } "lstat" | "lstat@FBSD_1.0" => { - let [path, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.macos_fbsd_solarish_lstat(path, buf)?; this.write_scalar(result, dest)?; } "fstat" | "fstat@FBSD_1.0" => { - let [fd, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [fd, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.macos_fbsd_solarish_fstat(fd, buf)?; this.write_scalar(result, dest)?; } "readdir_r" | "readdir_r@FBSD_1.0" => { - let [dirp, entry, result] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [dirp, entry, result] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.macos_fbsd_readdir_r(dirp, entry, result)?; this.write_scalar(result, dest)?; } // Miscellaneous "__error" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let errno_place = this.last_error_place()?; this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } @@ -167,7 +170,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Incomplete shims that we "stub out" just to get pre-main initialization code to work. // These shims are enabled only when the caller is in the standard library. "pthread_attr_get_np" if this.frame_in_std() => { - let [_thread, _attr] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [_thread, _attr] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.write_null(dest)?; } diff --git a/src/shims/unix/fs.rs b/src/shims/unix/fs.rs index 0f2878ad26..f9bcacf64c 100644 --- a/src/shims/unix/fs.rs +++ b/src/shims/unix/fs.rs @@ -13,9 +13,9 @@ use rustc_abi::Size; use rustc_data_structures::fx::FxHashMap; use self::shims::time::system_time_to_duration; -use crate::helpers::check_min_vararg_count; use crate::shims::files::FileHandle; use crate::shims::os_str::bytes_to_os_str; +use crate::shims::sig::check_min_vararg_count; use crate::shims::unix::fd::{FlockOp, UnixFileDescription}; use crate::*; diff --git a/src/shims/unix/linux/foreign_items.rs b/src/shims/unix/linux/foreign_items.rs index b3e99e6cc6..e7e0c3b6ec 100644 --- a/src/shims/unix/linux/foreign_items.rs +++ b/src/shims/unix/linux/foreign_items.rs @@ -37,48 +37,50 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // File related shims "readdir64" => { - let [dirp] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [dirp] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.linux_solarish_readdir64("dirent64", dirp)?; this.write_scalar(result, dest)?; } "sync_file_range" => { let [fd, offset, nbytes, flags] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.sync_file_range(fd, offset, nbytes, flags)?; this.write_scalar(result, dest)?; } "statx" => { let [dirfd, pathname, flags, mask, statxbuf] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.linux_statx(dirfd, pathname, flags, mask, statxbuf)?; this.write_scalar(result, dest)?; } // epoll, eventfd "epoll_create1" => { - let [flag] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [flag] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.epoll_create1(flag)?; this.write_scalar(result, dest)?; } "epoll_ctl" => { - let [epfd, op, fd, event] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [epfd, op, fd, event] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.epoll_ctl(epfd, op, fd, event)?; this.write_scalar(result, dest)?; } "epoll_wait" => { let [epfd, events, maxevents, timeout] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.epoll_wait(epfd, events, maxevents, timeout, dest)?; } "eventfd" => { - let [val, flag] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [val, flag] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.eventfd(val, flag)?; this.write_scalar(result, dest)?; } // Threading "pthread_setname_np" => { - let [thread, name] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [thread, name] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let res = match this.pthread_setname_np( this.read_scalar(thread)?, this.read_scalar(name)?, @@ -93,7 +95,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "pthread_getname_np" => { - let [thread, name, len] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [thread, name, len] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; // The function's behavior isn't portable between platforms. // In case of glibc, the length of the output buffer must // be not shorter than TASK_COMM_LEN. @@ -116,7 +119,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "gettid" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.unix_gettid(link_name.as_str())?; this.write_scalar(result, dest)?; } @@ -129,34 +132,35 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Miscellaneous "mmap64" => { let [addr, length, prot, flags, fd, offset] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, 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)?; } "mremap" => { let ([old_address, old_size, new_size, flags], _) = - this.check_shim_variadic(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_variadic_lenient(abi, CanonAbi::C, link_name, args)?; let ptr = this.mremap(old_address, old_size, new_size, flags)?; this.write_scalar(ptr, dest)?; } "__xpg_strerror_r" => { - let [errnum, buf, buflen] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [errnum, buf, buflen] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.strerror_r(errnum, buf, buflen)?; this.write_scalar(result, dest)?; } "__errno_location" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let errno_place = this.last_error_place()?; this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } "__libc_current_sigrtmin" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.write_int(SIGRTMIN, dest)?; } "__libc_current_sigrtmax" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.write_int(SIGRTMAX, dest)?; } @@ -164,7 +168,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Incomplete shims that we "stub out" just to get pre-main initialization code to work. // These shims are enabled only when the caller is in the standard library. "pthread_getattr_np" if this.frame_in_std() => { - let [_thread, _attr] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [_thread, _attr] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.write_null(dest)?; } diff --git a/src/shims/unix/linux_like/sync.rs b/src/shims/unix/linux_like/sync.rs index 9fad74c024..5f032c52de 100644 --- a/src/shims/unix/linux_like/sync.rs +++ b/src/shims/unix/linux_like/sync.rs @@ -1,5 +1,5 @@ use crate::concurrency::sync::FutexRef; -use crate::helpers::check_min_vararg_count; +use crate::shims::sig::check_min_vararg_count; use crate::*; struct LinuxFutex { diff --git a/src/shims/unix/linux_like/syscall.rs b/src/shims/unix/linux_like/syscall.rs index d3534e6e1b..106e6c448d 100644 --- a/src/shims/unix/linux_like/syscall.rs +++ b/src/shims/unix/linux_like/syscall.rs @@ -3,7 +3,7 @@ use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::callconv::FnAbi; -use crate::helpers::check_min_vararg_count; +use crate::shims::sig::check_min_vararg_count; use crate::shims::unix::env::EvalContextExt; use crate::shims::unix::linux_like::eventfd::EvalContextExt as _; use crate::shims::unix::linux_like::sync::futex; @@ -16,7 +16,7 @@ pub fn syscall<'tcx>( args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx> { - let ([op], varargs) = ecx.check_shim_variadic(abi, CanonAbi::C, link_name, args)?; + let ([op], varargs) = ecx.check_shim_sig_variadic_lenient(abi, CanonAbi::C, link_name, args)?; // The syscall variadic function is legal to call with more arguments than needed, // extra arguments are simply ignored. The important check is that when we use an // argument, we have to also check all arguments *before* it to ensure that they diff --git a/src/shims/unix/macos/foreign_items.rs b/src/shims/unix/macos/foreign_items.rs index 2330371809..297d903c6b 100644 --- a/src/shims/unix/macos/foreign_items.rs +++ b/src/shims/unix/macos/foreign_items.rs @@ -35,64 +35,67 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // errno "__error" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let errno_place = this.last_error_place()?; this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } // File related shims "close$NOCANCEL" => { - let [result] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [result] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.close(result)?; this.write_scalar(result, dest)?; } "stat" | "stat64" | "stat$INODE64" => { - let [path, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.macos_fbsd_solarish_stat(path, buf)?; this.write_scalar(result, dest)?; } "lstat" | "lstat64" | "lstat$INODE64" => { - let [path, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.macos_fbsd_solarish_lstat(path, buf)?; this.write_scalar(result, dest)?; } "fstat" | "fstat64" | "fstat$INODE64" => { - let [fd, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [fd, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.macos_fbsd_solarish_fstat(fd, buf)?; this.write_scalar(result, dest)?; } "opendir$INODE64" => { - let [name] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [name] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.opendir(name)?; this.write_scalar(result, dest)?; } "readdir_r" | "readdir_r$INODE64" => { - let [dirp, entry, result] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [dirp, entry, result] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.macos_fbsd_readdir_r(dirp, entry, result)?; this.write_scalar(result, dest)?; } "realpath$DARWIN_EXTSN" => { - let [path, resolved_path] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [path, resolved_path] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.realpath(path, resolved_path)?; this.write_scalar(result, dest)?; } "ioctl" => { let ([fd_num, cmd], varargs) = - this.check_shim_variadic(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_variadic_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.ioctl(fd_num, cmd, varargs)?; this.write_scalar(result, dest)?; } // Environment related shims "_NSGetEnviron" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let environ = this.machine.env_vars.unix().environ(); this.write_pointer(environ, dest)?; } // Random data generation "CCRandomGenerateBytes" => { - let [bytes, count] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [bytes, count] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let bytes = this.read_pointer(bytes)?; let count = this.read_target_usize(count)?; let success = this.eval_libc_i32("kCCSuccess"); @@ -102,28 +105,29 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Time related shims "mach_absolute_time" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.mach_absolute_time()?; this.write_scalar(result, dest)?; } "mach_timebase_info" => { - let [info] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [info] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.mach_timebase_info(info)?; this.write_scalar(result, dest)?; } // Access to command-line arguments "_NSGetArgc" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.write_pointer(this.machine.argc.expect("machine must be initialized"), dest)?; } "_NSGetArgv" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.write_pointer(this.machine.argv.expect("machine must be initialized"), dest)?; } "_NSGetExecutablePath" => { - let [buf, bufsize] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [buf, bufsize] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.check_no_isolation("`_NSGetExecutablePath`")?; let buf_ptr = this.read_pointer(buf)?; @@ -148,7 +152,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Thread-local storage "_tlv_atexit" => { - let [dtor, data] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [dtor, data] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let dtor = this.read_pointer(dtor)?; let dtor = this.get_ptr_fn(dtor)?.as_instance()?; let data = this.read_scalar(data)?; @@ -158,13 +163,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Querying system information "pthread_get_stackaddr_np" => { - let [thread] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [thread] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.read_target_usize(thread)?; let stack_addr = Scalar::from_uint(this.machine.stack_addr, this.pointer_size()); this.write_scalar(stack_addr, dest)?; } "pthread_get_stacksize_np" => { - let [thread] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [thread] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.read_target_usize(thread)?; let stack_size = Scalar::from_uint(this.machine.stack_size, this.pointer_size()); this.write_scalar(stack_size, dest)?; @@ -172,7 +177,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Threading "pthread_setname_np" => { - let [name] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [name] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; // The real implementation has logic in two places: // * in userland at https://github.com/apple-oss-distributions/libpthread/blob/c032e0b076700a0a47db75528a282b8d3a06531a/src/pthread.c#L1178-L1200, @@ -199,7 +204,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "pthread_getname_np" => { - let [thread, name, len] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [thread, name, len] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; // The function's behavior isn't portable between platforms. // In case of macOS, a truncated name (due to a too small buffer) @@ -223,7 +229,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "pthread_threadid_np" => { - let [thread, tid_ptr] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [thread, tid_ptr] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let res = this.apple_pthread_threadip_np(thread, tid_ptr)?; this.write_scalar(res, dest)?; } @@ -231,7 +238,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Synchronization primitives "os_sync_wait_on_address" => { let [addr_op, value_op, size_op, flags_op] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.os_sync_wait_on_address( addr_op, value_op, @@ -243,7 +250,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "os_sync_wait_on_address_with_deadline" => { let [addr_op, value_op, size_op, flags_op, clock_op, timeout_op] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.os_sync_wait_on_address( addr_op, value_op, @@ -255,7 +262,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "os_sync_wait_on_address_with_timeout" => { let [addr_op, value_op, size_op, flags_op, clock_op, timeout_op] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.os_sync_wait_on_address( addr_op, value_op, @@ -267,36 +274,36 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "os_sync_wake_by_address_any" => { let [addr_op, size_op, flags_op] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.os_sync_wake_by_address( addr_op, size_op, flags_op, /* all */ false, dest, )?; } "os_sync_wake_by_address_all" => { let [addr_op, size_op, flags_op] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.os_sync_wake_by_address( addr_op, size_op, flags_op, /* all */ true, dest, )?; } "os_unfair_lock_lock" => { - let [lock_op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [lock_op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.os_unfair_lock_lock(lock_op)?; } "os_unfair_lock_trylock" => { - let [lock_op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [lock_op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.os_unfair_lock_trylock(lock_op, dest)?; } "os_unfair_lock_unlock" => { - let [lock_op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [lock_op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.os_unfair_lock_unlock(lock_op)?; } "os_unfair_lock_assert_owner" => { - let [lock_op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [lock_op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.os_unfair_lock_assert_owner(lock_op)?; } "os_unfair_lock_assert_not_owner" => { - let [lock_op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [lock_op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.os_unfair_lock_assert_not_owner(lock_op)?; } diff --git a/src/shims/unix/solarish/foreign_items.rs b/src/shims/unix/solarish/foreign_items.rs index e3d15b89be..d7033a65fe 100644 --- a/src/shims/unix/solarish/foreign_items.rs +++ b/src/shims/unix/solarish/foreign_items.rs @@ -27,32 +27,34 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // epoll, eventfd (NOT available on Solaris!) "epoll_create1" => { this.assert_target_os("illumos", "epoll_create1"); - let [flag] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [flag] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.epoll_create1(flag)?; this.write_scalar(result, dest)?; } "epoll_ctl" => { this.assert_target_os("illumos", "epoll_ctl"); - let [epfd, op, fd, event] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [epfd, op, fd, event] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.epoll_ctl(epfd, op, fd, event)?; this.write_scalar(result, dest)?; } "epoll_wait" => { this.assert_target_os("illumos", "epoll_wait"); let [epfd, events, maxevents, timeout] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.epoll_wait(epfd, events, maxevents, timeout, dest)?; } "eventfd" => { this.assert_target_os("illumos", "eventfd"); - let [val, flag] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [val, flag] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.eventfd(val, flag)?; this.write_scalar(result, dest)?; } // Threading "pthread_setname_np" => { - let [thread, name] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [thread, name] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; // THREAD_NAME_MAX allows a thread name of 31+1 length // https://github.com/illumos/illumos-gate/blob/7671517e13b8123748eda4ef1ee165c6d9dba7fe/usr/src/uts/common/sys/thread.h#L613 let max_len = 32; @@ -70,7 +72,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "pthread_getname_np" => { - let [thread, name, len] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [thread, name, len] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; // See https://illumos.org/man/3C/pthread_getname_np for the error codes. let res = match this.pthread_getname_np( this.read_scalar(thread)?, @@ -87,22 +90,22 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // File related shims "stat" | "stat64" => { - let [path, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.macos_fbsd_solarish_stat(path, buf)?; this.write_scalar(result, dest)?; } "lstat" | "lstat64" => { - let [path, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.macos_fbsd_solarish_lstat(path, buf)?; this.write_scalar(result, dest)?; } "fstat" | "fstat64" => { - let [fd, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [fd, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.macos_fbsd_solarish_fstat(fd, buf)?; this.write_scalar(result, dest)?; } "readdir" => { - let [dirp] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [dirp] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.linux_solarish_readdir64("dirent", dirp)?; this.write_scalar(result, dest)?; } @@ -110,20 +113,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Sockets and pipes "__xnet_socketpair" => { let [domain, type_, protocol, sv] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.socketpair(domain, type_, protocol, sv)?; this.write_scalar(result, dest)?; } // Miscellaneous "___errno" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let errno_place = this.last_error_place()?; this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } "stack_getbounds" => { - let [stack] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [stack] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let stack = this.deref_pointer_as(stack, this.libc_ty_layout("stack_t"))?; this.write_int_fields_named( @@ -141,7 +144,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "pset_info" => { - let [pset, tpe, cpus, list] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [pset, tpe, cpus, list] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; // We do not need to handle the current process cpu mask, available_parallelism // implementation pass null anyway. We only care for the number of // cpus. @@ -170,7 +174,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "__sysconf_xpg7" => { - let [val] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [val] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.sysconf(val)?; this.write_scalar(result, dest)?; } diff --git a/src/shims/unwind.rs b/src/shims/unwind.rs index ba0c50b54b..0dd2b20487 100644 --- a/src/shims/unwind.rs +++ b/src/shims/unwind.rs @@ -16,7 +16,6 @@ use rustc_abi::ExternAbi; use rustc_middle::mir; use rustc_target::spec::PanicStrategy; -use self::helpers::check_intrinsic_arg_count; use crate::*; /// Holds all of the relevant data for when unwinding hits a `try` frame. @@ -60,7 +59,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// Handles the `catch_unwind` intrinsic. fn handle_catch_unwind( &mut self, - args: &[OpTy<'tcx>], + try_fn: &OpTy<'tcx>, + data: &OpTy<'tcx>, + catch_fn: &OpTy<'tcx>, dest: &MPlaceTy<'tcx>, ret: Option, ) -> InterpResult<'tcx> { @@ -78,7 +79,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // a pointer to `Box`. // Get all the arguments. - let [try_fn, data, catch_fn] = check_intrinsic_arg_count(args)?; let try_fn = this.read_pointer(try_fn)?; let data = this.read_immediate(data)?; let catch_fn = this.read_pointer(catch_fn)?; diff --git a/src/shims/wasi/foreign_items.rs b/src/shims/wasi/foreign_items.rs index 8d92d0f338..bfcdbd8130 100644 --- a/src/shims/wasi/foreign_items.rs +++ b/src/shims/wasi/foreign_items.rs @@ -23,12 +23,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // Allocation "posix_memalign" => { - let [memptr, align, size] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [memptr, align, size] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let result = this.posix_memalign(memptr, align, size)?; this.write_scalar(result, dest)?; } "aligned_alloc" => { - let [align, size] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [align, size] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let res = this.aligned_alloc(align, size)?; this.write_pointer(res, dest)?; } diff --git a/src/shims/windows/foreign_items.rs b/src/shims/windows/foreign_items.rs index 959abc0bac..7b13f1d908 100644 --- a/src/shims/windows/foreign_items.rs +++ b/src/shims/windows/foreign_items.rs @@ -157,42 +157,44 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // Environment related shims "GetEnvironmentVariableW" => { - let [name, buf, size] = this.check_shim(abi, sys_conv, link_name, args)?; + let [name, buf, size] = + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let result = this.GetEnvironmentVariableW(name, buf, size)?; this.write_scalar(result, dest)?; } "SetEnvironmentVariableW" => { - let [name, value] = this.check_shim(abi, sys_conv, link_name, args)?; + let [name, value] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let result = this.SetEnvironmentVariableW(name, value)?; this.write_scalar(result, dest)?; } "GetEnvironmentStringsW" => { - let [] = this.check_shim(abi, sys_conv, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let result = this.GetEnvironmentStringsW()?; this.write_pointer(result, dest)?; } "FreeEnvironmentStringsW" => { - let [env_block] = this.check_shim(abi, sys_conv, link_name, args)?; + let [env_block] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let result = this.FreeEnvironmentStringsW(env_block)?; this.write_scalar(result, dest)?; } "GetCurrentDirectoryW" => { - let [size, buf] = this.check_shim(abi, sys_conv, link_name, args)?; + let [size, buf] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let result = this.GetCurrentDirectoryW(size, buf)?; this.write_scalar(result, dest)?; } "SetCurrentDirectoryW" => { - let [path] = this.check_shim(abi, sys_conv, link_name, args)?; + let [path] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let result = this.SetCurrentDirectoryW(path)?; this.write_scalar(result, dest)?; } "GetUserProfileDirectoryW" => { - let [token, buf, size] = this.check_shim(abi, sys_conv, link_name, args)?; + let [token, buf, size] = + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let result = this.GetUserProfileDirectoryW(token, buf, size)?; this.write_scalar(result, dest)?; } "GetCurrentProcessId" => { - let [] = this.check_shim(abi, sys_conv, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let result = this.GetCurrentProcessId()?; this.write_scalar(result, dest)?; } @@ -209,7 +211,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { n, byte_offset, key, - ] = this.check_shim(abi, sys_conv, link_name, args)?; + ] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.NtWriteFile( handle, event, @@ -234,7 +236,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { n, byte_offset, key, - ] = this.check_shim(abi, sys_conv, link_name, args)?; + ] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.NtReadFile( handle, event, @@ -250,7 +252,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "GetFullPathNameW" => { let [filename, size, buffer, filepart] = - this.check_shim(abi, sys_conv, link_name, args)?; + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.check_no_isolation("`GetFullPathNameW`")?; let filename = this.read_pointer(filename)?; @@ -287,7 +289,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { creation_disposition, flags_and_attributes, template_file, - ] = this.check_shim(abi, sys_conv, link_name, args)?; + ] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let handle = this.CreateFileW( file_name, desired_access, @@ -300,18 +302,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(handle.to_scalar(this), dest)?; } "GetFileInformationByHandle" => { - let [handle, info] = this.check_shim(abi, sys_conv, link_name, args)?; + let [handle, info] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let res = this.GetFileInformationByHandle(handle, info)?; this.write_scalar(res, dest)?; } "DeleteFileW" => { - let [file_name] = this.check_shim(abi, sys_conv, link_name, args)?; + let [file_name] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let res = this.DeleteFileW(file_name)?; this.write_scalar(res, dest)?; } "SetFilePointerEx" => { let [file, distance_to_move, new_file_pointer, move_method] = - this.check_shim(abi, sys_conv, link_name, args)?; + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let res = this.SetFilePointerEx(file, distance_to_move, new_file_pointer, move_method)?; this.write_scalar(res, dest)?; @@ -319,7 +321,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Allocation "HeapAlloc" => { - let [handle, flags, size] = this.check_shim(abi, sys_conv, link_name, args)?; + let [handle, flags, size] = + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.read_target_isize(handle)?; let flags = this.read_scalar(flags)?.to_u32()?; let size = this.read_target_usize(size)?; @@ -341,7 +344,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_pointer(ptr, dest)?; } "HeapFree" => { - let [handle, flags, ptr] = this.check_shim(abi, sys_conv, link_name, args)?; + let [handle, flags, ptr] = + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.read_target_isize(handle)?; this.read_scalar(flags)?.to_u32()?; let ptr = this.read_pointer(ptr)?; @@ -354,7 +358,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "HeapReAlloc" => { let [handle, flags, old_ptr, size] = - this.check_shim(abi, sys_conv, link_name, args)?; + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.read_target_isize(handle)?; this.read_scalar(flags)?.to_u32()?; let old_ptr = this.read_pointer(old_ptr)?; @@ -374,7 +378,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_pointer(new_ptr, dest)?; } "LocalFree" => { - let [ptr] = this.check_shim(abi, sys_conv, link_name, args)?; + let [ptr] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let ptr = this.read_pointer(ptr)?; // "If the hMem parameter is NULL, LocalFree ignores the parameter and returns NULL." // (https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-localfree) @@ -386,17 +390,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // errno "SetLastError" => { - let [error] = this.check_shim(abi, sys_conv, link_name, args)?; + let [error] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let error = this.read_scalar(error)?; this.set_last_error(error)?; } "GetLastError" => { - let [] = this.check_shim(abi, sys_conv, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let last_error = this.get_last_error()?; this.write_scalar(last_error, dest)?; } "RtlNtStatusToDosError" => { - let [status] = this.check_shim(abi, sys_conv, link_name, args)?; + let [status] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let status = this.read_scalar(status)?.to_u32()?; let err = match status { // STATUS_MEDIA_WRITE_PROTECTED => ERROR_WRITE_PROTECT @@ -418,7 +422,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Querying system information "GetSystemInfo" => { // Also called from `page_size` crate. - let [system_info] = this.check_shim(abi, sys_conv, link_name, args)?; + let [system_info] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let system_info = this.deref_pointer_as(system_info, this.windows_ty_layout("SYSTEM_INFO"))?; // Initialize with `0`. @@ -441,19 +445,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // This just creates a key; Windows does not natively support TLS destructors. // Create key and return it. - let [] = this.check_shim(abi, sys_conv, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let key = this.machine.tls.create_tls_key(None, dest.layout.size)?; this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?; } "TlsGetValue" => { - let [key] = this.check_shim(abi, sys_conv, link_name, args)?; + let [key] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let key = u128::from(this.read_scalar(key)?.to_u32()?); let active_thread = this.active_thread(); let ptr = this.machine.tls.load_tls(key, active_thread, this)?; this.write_scalar(ptr, dest)?; } "TlsSetValue" => { - let [key, new_ptr] = this.check_shim(abi, sys_conv, link_name, args)?; + let [key, new_ptr] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let key = u128::from(this.read_scalar(key)?.to_u32()?); let active_thread = this.active_thread(); let new_data = this.read_scalar(new_ptr)?; @@ -463,7 +467,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_int(1, dest)?; } "TlsFree" => { - let [key] = this.check_shim(abi, sys_conv, link_name, args)?; + let [key] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let key = u128::from(this.read_scalar(key)?.to_u32()?); this.machine.tls.delete_tls_key(key)?; @@ -473,7 +477,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Access to command-line arguments "GetCommandLineW" => { - let [] = this.check_shim(abi, sys_conv, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.write_pointer( this.machine.cmd_line.expect("machine must be initialized"), dest, @@ -483,29 +487,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Time related shims "GetSystemTimeAsFileTime" | "GetSystemTimePreciseAsFileTime" => { #[allow(non_snake_case)] - let [LPFILETIME] = this.check_shim(abi, sys_conv, link_name, args)?; + let [LPFILETIME] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.GetSystemTimeAsFileTime(link_name.as_str(), LPFILETIME)?; } "QueryPerformanceCounter" => { #[allow(non_snake_case)] - let [lpPerformanceCount] = this.check_shim(abi, sys_conv, link_name, args)?; + let [lpPerformanceCount] = + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let result = this.QueryPerformanceCounter(lpPerformanceCount)?; this.write_scalar(result, dest)?; } "QueryPerformanceFrequency" => { #[allow(non_snake_case)] - let [lpFrequency] = this.check_shim(abi, sys_conv, link_name, args)?; + let [lpFrequency] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let result = this.QueryPerformanceFrequency(lpFrequency)?; this.write_scalar(result, dest)?; } "Sleep" => { - let [timeout] = this.check_shim(abi, sys_conv, link_name, args)?; + let [timeout] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.Sleep(timeout)?; } "CreateWaitableTimerExW" => { let [attributes, name, flags, access] = - this.check_shim(abi, sys_conv, link_name, args)?; + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.read_pointer(attributes)?; this.read_pointer(name)?; this.read_scalar(flags)?.to_u32()?; @@ -519,27 +524,28 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Synchronization primitives "InitOnceBeginInitialize" => { let [ptr, flags, pending, context] = - this.check_shim(abi, sys_conv, link_name, args)?; + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.InitOnceBeginInitialize(ptr, flags, pending, context, dest)?; } "InitOnceComplete" => { - let [ptr, flags, context] = this.check_shim(abi, sys_conv, link_name, args)?; + let [ptr, flags, context] = + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let result = this.InitOnceComplete(ptr, flags, context)?; this.write_scalar(result, dest)?; } "WaitOnAddress" => { let [ptr_op, compare_op, size_op, timeout_op] = - this.check_shim(abi, sys_conv, link_name, args)?; + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.WaitOnAddress(ptr_op, compare_op, size_op, timeout_op, dest)?; } "WakeByAddressSingle" => { - let [ptr_op] = this.check_shim(abi, sys_conv, link_name, args)?; + let [ptr_op] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.WakeByAddressSingle(ptr_op)?; } "WakeByAddressAll" => { - let [ptr_op] = this.check_shim(abi, sys_conv, link_name, args)?; + let [ptr_op] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.WakeByAddressAll(ptr_op)?; } @@ -547,7 +553,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Dynamic symbol loading "GetProcAddress" => { #[allow(non_snake_case)] - let [hModule, lpProcName] = this.check_shim(abi, sys_conv, link_name, args)?; + let [hModule, lpProcName] = + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.read_target_isize(hModule)?; let name = this.read_c_str(this.read_pointer(lpProcName)?)?; if let Ok(name) = str::from_utf8(name) @@ -563,7 +570,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Threading "CreateThread" => { let [security, stacksize, start, arg, flags, thread] = - this.check_shim(abi, sys_conv, link_name, args)?; + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let thread_id = this.CreateThread(security, stacksize, start, arg, flags, thread)?; @@ -571,12 +578,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(Handle::Thread(thread_id).to_scalar(this), dest)?; } "WaitForSingleObject" => { - let [handle, timeout] = this.check_shim(abi, sys_conv, link_name, args)?; + let [handle, timeout] = + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.WaitForSingleObject(handle, timeout, dest)?; } "GetCurrentProcess" => { - let [] = this.check_shim(abi, sys_conv, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.write_scalar( Handle::Pseudo(PseudoHandle::CurrentProcess).to_scalar(this), @@ -584,7 +592,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; } "GetCurrentThread" => { - let [] = this.check_shim(abi, sys_conv, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.write_scalar( Handle::Pseudo(PseudoHandle::CurrentThread).to_scalar(this), @@ -592,7 +600,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; } "SetThreadDescription" => { - let [handle, name] = this.check_shim(abi, sys_conv, link_name, args)?; + let [handle, name] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let handle = this.read_handle(handle, "SetThreadDescription")?; let name = this.read_wide_str(this.read_pointer(name)?)?; @@ -607,7 +615,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(Scalar::from_u32(0), dest)?; } "GetThreadDescription" => { - let [handle, name_ptr] = this.check_shim(abi, sys_conv, link_name, args)?; + let [handle, name_ptr] = + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let handle = this.read_handle(handle, "GetThreadDescription")?; let name_ptr = this.deref_pointer_as(name_ptr, this.machine.layouts.mut_raw_ptr)?; // the pointer where we should store the ptr to the name @@ -630,7 +639,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "GetThreadId" => { - let [handle] = this.check_shim(abi, sys_conv, link_name, args)?; + let [handle] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let handle = this.read_handle(handle, "GetThreadId")?; let thread = match handle { Handle::Thread(thread) => thread, @@ -641,7 +650,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(Scalar::from_u32(tid), dest)?; } "GetCurrentThreadId" => { - let [] = this.check_shim(abi, sys_conv, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let thread = this.active_thread(); let tid = this.get_tid(thread); this.write_scalar(Scalar::from_u32(tid), dest)?; @@ -649,7 +658,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Miscellaneous "ExitProcess" => { - let [code] = this.check_shim(abi, sys_conv, link_name, args)?; + let [code] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; // Windows technically uses u32, but we unify everything to a Unix-style i32. let code = this.read_scalar(code)?.to_i32()?; throw_machine_stop!(TerminationInfo::Exit { code, leak_check: false }); @@ -657,7 +666,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "SystemFunction036" => { // used by getrandom 0.1 // This is really 'RtlGenRandom'. - let [ptr, len] = this.check_shim(abi, sys_conv, link_name, args)?; + let [ptr, len] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let ptr = this.read_pointer(ptr)?; let len = this.read_scalar(len)?.to_u32()?; this.gen_random(ptr, len.into())?; @@ -665,7 +674,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "ProcessPrng" => { // used by `std` - let [ptr, len] = this.check_shim(abi, sys_conv, link_name, args)?; + let [ptr, len] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let ptr = this.read_pointer(ptr)?; let len = this.read_target_usize(len)?; this.gen_random(ptr, len)?; @@ -674,7 +683,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "BCryptGenRandom" => { // used by getrandom 0.2 let [algorithm, ptr, len, flags] = - this.check_shim(abi, sys_conv, link_name, args)?; + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let algorithm = this.read_scalar(algorithm)?; let algorithm = algorithm.to_target_usize(this)?; let ptr = this.read_pointer(ptr)?; @@ -708,7 +717,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "GetConsoleScreenBufferInfo" => { // `term` needs this, so we fake it. - let [console, buffer_info] = this.check_shim(abi, sys_conv, link_name, args)?; + let [console, buffer_info] = + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.read_target_isize(console)?; // FIXME: this should use deref_pointer_as, but CONSOLE_SCREEN_BUFFER_INFO is not in std this.deref_pointer(buffer_info)?; @@ -717,13 +727,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_null(dest)?; } "GetStdHandle" => { - let [which] = this.check_shim(abi, sys_conv, link_name, args)?; + let [which] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let res = this.GetStdHandle(which)?; this.write_scalar(res, dest)?; } "DuplicateHandle" => { let [src_proc, src_handle, target_proc, target_handle, access, inherit, options] = - this.check_shim(abi, sys_conv, link_name, args)?; + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let res = this.DuplicateHandle( src_proc, src_handle, @@ -736,14 +746,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "CloseHandle" => { - let [handle] = this.check_shim(abi, sys_conv, link_name, args)?; + let [handle] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let ret = this.CloseHandle(handle)?; this.write_scalar(ret, dest)?; } "GetModuleFileNameW" => { - let [handle, filename, size] = this.check_shim(abi, sys_conv, link_name, args)?; + let [handle, filename, size] = + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.check_no_isolation("`GetModuleFileNameW`")?; let handle = this.read_handle(handle, "GetModuleFileNameW")?; @@ -777,7 +788,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "FormatMessageW" => { let [flags, module, message_id, language_id, buffer, size, arguments] = - this.check_shim(abi, sys_conv, link_name, args)?; + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; let flags = this.read_scalar(flags)?.to_u32()?; let _module = this.read_pointer(module)?; // seems to contain a module name @@ -812,26 +823,28 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Incomplete shims that we "stub out" just to get pre-main initialization code to work. // These shims are enabled only when the caller is in the standard library. "GetProcessHeap" if this.frame_in_std() => { - let [] = this.check_shim(abi, sys_conv, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; // Just fake a HANDLE // It's fine to not use the Handle type here because its a stub this.write_int(1, dest)?; } "GetModuleHandleA" if this.frame_in_std() => { #[allow(non_snake_case)] - let [_lpModuleName] = this.check_shim(abi, sys_conv, link_name, args)?; + let [_lpModuleName] = + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; // We need to return something non-null here to make `compat_fn!` work. this.write_int(1, dest)?; } "SetConsoleTextAttribute" if this.frame_in_std() => { #[allow(non_snake_case)] let [_hConsoleOutput, _wAttribute] = - this.check_shim(abi, sys_conv, link_name, args)?; + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; // Pretend these does not exist / nothing happened, by returning zero. this.write_null(dest)?; } "GetConsoleMode" if this.frame_in_std() => { - let [console, mode] = this.check_shim(abi, sys_conv, link_name, args)?; + let [console, mode] = + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.read_target_isize(console)?; this.deref_pointer_as(mode, this.machine.layouts.u32)?; // Indicate an error. @@ -839,25 +852,27 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "GetFileType" if this.frame_in_std() => { #[allow(non_snake_case)] - let [_hFile] = this.check_shim(abi, sys_conv, link_name, args)?; + let [_hFile] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; // Return unknown file type. this.write_null(dest)?; } "AddVectoredExceptionHandler" if this.frame_in_std() => { #[allow(non_snake_case)] - let [_First, _Handler] = this.check_shim(abi, sys_conv, link_name, args)?; + let [_First, _Handler] = + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; // Any non zero value works for the stdlib. This is just used for stack overflows anyway. this.write_int(1, dest)?; } "SetThreadStackGuarantee" if this.frame_in_std() => { #[allow(non_snake_case)] - let [_StackSizeInBytes] = this.check_shim(abi, sys_conv, link_name, args)?; + let [_StackSizeInBytes] = + this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; // Any non zero value works for the stdlib. This is just used for stack overflows anyway. this.write_int(1, dest)?; } // this is only callable from std because we know that std ignores the return value "SwitchToThread" if this.frame_in_std() => { - let [] = this.check_shim(abi, sys_conv, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?; this.yield_active_thread(); @@ -876,7 +891,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ); } // This function looks and behaves excatly like miri_start_unwind. - let [payload] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [payload] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; this.handle_miri_start_unwind(payload)?; return interp_ok(EmulateItemResult::NeedsUnwind); } diff --git a/src/shims/x86/aesni.rs b/src/shims/x86/aesni.rs index 058ca24e73..fdd3e78c61 100644 --- a/src/shims/x86/aesni.rs +++ b/src/shims/x86/aesni.rs @@ -26,7 +26,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `state` with the corresponding 128-bit key of `key`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdec_si128 "aesdec" | "aesdec.256" | "aesdec.512" => { - let [state, key] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [state, key] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; aes_round(this, state, key, dest, |state, key| { let key = aes::Block::from(key.to_le_bytes()); let mut state = aes::Block::from(state.to_le_bytes()); @@ -42,7 +43,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `state` with the corresponding 128-bit key of `key`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdeclast_si128 "aesdeclast" | "aesdeclast.256" | "aesdeclast.512" => { - let [state, key] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [state, key] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; aes_round(this, state, key, dest, |state, key| { let mut state = aes::Block::from(state.to_le_bytes()); @@ -66,7 +68,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `state` with the corresponding 128-bit key of `key`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenc_si128 "aesenc" | "aesenc.256" | "aesenc.512" => { - let [state, key] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [state, key] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; aes_round(this, state, key, dest, |state, key| { let key = aes::Block::from(key.to_le_bytes()); let mut state = aes::Block::from(state.to_le_bytes()); @@ -82,7 +85,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `state` with the corresponding 128-bit key of `key`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenclast_si128 "aesenclast" | "aesenclast.256" | "aesenclast.512" => { - let [state, key] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [state, key] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; aes_round(this, state, key, dest, |state, key| { let mut state = aes::Block::from(state.to_le_bytes()); // `aes::hazmat::cipher_round` does the following operations: @@ -102,7 +106,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Used to implement the _mm_aesimc_si128 function. // Performs the AES InvMixColumns operation on `op` "aesimc" => { - let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; // Transmute to `u128` let op = op.transmute(this.machine.layouts.u128, this)?; let dest = dest.transmute(this.machine.layouts.u128, this)?; diff --git a/src/shims/x86/avx.rs b/src/shims/x86/avx.rs index 83d23d6ad3..269ce3b51b 100644 --- a/src/shims/x86/avx.rs +++ b/src/shims/x86/avx.rs @@ -33,7 +33,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // matches the IEEE min/max operations, while x86 has different // semantics. "min.ps.256" | "max.ps.256" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = match unprefixed_name { "min.ps.256" => FloatBinOp::Min, @@ -45,7 +46,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Used to implement _mm256_min_pd and _mm256_max_pd functions. "min.pd.256" | "max.pd.256" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = match unprefixed_name { "min.pd.256" => FloatBinOp::Min, @@ -58,21 +60,23 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Used to implement the _mm256_round_ps function. // Rounds the elements of `op` according to `rounding`. "round.ps.256" => { - let [op, rounding] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op, rounding] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; round_all::(this, op, rounding, dest)?; } // Used to implement the _mm256_round_pd function. // Rounds the elements of `op` according to `rounding`. "round.pd.256" => { - let [op, rounding] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op, rounding] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; round_all::(this, op, rounding, dest)?; } // Used to implement _mm256_{rcp,rsqrt}_ps functions. // Performs the operations on all components of `op`. "rcp.ps.256" | "rsqrt.ps.256" => { - let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = match unprefixed_name { "rcp.ps.256" => FloatUnaryOp::Rcp, @@ -84,7 +88,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Used to implement the _mm256_dp_ps function. "dp.ps.256" => { - let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, imm] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; conditional_dot_product(this, left, right, imm, dest)?; } @@ -92,7 +97,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Horizontally add/subtract adjacent floating point values // in `left` and `right`. "hadd.ps.256" | "hadd.pd.256" | "hsub.ps.256" | "hsub.pd.256" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = match unprefixed_name { "hadd.ps.256" | "hadd.pd.256" => mir::BinOp::Add, @@ -107,7 +113,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // and `right`. For each component, returns 0 if false or u32::MAX // if true. "cmp.ps.256" => { - let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, imm] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; @@ -119,7 +126,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // and `right`. For each component, returns 0 if false or u64::MAX // if true. "cmp.pd.256" => { - let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, imm] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; @@ -130,7 +138,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // and _mm256_cvttpd_epi32 functions. // Converts packed f32/f64 to packed i32. "cvt.ps2dq.256" | "cvtt.ps2dq.256" | "cvt.pd2dq.256" | "cvtt.pd2dq.256" => { - let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let rnd = match unprefixed_name { // "current SSE rounding mode", assume nearest @@ -148,7 +156,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // sequence of 4-element arrays, and we shuffle each of these arrays, where // `control` determines which element of the current `data` array is written. "vpermilvar.ps" | "vpermilvar.ps.256" => { - let [data, control] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [data, control] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (data, data_len) = this.project_to_simd(data)?; let (control, control_len) = this.project_to_simd(control)?; @@ -181,7 +190,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // where `right` determines which element of the current `left` array is // written. "vpermilvar.pd" | "vpermilvar.pd.256" => { - let [data, control] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [data, control] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (data, data_len) = this.project_to_simd(data)?; let (control, control_len) = this.project_to_simd(control)?; @@ -213,7 +223,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // For each 128-bit element of `dest`, copies one from `left`, `right` or // zero, according to `imm`. "vperm2f128.ps.256" | "vperm2f128.pd.256" | "vperm2f128.si.256" => { - let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, imm] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; assert_eq!(dest.layout, left.layout); assert_eq!(dest.layout, right.layout); @@ -256,7 +267,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // is one, it is loaded from `ptr.wrapping_add(i)`, otherwise zero is // loaded. "maskload.ps" | "maskload.pd" | "maskload.ps.256" | "maskload.pd.256" => { - let [ptr, mask] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [ptr, mask] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; mask_load(this, ptr, mask, dest)?; } @@ -266,7 +277,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // is one, it is stored into `ptr.wapping_add(i)`. // Unlike SSE2's _mm_maskmoveu_si128, these are not non-temporal stores. "maskstore.ps" | "maskstore.pd" | "maskstore.ps.256" | "maskstore.pd.256" => { - let [ptr, mask, value] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [ptr, mask, value] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; mask_store(this, ptr, mask, value)?; } @@ -276,7 +288,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // the data crosses a cache line, but for Miri this is just a regular // unaligned read. "ldu.dq.256" => { - let [src_ptr] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [src_ptr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let src_ptr = this.read_pointer(src_ptr)?; let dest = dest.force_mplace(this)?; @@ -288,7 +300,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Tests `op & mask == 0`, `op & mask == mask` or // `op & mask != 0 && op & mask != mask` "ptestz.256" | "ptestc.256" | "ptestnzc.256" => { - let [op, mask] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op, mask] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (all_zero, masked_set) = test_bits_masked(this, op, mask)?; let res = match unprefixed_name { @@ -311,7 +323,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "vtestz.pd.256" | "vtestc.pd.256" | "vtestnzc.pd.256" | "vtestz.pd" | "vtestc.pd" | "vtestnzc.pd" | "vtestz.ps.256" | "vtestc.ps.256" | "vtestnzc.ps.256" | "vtestz.ps" | "vtestc.ps" | "vtestnzc.ps" => { - let [op, mask] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op, mask] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (direct, negated) = test_high_bits_masked(this, op, mask)?; let res = match unprefixed_name { @@ -333,7 +345,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // compiler, making these functions no-ops. // The only thing that needs to be ensured is the correct calling convention. - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; } _ => return interp_ok(EmulateItemResult::NotSupported), } diff --git a/src/shims/x86/avx2.rs b/src/shims/x86/avx2.rs index 49d5977078..ca80c0eba1 100644 --- a/src/shims/x86/avx2.rs +++ b/src/shims/x86/avx2.rs @@ -28,7 +28,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Used to implement the _mm256_abs_epi{8,16,32} functions. // Calculates the absolute value of packed 8/16/32-bit integers. "pabs.b" | "pabs.w" | "pabs.d" => { - let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; int_abs(this, op, dest)?; } @@ -36,7 +36,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Horizontally add / add with saturation / subtract adjacent 16/32-bit // integer values in `left` and `right`. "phadd.w" | "phadd.sw" | "phadd.d" | "phsub.w" | "phsub.sw" | "phsub.d" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (which, saturating) = match unprefixed_name { "phadd.w" | "phadd.d" => (mir::BinOp::Add, false), @@ -57,7 +58,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { | "gather.d.pd.256" | "gather.q.pd" | "gather.q.pd.256" | "gather.d.ps" | "gather.d.ps.256" | "gather.q.ps" | "gather.q.ps.256" => { let [src, slice, offsets, mask, scale] = - this.check_shim(abi, CanonAbi::C, link_name, args)?; + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; assert_eq!(dest.layout, src.layout); @@ -114,7 +115,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // intermediate signed 32-bit integers. Horizontally add adjacent pairs of // intermediate 32-bit integers, and pack the results in `dest`. "pmadd.wd" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -150,7 +152,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // the saturating sum of the products with indices `2*i` and `2*i+1` // produces the output at index `i`. "pmadd.ub.sw" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -184,7 +187,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // is one, it is loaded from `ptr.wrapping_add(i)`, otherwise zero is // loaded. "maskload.d" | "maskload.q" | "maskload.d.256" | "maskload.q.256" => { - let [ptr, mask] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [ptr, mask] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; mask_load(this, ptr, mask, dest)?; } @@ -194,7 +197,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // is one, it is stored into `ptr.wapping_add(i)`. // Unlike SSE2's _mm_maskmoveu_si128, these are not non-temporal stores. "maskstore.d" | "maskstore.q" | "maskstore.d.256" | "maskstore.q.256" => { - let [ptr, mask, value] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [ptr, mask, value] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; mask_store(this, ptr, mask, value)?; } @@ -205,7 +209,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // offsets specified in `imm`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_mpsadbw_epu8 "mpsadbw" => { - let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, imm] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; mpsadbw(this, left, right, imm, dest)?; } @@ -216,7 +221,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // 1 and then taking the bits `1..=16`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_mulhrs_epi16 "pmul.hr.sw" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; pmulhrsw(this, left, right, dest)?; } @@ -224,7 +230,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Converts two 16-bit integer vectors to a single 8-bit integer // vector with signed saturation. "packsswb" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; packsswb(this, left, right, dest)?; } @@ -232,7 +239,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Converts two 32-bit integer vectors to a single 16-bit integer // vector with signed saturation. "packssdw" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; packssdw(this, left, right, dest)?; } @@ -240,7 +248,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Converts two 16-bit signed integer vectors to a single 8-bit // unsigned integer vector with saturation. "packuswb" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; packuswb(this, left, right, dest)?; } @@ -248,7 +257,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Concatenates two 32-bit signed integer vectors and converts // the result to a 16-bit unsigned integer vector with saturation. "packusdw" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; packusdw(this, left, right, dest)?; } @@ -257,7 +267,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Shuffles `left` using the three low bits of each element of `right` // as indices. "permd" | "permps" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -277,7 +288,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Used to implement the _mm256_permute2x128_si256 function. // Shuffles 128-bit blocks of `a` and `b` using `imm` as pattern. "vperm2i128" => { - let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, imm] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; assert_eq!(left.layout.size.bits(), 256); assert_eq!(right.layout.size.bits(), 256); @@ -314,7 +326,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // in `dest`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_sad_epu8 "psad.bw" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -346,7 +359,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Shuffles bytes from `left` using `right` as pattern. // Each 128-bit block is shuffled independently. "pshuf.b" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -377,7 +391,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // is writen to the corresponding output element. // Basically, we multiply `left` with `right.signum()`. "psign.b" | "psign.w" | "psign.d" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; psign(this, left, right, dest)?; } @@ -391,7 +406,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // is copied to remaining bits. "psll.w" | "psrl.w" | "psra.w" | "psll.d" | "psrl.d" | "psra.d" | "psll.q" | "psrl.q" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = match unprefixed_name { "psll.w" | "psll.d" | "psll.q" => ShiftOp::Left, @@ -406,7 +422,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // (except _mm{,256}_srav_epi64, which are not available in AVX2). "psllv.d" | "psllv.d.256" | "psllv.q" | "psllv.q.256" | "psrlv.d" | "psrlv.d.256" | "psrlv.q" | "psrlv.q.256" | "psrav.d" | "psrav.d.256" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = match unprefixed_name { "psllv.d" | "psllv.d.256" | "psllv.q" | "psllv.q.256" => ShiftOp::Left, diff --git a/src/shims/x86/bmi.rs b/src/shims/x86/bmi.rs index 80b1b2e16e..140e31cc51 100644 --- a/src/shims/x86/bmi.rs +++ b/src/shims/x86/bmi.rs @@ -35,7 +35,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(EmulateItemResult::NotSupported); } - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let left = this.read_scalar(left)?; let right = this.read_scalar(right)?; diff --git a/src/shims/x86/gfni.rs b/src/shims/x86/gfni.rs index f83ce560c8..9a98a80d6d 100644 --- a/src/shims/x86/gfni.rs +++ b/src/shims/x86/gfni.rs @@ -31,14 +31,16 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // See `affine_transform` for details. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=gf2p8affine_ "vgf2p8affineqb.128" | "vgf2p8affineqb.256" | "vgf2p8affineqb.512" => { - let [left, right, imm8] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, imm8] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; affine_transform(this, left, right, imm8, dest, /* inverse */ false)?; } // Used to implement the `_mm{, 256, 512}_gf2p8affineinv_epi64_epi8` functions. // See `affine_transform` for details. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=gf2p8affineinv "vgf2p8affineinvqb.128" | "vgf2p8affineinvqb.256" | "vgf2p8affineinvqb.512" => { - let [left, right, imm8] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, imm8] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; affine_transform(this, left, right, imm8, dest, /* inverse */ true)?; } // Used to implement the `_mm{, 256, 512}_gf2p8mul_epi8` functions. @@ -47,7 +49,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // polynomial representation with the reduction polynomial x^8 + x^4 + x^3 + x + 1. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=gf2p8mul "vgf2p8mulb.128" | "vgf2p8mulb.256" | "vgf2p8mulb.512" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; let (dest, dest_len) = this.project_to_simd(dest)?; diff --git a/src/shims/x86/mod.rs b/src/shims/x86/mod.rs index fbfe459711..3324b7b024 100644 --- a/src/shims/x86/mod.rs +++ b/src/shims/x86/mod.rs @@ -45,7 +45,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(EmulateItemResult::NotSupported); } - let [cb_in, a, b] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [cb_in, a, b] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let op = if unprefixed_name.starts_with("add") { mir::BinOp::AddWithOverflow } else { @@ -67,7 +68,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if is_u64 && this.tcx.sess.target.arch != "x86_64" { return interp_ok(EmulateItemResult::NotSupported); } - let [c_in, a, b, out] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [c_in, a, b, out] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let out = this.deref_pointer_as( out, if is_u64 { this.machine.layouts.u64 } else { this.machine.layouts.u32 }, @@ -84,7 +86,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // the instruction behaves like a no-op, so it is always safe to call the // intrinsic. "sse2.pause" => { - let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; // Only exhibit the spin-loop hint behavior when SSE2 is enabled. if this.tcx.sess.unstable_target_features.contains(&Symbol::intern("sse2")) { this.yield_active_thread(); @@ -103,7 +105,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { len = 8; } - let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, imm] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; pclmulqdq(this, left, right, imm, dest, len)?; } diff --git a/src/shims/x86/sha.rs b/src/shims/x86/sha.rs index d37fad3e6c..00fe58119e 100644 --- a/src/shims/x86/sha.rs +++ b/src/shims/x86/sha.rs @@ -53,7 +53,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match unprefixed_name { // Used to implement the _mm_sha256rnds2_epu32 function. "256rnds2" => { - let [a, b, k] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [a, b, k] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (a_reg, a_len) = this.project_to_simd(a)?; let (b_reg, b_len) = this.project_to_simd(b)?; @@ -74,7 +74,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Used to implement the _mm_sha256msg1_epu32 function. "256msg1" => { - let [a, b] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [a, b] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (a_reg, a_len) = this.project_to_simd(a)?; let (b_reg, b_len) = this.project_to_simd(b)?; @@ -92,7 +92,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Used to implement the _mm_sha256msg2_epu32 function. "256msg2" => { - let [a, b] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [a, b] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (a_reg, a_len) = this.project_to_simd(a)?; let (b_reg, b_len) = this.project_to_simd(b)?; diff --git a/src/shims/x86/sse.rs b/src/shims/x86/sse.rs index 1ec15d609c..6d8def5b53 100644 --- a/src/shims/x86/sse.rs +++ b/src/shims/x86/sse.rs @@ -34,7 +34,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Performs the operations on the first component of `left` and // `right` and copies the remaining components from `left`. "min.ss" | "max.ss" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = match unprefixed_name { "min.ss" => FloatBinOp::Min, @@ -50,7 +51,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // matches the IEEE min/max operations, while x86 has different // semantics. "min.ps" | "max.ps" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = match unprefixed_name { "min.ps" => FloatBinOp::Min, @@ -64,7 +66,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Performs the operations on the first component of `op` and // copies the remaining components from `op`. "rcp.ss" | "rsqrt.ss" => { - let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = match unprefixed_name { "rcp.ss" => FloatUnaryOp::Rcp, @@ -77,7 +79,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Used to implement _mm_{sqrt,rcp,rsqrt}_ps functions. // Performs the operations on all components of `op`. "rcp.ps" | "rsqrt.ps" => { - let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = match unprefixed_name { "rcp.ps" => FloatUnaryOp::Rcp, @@ -96,7 +98,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_ss are SSE functions // with hard-coded operations. "cmp.ss" => { - let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, imm] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; @@ -112,7 +115,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_ps are SSE functions // with hard-coded operations. "cmp.ps" => { - let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, imm] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; @@ -125,7 +129,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "comieq.ss" | "comilt.ss" | "comile.ss" | "comigt.ss" | "comige.ss" | "comineq.ss" | "ucomieq.ss" | "ucomilt.ss" | "ucomile.ss" | "ucomigt.ss" | "ucomige.ss" | "ucomineq.ss" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -153,7 +158,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // _mm_cvtss_si64 and _mm_cvttss_si64 functions. // Converts the first component of `op` from f32 to i32/i64. "cvtss2si" | "cvttss2si" | "cvtss2si64" | "cvttss2si64" => { - let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (op, _) = this.project_to_simd(op)?; let op = this.read_immediate(&this.project_index(&op, 0)?)?; @@ -181,7 +186,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // are copied from `left`. // https://www.felixcloutier.com/x86/cvtsi2ss "cvtsi2ss" | "cvtsi642ss" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (dest, dest_len) = this.project_to_simd(dest)?; diff --git a/src/shims/x86/sse2.rs b/src/shims/x86/sse2.rs index d6052f8307..8f53adfb5e 100644 --- a/src/shims/x86/sse2.rs +++ b/src/shims/x86/sse2.rs @@ -41,7 +41,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // intermediate signed 32-bit integers. Horizontally add adjacent pairs of // intermediate 32-bit integers, and pack the results in `dest`. "pmadd.wd" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -79,7 +80,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sad_epu8 "psad.bw" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -117,7 +119,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // is copied to remaining bits. "psll.w" | "psrl.w" | "psra.w" | "psll.d" | "psrl.d" | "psra.d" | "psll.q" | "psrl.q" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = match unprefixed_name { "psll.w" | "psll.d" | "psll.q" => ShiftOp::Left, @@ -132,7 +135,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // and _mm_cvttpd_epi32 functions. // Converts packed f32/f64 to packed i32. "cvtps2dq" | "cvttps2dq" | "cvtpd2dq" | "cvttpd2dq" => { - let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (op_len, _) = op.layout.ty.simd_size_and_type(*this.tcx); let (dest_len, _) = dest.layout.ty.simd_size_and_type(*this.tcx); @@ -169,7 +172,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Converts two 16-bit integer vectors to a single 8-bit integer // vector with signed saturation. "packsswb.128" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; packsswb(this, left, right, dest)?; } @@ -177,7 +181,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Converts two 16-bit signed integer vectors to a single 8-bit // unsigned integer vector with saturation. "packuswb.128" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; packuswb(this, left, right, dest)?; } @@ -185,7 +190,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Converts two 32-bit integer vectors to a single 16-bit integer // vector with signed saturation. "packssdw.128" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; packssdw(this, left, right, dest)?; } @@ -195,7 +201,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // matches the IEEE min/max operations, while x86 has different // semantics. "min.sd" | "max.sd" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = match unprefixed_name { "min.sd" => FloatBinOp::Min, @@ -211,7 +218,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // matches the IEEE min/max operations, while x86 has different // semantics. "min.pd" | "max.pd" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = match unprefixed_name { "min.pd" => FloatBinOp::Min, @@ -230,7 +238,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_sd are SSE2 functions // with hard-coded operations. "cmp.sd" => { - let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, imm] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; @@ -246,7 +255,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_pd are SSE2 functions // with hard-coded operations. "cmp.pd" => { - let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, imm] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; @@ -259,7 +269,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "comieq.sd" | "comilt.sd" | "comile.sd" | "comigt.sd" | "comige.sd" | "comineq.sd" | "ucomieq.sd" | "ucomilt.sd" | "ucomile.sd" | "ucomigt.sd" | "ucomige.sd" | "ucomineq.sd" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -287,7 +298,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // _mm_cvtsd_si64 and _mm_cvttsd_si64 functions. // Converts the first component of `op` from f64 to i32/i64. "cvtsd2si" | "cvttsd2si" | "cvtsd2si64" | "cvttsd2si64" => { - let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (op, _) = this.project_to_simd(op)?; let op = this.read_immediate(&this.project_index(&op, 0)?)?; @@ -313,7 +324,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Converts the first f64/f32 from `right` to f32/f64 and copies // the remaining elements from `left` "cvtsd2ss" | "cvtss2sd" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, _) = this.project_to_simd(right)?; diff --git a/src/shims/x86/sse3.rs b/src/shims/x86/sse3.rs index ebf3cb5c3e..0fd8c3bc38 100644 --- a/src/shims/x86/sse3.rs +++ b/src/shims/x86/sse3.rs @@ -26,7 +26,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Horizontally add/subtract adjacent floating point values // in `left` and `right`. "hadd.ps" | "hadd.pd" | "hsub.ps" | "hsub.pd" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let which = match unprefixed_name { "hadd.ps" | "hadd.pd" => mir::BinOp::Add, @@ -42,7 +43,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // the data crosses a cache line, but for Miri this is just a regular // unaligned read. "ldu.dq" => { - let [src_ptr] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [src_ptr] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let src_ptr = this.read_pointer(src_ptr)?; let dest = dest.force_mplace(this)?; diff --git a/src/shims/x86/sse41.rs b/src/shims/x86/sse41.rs index 6797039cf5..7736b5e443 100644 --- a/src/shims/x86/sse41.rs +++ b/src/shims/x86/sse41.rs @@ -28,7 +28,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // bits `4..=5` if `imm`, and `i`th bit specifies whether element // `i` is zeroed. "insertps" => { - let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, imm] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -63,7 +64,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Concatenates two 32-bit signed integer vectors and converts // the result to a 16-bit unsigned integer vector with saturation. "packusdw" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; packusdw(this, left, right, dest)?; } @@ -73,7 +75,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // products, and conditionally stores the sum in `dest` using the low // 4 bits of `imm`. "dpps" | "dppd" => { - let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, imm] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; conditional_dot_product(this, left, right, imm, dest)?; } @@ -81,14 +84,16 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // functions. Rounds the first element of `right` according to `rounding` // and copies the remaining elements from `left`. "round.ss" => { - let [left, right, rounding] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, rounding] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; round_first::(this, left, right, rounding, dest)?; } // Used to implement the _mm_floor_ps, _mm_ceil_ps and _mm_round_ps // functions. Rounds the elements of `op` according to `rounding`. "round.ps" => { - let [op, rounding] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op, rounding] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; round_all::(this, op, rounding, dest)?; } @@ -96,14 +101,16 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // functions. Rounds the first element of `right` according to `rounding` // and copies the remaining elements from `left`. "round.sd" => { - let [left, right, rounding] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, rounding] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; round_first::(this, left, right, rounding, dest)?; } // Used to implement the _mm_floor_pd, _mm_ceil_pd and _mm_round_pd // functions. Rounds the elements of `op` according to `rounding`. "round.pd" => { - let [op, rounding] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op, rounding] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; round_all::(this, op, rounding, dest)?; } @@ -111,7 +118,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Find the minimum unsinged 16-bit integer in `op` and // returns its value and position. "phminposuw" => { - let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (op, op_len) = this.project_to_simd(op)?; let (dest, dest_len) = this.project_to_simd(dest)?; @@ -145,7 +152,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // offsets specified in `imm`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mpsadbw_epu8 "mpsadbw" => { - let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right, imm] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; mpsadbw(this, left, right, imm, dest)?; } @@ -154,7 +162,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Tests `(op & mask) == 0`, `(op & mask) == mask` or // `(op & mask) != 0 && (op & mask) != mask` "ptestz" | "ptestc" | "ptestnzc" => { - let [op, mask] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op, mask] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (all_zero, masked_set) = test_bits_masked(this, op, mask)?; let res = match unprefixed_name { diff --git a/src/shims/x86/sse42.rs b/src/shims/x86/sse42.rs index 7e1e1482ef..72c5039a12 100644 --- a/src/shims/x86/sse42.rs +++ b/src/shims/x86/sse42.rs @@ -222,7 +222,8 @@ fn deconstruct_args<'tcx>( }; if is_explicit { - let [str1, len1, str2, len2, imm] = ecx.check_shim(abi, CanonAbi::C, link_name, args)?; + let [str1, len1, str2, len2, imm] = + ecx.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let imm = ecx.read_scalar(imm)?.to_u8()?; let default_len = default_len::(imm); @@ -235,7 +236,7 @@ fn deconstruct_args<'tcx>( interp_ok((str1, str2, Some((len1, len2)), imm)) } else { - let [str1, str2, imm] = ecx.check_shim(abi, CanonAbi::C, link_name, args)?; + let [str1, str2, imm] = ecx.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let imm = ecx.read_scalar(imm)?.to_u8()?; let array_layout = array_layout_fn(ecx, imm)?; @@ -385,7 +386,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // search for a null terminator (see `deconstruct_args` for more details). // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=924,925 "pcmpistriz128" | "pcmpistris128" => { - let [str1, str2, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [str1, str2, imm] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let imm = this.read_scalar(imm)?.to_u8()?; let str = if unprefixed_name == "pcmpistris128" { str1 } else { str2 }; @@ -405,7 +407,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // than 16 for byte-sized operands or 8 for word-sized operands. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=1046,1047 "pcmpestriz128" | "pcmpestris128" => { - let [_, len1, _, len2, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [_, len1, _, len2, imm] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let len = if unprefixed_name == "pcmpestris128" { len1 } else { len2 }; let len = this.read_scalar(len)?.to_i32()?; let imm = this.read_scalar(imm)?.to_u8()?; @@ -432,7 +435,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(EmulateItemResult::NotSupported); } - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let left = this.read_scalar(left)?; let right = this.read_scalar(right)?; diff --git a/src/shims/x86/ssse3.rs b/src/shims/x86/ssse3.rs index 310d6b8f76..52ad6bd441 100644 --- a/src/shims/x86/ssse3.rs +++ b/src/shims/x86/ssse3.rs @@ -25,7 +25,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Used to implement the _mm_abs_epi{8,16,32} functions. // Calculates the absolute value of packed 8/16/32-bit integers. "pabs.b.128" | "pabs.w.128" | "pabs.d.128" => { - let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; int_abs(this, op, dest)?; } @@ -33,7 +33,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Shuffles bytes from `left` using `right` as pattern. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_shuffle_epi8 "pshuf.b.128" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -62,7 +63,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // integer values in `left` and `right`. "phadd.w.128" | "phadd.sw.128" | "phadd.d.128" | "phsub.w.128" | "phsub.sw.128" | "phsub.d.128" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (which, saturating) = match unprefixed_name { "phadd.w.128" | "phadd.d.128" => (mir::BinOp::Add, false), @@ -81,7 +83,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // produces the output at index `i`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_maddubs_epi16 "pmadd.ub.sw.128" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -116,7 +119,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // 1 and then taking the bits `1..=16`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mulhrs_epi16 "pmul.hr.sw.128" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; pmulhrsw(this, left, right, dest)?; } @@ -126,7 +130,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // is writen to the corresponding output element. // Basically, we multiply `left` with `right.signum()`. "psign.b.128" | "psign.w.128" | "psign.d.128" => { - let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?; + let [left, right] = + this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; psign(this, left, right, dest)?; }