Skip to content

Detect std by checking if the crate defines #[lang = "start"] rather than string comparison #1823

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from Jun 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 5 additions & 5 deletions src/shims/posix/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand All @@ -488,28 +488,28 @@ 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)?;
}

| "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)?;
Expand Down
4 changes: 1 addition & 3 deletions src/shims/posix/linux/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand Down
2 changes: 1 addition & 1 deletion src/shims/posix/macos/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand Down
22 changes: 6 additions & 16 deletions src/shims/windows/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand All @@ -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)]
Expand All @@ -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)?;
Expand Down
13 changes: 13 additions & 0 deletions tests/compile-fail/unsupported_signal.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 5 additions & 0 deletions tests/run-pass/extern_crate_std_in_main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#![no_std]

fn main() {
extern crate std;
}
5 changes: 5 additions & 0 deletions tests/run-pass/rename_std.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#![no_std]

extern crate std as foo;

fn main() {}