]> git.lizzy.rs Git - rust.git/commitdiff
Detect `std` by checking if the crate defines `#[lang = "start"]` rather than string...
authorhyd-dev <yd-huang@outlook.com>
Thu, 3 Jun 2021 09:58:24 +0000 (17:58 +0800)
committerhyd-dev <yd-huang@outlook.com>
Sun, 6 Jun 2021 03:12:05 +0000 (11:12 +0800)
src/helpers.rs
src/shims/posix/foreign_items.rs
src/shims/posix/linux/foreign_items.rs
src/shims/posix/macos/foreign_items.rs
src/shims/windows/foreign_items.rs
tests/compile-fail/unsupported_get_process_heap.rs [new file with mode: 0644]
tests/compile-fail/unsupported_signal.rs [new file with mode: 0644]
tests/run-pass/extern_crate_std_in_main.rs [new file with mode: 0644]
tests/run-pass/rename_std.rs [new file with mode: 0644]
tests/run-pass/std_only_foreign_function.rs [new file with mode: 0644]

index b71f830b2b10a214cfd8a25a7876413373932c39..7f99aa1997068ae3099f0d01112423af4b71e488 100644 (file)
@@ -628,6 +628,12 @@ fn check_abi<'a>(&self, abi: Abi, exp_abi: Abi) -> InterpResult<'a, ()> {
         }
         Ok(())
     }
+
+    fn in_std(&self) -> bool {
+        let this = self.eval_context_ref();
+        this.tcx.def_path(this.frame().instance.def_id()).krate
+            == this.tcx.def_path(this.tcx.lang_items().start_fn().unwrap()).krate
+    }
 }
 
 /// Check that the number of args is what we expect.
index a756256aab41976f64b583a15d4a358d660071f5..bbd46af52a9b71a7ea287af27ae95a93f69c1fe6 100644 (file)
@@ -475,7 +475,7 @@ fn emulate_foreign_item_by_name(
             // 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.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 @@ fn emulate_foreign_item_by_name(
 
             | "pthread_attr_init"
             | "pthread_attr_destroy"
-            if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
+            if this.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.in_std() => {
                 this.check_abi(abi, Abi::C { unwind: false })?;
                 let &[_, _] = check_arg_count(args)?;
                 this.write_null(dest)?;
@@ -502,14 +502,14 @@ fn emulate_foreign_item_by_name(
 
             | "signal"
             | "sigaltstack"
-            if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
+            if this.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.in_std() => {
                 this.check_abi(abi, Abi::C { unwind: false })?;
                 let &[_, _, _] = check_arg_count(args)?;
                 this.write_null(dest)?;
index 598d89fe1f343306972e01740fb048a3fdba4fb6..9b0576662f477e64ba2a8cb9028e583c0b37313e 100644 (file)
@@ -207,9 +207,7 @@ fn emulate_foreign_item_by_name(
 
             // 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.in_std() => {
                 this.check_abi(abi, Abi::C { unwind: false })?;
                 let &[ref _thread, ref _attr] = check_arg_count(args)?;
                 this.write_null(dest)?;
index d54e1bfbe8195a4b74a70691f0afefe3e58c6cb0..1467a95a0d3e2b96d83ff99581d6183a5a0480b1 100644 (file)
@@ -149,7 +149,7 @@ fn emulate_foreign_item_by_name(
 
             // 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.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)?;
index 3c7451352dfd24d81fcfae3a3adc0cf2a13b02bf..fd845cde31125dae254d76be308736c0a49019e8 100644 (file)
@@ -348,35 +348,27 @@ fn emulate_foreign_item_by_name(
 
             // 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.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.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.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.in_std() => {
                 this.check_abi(abi, Abi::System { unwind: false })?;
                 #[allow(non_snake_case)]
                 let &[_StackSizeInBytes] = check_arg_count(args)?;
@@ -387,7 +379,7 @@ fn emulate_foreign_item_by_name(
             | "EnterCriticalSection"
             | "LeaveCriticalSection"
             | "DeleteCriticalSection"
-                if this.frame().instance.to_string().starts_with("std::sys::windows::") =>
+                if this.in_std() =>
             {
                 this.check_abi(abi, Abi::System { unwind: false })?;
                 #[allow(non_snake_case)]
@@ -401,9 +393,7 @@ fn emulate_foreign_item_by_name(
                 // (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.in_std() => {
                 this.check_abi(abi, Abi::System { unwind: false })?;
                 #[allow(non_snake_case)]
                 let &[ref _lpCriticalSection] = check_arg_count(args)?;
diff --git a/tests/compile-fail/unsupported_get_process_heap.rs b/tests/compile-fail/unsupported_get_process_heap.rs
new file mode 100644 (file)
index 0000000..4fd5f4b
--- /dev/null
@@ -0,0 +1,12 @@
+//! `GetProcessHeap()` is special on Windows that it's only supported within libstd.
+//! (On Linux and macOS, it's just always unsupported.)
+
+fn main() {
+    extern "system" {
+        fn GetProcessHeap() -> *mut std::ffi::c_void;
+    }
+    unsafe {
+        GetProcessHeap();
+        //~^ ERROR unsupported operation: can't call foreign function: GetProcessHeap
+    }
+}
diff --git a/tests/compile-fail/unsupported_signal.rs b/tests/compile-fail/unsupported_signal.rs
new file mode 100644 (file)
index 0000000..7931747
--- /dev/null
@@ -0,0 +1,12 @@
+//! `signal()` is special on Linux and macOS that it's only supported within libstd.
+// 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
+    }
+}
diff --git a/tests/run-pass/extern_crate_std_in_main.rs b/tests/run-pass/extern_crate_std_in_main.rs
new file mode 100644 (file)
index 0000000..8f71e61
--- /dev/null
@@ -0,0 +1,5 @@
+#![no_std]
+
+fn main() {
+    extern crate std;
+}
diff --git a/tests/run-pass/rename_std.rs b/tests/run-pass/rename_std.rs
new file mode 100644 (file)
index 0000000..7e82e53
--- /dev/null
@@ -0,0 +1,5 @@
+#![no_std]
+
+extern crate std as foo;
+
+fn main() {}
diff --git a/tests/run-pass/std_only_foreign_function.rs b/tests/run-pass/std_only_foreign_function.rs
new file mode 100644 (file)
index 0000000..959103e
--- /dev/null
@@ -0,0 +1,39 @@
+//! Make sure we can call foreign functions that are only allowed within libstd if we are "libstd"
+//! (defining the `start` lang item).
+#![feature(lang_items, rustc_private, core_intrinsics)]
+#![no_std]
+
+use core::{intrinsics, panic::PanicInfo};
+
+#[lang = "eh_personality"]
+fn rust_eh_personality() {}
+
+#[panic_handler]
+fn panic_handler(_: &PanicInfo<'_>) -> ! {
+    intrinsics::abort()
+}
+
+#[lang = "start"]
+fn start(main: fn(), _argc: isize, _argv: *const *const u8) -> isize {
+    main();
+    0
+}
+
+fn main() {
+    #[cfg(unix)]
+    unsafe {
+        extern crate libc;
+        assert_eq!(libc::signal(libc::SIGPIPE, libc::SIG_IGN), 0);
+    }
+    #[cfg(windows)]
+    unsafe {
+        extern "system" {
+            fn GetProcessHeap() -> *mut core::ffi::c_void;
+            fn ExitProcess(code: u32) -> !;
+        }
+        assert_eq!(GetProcessHeap() as usize, 1);
+        // Early exit to avoid the requirement of
+        // `std::sys::windows::thread_local_key::p_thread_callback`.
+        ExitProcess(0);
+    }
+}