From 893843fd455aa515a5d05cc8e70a970a84dab35d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 14 Mar 2021 15:30:37 +0100 Subject: [PATCH 01/11] when Miri calls a function ptr, make sure it has the right ABI --- src/eval.rs | 2 ++ src/helpers.rs | 6 ++++++ src/machine.rs | 1 + src/shims/panic.rs | 5 +++++ src/shims/posix/thread.rs | 2 ++ src/shims/tls.rs | 4 ++++ tests/compile-fail/concurrency/unwind_top_of_stack.rs | 5 ++++- 7 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/eval.rs b/src/eval.rs index 7a29d91d2d..bd1aebe00d 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -8,6 +8,7 @@ use log::info; use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, layout::LayoutCx, TyCtxt}; use rustc_target::abi::LayoutOf; +use rustc_target::spec::abi::Abi; use crate::*; @@ -189,6 +190,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( // Call start function. ecx.call_function( start_instance, + Abi::Rust, &[main_ptr.into(), argc.into(), argv.into()], Some(&ret_place.into()), StackPopCleanup::None { cleanup: true }, diff --git a/src/helpers.rs b/src/helpers.rs index e98488b9bf..1f1c992275 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -161,11 +161,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx fn call_function( &mut self, f: ty::Instance<'tcx>, + caller_abi: Abi, args: &[Immediate], dest: Option<&PlaceTy<'tcx, Tag>>, stack_pop: StackPopCleanup, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); + let param_env = ty::ParamEnv::reveal_all(); // in Miri this is always the param_env we use... and this.param_env is private. + let callee_abi = f.ty(*this.tcx, param_env).fn_sig(*this.tcx).abi(); + if callee_abi != caller_abi { + throw_ub_format!("calling a function with ABI {} using caller ABI {}", callee_abi.name(), caller_abi.name()) + } // Push frame. let mir = &*this.load_mir(f.def, None)?; diff --git a/src/machine.rs b/src/machine.rs index 1415f7506a..99cb3bf2b2 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -430,6 +430,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> { let malloc = ty::Instance::mono(ecx.tcx.tcx, malloc); ecx.call_function( malloc, + Abi::Rust, &[size.into(), align.into()], Some(dest), // Don't do anything when we are done. The `statement()` function will increment diff --git a/src/shims/panic.rs b/src/shims/panic.rs index abc7aa2ad1..2c6d31549c 100644 --- a/src/shims/panic.rs +++ b/src/shims/panic.rs @@ -15,6 +15,7 @@ use log::trace; use rustc_middle::{mir, ty}; use rustc_target::spec::PanicStrategy; +use rustc_target::spec::abi::Abi; use crate::*; use helpers::check_arg_count; @@ -94,6 +95,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let ret_place = MPlaceTy::dangling(this.machine.layouts.unit, this).into(); this.call_function( f_instance, + Abi::Rust, &[data.into()], Some(&ret_place), // Directly return to caller. @@ -145,6 +147,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let ret_place = MPlaceTy::dangling(this.machine.layouts.unit, this).into(); this.call_function( f_instance, + Abi::Rust, &[catch_unwind.data.into(), payload.into()], Some(&ret_place), // Directly return to caller of `try`. @@ -174,6 +177,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let panic = ty::Instance::mono(this.tcx.tcx, panic); this.call_function( panic, + Abi::Rust, &[msg.to_ref()], None, StackPopCleanup::Goto { ret: None, unwind }, @@ -202,6 +206,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let panic_bounds_check = ty::Instance::mono(this.tcx.tcx, panic_bounds_check); this.call_function( panic_bounds_check, + Abi::Rust, &[index.into(), len.into()], None, StackPopCleanup::Goto { ret: None, unwind }, diff --git a/src/shims/posix/thread.rs b/src/shims/posix/thread.rs index 40663326b4..fb1c018fc3 100644 --- a/src/shims/posix/thread.rs +++ b/src/shims/posix/thread.rs @@ -2,6 +2,7 @@ use std::convert::TryInto; use crate::*; use rustc_target::abi::LayoutOf; +use rustc_target::spec::abi::Abi; impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> { @@ -50,6 +51,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.call_function( instance, + Abi::C { unwind: false }, &[*func_arg], Some(&ret_place.into()), StackPopCleanup::None { cleanup: true }, diff --git a/src/shims/tls.rs b/src/shims/tls.rs index 36bae2af9c..ef77949efa 100644 --- a/src/shims/tls.rs +++ b/src/shims/tls.rs @@ -9,6 +9,7 @@ use log::trace; use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty; use rustc_target::abi::{Size, HasDataLayout}; +use rustc_target::spec::abi::Abi; use crate::*; @@ -244,6 +245,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let ret_place = MPlaceTy::dangling(this.machine.layouts.unit, this).into(); this.call_function( thread_callback, + Abi::System { unwind: false }, &[Scalar::null_ptr(this).into(), reason.into(), Scalar::null_ptr(this).into()], Some(&ret_place), StackPopCleanup::None { cleanup: true }, @@ -266,6 +268,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let ret_place = MPlaceTy::dangling(this.machine.layouts.unit, this).into(); this.call_function( instance, + Abi::C { unwind: false }, &[data.into()], Some(&ret_place), StackPopCleanup::None { cleanup: true }, @@ -306,6 +309,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let ret_place = MPlaceTy::dangling(this.machine.layouts.unit, this).into(); this.call_function( instance, + Abi::C { unwind: false }, &[ptr.into()], Some(&ret_place), StackPopCleanup::None { cleanup: true }, diff --git a/tests/compile-fail/concurrency/unwind_top_of_stack.rs b/tests/compile-fail/concurrency/unwind_top_of_stack.rs index c13a2ac8bb..8f3bb17470 100644 --- a/tests/compile-fail/concurrency/unwind_top_of_stack.rs +++ b/tests/compile-fail/concurrency/unwind_top_of_stack.rs @@ -1,7 +1,10 @@ // ignore-windows: Concurrency on Windows is not supported yet. -// error-pattern: unwinding past the topmost frame of the stack +// error-pattern: calling a function with ABI C-unwind using caller ABI C //! Unwinding past the top frame of a stack is Undefined Behavior. +//! However, it is impossible to do that in pure Rust since one cannot write an unwinding +//! function with `C` ABI... so let's instead test that we are indeed correctly checking +//! the callee ABI in `pthread_create`. #![feature(rustc_private, c_unwind)] From d1dec9cd233bf28f2bab14126c3d9df93683ae17 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 14 Mar 2021 15:38:22 +0100 Subject: [PATCH 02/11] don't ICE when callee has the wrong number of arguments --- src/helpers.rs | 8 ++++-- .../compile-fail/concurrency/too_few_args.rs | 26 +++++++++++++++++++ .../compile-fail/concurrency/too_many_args.rs | 26 +++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 tests/compile-fail/concurrency/too_few_args.rs create mode 100644 tests/compile-fail/concurrency/too_many_args.rs diff --git a/src/helpers.rs b/src/helpers.rs index 1f1c992275..7fe0ae0a97 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -181,11 +181,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let mut callee_args = this.frame().body.args_iter(); for arg in args { let callee_arg = this.local_place( - callee_args.next().expect("callee has fewer arguments than expected"), + callee_args.next().ok_or_else(|| + err_ub_format!("callee has fewer arguments than expected") + )? )?; this.write_immediate(*arg, &callee_arg)?; } - assert_eq!(callee_args.next(), None, "callee has more arguments than expected"); + if callee_args.next().is_some() { + throw_ub_format!("callee has more arguments than expected"); + } Ok(()) } diff --git a/tests/compile-fail/concurrency/too_few_args.rs b/tests/compile-fail/concurrency/too_few_args.rs new file mode 100644 index 0000000000..e2dfa33af8 --- /dev/null +++ b/tests/compile-fail/concurrency/too_few_args.rs @@ -0,0 +1,26 @@ +// ignore-windows: Concurrency on Windows is not supported yet. +// error-pattern: callee has fewer arguments than expected + +//! The thread function must have exactly one argument. + +#![feature(rustc_private)] + +extern crate libc; + +use std::{mem, ptr}; + +extern "C" fn thread_start() -> *mut libc::c_void { + panic!() +} + +fn main() { + unsafe { + let mut native: libc::pthread_t = mem::zeroed(); + let attr: libc::pthread_attr_t = mem::zeroed(); + // assert_eq!(libc::pthread_attr_init(&mut attr), 0); FIXME: this function is not yet implemented. + let thread_start: extern "C" fn() -> *mut libc::c_void = thread_start; + let thread_start: extern "C" fn(*mut libc::c_void) -> *mut libc::c_void = mem::transmute(thread_start); + assert_eq!(libc::pthread_create(&mut native, &attr, thread_start, ptr::null_mut()), 0); + assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0); + } +} diff --git a/tests/compile-fail/concurrency/too_many_args.rs b/tests/compile-fail/concurrency/too_many_args.rs new file mode 100644 index 0000000000..0ef12b0707 --- /dev/null +++ b/tests/compile-fail/concurrency/too_many_args.rs @@ -0,0 +1,26 @@ +// ignore-windows: Concurrency on Windows is not supported yet. +// error-pattern: callee has more arguments than expected + +//! The thread function must have exactly one argument. + +#![feature(rustc_private)] + +extern crate libc; + +use std::{mem, ptr}; + +extern "C" fn thread_start(_null: *mut libc::c_void, _x: i32) -> *mut libc::c_void { + panic!() +} + +fn main() { + unsafe { + let mut native: libc::pthread_t = mem::zeroed(); + let attr: libc::pthread_attr_t = mem::zeroed(); + // assert_eq!(libc::pthread_attr_init(&mut attr), 0); FIXME: this function is not yet implemented. + let thread_start: extern "C" fn(*mut libc::c_void, i32) -> *mut libc::c_void = thread_start; + let thread_start: extern "C" fn(*mut libc::c_void) -> *mut libc::c_void = mem::transmute(thread_start); + assert_eq!(libc::pthread_create(&mut native, &attr, thread_start, ptr::null_mut()), 0); + assert_eq!(libc::pthread_join(native, ptr::null_mut()), 0); + } +} From c9ff02f549cf30cf9f3007b34fde89dcf0f46ac2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 14 Mar 2021 17:03:20 +0100 Subject: [PATCH 03/11] ensure we catch incorrectly unwinding calls --- tests/compile-fail/panic/bad_unwind.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tests/compile-fail/panic/bad_unwind.rs diff --git a/tests/compile-fail/panic/bad_unwind.rs b/tests/compile-fail/panic/bad_unwind.rs new file mode 100644 index 0000000000..fde2c19af0 --- /dev/null +++ b/tests/compile-fail/panic/bad_unwind.rs @@ -0,0 +1,16 @@ +// error-pattern: calling a function with ABI C-unwind using caller ABI C +#![feature(c_unwind)] + +//! Unwinding when the caller ABI is "C" (without "-unwind") is UB. +//! Currently we detect the ABI mismatch; we could probably allow such calls in principle one day +//! but then we have to detect the unexpected unwinding. + +extern "C-unwind" fn unwind() { + panic!(); +} + +fn main() { + let unwind: extern "C-unwind" fn() = unwind; + let unwind: extern "C" fn() = unsafe { std::mem::transmute(unwind) }; + std::panic::catch_unwind(|| unwind()).unwrap_err(); +} From 15465a58812f7af4f5d27eb87da191b344d281b5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 14 Mar 2021 17:10:45 +0100 Subject: [PATCH 04/11] don't ICE when we unwind despite panic=abort --- src/shims/panic.rs | 4 +++- tests/compile-fail/panic/unwind_panic_abort.rs | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 tests/compile-fail/panic/unwind_panic_abort.rs diff --git a/src/shims/panic.rs b/src/shims/panic.rs index abc7aa2ad1..8f06e5276f 100644 --- a/src/shims/panic.rs +++ b/src/shims/panic.rs @@ -45,7 +45,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx trace!("miri_start_panic: {:?}", this.frame().instance); // Make sure we only start unwinding when this matches our panic strategy. - assert_eq!(this.tcx.sess.panic_strategy(), PanicStrategy::Unwind); + if this.tcx.sess.panic_strategy() != PanicStrategy::Unwind { + throw_ub_format!("unwinding despite panic=abort"); + } // Get the raw pointer stored in arg[0] (the panic payload). let &[ref payload] = check_arg_count(args)?; diff --git a/tests/compile-fail/panic/unwind_panic_abort.rs b/tests/compile-fail/panic/unwind_panic_abort.rs new file mode 100644 index 0000000000..05284eb770 --- /dev/null +++ b/tests/compile-fail/panic/unwind_panic_abort.rs @@ -0,0 +1,11 @@ +// compile-flags: -Cpanic=abort + +//! Unwinding despite `-C panic=abort` is an error. + +extern "Rust" { + fn miri_start_panic(payload: *mut u8) -> !; +} + +fn main() { + unsafe { miri_start_panic(&mut 0); } //~ ERROR unwinding despite panic=abort +} From 1c7d7471dae217810f48e594baca2e143a38da10 Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Wed, 17 Mar 2021 00:40:53 +0800 Subject: [PATCH 05/11] Don't duplicate `check_abi()` --- src/helpers.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/helpers.rs b/src/helpers.rs index 7fe0ae0a97..fe4766d877 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -169,9 +169,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let this = self.eval_context_mut(); let param_env = ty::ParamEnv::reveal_all(); // in Miri this is always the param_env we use... and this.param_env is private. let callee_abi = f.ty(*this.tcx, param_env).fn_sig(*this.tcx).abi(); - if callee_abi != caller_abi { - throw_ub_format!("calling a function with ABI {} using caller ABI {}", callee_abi.name(), caller_abi.name()) - } + check_abi(caller_abi, callee_abi)?; // Push frame. let mir = &*this.load_mir(f.def, None)?; From bbc348539bce27627c60b4a27d6a822643f1c002 Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Wed, 17 Mar 2021 04:21:17 +0800 Subject: [PATCH 06/11] Unsupported foreign non-"C"/"system"-ABI function calls are not UB --- src/shims/foreign_items.rs | 30 +++++++++++++++++++ src/shims/posix/foreign_items.rs | 12 ++++---- src/shims/posix/linux/foreign_items.rs | 6 ++-- src/shims/posix/macos/foreign_items.rs | 8 +++-- src/shims/windows/foreign_items.rs | 8 ++--- .../unsupported_foreign_function.rs | 9 ++++++ tests/compile-fail/unsupported_posix_dlsym.rs | 14 +++++++++ .../compile-fail/unsupported_windows_dlsym.rs | 18 +++++++++++ 8 files changed, 88 insertions(+), 17 deletions(-) create mode 100644 tests/compile-fail/unsupported_foreign_function.rs create mode 100644 tests/compile-fail/unsupported_posix_dlsym.rs create mode 100644 tests/compile-fail/unsupported_windows_dlsym.rs diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index 373d529961..599d7268a3 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -13,6 +13,36 @@ use crate::*; use super::backtrace::EvalContextExt as _; use helpers::{check_abi, check_arg_count}; +/// This macro behaves just like `match $link_name { ... }`, but inserts a +/// `$crate::helpers::check_abi($abi, $exp_abi)?` call at each match arm +/// except the wildcard one. +#[macro_export] +macro_rules! match_with_abi_check { + ($link_name:expr, $abi:expr, $exp_abi:expr, { + $(|)? $($pattern:pat)|+ $(if $guard:expr)? => $shim_impl:block + $($remaining:tt)+ + }) => { + match ($link_name, $abi, $exp_abi) { + ($($pattern)|+, abi, exp_abi) $(if $guard)? => { + $crate::helpers::check_abi(abi, exp_abi)?; + $shim_impl + } + (link_name, abi, exp_abi) => match_with_abi_check!( + link_name, + abi, + exp_abi, + { $($remaining)* } + ), + } + }; + ($link_name:ident, $abi:ident, $exp_abi:ident, { + _ => $fallback:expr $(,)? + }) => ({ + let _ = ($link_name, $abi, $exp_abi); + $fallback + }); +} + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> { /// Returns the minimum alignment for the target architecture for allocations of the given size. diff --git a/src/shims/posix/foreign_items.rs b/src/shims/posix/foreign_items.rs index fdbe88cd7d..e773c8bcf3 100644 --- a/src/shims/posix/foreign_items.rs +++ b/src/shims/posix/foreign_items.rs @@ -5,7 +5,7 @@ use rustc_target::abi::{Align, LayoutOf, Size}; use rustc_target::spec::abi::Abi; use crate::*; -use helpers::{check_abi, check_arg_count}; +use helpers::check_arg_count; use shims::posix::fs::EvalContextExt as _; use shims::posix::sync::EvalContextExt as _; use shims::posix::thread::EvalContextExt as _; @@ -22,9 +22,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx ) -> InterpResult<'tcx, bool> { let this = self.eval_context_mut(); - check_abi(abi, Abi::C { unwind: false })?; - - match link_name { + match_with_abi_check!(link_name, abi, Abi::C { unwind: false }, { // Environment related shims "getenv" => { let &[ref name] = check_arg_count(args)?; @@ -458,12 +456,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Platform-specific shims _ => { match this.tcx.sess.target.os.as_str() { - "linux" => return shims::posix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, args, dest, ret), - "macos" => return shims::posix::macos::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, args, dest, ret), + "linux" => return shims::posix::linux::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret), + "macos" => return shims::posix::macos::foreign_items::EvalContextExt::emulate_foreign_item_by_name(this, link_name, abi, args, dest, ret), _ => unreachable!(), } } - }; + }); Ok(true) } diff --git a/src/shims/posix/linux/foreign_items.rs b/src/shims/posix/linux/foreign_items.rs index 2a3b512bcd..f61e37284e 100644 --- a/src/shims/posix/linux/foreign_items.rs +++ b/src/shims/posix/linux/foreign_items.rs @@ -1,4 +1,5 @@ use rustc_middle::mir; +use rustc_target::spec::abi::Abi; use crate::*; use crate::helpers::check_arg_count; @@ -12,13 +13,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx fn emulate_foreign_item_by_name( &mut self, link_name: &str, + abi: Abi, args: &[OpTy<'tcx, Tag>], dest: &PlaceTy<'tcx, Tag>, _ret: mir::BasicBlock, ) -> InterpResult<'tcx, bool> { let this = self.eval_context_mut(); - match link_name { + match_with_abi_check!(link_name, abi, Abi::C { unwind: false }, { // errno "__errno_location" => { let &[] = check_arg_count(args)?; @@ -189,7 +191,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } _ => throw_unsup_format!("can't call foreign function: {}", link_name), - }; + }); Ok(true) } diff --git a/src/shims/posix/macos/foreign_items.rs b/src/shims/posix/macos/foreign_items.rs index 1ea1214830..cb57c4d2f6 100644 --- a/src/shims/posix/macos/foreign_items.rs +++ b/src/shims/posix/macos/foreign_items.rs @@ -1,4 +1,5 @@ use rustc_middle::mir; +use rustc_target::spec::abi::Abi; use crate::*; use helpers::check_arg_count; @@ -10,13 +11,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx fn emulate_foreign_item_by_name( &mut self, link_name: &str, + abi: Abi, args: &[OpTy<'tcx, Tag>], dest: &PlaceTy<'tcx, Tag>, _ret: mir::BasicBlock, ) -> InterpResult<'tcx, bool> { let this = self.eval_context_mut(); - match link_name { + match_with_abi_check!(link_name, abi, Abi::C { unwind: false }, { // errno "__error" => { let &[] = check_arg_count(args)?; @@ -83,7 +85,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let &[ref info] = check_arg_count(args)?; let result = this.mach_timebase_info(info)?; this.write_scalar(Scalar::from_i32(result), dest)?; - }, + } // Access to command-line arguments "_NSGetArgc" => { @@ -136,7 +138,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } _ => throw_unsup_format!("can't call foreign function: {}", link_name), - }; + }); Ok(true) } diff --git a/src/shims/windows/foreign_items.rs b/src/shims/windows/foreign_items.rs index d9c5ce7896..9e8e6b5898 100644 --- a/src/shims/windows/foreign_items.rs +++ b/src/shims/windows/foreign_items.rs @@ -5,7 +5,7 @@ use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; use crate::*; -use helpers::{check_abi, check_arg_count}; +use helpers::check_arg_count; use shims::windows::sync::EvalContextExt as _; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {} @@ -20,14 +20,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx ) -> InterpResult<'tcx, bool> { let this = self.eval_context_mut(); - check_abi(abi, Abi::System { unwind: false })?; - // Windows API stubs. // HANDLE = isize // DWORD = ULONG = u32 // BOOL = i32 // BOOLEAN = u8 - match link_name { + match_with_abi_check!(link_name, abi, Abi::System { unwind: false }, { // Environment related shims "GetEnvironmentVariableW" => { let &[ref name, ref buf, ref size] = check_arg_count(args)?; @@ -340,7 +338,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } _ => throw_unsup_format!("can't call foreign function: {}", link_name), - } + }); Ok(true) } diff --git a/tests/compile-fail/unsupported_foreign_function.rs b/tests/compile-fail/unsupported_foreign_function.rs new file mode 100644 index 0000000000..b7f4d9038e --- /dev/null +++ b/tests/compile-fail/unsupported_foreign_function.rs @@ -0,0 +1,9 @@ +fn main() { + extern "Rust" { + fn foo(); + } + + unsafe { + foo(); //~ ERROR unsupported operation: can't call foreign function: foo + } +} diff --git a/tests/compile-fail/unsupported_posix_dlsym.rs b/tests/compile-fail/unsupported_posix_dlsym.rs new file mode 100644 index 0000000000..07859b3118 --- /dev/null +++ b/tests/compile-fail/unsupported_posix_dlsym.rs @@ -0,0 +1,14 @@ +// ignore-windows: No dlsym() on Windows + +#![feature(rustc_private)] + +extern crate libc; + +use std::ptr; + +fn main() { + unsafe { + libc::dlsym(ptr::null_mut(), b"foo\0".as_ptr().cast()); + //~^ ERROR unsupported operation: unsupported + } +} diff --git a/tests/compile-fail/unsupported_windows_dlsym.rs b/tests/compile-fail/unsupported_windows_dlsym.rs new file mode 100644 index 0000000000..757eb81592 --- /dev/null +++ b/tests/compile-fail/unsupported_windows_dlsym.rs @@ -0,0 +1,18 @@ +// ignore-linux: GetProcAddress() is not available on Linux +// ignore-macos: GetProcAddress() is not available on macOS + +use std::{ffi::c_void, os::raw::c_char, ptr}; + +extern "system" { + fn GetProcAddress( + hModule: *mut c_void, + lpProcName: *const c_char, + ) -> extern "system" fn() -> isize; +} + +fn main() { + unsafe { + GetProcAddress(ptr::null_mut(), b"foo\0".as_ptr().cast()); + //~^ ERROR unsupported operation: unsupported Windows dlsym: foo + } +} From 3ee865461f3fa128835f3d79ea5f396e6ebdf6c1 Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Wed, 17 Mar 2021 21:51:07 +0800 Subject: [PATCH 07/11] Revert "Don't duplicate `check_abi()`" This reverts commit 1c7d7471dae217810f48e594baca2e143a38da10. --- src/helpers.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/helpers.rs b/src/helpers.rs index fe4766d877..7fe0ae0a97 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -169,7 +169,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx let this = self.eval_context_mut(); let param_env = ty::ParamEnv::reveal_all(); // in Miri this is always the param_env we use... and this.param_env is private. let callee_abi = f.ty(*this.tcx, param_env).fn_sig(*this.tcx).abi(); - check_abi(caller_abi, callee_abi)?; + if callee_abi != caller_abi { + throw_ub_format!("calling a function with ABI {} using caller ABI {}", callee_abi.name(), caller_abi.name()) + } // Push frame. let mir = &*this.load_mir(f.def, None)?; From 633ac2a22226b27981b52ce6ed5af47fcc251746 Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Wed, 17 Mar 2021 21:55:45 +0800 Subject: [PATCH 08/11] Remove meaningless tests --- tests/compile-fail/unsupported_posix_dlsym.rs | 14 -------------- .../compile-fail/unsupported_windows_dlsym.rs | 18 ------------------ 2 files changed, 32 deletions(-) delete mode 100644 tests/compile-fail/unsupported_posix_dlsym.rs delete mode 100644 tests/compile-fail/unsupported_windows_dlsym.rs diff --git a/tests/compile-fail/unsupported_posix_dlsym.rs b/tests/compile-fail/unsupported_posix_dlsym.rs deleted file mode 100644 index 07859b3118..0000000000 --- a/tests/compile-fail/unsupported_posix_dlsym.rs +++ /dev/null @@ -1,14 +0,0 @@ -// ignore-windows: No dlsym() on Windows - -#![feature(rustc_private)] - -extern crate libc; - -use std::ptr; - -fn main() { - unsafe { - libc::dlsym(ptr::null_mut(), b"foo\0".as_ptr().cast()); - //~^ ERROR unsupported operation: unsupported - } -} diff --git a/tests/compile-fail/unsupported_windows_dlsym.rs b/tests/compile-fail/unsupported_windows_dlsym.rs deleted file mode 100644 index 757eb81592..0000000000 --- a/tests/compile-fail/unsupported_windows_dlsym.rs +++ /dev/null @@ -1,18 +0,0 @@ -// ignore-linux: GetProcAddress() is not available on Linux -// ignore-macos: GetProcAddress() is not available on macOS - -use std::{ffi::c_void, os::raw::c_char, ptr}; - -extern "system" { - fn GetProcAddress( - hModule: *mut c_void, - lpProcName: *const c_char, - ) -> extern "system" fn() -> isize; -} - -fn main() { - unsafe { - GetProcAddress(ptr::null_mut(), b"foo\0".as_ptr().cast()); - //~^ ERROR unsupported operation: unsupported Windows dlsym: foo - } -} From 7ec919daa4c3e211dd2ef56014a11f967c583013 Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Wed, 17 Mar 2021 22:12:08 +0800 Subject: [PATCH 09/11] Remove the macro and expand it manually --- src/shims/foreign_items.rs | 30 ------------ src/shims/posix/foreign_items.rs | 67 ++++++++++++++++++++++++-- src/shims/posix/linux/foreign_items.rs | 22 +++++++-- src/shims/posix/macos/foreign_items.rs | 27 +++++++++-- src/shims/windows/foreign_items.rs | 45 +++++++++++++++-- 5 files changed, 148 insertions(+), 43 deletions(-) diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index 599d7268a3..373d529961 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -13,36 +13,6 @@ use crate::*; use super::backtrace::EvalContextExt as _; use helpers::{check_abi, check_arg_count}; -/// This macro behaves just like `match $link_name { ... }`, but inserts a -/// `$crate::helpers::check_abi($abi, $exp_abi)?` call at each match arm -/// except the wildcard one. -#[macro_export] -macro_rules! match_with_abi_check { - ($link_name:expr, $abi:expr, $exp_abi:expr, { - $(|)? $($pattern:pat)|+ $(if $guard:expr)? => $shim_impl:block - $($remaining:tt)+ - }) => { - match ($link_name, $abi, $exp_abi) { - ($($pattern)|+, abi, exp_abi) $(if $guard)? => { - $crate::helpers::check_abi(abi, exp_abi)?; - $shim_impl - } - (link_name, abi, exp_abi) => match_with_abi_check!( - link_name, - abi, - exp_abi, - { $($remaining)* } - ), - } - }; - ($link_name:ident, $abi:ident, $exp_abi:ident, { - _ => $fallback:expr $(,)? - }) => ({ - let _ = ($link_name, $abi, $exp_abi); - $fallback - }); -} - impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> { /// Returns the minimum alignment for the target architecture for allocations of the given size. diff --git a/src/shims/posix/foreign_items.rs b/src/shims/posix/foreign_items.rs index e773c8bcf3..b3d53cdc10 100644 --- a/src/shims/posix/foreign_items.rs +++ b/src/shims/posix/foreign_items.rs @@ -5,7 +5,7 @@ use rustc_target::abi::{Align, LayoutOf, Size}; use rustc_target::spec::abi::Abi; use crate::*; -use helpers::check_arg_count; +use helpers::{check_abi, check_arg_count}; use shims::posix::fs::EvalContextExt as _; use shims::posix::sync::EvalContextExt as _; use shims::posix::thread::EvalContextExt as _; @@ -22,30 +22,35 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx ) -> InterpResult<'tcx, bool> { let this = self.eval_context_mut(); - match_with_abi_check!(link_name, abi, Abi::C { unwind: false }, { + match link_name { // Environment related shims "getenv" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref name] = check_arg_count(args)?; let result = this.getenv(name)?; this.write_scalar(result, dest)?; } "unsetenv" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref name] = check_arg_count(args)?; let result = this.unsetenv(name)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "setenv" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref name, ref value, ref overwrite] = check_arg_count(args)?; this.read_scalar(overwrite)?.to_i32()?; let result = this.setenv(name, value)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "getcwd" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref buf, ref size] = check_arg_count(args)?; let result = this.getcwd(buf, size)?; this.write_scalar(result, dest)?; } "chdir" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref path] = check_arg_count(args)?; let result = this.chdir(path)?; this.write_scalar(Scalar::from_i32(result), dest)?; @@ -53,15 +58,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // File related shims "open" | "open64" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref path, ref flag, ref mode] = check_arg_count(args)?; let result = this.open(path, flag, mode)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "fcntl" => { + check_abi(abi, Abi::C { unwind: false })?; let result = this.fcntl(args)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "read" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref fd, ref buf, ref count] = check_arg_count(args)?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_scalar(buf)?.check_init()?; @@ -70,6 +78,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_scalar(Scalar::from_machine_isize(result, this), dest)?; } "write" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref fd, ref buf, ref n] = check_arg_count(args)?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_scalar(buf)?.check_init()?; @@ -80,52 +89,62 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_scalar(Scalar::from_machine_isize(result, this), dest)?; } "unlink" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref path] = check_arg_count(args)?; let result = this.unlink(path)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "symlink" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref target, ref linkpath] = check_arg_count(args)?; let result = this.symlink(target, linkpath)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "rename" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref oldpath, ref newpath] = check_arg_count(args)?; let result = this.rename(oldpath, newpath)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "mkdir" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref path, ref mode] = check_arg_count(args)?; let result = this.mkdir(path, mode)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "rmdir" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref path] = check_arg_count(args)?; let result = this.rmdir(path)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "closedir" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref dirp] = check_arg_count(args)?; let result = this.closedir(dirp)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "lseek" | "lseek64" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref fd, ref offset, ref whence] = check_arg_count(args)?; let result = this.lseek64(fd, offset, whence)?; // "lseek" is only used on macOS which is 64bit-only, so `i64` always works. this.write_scalar(Scalar::from_i64(result), dest)?; } "fsync" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref fd] = check_arg_count(args)?; let result = this.fsync(fd)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "fdatasync" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref fd] = check_arg_count(args)?; let result = this.fdatasync(fd)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "readlink" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref pathname, ref buf, ref bufsize] = check_arg_count(args)?; let result = this.readlink(pathname, buf, bufsize)?; this.write_scalar(Scalar::from_machine_isize(result, this), dest)?; @@ -133,6 +152,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Allocation "posix_memalign" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref ret, ref align, ref size] = check_arg_count(args)?; let ret = this.deref_operand(ret)?; let align = this.read_scalar(align)?.to_machine_usize(this)?; @@ -163,6 +183,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Dynamic symbol loading "dlsym" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref handle, ref symbol] = check_arg_count(args)?; this.read_scalar(handle)?.to_machine_usize(this)?; let symbol = this.read_scalar(symbol)?.check_init()?; @@ -177,6 +198,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Querying system information "sysconf" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref name] = check_arg_count(args)?; let name = this.read_scalar(name)?.to_i32()?; @@ -202,6 +224,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Thread-local storage "pthread_key_create" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref key, ref dtor] = check_arg_count(args)?; let key_place = this.deref_operand(key)?; let dtor = this.read_scalar(dtor)?.check_init()?; @@ -230,6 +253,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_null(dest)?; } "pthread_key_delete" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref key] = check_arg_count(args)?; let key = this.force_bits(this.read_scalar(key)?.check_init()?, key.layout.size)?; this.machine.tls.delete_tls_key(key)?; @@ -237,6 +261,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_null(dest)?; } "pthread_getspecific" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref key] = check_arg_count(args)?; let key = this.force_bits(this.read_scalar(key)?.check_init()?, key.layout.size)?; let active_thread = this.get_active_thread(); @@ -244,6 +269,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_scalar(ptr, dest)?; } "pthread_setspecific" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref key, ref new_ptr] = check_arg_count(args)?; let key = this.force_bits(this.read_scalar(key)?.check_init()?, key.layout.size)?; let active_thread = this.get_active_thread(); @@ -256,110 +282,132 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Synchronization primitives "pthread_mutexattr_init" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref attr] = check_arg_count(args)?; let result = this.pthread_mutexattr_init(attr)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_mutexattr_settype" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref attr, ref kind] = check_arg_count(args)?; let result = this.pthread_mutexattr_settype(attr, kind)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_mutexattr_destroy" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref attr] = check_arg_count(args)?; let result = this.pthread_mutexattr_destroy(attr)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_mutex_init" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref mutex, ref attr] = check_arg_count(args)?; let result = this.pthread_mutex_init(mutex, attr)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_mutex_lock" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref mutex] = check_arg_count(args)?; let result = this.pthread_mutex_lock(mutex)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_mutex_trylock" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref mutex] = check_arg_count(args)?; let result = this.pthread_mutex_trylock(mutex)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_mutex_unlock" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref mutex] = check_arg_count(args)?; let result = this.pthread_mutex_unlock(mutex)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_mutex_destroy" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref mutex] = check_arg_count(args)?; let result = this.pthread_mutex_destroy(mutex)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_rwlock_rdlock" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref rwlock] = check_arg_count(args)?; let result = this.pthread_rwlock_rdlock(rwlock)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_rwlock_tryrdlock" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref rwlock] = check_arg_count(args)?; let result = this.pthread_rwlock_tryrdlock(rwlock)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_rwlock_wrlock" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref rwlock] = check_arg_count(args)?; let result = this.pthread_rwlock_wrlock(rwlock)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_rwlock_trywrlock" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref rwlock] = check_arg_count(args)?; let result = this.pthread_rwlock_trywrlock(rwlock)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_rwlock_unlock" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref rwlock] = check_arg_count(args)?; let result = this.pthread_rwlock_unlock(rwlock)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_rwlock_destroy" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref rwlock] = check_arg_count(args)?; let result = this.pthread_rwlock_destroy(rwlock)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_condattr_init" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref attr] = check_arg_count(args)?; let result = this.pthread_condattr_init(attr)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_condattr_destroy" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref attr] = check_arg_count(args)?; let result = this.pthread_condattr_destroy(attr)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_cond_init" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref cond, ref attr] = check_arg_count(args)?; let result = this.pthread_cond_init(cond, attr)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_cond_signal" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref cond] = check_arg_count(args)?; let result = this.pthread_cond_signal(cond)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_cond_broadcast" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref cond] = check_arg_count(args)?; let result = this.pthread_cond_broadcast(cond)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_cond_wait" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref cond, ref mutex] = check_arg_count(args)?; let result = this.pthread_cond_wait(cond, mutex)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_cond_timedwait" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref cond, ref mutex, ref abstime] = check_arg_count(args)?; this.pthread_cond_timedwait(cond, mutex, abstime, dest)?; } "pthread_cond_destroy" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref cond] = check_arg_count(args)?; let result = this.pthread_cond_destroy(cond)?; this.write_scalar(Scalar::from_i32(result), dest)?; @@ -367,30 +415,36 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Threading "pthread_create" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref thread, ref attr, ref start, ref arg] = check_arg_count(args)?; let result = this.pthread_create(thread, attr, start, arg)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_join" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref thread, ref retval] = check_arg_count(args)?; let result = this.pthread_join(thread, retval)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_detach" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref thread] = check_arg_count(args)?; let result = this.pthread_detach(thread)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_self" => { + check_abi(abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; this.pthread_self(dest)?; } "sched_yield" => { + check_abi(abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; let result = this.sched_yield()?; this.write_scalar(Scalar::from_i32(result), dest)?; } "nanosleep" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref req, ref rem] = check_arg_count(args)?; let result = this.nanosleep(req, rem)?; this.write_scalar(Scalar::from_i32(result), dest)?; @@ -398,6 +452,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Miscellaneous "isatty" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref fd] = check_arg_count(args)?; this.read_scalar(fd)?.to_i32()?; // "returns 1 if fd is an open file descriptor referring to a terminal; otherwise 0 is returned, and errno is set to indicate the error" @@ -407,6 +462,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_null(dest)?; } "pthread_atfork" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref prepare, ref parent, ref child] = check_arg_count(args)?; this.force_bits(this.read_scalar(prepare)?.check_init()?, this.memory.pointer_size())?; this.force_bits(this.read_scalar(parent)?.check_init()?, this.memory.pointer_size())?; @@ -419,6 +475,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // These shims are enabled only when the caller is in the standard library. "pthread_attr_getguardsize" if this.frame().instance.to_string().starts_with("std::sys::unix::") => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref _attr, ref guard_size] = check_arg_count(args)?; let guard_size = this.deref_operand(guard_size)?; let guard_size_layout = this.libc_ty_layout("size_t")?; @@ -431,11 +488,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx | "pthread_attr_init" | "pthread_attr_destroy" if this.frame().instance.to_string().starts_with("std::sys::unix::") => { + check_abi(abi, Abi::C { unwind: false })?; let &[_] = check_arg_count(args)?; this.write_null(dest)?; } | "pthread_attr_setstacksize" if this.frame().instance.to_string().starts_with("std::sys::unix::") => { + check_abi(abi, Abi::C { unwind: false })?; let &[_, _] = check_arg_count(args)?; this.write_null(dest)?; } @@ -443,12 +502,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx | "signal" | "sigaltstack" if this.frame().instance.to_string().starts_with("std::sys::unix::") => { + check_abi(abi, Abi::C { unwind: false })?; let &[_, _] = check_arg_count(args)?; this.write_null(dest)?; } | "sigaction" | "mprotect" if this.frame().instance.to_string().starts_with("std::sys::unix::") => { + check_abi(abi, Abi::C { unwind: false })?; let &[_, _, _] = check_arg_count(args)?; this.write_null(dest)?; } @@ -461,7 +522,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx _ => unreachable!(), } } - }); + }; Ok(true) } diff --git a/src/shims/posix/linux/foreign_items.rs b/src/shims/posix/linux/foreign_items.rs index f61e37284e..fe989b5924 100644 --- a/src/shims/posix/linux/foreign_items.rs +++ b/src/shims/posix/linux/foreign_items.rs @@ -2,7 +2,7 @@ use rustc_middle::mir; use rustc_target::spec::abi::Abi; use crate::*; -use crate::helpers::check_arg_count; +use crate::helpers::{check_abi, check_arg_count}; use shims::posix::fs::EvalContextExt as _; use shims::posix::linux::sync::futex; use shims::posix::sync::EvalContextExt as _; @@ -20,9 +20,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx ) -> InterpResult<'tcx, bool> { let this = self.eval_context_mut(); - match_with_abi_check!(link_name, abi, Abi::C { unwind: false }, { + match link_name { // errno "__errno_location" => { + check_abi(abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; let errno_place = this.last_error_place()?; this.write_scalar(errno_place.to_ref().to_scalar()?, dest)?; @@ -32,27 +33,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // These symbols have different names on Linux and macOS, which is the only reason they are not // in the `posix` module. "close" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref fd] = check_arg_count(args)?; let result = this.close(fd)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "opendir" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref name] = check_arg_count(args)?; let result = this.opendir(name)?; this.write_scalar(result, dest)?; } "readdir64_r" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref dirp, ref entry, ref result] = check_arg_count(args)?; let result = this.linux_readdir64_r(dirp, entry, result)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "ftruncate64" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref fd, ref length] = check_arg_count(args)?; let result = this.ftruncate64(fd, length)?; this.write_scalar(Scalar::from_i32(result), dest)?; } // Linux-only "posix_fadvise" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref fd, ref offset, ref len, ref advice] = check_arg_count(args)?; this.read_scalar(fd)?.to_i32()?; this.read_scalar(offset)?.to_machine_isize(this)?; @@ -62,6 +68,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_null(dest)?; } "sync_file_range" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref fd, ref offset, ref nbytes, ref flags] = check_arg_count(args)?; let result = this.sync_file_range(fd, offset, nbytes, flags)?; this.write_scalar(Scalar::from_i32(result), dest)?; @@ -69,6 +76,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Time related shims "clock_gettime" => { + check_abi(abi, Abi::C { unwind: false })?; // This is a POSIX function but it has only been tested on linux. let &[ref clk_id, ref tp] = check_arg_count(args)?; let result = this.clock_gettime(clk_id, tp)?; @@ -77,6 +85,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Querying system information "pthread_attr_getstack" => { + check_abi(abi, Abi::C { unwind: false })?; // We don't support "pthread_attr_setstack", so we just pretend all stacks have the same values here. let &[ref attr_place, ref addr_place, ref size_place] = check_arg_count(args)?; this.deref_operand(attr_place)?; @@ -98,16 +107,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Threading "prctl" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref option, ref arg2, ref arg3, ref arg4, ref arg5] = check_arg_count(args)?; let result = this.prctl(option, arg2, arg3, arg4, arg5)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_condattr_setclock" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref attr, ref clock_id] = check_arg_count(args)?; let result = this.pthread_condattr_setclock(attr, clock_id)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "pthread_condattr_getclock" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref attr, ref clock_id] = check_arg_count(args)?; let result = this.pthread_condattr_getclock(attr, clock_id)?; this.write_scalar(Scalar::from_i32(result), dest)?; @@ -115,6 +127,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Dynamically invoked syscalls "syscall" => { + check_abi(abi, Abi::C { unwind: false })?; // The syscall variadic function is legal to call with more arguments than needed, // extra arguments are simply ignored. However, all arguments need to be scalars; // other types might be treated differently by the calling convention. @@ -169,10 +182,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Miscelanneous "getrandom" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref ptr, ref len, ref flags] = check_arg_count(args)?; getrandom(this, ptr, len, flags, dest)?; } "sched_getaffinity" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref pid, ref cpusetsize, ref mask] = check_arg_count(args)?; this.read_scalar(pid)?.to_i32()?; this.read_scalar(cpusetsize)?.to_machine_usize(this)?; @@ -186,12 +201,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, '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().instance.to_string().starts_with("std::sys::unix::") => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref _thread, ref _attr] = check_arg_count(args)?; this.write_null(dest)?; } _ => throw_unsup_format!("can't call foreign function: {}", link_name), - }); + }; Ok(true) } diff --git a/src/shims/posix/macos/foreign_items.rs b/src/shims/posix/macos/foreign_items.rs index cb57c4d2f6..dce9eea668 100644 --- a/src/shims/posix/macos/foreign_items.rs +++ b/src/shims/posix/macos/foreign_items.rs @@ -2,7 +2,7 @@ use rustc_middle::mir; use rustc_target::spec::abi::Abi; use crate::*; -use helpers::check_arg_count; +use helpers::{check_abi, check_arg_count}; use shims::posix::fs::EvalContextExt as _; use shims::posix::thread::EvalContextExt as _; @@ -18,9 +18,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx ) -> InterpResult<'tcx, bool> { let this = self.eval_context_mut(); - match_with_abi_check!(link_name, abi, Abi::C { unwind: false }, { + match link_name { // errno "__error" => { + check_abi(abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; let errno_place = this.last_error_place()?; this.write_scalar(errno_place.to_ref().to_scalar()?, dest)?; @@ -28,36 +29,43 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // File related shims "close" | "close$NOCANCEL" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref result] = check_arg_count(args)?; let result = this.close(result)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "stat" | "stat$INODE64" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref path, ref buf] = check_arg_count(args)?; let result = this.macos_stat(path, buf)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "lstat" | "lstat$INODE64" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref path, ref buf] = check_arg_count(args)?; let result = this.macos_lstat(path, buf)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "fstat" | "fstat$INODE64" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref fd, ref buf] = check_arg_count(args)?; let result = this.macos_fstat(fd, buf)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "opendir" | "opendir$INODE64" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref name] = check_arg_count(args)?; let result = this.opendir(name)?; this.write_scalar(result, dest)?; } "readdir_r" | "readdir_r$INODE64" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref dirp, ref entry, ref result] = check_arg_count(args)?; let result = this.macos_readdir_r(dirp, entry, result)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "ftruncate" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref fd, ref length] = check_arg_count(args)?; let result = this.ftruncate64(fd, length)?; this.write_scalar(Scalar::from_i32(result), dest)?; @@ -65,40 +73,47 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Environment related shims "_NSGetEnviron" => { + check_abi(abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; this.write_scalar(this.machine.env_vars.environ.unwrap().ptr, dest)?; } // Time related shims "gettimeofday" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref tv, ref tz] = check_arg_count(args)?; let result = this.gettimeofday(tv, tz)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "mach_absolute_time" => { + check_abi(abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; let result = this.mach_absolute_time()?; this.write_scalar(Scalar::from_u64(result), dest)?; } "mach_timebase_info" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref info] = check_arg_count(args)?; let result = this.mach_timebase_info(info)?; this.write_scalar(Scalar::from_i32(result), dest)?; - } + }, // Access to command-line arguments "_NSGetArgc" => { + check_abi(abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; this.write_scalar(this.machine.argc.expect("machine must be initialized"), dest)?; } "_NSGetArgv" => { + check_abi(abi, Abi::C { unwind: false })?; let &[] = check_arg_count(args)?; this.write_scalar(this.machine.argv.expect("machine must be initialized"), dest)?; } // Thread-local storage "_tlv_atexit" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref dtor, ref data] = check_arg_count(args)?; let dtor = this.read_scalar(dtor)?.check_init()?; let dtor = this.memory.get_fn(dtor)?.as_instance()?; @@ -109,12 +124,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Querying system information "pthread_get_stackaddr_np" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref thread] = check_arg_count(args)?; this.read_scalar(thread)?.to_machine_usize(this)?; let stack_addr = Scalar::from_uint(STACK_ADDR, this.pointer_size()); this.write_scalar(stack_addr, dest)?; } "pthread_get_stacksize_np" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref thread] = check_arg_count(args)?; this.read_scalar(thread)?.to_machine_usize(this)?; let stack_size = Scalar::from_uint(STACK_SIZE, this.pointer_size()); @@ -123,6 +140,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Threading "pthread_setname_np" => { + check_abi(abi, Abi::C { unwind: false })?; let &[ref name] = check_arg_count(args)?; let name = this.read_scalar(name)?.check_init()?; this.pthread_setname_np(name)?; @@ -131,6 +149,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, '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. "mmap" if this.frame().instance.to_string().starts_with("std::sys::unix::") => { + check_abi(abi, Abi::C { unwind: false })?; // This is a horrible hack, but since the guard page mechanism calls mmap and expects a particular return value, we just give it that value. let &[ref addr, _, _, _, _, _] = check_arg_count(args)?; let addr = this.read_scalar(addr)?.check_init()?; @@ -138,7 +157,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } _ => throw_unsup_format!("can't call foreign function: {}", link_name), - }); + }; Ok(true) } diff --git a/src/shims/windows/foreign_items.rs b/src/shims/windows/foreign_items.rs index 9e8e6b5898..72b776380b 100644 --- a/src/shims/windows/foreign_items.rs +++ b/src/shims/windows/foreign_items.rs @@ -5,7 +5,7 @@ use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; use crate::*; -use helpers::check_arg_count; +use helpers::{check_abi, check_arg_count}; use shims::windows::sync::EvalContextExt as _; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {} @@ -25,34 +25,40 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // DWORD = ULONG = u32 // BOOL = i32 // BOOLEAN = u8 - match_with_abi_check!(link_name, abi, Abi::System { unwind: false }, { + match link_name { // Environment related shims "GetEnvironmentVariableW" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref name, ref buf, ref size] = check_arg_count(args)?; let result = this.GetEnvironmentVariableW(name, buf, size)?; this.write_scalar(Scalar::from_u32(result), dest)?; } "SetEnvironmentVariableW" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref name, ref value] = check_arg_count(args)?; let result = this.SetEnvironmentVariableW(name, value)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "GetEnvironmentStringsW" => { + check_abi(abi, Abi::System { unwind: false })?; let &[] = check_arg_count(args)?; let result = this.GetEnvironmentStringsW()?; this.write_scalar(result, dest)?; } "FreeEnvironmentStringsW" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref env_block] = check_arg_count(args)?; let result = this.FreeEnvironmentStringsW(env_block)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "GetCurrentDirectoryW" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref size, ref buf] = check_arg_count(args)?; let result = this.GetCurrentDirectoryW(size, buf)?; this.write_scalar(Scalar::from_u32(result), dest)?; } "SetCurrentDirectoryW" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref path] = check_arg_count(args)?; let result = this.SetCurrentDirectoryW(path)?; this.write_scalar(Scalar::from_i32(result), dest)?; @@ -60,6 +66,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // File related shims "GetStdHandle" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref which] = check_arg_count(args)?; let which = this.read_scalar(which)?.to_i32()?; // We just make this the identity function, so we know later in `WriteFile` @@ -67,6 +74,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_scalar(Scalar::from_machine_isize(which.into(), this), dest)?; } "WriteFile" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref handle, ref buf, ref n, ref written_ptr, ref overlapped] = check_arg_count(args)?; this.read_scalar(overlapped)?.to_machine_usize(this)?; // this is a poiner, that we ignore let handle = this.read_scalar(handle)?.to_machine_isize(this)?; @@ -102,6 +110,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Allocation "HeapAlloc" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref handle, ref flags, ref size] = check_arg_count(args)?; this.read_scalar(handle)?.to_machine_isize(this)?; let flags = this.read_scalar(flags)?.to_u32()?; @@ -111,6 +120,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_scalar(res, dest)?; } "HeapFree" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref handle, ref flags, ref ptr] = check_arg_count(args)?; this.read_scalar(handle)?.to_machine_isize(this)?; this.read_scalar(flags)?.to_u32()?; @@ -119,6 +129,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_scalar(Scalar::from_i32(1), dest)?; } "HeapReAlloc" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref handle, ref flags, ref ptr, ref size] = check_arg_count(args)?; this.read_scalar(handle)?.to_machine_isize(this)?; this.read_scalar(flags)?.to_u32()?; @@ -130,11 +141,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // errno "SetLastError" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref error] = check_arg_count(args)?; let error = this.read_scalar(error)?.check_init()?; this.set_last_error(error)?; } "GetLastError" => { + check_abi(abi, Abi::System { unwind: false })?; let &[] = check_arg_count(args)?; let last_error = this.get_last_error()?; this.write_scalar(last_error, dest)?; @@ -142,6 +155,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Querying system information "GetSystemInfo" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref system_info] = check_arg_count(args)?; let system_info = this.deref_operand(system_info)?; // Initialize with `0`. @@ -157,6 +171,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Thread-local storage "TlsAlloc" => { + check_abi(abi, Abi::System { unwind: false })?; // This just creates a key; Windows does not natively support TLS destructors. // Create key and return it. @@ -165,6 +180,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?; } "TlsGetValue" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref key] = check_arg_count(args)?; let key = u128::from(this.read_scalar(key)?.to_u32()?); let active_thread = this.get_active_thread(); @@ -172,6 +188,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_scalar(ptr, dest)?; } "TlsSetValue" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref key, ref new_ptr] = check_arg_count(args)?; let key = u128::from(this.read_scalar(key)?.to_u32()?); let active_thread = this.get_active_thread(); @@ -184,6 +201,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Access to command-line arguments "GetCommandLineW" => { + check_abi(abi, Abi::System { unwind: false })?; let &[] = check_arg_count(args)?; this.write_scalar( this.machine.cmd_line.expect("machine must be initialized"), @@ -193,17 +211,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Time related shims "GetSystemTimeAsFileTime" => { + check_abi(abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[ref LPFILETIME] = check_arg_count(args)?; this.GetSystemTimeAsFileTime(LPFILETIME)?; } "QueryPerformanceCounter" => { + check_abi(abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[ref lpPerformanceCount] = check_arg_count(args)?; let result = this.QueryPerformanceCounter(lpPerformanceCount)?; this.write_scalar(Scalar::from_i32(result), dest)?; } "QueryPerformanceFrequency" => { + check_abi(abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[ref lpFrequency] = check_arg_count(args)?; let result = this.QueryPerformanceFrequency(lpFrequency)?; @@ -212,27 +233,33 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Synchronization primitives "AcquireSRWLockExclusive" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref ptr] = check_arg_count(args)?; this.AcquireSRWLockExclusive(ptr)?; } "ReleaseSRWLockExclusive" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref ptr] = check_arg_count(args)?; this.ReleaseSRWLockExclusive(ptr)?; } "TryAcquireSRWLockExclusive" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref ptr] = check_arg_count(args)?; let ret = this.TryAcquireSRWLockExclusive(ptr)?; this.write_scalar(Scalar::from_u8(ret), dest)?; } "AcquireSRWLockShared" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref ptr] = check_arg_count(args)?; this.AcquireSRWLockShared(ptr)?; } "ReleaseSRWLockShared" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref ptr] = check_arg_count(args)?; this.ReleaseSRWLockShared(ptr)?; } "TryAcquireSRWLockShared" => { + check_abi(abi, Abi::System { unwind: false })?; let &[ref ptr] = check_arg_count(args)?; let ret = this.TryAcquireSRWLockShared(ptr)?; this.write_scalar(Scalar::from_u8(ret), dest)?; @@ -240,6 +267,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Dynamic symbol loading "GetProcAddress" => { + check_abi(abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[ref hModule, ref lpProcName] = check_arg_count(args)?; this.read_scalar(hModule)?.to_machine_isize(this)?; @@ -254,6 +282,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Miscellaneous "SystemFunction036" => { + check_abi(abi, Abi::System { unwind: false })?; // The actual name of 'RtlGenRandom' let &[ref ptr, ref len] = check_arg_count(args)?; let ptr = this.read_scalar(ptr)?.check_init()?; @@ -262,6 +291,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_scalar(Scalar::from_bool(true), dest)?; } "GetConsoleScreenBufferInfo" => { + check_abi(abi, Abi::System { unwind: false })?; // `term` needs this, so we fake it. let &[ref console, ref buffer_info] = check_arg_count(args)?; this.read_scalar(console)?.to_machine_isize(this)?; @@ -271,6 +301,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_null(dest)?; } "GetConsoleMode" => { + check_abi(abi, Abi::System { unwind: false })?; // Windows "isatty" (in libtest) needs this, so we fake it. let &[ref console, ref mode] = check_arg_count(args)?; this.read_scalar(console)?.to_machine_isize(this)?; @@ -280,6 +311,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_null(dest)?; } "SwitchToThread" => { + check_abi(abi, Abi::System { unwind: false })?; let &[] = check_arg_count(args)?; // Note that once Miri supports concurrency, this will need to return a nonzero // value if this call does result in switching to another thread. @@ -288,29 +320,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Better error for attempts to create a thread "CreateThread" => { + check_abi(abi, Abi::System { unwind: false })?; throw_unsup_format!("Miri does not support concurrency on Windows"); } // 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().instance.to_string().starts_with("std::sys::windows::") => { + check_abi(abi, Abi::System { unwind: false })?; let &[] = check_arg_count(args)?; // Just fake a HANDLE this.write_scalar(Scalar::from_machine_isize(1, this), dest)?; } "SetConsoleTextAttribute" if this.frame().instance.to_string().starts_with("std::sys::windows::") => { + check_abi(abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[ref _hConsoleOutput, ref _wAttribute] = check_arg_count(args)?; // Pretend these does not exist / nothing happened, by returning zero. this.write_null(dest)?; } "AddVectoredExceptionHandler" if this.frame().instance.to_string().starts_with("std::sys::windows::") => { + check_abi(abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[ref _First, ref _Handler] = check_arg_count(args)?; // Any non zero value works for the stdlib. This is just used for stack overflows anyway. this.write_scalar(Scalar::from_machine_usize(1, this), dest)?; } "SetThreadStackGuarantee" if this.frame().instance.to_string().starts_with("std::sys::windows::") => { + check_abi(abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[_StackSizeInBytes] = check_arg_count(args)?; // Any non zero value works for the stdlib. This is just used for stack overflows anyway. @@ -321,6 +358,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx | "LeaveCriticalSection" | "DeleteCriticalSection" if this.frame().instance.to_string().starts_with("std::sys::windows::") => { + check_abi(abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[ref _lpCriticalSection] = check_arg_count(args)?; assert_eq!(this.get_total_thread_count(), 1, "concurrency on Windows is not supported"); @@ -330,6 +368,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } "TryEnterCriticalSection" if this.frame().instance.to_string().starts_with("std::sys::windows::") => { + check_abi(abi, Abi::System { unwind: false })?; #[allow(non_snake_case)] let &[ref _lpCriticalSection] = check_arg_count(args)?; assert_eq!(this.get_total_thread_count(), 1, "concurrency on Windows is not supported"); @@ -338,7 +377,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } _ => throw_unsup_format!("can't call foreign function: {}", link_name), - }); + } Ok(true) } From 4f899ce9acb3827cc45fd4a8672372b1ff64b8b2 Mon Sep 17 00:00:00 2001 From: bstrie <865233+bstrie@users.noreply.github.com> Date: Wed, 17 Mar 2021 18:34:44 -0400 Subject: [PATCH 10/11] Replace deprecated `collections::Bound` --- src/shims/tls.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shims/tls.rs b/src/shims/tls.rs index ef77949efa..3339e3bee1 100644 --- a/src/shims/tls.rs +++ b/src/shims/tls.rs @@ -174,7 +174,7 @@ impl<'tcx> TlsData<'tcx> { key: Option, thread_id: ThreadId, ) -> Option<(ty::Instance<'tcx>, Scalar, TlsKey)> { - use std::collections::Bound::*; + use std::ops::Bound::*; let thread_local = &mut self.keys; let start = match key { From fc88c6ccca6849b1e7909f8d10a8968e12bcbb29 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 18 Mar 2021 00:19:53 +0100 Subject: [PATCH 11/11] rustup --- rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-version b/rust-version index f064064db1..bd571f788a 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -b3ac52646f7591a811fa9bf55995b24fd17ece08 +36f1f04f18b89ba4a999bcfd6584663fd6fc1c5d