Auto merge of #1823 - hyd-dev:extern-crate-std, r=RalfJung
Detect `std` by checking if the crate defines `#[lang = "start"]` rather than string comparison I also considered to compare the crate name with `sym::std`, but it's easy to name any crate `std` by using `--crate-name std`, so I don't think that is robust enough. Note that this only checks the crate, it does not check whether the call is in `sys::unix` or `sys::windows`, unlike the previous implementation, but I think it's already robust enough. Fixes #1821.
This commit is contained in:
commit
28fbf81c40
8 changed files with 44 additions and 25 deletions
|
|
@ -628,6 +628,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn frame_in_std(&self) -> bool {
|
||||
let this = self.eval_context_ref();
|
||||
this.tcx.lang_items().start_fn().map_or(false, |start_fn| {
|
||||
this.tcx.def_path(this.frame().instance.def_id()).krate
|
||||
== this.tcx.def_path(start_fn).krate
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that the number of args is what we expect.
|
||||
|
|
|
|||
|
|
@ -475,7 +475,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.
|
||||
"pthread_attr_getguardsize"
|
||||
if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
|
||||
if this.frame_in_std() => {
|
||||
this.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)?;
|
||||
|
|
@ -488,13 +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::") => {
|
||||
if this.frame_in_std() => {
|
||||
this.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::") => {
|
||||
if this.frame_in_std() => {
|
||||
this.check_abi(abi, Abi::C { unwind: false })?;
|
||||
let &[_, _] = check_arg_count(args)?;
|
||||
this.write_null(dest)?;
|
||||
|
|
@ -502,14 +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::") => {
|
||||
if this.frame_in_std() => {
|
||||
this.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::") => {
|
||||
if this.frame_in_std() => {
|
||||
this.check_abi(abi, Abi::C { unwind: false })?;
|
||||
let &[_, _, _] = check_arg_count(args)?;
|
||||
this.write_null(dest)?;
|
||||
|
|
|
|||
|
|
@ -207,9 +207,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.
|
||||
"pthread_getattr_np"
|
||||
if this.frame().instance.to_string().starts_with("std::sys::unix::") =>
|
||||
{
|
||||
"pthread_getattr_np" if this.frame_in_std() => {
|
||||
this.check_abi(abi, Abi::C { unwind: false })?;
|
||||
let &[ref _thread, ref _attr] = check_arg_count(args)?;
|
||||
this.write_null(dest)?;
|
||||
|
|
|
|||
|
|
@ -149,7 +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::") => {
|
||||
"mmap" if this.frame_in_std() => {
|
||||
this.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)?;
|
||||
|
|
|
|||
|
|
@ -348,35 +348,27 @@ 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.
|
||||
"GetProcessHeap"
|
||||
if this.frame().instance.to_string().starts_with("std::sys::windows::") =>
|
||||
{
|
||||
"GetProcessHeap" if this.frame_in_std() => {
|
||||
this.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::") =>
|
||||
{
|
||||
"SetConsoleTextAttribute" if this.frame_in_std() => {
|
||||
this.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::") =>
|
||||
{
|
||||
"AddVectoredExceptionHandler" if this.frame_in_std() => {
|
||||
this.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::") =>
|
||||
{
|
||||
"SetThreadStackGuarantee" if this.frame_in_std() => {
|
||||
this.check_abi(abi, Abi::System { unwind: false })?;
|
||||
#[allow(non_snake_case)]
|
||||
let &[_StackSizeInBytes] = check_arg_count(args)?;
|
||||
|
|
@ -387,7 +379,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
| "EnterCriticalSection"
|
||||
| "LeaveCriticalSection"
|
||||
| "DeleteCriticalSection"
|
||||
if this.frame().instance.to_string().starts_with("std::sys::windows::") =>
|
||||
if this.frame_in_std() =>
|
||||
{
|
||||
this.check_abi(abi, Abi::System { unwind: false })?;
|
||||
#[allow(non_snake_case)]
|
||||
|
|
@ -401,9 +393,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
// (Windows locks are reentrant, and we have only 1 thread,
|
||||
// so not doing any futher checks here is at least not incorrect.)
|
||||
}
|
||||
"TryEnterCriticalSection"
|
||||
if this.frame().instance.to_string().starts_with("std::sys::windows::") =>
|
||||
{
|
||||
"TryEnterCriticalSection" if this.frame_in_std() => {
|
||||
this.check_abi(abi, Abi::System { unwind: false })?;
|
||||
#[allow(non_snake_case)]
|
||||
let &[ref _lpCriticalSection] = check_arg_count(args)?;
|
||||
|
|
|
|||
13
tests/compile-fail/unsupported_signal.rs
Normal file
13
tests/compile-fail/unsupported_signal.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
//! `signal()` is special on Linux and macOS that it's only supported within libstd.
|
||||
//! The implementation is not complete enough to permit user code to call it.
|
||||
// ignore-windows: No libc on Windows
|
||||
#![feature(rustc_private)]
|
||||
|
||||
extern crate libc;
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
libc::signal(libc::SIGPIPE, libc::SIG_IGN);
|
||||
//~^ ERROR unsupported operation: can't call foreign function: signal
|
||||
}
|
||||
}
|
||||
5
tests/run-pass/extern_crate_std_in_main.rs
Normal file
5
tests/run-pass/extern_crate_std_in_main.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#![no_std]
|
||||
|
||||
fn main() {
|
||||
extern crate std;
|
||||
}
|
||||
5
tests/run-pass/rename_std.rs
Normal file
5
tests/run-pass/rename_std.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#![no_std]
|
||||
|
||||
extern crate std as foo;
|
||||
|
||||
fn main() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue