Enforce unsafe surrounding block on safe-to-call functions

This commit is contained in:
David Tolnay 2020-11-11 10:48:32 -08:00
parent 8685745538
commit 7be5b1f134
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
14 changed files with 28 additions and 16 deletions

View File

@ -90,7 +90,7 @@ mod ffi {
fn next_chunk(buf: &mut MultiBuf) -> &[u8];
}
extern "C++" {
unsafe extern "C++" {
// One or more headers with the matching C++ declarations. Our code
// generators don't read it but it gets #include'd and used in static
// assertions to ensure our picture of the FFI boundary is accurate.

View File

@ -14,7 +14,7 @@ mod ffi {
}
// C++ types and signatures exposed to Rust.
extern "C++" {
unsafe extern "C++" {
include!("demo/include/blobstore.h");
type BlobstoreClient;

View File

@ -6,7 +6,7 @@ fn test_positive() {
let rs = quote! {
#[cxx::bridge]
mod ffi {
extern "C++" {
unsafe extern "C++" {
fn in_C();
}
extern "Rust" {

View File

@ -30,7 +30,7 @@ use self::kind::{Kind, Opaque, Trivial};
/// # mod file1 {
/// #[cxx::bridge(namespace = "example")]
/// pub mod ffi {
/// extern "C++" {
/// unsafe extern "C++" {
/// type Demo;
///
/// fn create_demo() -> UniquePtr<Demo>;
@ -41,7 +41,7 @@ use self::kind::{Kind, Opaque, Trivial};
/// // file2.rs
/// #[cxx::bridge(namespace = "example")]
/// pub mod ffi {
/// extern "C++" {
/// unsafe extern "C++" {
/// type Demo = crate::file1::ffi::Demo;
///
/// fn take_ref_demo(demo: &Demo);
@ -80,7 +80,7 @@ use self::kind::{Kind, Opaque, Trivial};
///
/// #[cxx::bridge(namespace = "folly")]
/// pub mod ffi {
/// extern "C++" {
/// unsafe extern "C++" {
/// include!("rust_cxx_bindings.h");
///
/// type StringPiece = crate::folly_sys::StringPiece;

View File

@ -86,7 +86,7 @@
//! fn next_chunk(buf: &mut MultiBuf) -> &[u8];
//! }
//!
//! extern "C++" {
//! unsafe extern "C++" {
//! // One or more headers with the matching C++ declarations. Our code
//! // generators don't read it but it gets #include'd and used in static
//! // assertions to ensure our picture of the FFI boundary is accurate.

View File

@ -204,7 +204,7 @@ fn parse_foreign_mod(
Lang::Rust => {
if foreign_mod.unsafety.is_some() {
let unsafety = foreign_mod.unsafety;
let abi = foreign_mod.abi;
let abi = &foreign_mod.abi;
let span = quote!(#unsafety #abi);
cx.error(span, "extern \"Rust\" block does not need to be unsafe");
}
@ -253,6 +253,18 @@ fn parse_foreign_mod(
}
}
if !trusted
&& items.iter().any(|api| match api {
Api::CxxFunction(efn) => efn.unsafety.is_none(),
_ => false,
})
{
cx.error(
foreign_mod.abi,
"block must be declared `unsafe extern \"C++\"` if it contains any safe-to-call C++ functions",
);
}
let mut types = items.iter().filter_map(|item| match item {
Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.name),
Api::TypeAlias(alias) => Some(&alias.name),

View File

@ -6,7 +6,7 @@ use std::str;
const BRIDGE0: &str = r#"
#[cxx::bridge]
mod ffi {
extern "C++" {
unsafe extern "C++" {
pub fn do_cpp_thing(foo: &str);
}
}

View File

@ -15,7 +15,7 @@ pub mod ffi2 {
impl UniquePtr<F> {}
impl UniquePtr<G> {}
extern "C++" {
unsafe extern "C++" {
include!("tests/ffi/tests.h");
type D = crate::other::D;

View File

@ -116,7 +116,7 @@ pub mod ffi {
i: i32,
}
extern "C++" {
unsafe extern "C++" {
include!("tests/ffi/tests.h");
type C;

View File

@ -3,7 +3,7 @@
#[rustfmt::skip]
#[cxx::bridge(namespace = "tests")]
pub mod ffi {
extern "C++" {
unsafe extern "C++" {
include!("tests/ffi/tests.h");
type C = crate::ffi::C;

View File

@ -1,6 +1,6 @@
#[cxx::bridge]
mod ffi {
extern "C++" {
unsafe extern "C++" {
type C;
fn f(&'static self);
}

View File

@ -1,6 +1,6 @@
#[cxx::bridge]
mod ffi {
extern "C++" {
unsafe extern "C++" {
type ThingC;
fn repro_c(t: &&ThingC);
}

View File

@ -1,6 +1,6 @@
#[cxx::bridge]
mod ffi {
extern "C++" {
unsafe extern "C++" {
type One;
type Two;
fn f(&mut self);

View File

@ -1,6 +1,6 @@
#[cxx::bridge]
mod ffi {
extern "C++" {
unsafe extern "C++" {
fn f(self: &Unrecognized);
}
}