diff --git a/src/abi.md b/src/abi.md index 374dd6d45..09ff20b16 100644 --- a/src/abi.md +++ b/src/abi.md @@ -66,16 +66,27 @@ item's name. Additionally, the item will be publicly exported from the produced library or object file, similar to the [`used` attribute](#the-used-attribute). +This attribute is unsafe as an unmangled symbol may collide with another symbol +with the same name (or with a well-known symbol), leading to undefined behavior. + +```rust +#[unsafe(no_mangle)] +extern "C" fn foo() {} +``` + ## The `link_section` attribute The *`link_section` attribute* specifies the section of the object file that a [function] or [static]'s content will be placed into. It uses the [_MetaNameValueStr_] syntax to specify the section name. +This attribute is unsafe as it allows users to place data and code into sections +of memory not expecting them, such as mutable data into read-only areas. + ```rust,no_run -#[no_mangle] -#[link_section = ".example_section"] +#[unsafe(no_mangle)] +#[unsafe(link_section = ".example_section")] pub static VAR1: u32 = 1; ``` @@ -85,8 +96,12 @@ The *`export_name` attribute* specifies the name of the symbol that will be exported on a [function] or [static]. It uses the [_MetaNameValueStr_] syntax to specify the symbol name. +This attribute is unsafe as a symbol with a custom name may collide with another +symbol with the same name (or with a well-known symbol), leading to undefined +behavior. + ```rust -#[export_name = "exported_symbol_name"] +#[unsafe(export_name = "exported_symbol_name")] pub fn name_in_rust() { } ``` diff --git a/src/attributes.md b/src/attributes.md index a56e276f6..f3ca9173e 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -9,7 +9,8 @@ >    `#` `[` _Attr_ `]` > > _Attr_ :\ ->    [_SimplePath_] _AttrInput_? +>       [_SimplePath_] _AttrInput_?\ +>    | `unsafe` `(` [_SimplePath_] _AttrInput_? `)` > > _AttrInput_ :\ >       [_DelimTokenTree_]\ @@ -29,6 +30,17 @@ Attributes other than macro attributes also allow the input to be an equals sign (`=`) followed by an expression. See the [meta item syntax](#meta-item-attribute-syntax) below for more details. +An attribute may be unsafe to apply. To avoid undefined behavior when using +these attributes, certain obligations that cannot be checked by the compiler +must be met. To assert these have been, the attribute is wrapped in +`unsafe(..)`, e.g. `#[unsafe(no_mangle)]`. + +The following attributes are unsafe: + +* [`export_name`] +* [`link_section`] +* [`no_mangle`] + Attributes can be classified into the following kinds: * [Built-in attributes] diff --git a/src/unsafe-keyword.md b/src/unsafe-keyword.md index df68a74cc..20aa1aa56 100644 --- a/src/unsafe-keyword.md +++ b/src/unsafe-keyword.md @@ -1,10 +1,10 @@ # The `unsafe` keyword The `unsafe` keyword can occur in several different contexts: -unsafe functions (`unsafe fn`), unsafe blocks (`unsafe {}`), unsafe traits (`unsafe trait`), unsafe trait implementations (`unsafe impl`), and unsafe external blocks (`unsafe extern`). +unsafe functions (`unsafe fn`), unsafe blocks (`unsafe {}`), unsafe traits (`unsafe trait`), unsafe trait implementations (`unsafe impl`), unsafe external blocks (`unsafe extern`), and unsafe attributes (`#[unsafe(attr)]`). It plays several different roles, depending on where it is used and whether the `unsafe_op_in_unsafe_fn` lint is enabled: - it is used to mark code that *defines* extra safety conditions (`unsafe fn`, `unsafe trait`) -- it is used to mark code that needs to *satisfy* extra safety conditions (`unsafe {}`, `unsafe impl`, `unsafe fn` without [`unsafe_op_in_unsafe_fn`], `unsafe extern`) +- it is used to mark code that needs to *satisfy* extra safety conditions (`unsafe {}`, `unsafe impl`, `unsafe fn` without [`unsafe_op_in_unsafe_fn`], `unsafe extern`, `#[unsafe(attr)]`) The following discusses each of these cases. See the [keyword documentation][keyword] for some illustrative examples. @@ -62,3 +62,9 @@ Unsafe trait implementations are the logical dual to unsafe traits: where unsafe The programmer who declares an [external block] must assure that the signatures of the items contained within are correct. Failing to do so may lead to undefined behavior. That this obligation has been met is indicated by writing `unsafe extern`. [external block]: items/external-blocks.md + +## Unsafe attributes (`#[unsafe(attr)]`) + +An [unsafe attribute] is one that has extra safety conditions that must be upheld when using the attribute. The compiler cannot check whether these conditions have been upheld. To assert that they have been, these attributes must be wrapped in `unsafe(..)`, e.g. `#[unsafe(no_mangle)]`. + +[unsafe attribute]: attributes.md diff --git a/src/unsafety.md b/src/unsafety.md index 237a4bfec..9383eba9d 100644 --- a/src/unsafety.md +++ b/src/unsafety.md @@ -12,6 +12,7 @@ Rust: - Calling an unsafe function (including an intrinsic or foreign function). - Implementing an [unsafe trait]. - Declaring an [`extern`] block. +- Applying an [unsafe attribute] to an item. [`extern`]: items/external-blocks.md [`union`]: items/unions.md @@ -19,3 +20,4 @@ Rust: [external]: items/external-blocks.md [raw pointer]: types/pointer.md [unsafe trait]: items/traits.md#unsafe-traits +[unsafe attribute]: attributes.md