From cc225e1c6476d1b19bd27d6ec4eb5fc30a107265 Mon Sep 17 00:00:00 2001 From: "Robert C. Seacord" Date: Fri, 2 Jan 2026 16:15:32 -0500 Subject: [PATCH 1/9] Add guideline: assure visibility of unsafe tokens in unsafe code --- .../attributes/gui_ZDLZzjeOwLSU.rst.inc | 64 +++++++++++++++++++ src/coding-guidelines/attributes/index.rst | 2 + 2 files changed, 66 insertions(+) create mode 100644 src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc diff --git a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc new file mode 100644 index 000000000..c208a8bee --- /dev/null +++ b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc @@ -0,0 +1,64 @@ +.. SPDX-License-Identifier: MIT OR Apache-2.0 + SPDX-FileCopyrightText: The Coding Guidelines Subcommittee Contributors + +.. guideline:: Use at least Rust Edition 2024 + :id: gui_ZDLZzjeOwLSU + :category: required + :status: draft + :release: 1.85-latest + :fls: fls_8kqo952gjhaf + :decidability: decidable + :scope: crate + :tags: readability,reduce-human-error + + Use at least Rust Edition 2024 to enforce ``unsafe`` tokens must be made visible in all locations where the compiler is aware an ``unsafe`` obligation extends to the code. + + .. rationale:: + :id: rat_eQV3s9ggNegr + :status: draft + + In Rust Edition 2024, several forms of code which involved explicit usage of ``unsafe`` tokens in new locations (attributes and ``extern`` blocks) were made mandatory. Due to backwards compatibility concerns, these did not previously require ``unsafe``. Some cases involving ``unsafe`` attributes were still linted against in some previous Rust versions by the ``unsafe_code`` lint, after it was discovered they had safety concerns, but due to backwards compatibility concerns they did not initially require use of a visible ``unsafe`` token. In Rust Edition 2024, however, it is both possible and required to use ``unsafe`` appropriately in these contexts. + + .. non_compliant_example:: + :id: non_compl_ex_FdmuPXGZr4EO + :status: draft + + An ``extern`` block can cause UB if it is misdeclared. This applies even if the definitions are not called, as the wrong definition may still prevail, especially after linking is considered. + + .. rust-example:: + + use std::ffi; + + // If another function by this name is in the compiled object's namespace, + // Rust allows undefined behavior from the program linker or loader. + // An `unsafe` token is not required in Rust 2021, though it is linted as such. + #[no_mangle] + fn something() {} + + extern "C" { + // If malloc in the compiled object's namespace accepts a usize argument, + // the compiler may generate code for calls to this function using this definition, + // thus the runtime behavior is undefined. + fn malloc(size: f32) -> *mut ffi::c_void; + } + + + .. compliant_example:: + :id: compl_ex_wR1FEyLRKmrq + :status: draft + + Using at least Rust Edition 2024 enforces that these things that involve safety obligations require the ``unsafe`` token. + + .. rust-example:: + + use std::ffi; + + #[unsafe(no_mangle)] + fn something() {} + + unsafe extern "C" { + // Here the assumption is that malloc is the one defined by C's stdlib.h + // and that size_of::() == size_of::() + fn malloc(size: usize) -> *mut ffi::c_void; + fn free(ptr: *mut ffi::c_void); + } diff --git a/src/coding-guidelines/attributes/index.rst b/src/coding-guidelines/attributes/index.rst index f952c3d4b..3d825b326 100644 --- a/src/coding-guidelines/attributes/index.rst +++ b/src/coding-guidelines/attributes/index.rst @@ -5,3 +5,5 @@ Attributes ========== + +.. include:: gui_ZDLZzjeOwLSU.rst.inc From 94ef37896f77b77ea2f6b2872a96c958c97f986d Mon Sep 17 00:00:00 2001 From: "Robert C. Seacord" Date: Fri, 2 Jan 2026 17:08:50 -0500 Subject: [PATCH 2/9] Revise guideline for unsafe token visibility Updated guideline to ensure visibility of unsafe tokens in unsafe code, reflecting changes in Rust Edition 2024. Added rationale and examples to clarify requirements. --- .../attributes/gui_ZDLZzjeOwLSU.rst.inc | 114 +++++++++++++++++- 1 file changed, 109 insertions(+), 5 deletions(-) diff --git a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc index c208a8bee..0dfc42888 100644 --- a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc +++ b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc @@ -1,7 +1,7 @@ .. SPDX-License-Identifier: MIT OR Apache-2.0 SPDX-FileCopyrightText: The Coding Guidelines Subcommittee Contributors -.. guideline:: Use at least Rust Edition 2024 +.. guideline:: Assure visibility of ``unsafe`` tokens in unsafe code :id: gui_ZDLZzjeOwLSU :category: required :status: draft @@ -9,21 +9,68 @@ :fls: fls_8kqo952gjhaf :decidability: decidable :scope: crate - :tags: readability,reduce-human-error + :tags: readability, reduce-human-error - Use at least Rust Edition 2024 to enforce ``unsafe`` tokens must be made visible in all locations where the compiler is aware an ``unsafe`` obligation extends to the code. + Assure visibility of ``unsafe`` tokens in all locations where the compiler is aware an ``unsafe`` obligation extends to the code. + + In Rust Edition 2024 :cite:`gui_aB3cDe4fGh5i:RUST-EDITION-GUIDE`, several forms of code which involved explicit usage of ``unsafe`` tokens + were made mandatory in attributes and ``extern`` blocks :cite:`gui_jK6lMn7oPq8r:RUST-REF-UNSAFE-KEYWORD`. + Prior Rust editions did not require an ``unsafe`` in these locations. + Some cases involving ``unsafe`` attributes were still linted against in some previous Rust versions by the ``unsafe_code`` lint + :cite:`gui_sT9uVw0xYz1a:RUST-LINT-UNSAFE`, + after it was discovered they had safety concerns, + but due to backwards compatibility concerns they did not initially require use of a visible ``unsafe`` token. + Starting with Rust Edition 2024, the use ``unsafe`` is required in these contexts. + + Rust 1.82 enabled use of ``unsafe`` around attributes: https://github.com/rust-lang/blog.rust-lang.org/blob/27e63bd0c2e68dd8b4eb06b67194cc4c2a9e84be/posts/2024-10-17-Rust-1.82.0.md#unsafe-attributes + + It also included unsafe extern on stable: https://github.com/rust-lang/blog.rust-lang.org/blob/main/content/Rust-1.82.0.md#safe-items-with-unsafe-extern + + Unfortunately, it seems we never started warning about ``unsafe_code`` for two attributes, oddly enough: ``link`` and ``link_ordinal``. + + I believe those attributes require themselves to be on ``extern "C"`` blocks, so they are implicitly covered by unsafe extern. + + Each of the attributes referenced by this issue must be explicitly marked unsafe as well as ``extern "C" {}`` blocks: rust-lang/rust#82499 .. rationale:: :id: rat_eQV3s9ggNegr :status: draft - In Rust Edition 2024, several forms of code which involved explicit usage of ``unsafe`` tokens in new locations (attributes and ``extern`` blocks) were made mandatory. Due to backwards compatibility concerns, these did not previously require ``unsafe``. Some cases involving ``unsafe`` attributes were still linted against in some previous Rust versions by the ``unsafe_code`` lint, after it was discovered they had safety concerns, but due to backwards compatibility concerns they did not initially require use of a visible ``unsafe`` token. In Rust Edition 2024, however, it is both possible and required to use ``unsafe`` appropriately in these contexts. + * Auditability and Review + * ``unsafe`` blocks create clear audit boundaries where reviewers can focus attention on code that may + violate safety guarantees :cite:`gui_bC2dEf3gHi4j:RUSTNOMICON-MEET-SAFE` + * Safety-critical standards like ISO 26262 :cite:`gui_kL5mNo6pQr7s:ISO-26262` and DO-178C :cite:`gui_tU8vWx9yZa0b:DO-178C` require traceability of hazardous operations + * Helps enumerate and document all places where safety requirements must be manually upheld + + * Explicit Acknowledgment of Responsibility + + * The ``unsafe`` keyword signals that the programmer is taking responsibility for upholding invariants the compiler cannot verify + * Prevents accidental use of ``unsafe`` operations without conscious decision + * Aligns with the principle of "defense in depth" in safety-critical systems + + * Visibility + + * Encouraging visibility discourages hiding unsafe operations inside safe-looking abstractions without proper encapsulation + + * Static Analysis and Tooling + + * Tools like ``cargo-geiger`` :cite:`gui_cD3eGh4iJk5l:CARGO-GEIGER`, ``unsafe-inspect``, and custom linters can automatically locate and count unsafe blocks + * Enables metrics like "unsafe density" for safety assessments + * Supports qualification evidence required by certification standards + + * Traceability for Certification + + * Safety-critical certifications require demonstrating that hazardous operations are identified and controlled + * Visible ``unsafe`` tokens provide direct linkage to safety cases and hazard analyses + * Facilitates the required documentation that each unsafe operation has been reviewed and justified .. non_compliant_example:: :id: non_compl_ex_FdmuPXGZr4EO :status: draft - An ``extern`` block can cause UB if it is misdeclared. This applies even if the definitions are not called, as the wrong definition may still prevail, especially after linking is considered. + An ``extern`` block can cause undefined behavior if it is misdeclared :cite:`gui_jK6lMn7oPq8r:RUST-REF-UNSAFE-KEYWORD`. + This applies even if the definitions are not called, as the wrong definition may still prevail, + especially after linking is considered. .. rust-example:: @@ -42,6 +89,19 @@ fn malloc(size: f32) -> *mut ffi::c_void; } + fn main() { + // Call the no_mangle function + something(); + + // Call the extern function (requires unsafe block) + unsafe { + let ptr = malloc(1024.0); + if !ptr.is_null() { + // In a real program, we'd use the allocated memory here + // and then free it with libc::free + println!("malloc returned: {:?}", ptr); + } + } .. compliant_example:: :id: compl_ex_wR1FEyLRKmrq @@ -62,3 +122,47 @@ fn malloc(size: usize) -> *mut ffi::c_void; fn free(ptr: *mut ffi::c_void); } + .. bibliography:: + :id: bib_WNCi5njUWLuZ + :status: draft + + .. list-table:: + :header-rows: 0 + :widths: auto + :class: bibliography-table + + * - :bibentry:`gui_aB3cDe4fGh5i:RUST-EDITION-GUIDE` + - The Rust Edition Guide. "Rust 2024." https://doc.rust-lang.org/edition-guide/rust-2024/index.html. + + * - :bibentry:`gui_jK6lMn7oPq8r:RUST-REF-UNSAFE-KEYWORD` + - The Rust Reference. "Unsafe Keyword." https://doc.rust-lang.org/reference/unsafe-keyword.html. + + * - :bibentry:`gui_sT9uVw0xYz1a:RUST-LINT-UNSAFE` + - Rust Compiler Lint Documentation. "unsafe_code." https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unsafe-code. + + * - :bibentry:`gui_bC2dEf3gHi4j:RUSTNOMICON-MEET-SAFE` + - The Rustonomicon. "Meet Safe and Unsafe." https://doc.rust-lang.org/nomicon/meet-safe-and-unsafe.html. + + * - :bibentry:`gui_kL5mNo6pQr7s:ISO-26262` + - International Organization for Standardization. "ISO 26262 - Road vehicles - Functional safety." https://www.iso.org/standard/68383.html. + + * - :bibentry:`gui_tU8vWx9yZa0b:DO-178C` + - RTCA, Inc. "DO-178C: Software Considerations in Airborne Systems and Equipment Certification." https://store.accuristech.com/standards/rtca-do-178c. + + * - :bibentry:`gui_cD3eGh4iJk5l:CARGO-GEIGER` + - cargo-geiger contributors. "cargo-geiger: Detects usage of unsafe Rust." https://github.com/geiger-rs/cargo-geiger. + + * - :bibentry:`gui_mN6oQp7rSt8u:RUST-REF-EXTERN` + - The Rust Reference. "External blocks." https://doc.rust-lang.org/reference/items/external-blocks.html. + + * - :bibentry:`gui_vW9xYz0aAb1c:RUST-REF-UNSAFE-ATTR` + - The Rust Reference. "Unsafe attributes." https://doc.rust-lang.org/reference/attributes.html#unsafe-attributes. + + * - :bibentry:`gui_dE2fGh3iJk4l:FERROCENE-SPEC` + - Ferrocene GmbH. "Ferrocene Language Specification." https://spec.ferrocene.dev/. + + * - :bibentry:`gui_0cuTYG8RVYjg:RUST-REF-UNION` + - The Rust Reference. "Unions." https://doc.rust-lang.org/reference/items/unions.html. + + * - :bibentry:`gui_0cuTYG8RVYjg:UCG-VALIDITY` + - Rust Unsafe Code Guidelines. "Validity and Safety Invariant." https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#validity-and-safety-invariant. From e86070747fd07f631face7aeaff4cd26a17f916d Mon Sep 17 00:00:00 2001 From: "Robert C. Seacord" Date: Fri, 2 Jan 2026 20:58:19 -0500 Subject: [PATCH 3/9] Revise guideline for 'unsafe' keyword visibility Update guideline to ensure visibility of 'unsafe' keyword in unsafe code, reflecting changes in Rust Edition 2024. --- .../attributes/gui_ZDLZzjeOwLSU.rst.inc | 272 ++++++++++++++---- 1 file changed, 219 insertions(+), 53 deletions(-) diff --git a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc index 0dfc42888..7b1f0a668 100644 --- a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc +++ b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc @@ -1,7 +1,7 @@ .. SPDX-License-Identifier: MIT OR Apache-2.0 SPDX-FileCopyrightText: The Coding Guidelines Subcommittee Contributors -.. guideline:: Assure visibility of ``unsafe`` tokens in unsafe code +.. guideline:: Assure visibility of ``unsafe`` keyword in unsafe code :id: gui_ZDLZzjeOwLSU :category: required :status: draft @@ -11,97 +11,155 @@ :scope: crate :tags: readability, reduce-human-error - Assure visibility of ``unsafe`` tokens in all locations where the compiler is aware an ``unsafe`` obligation extends to the code. + Mark all code that may violate safety guarantees with a visible ``unsafe`` keyword :cite:`gui_jK6lMn7oPq8r:RUST-REF-UNSAFE-KEYWORD`. + + The following constructs require explicit ``unsafe`` visibility: - In Rust Edition 2024 :cite:`gui_aB3cDe4fGh5i:RUST-EDITION-GUIDE`, several forms of code which involved explicit usage of ``unsafe`` tokens - were made mandatory in attributes and ``extern`` blocks :cite:`gui_jK6lMn7oPq8r:RUST-REF-UNSAFE-KEYWORD`. - Prior Rust editions did not require an ``unsafe`` in these locations. - Some cases involving ``unsafe`` attributes were still linted against in some previous Rust versions by the ``unsafe_code`` lint - :cite:`gui_sT9uVw0xYz1a:RUST-LINT-UNSAFE`, - after it was discovered they had safety concerns, - but due to backwards compatibility concerns they did not initially require use of a visible ``unsafe`` token. - Starting with Rust Edition 2024, the use ``unsafe`` is required in these contexts. + * ``extern`` blocks must be declared as ``unsafe extern`` + * The ``#[no_mangle]`` attribute must be written as ``#[unsafe(no_mangle)]`` + * The ``#[export_name]`` attribute must be written as ``#[unsafe(export_name)]`` + * The ``#[link_section]`` attribute must be written as ``#[unsafe(link_section)]`` - Rust 1.82 enabled use of ``unsafe`` around attributes: https://github.com/rust-lang/blog.rust-lang.org/blob/27e63bd0c2e68dd8b4eb06b67194cc4c2a9e84be/posts/2024-10-17-Rust-1.82.0.md#unsafe-attributes + .. note:: - It also included unsafe extern on stable: https://github.com/rust-lang/blog.rust-lang.org/blob/main/content/Rust-1.82.0.md#safe-items-with-unsafe-extern - - Unfortunately, it seems we never started warning about ``unsafe_code`` for two attributes, oddly enough: ``link`` and ``link_ordinal``. - - I believe those attributes require themselves to be on ``extern "C"`` blocks, so they are implicitly covered by unsafe extern. - - Each of the attributes referenced by this issue must be explicitly marked unsafe as well as ``extern "C" {}`` blocks: rust-lang/rust#82499 + Starting with Rust Edition 2024, the use of ``unsafe`` is required in these contexts. + The ``#[link]`` and ``#[link_ordinal]`` attributes are implicitly covered by the + ``unsafe extern`` requirement, as they must appear on ``extern`` blocks. + See rust-lang/rust#82499 for the tracking issue on unsafe attributes. .. rationale:: :id: rat_eQV3s9ggNegr :status: draft * Auditability and Review - * ``unsafe`` blocks create clear audit boundaries where reviewers can focus attention on code that may - violate safety guarantees :cite:`gui_bC2dEf3gHi4j:RUSTNOMICON-MEET-SAFE` - * Safety-critical standards like ISO 26262 :cite:`gui_kL5mNo6pQr7s:ISO-26262` and DO-178C :cite:`gui_tU8vWx9yZa0b:DO-178C` require traceability of hazardous operations - * Helps enumerate and document all places where safety requirements must be manually upheld + + * ``unsafe`` blocks create clear audit boundaries where reviewers can focus on code that may violate Rust's safety guarantees :cite:`gui_bC2dEf3gHi4j:RUSTNOMICON-MEET-SAFE` + * Safety-critical standards like ISO 26262 :cite:`gui_kL5mNo6pQr7s:ISO-26262` and DO-178C :cite:`gui_tU8vWx9yZa0b:DO-178C` require traceability of hazardous operations + * Helps enumerate and document all places where safety requirements must be manually upheld + * Satisfies ISO 26262 Part 6, Table 1, objective 1c (use of language subsets) + * Satisfies DO-178C Section 6.3.4.f (source code traceability) * Explicit Acknowledgment of Responsibility - * The ``unsafe`` keyword signals that the programmer is taking responsibility for upholding invariants the compiler cannot verify - * Prevents accidental use of ``unsafe`` operations without conscious decision - * Aligns with the principle of "defense in depth" in safety-critical systems + * The ``unsafe`` keyword signals that the programmer is taking responsibility for upholding invariants the compiler cannot verify + * Prevents accidental use of ``unsafe`` operations without conscious decision + * Aligns with the principle of "defense in depth" in safety-critical systems * Visibility - * Encouraging visibility discourages hiding unsafe operations inside safe-looking abstractions without proper encapsulation + * Encouraging visibility discourages hiding unsafe operations inside safe-looking abstractions without proper encapsulation + * Macros that expand to unsafe code should preserve the ``unsafe`` token visibility * Static Analysis and Tooling - * Tools like ``cargo-geiger`` :cite:`gui_cD3eGh4iJk5l:CARGO-GEIGER`, ``unsafe-inspect``, and custom linters can automatically locate and count unsafe blocks - * Enables metrics like "unsafe density" for safety assessments - * Supports qualification evidence required by certification standards + * Tools like ``cargo-geiger`` :cite:`gui_cD3eGh4iJk5l:CARGO-GEIGER`, ``unsafe-inspect``, and custom linters can automatically locate and count unsafe blocks + * Enables metrics like "unsafe density" for safety assessments + * Supports qualification evidence required by certification standards * Traceability for Certification - * Safety-critical certifications require demonstrating that hazardous operations are identified and controlled - * Visible ``unsafe`` tokens provide direct linkage to safety cases and hazard analyses - * Facilitates the required documentation that each unsafe operation has been reviewed and justified + * Safety-critical certifications require demonstrating that hazardous operations are identified and controlled + * Visible ``unsafe`` tokens provide direct linkage to safety cases and hazard analyses + * Facilitates the required documentation that each unsafe operation has been reviewed and justified + + .. non_compliant_example:: + :id: non_compl_ex_FdmuPXGZr4EP + :status: draft + + The ``#[no_mangle]`` attribute is unsafe because it can be used to declare a + function identifier that conflicts with an existing symbol. + This noncompliant example declares an unmangled function named 'malloc'. + This identifier may conflict with the 'malloc' function from C, + if the C library is linked with the executable. + + This noncompliant example requires Rust Edition 2021 or earlier to compile. + + .. rust-example:: + + // Undefined behavior by the linker or loader is possible + // if another 'something' function is defined. + #[no_mangle] + fn malloc() {} + + fn main() { + // Call the unmangled function + malloc(); + } .. non_compliant_example:: :id: non_compl_ex_FdmuPXGZr4EO :status: draft - An ``extern`` block can cause undefined behavior if it is misdeclared :cite:`gui_jK6lMn7oPq8r:RUST-REF-UNSAFE-KEYWORD`. - This applies even if the definitions are not called, as the wrong definition may still prevail, - especially after linking is considered. + This noncompliant example misdeclares the ``malloc`` function in the ``extern "C"`` block + specifying the type of ``size`` parameter as ``f32`` instead of ``usize``. + + An ``extern`` block is unsafe because undefined behavior can occur if types or functions are misdeclared. + This is true even if these types or functions are not used. + This noncompliant example requires Rust Edition 2021 or earlier to compile. .. rust-example:: use std::ffi; - // If another function by this name is in the compiled object's namespace, - // Rust allows undefined behavior from the program linker or loader. - // An `unsafe` token is not required in Rust 2021, though it is linted as such. - #[no_mangle] - fn something() {} - extern "C" { - // If malloc in the compiled object's namespace accepts a usize argument, - // the compiler may generate code for calls to this function using this definition, - // thus the runtime behavior is undefined. + // If 'malloc' is otherwise defined with a 'usize' argument, the compiler + // may generate code for calls to this function using this incompatible declaration, + // resulting in undefined behavior. fn malloc(size: f32) -> *mut ffi::c_void; } fn main() { - // Call the no_mangle function - something(); - - // Call the extern function (requires unsafe block) + // Call the extern "C" function (requires an 'unsafe' block) unsafe { let ptr = malloc(1024.0); if !ptr.is_null() { - // In a real program, we'd use the allocated memory here - // and then free it with libc::free + // Use the allocated memory then free it with 'libc::free' println!("malloc returned: {:?}", ptr); } - } + } + } + + .. non_compliant_example:: + :id: non_compl_ex_Hk3mNp5qRs7t + :status: draft + + The ``#[export_name]`` and ``#[link_section]`` attributes can cause undefined behavior if misused, + as they affect symbol resolution and memory layout at link time. + Without the ``unsafe`` keyword, these hazards are not visible to reviewers or tools. + This noncompliant example requires Rust Edition 2021 or earlier to compile. + + .. rust-example:: + + // Missing unsafe marker - noncompliant in Rust 2024 + #[export_name = "custom_symbol"] + pub fn my_function() {} + + // Missing unsafe marker - noncompliant in Rust 2024 + #[link_section = ".custom_section"] + static DATA: u32 = 42; + + .. non_compliant_example:: + :id: non_compl_ex_Jm4oQr6sUv8w + :status: draft + + Macros that generate unsafe code without preserving the ``unsafe`` token visibility + obscure safety-critical code from auditors and static analysis tools. + + .. rust-example:: + + // This macro hides the unsafe token from callers - noncompliant + macro_rules! hidden_unsafe_call { + ($ptr:expr) => { + unsafe { *$ptr } + }; + } + + fn main() { + let x = 42; + let ptr = &x as *const i32; + // The unsafe operation is hidden from the caller + let val = hidden_unsafe_call!(ptr); + } .. compliant_example:: :id: compl_ex_wR1FEyLRKmrq @@ -122,6 +180,114 @@ fn malloc(size: usize) -> *mut ffi::c_void; fn free(ptr: *mut ffi::c_void); } + + fn main() { + // Call the no_mangle function (safe to call) + something(); + + // Call the extern functions (requires unsafe block) + unsafe { + let ptr = malloc(1024); + if !ptr.is_null() { + // Use the allocated memory... + free(ptr); + } + } + } + + .. compliant_example:: + :id: compl_ex_xY2zAb3cDe4f + :status: draft + + The ``#[export_name]`` and ``#[link_section]`` attributes must use the ``unsafe()`` wrapper + to make their safety implications visible. + + .. rust-example:: + + #[unsafe(export_name = "custom_symbol")] + pub fn my_function() {} + + #[unsafe(link_section = ".custom_section")] + static DATA: u32 = 42; + + .. compliant_example:: + :id: compl_ex_gH5iJk6lMn7o + :status: draft + + Macros that involve unsafe operations should require the caller to provide the ``unsafe`` + token, preserving visibility for auditors and tools. + + .. rust-example:: + + // This macro requires the caller to acknowledge the unsafe operation - compliant + macro_rules! unsafe_deref { + ($ptr:expr) => { + *$ptr + }; + } + + fn main() { + let x = 42; + let ptr = &x as *const i32; + // The unsafe operation is visible at the call site + let val = unsafe { unsafe_deref!(ptr) }; + } + + .. enforcement:: + :id: enf_pQ8rSt9uVw0x + :status: draft + + This guideline can be enforced through the following mechanisms: + + * **Rust Edition 2024**: Migrating to Rust Edition 2024 makes violations of this guideline + compilation errors for ``extern`` blocks and unsafe attributes. + + * **Compiler Lints**: Enable the following lints: + + * ``#![deny(unsafe_code)]`` - Denies all unsafe code (use ``#[allow(unsafe_code)]`` for justified exceptions) + * ``#![deny(unsafe_op_in_unsafe_fn)]`` - Requires explicit unsafe blocks within unsafe functions + * ``#![warn(unsafe_attr_outside_unsafe)]`` - Warns about unsafe attributes without the ``unsafe()`` wrapper (pre-2024) + + * **Static Analysis Tools**: + + * ``cargo-geiger`` - Counts and reports unsafe code usage + * ``cargo-audit`` - Checks for known vulnerabilities in dependencies + * Custom Clippy lints for project-specific requirements + + * **Code Review**: Manual review of all code containing ``unsafe`` tokens should be + part of the development process, with documented justification for each usage. + + .. exceptions:: + :id: exc_yZ1aAb2cDe3f + :status: draft + + Deviations from this guideline may be permitted under the following conditions: + + * **Legacy Code Migration**: When migrating pre-2024 code, a documented migration plan + with timeline for compliance is acceptable. + + * **Third-Party Dependencies**: Dependencies not under project control that violate this + guideline must be documented in the safety case with risk assessment. + + * **Performance-Critical Sections**: Where the ``unsafe`` wrapper syntax causes measurable + compilation overhead, document the deviation with benchmarks. + + All deviations require: + + 1. Written justification documenting why the deviation is necessary + 2. Risk assessment of the safety implications + 3. Approval from the project's safety authority + 4. Tracking in the project's deviation log + + .. related_guidelines:: + :id: rel_gH4iJk5lMn6o + :status: draft + + * Minimize the scope of unsafe blocks + * Document safety invariants for all unsafe code with ``// SAFETY:`` comments + * Prefer safe abstractions over raw unsafe code + * Use ``#![forbid(unsafe_code)]`` at crate level where possible, with explicit exceptions + .. bibliography:: :id: bib_WNCi5njUWLuZ :status: draft @@ -161,8 +327,8 @@ * - :bibentry:`gui_dE2fGh3iJk4l:FERROCENE-SPEC` - Ferrocene GmbH. "Ferrocene Language Specification." https://spec.ferrocene.dev/. - * - :bibentry:`gui_0cuTYG8RVYjg:RUST-REF-UNION` + * - :bibentry:`gui_eF3gHi4jKl5m:RUST-REF-UNION` - The Rust Reference. "Unions." https://doc.rust-lang.org/reference/items/unions.html. - * - :bibentry:`gui_0cuTYG8RVYjg:UCG-VALIDITY` + * - :bibentry:`gui_fG4hIj5kLm6n:UCG-VALIDITY` - Rust Unsafe Code Guidelines. "Validity and Safety Invariant." https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#validity-and-safety-invariant. From afa1cf4db17494de81bbb1cef01cb9f8485f31ac Mon Sep 17 00:00:00 2001 From: "Robert C. Seacord" Date: Fri, 2 Jan 2026 21:02:05 -0500 Subject: [PATCH 4/9] Fix formatting and update Rust examples in guidelines --- .../attributes/gui_ZDLZzjeOwLSU.rst.inc | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc index 7b1f0a668..144cda085 100644 --- a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc +++ b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc @@ -75,6 +75,7 @@ This noncompliant example requires Rust Edition 2021 or earlier to compile. .. rust-example:: + :compile_fail: // Undefined behavior by the linker or loader is possible // if another 'something' function is defined. @@ -98,26 +99,27 @@ This noncompliant example requires Rust Edition 2021 or earlier to compile. .. rust-example:: - - use std::ffi; - - extern "C" { - // If 'malloc' is otherwise defined with a 'usize' argument, the compiler - // may generate code for calls to this function using this incompatible declaration, - // resulting in undefined behavior. - fn malloc(size: f32) -> *mut ffi::c_void; - } - - fn main() { - // Call the extern "C" function (requires an 'unsafe' block) - unsafe { - let ptr = malloc(1024.0); - if !ptr.is_null() { - // Use the allocated memory then free it with 'libc::free' - println!("malloc returned: {:?}", ptr); - } - } - } + :compile_fail: + + use std::ffi; + + extern "C" { + // If 'malloc' is otherwise defined with a 'usize' argument, the compiler + // may generate code for calls to this function using this incompatible declaration, + // resulting in undefined behavior. + fn malloc(size: f32) -> *mut ffi::c_void; + } + + fn main() { + // Call the extern "C" function (requires an 'unsafe' block) + unsafe { + let ptr = malloc(1024.0); + if !ptr.is_null() { + // Use the allocated memory then free it with 'libc::free' + println!("malloc returned: {:?}", ptr); + } + } + } .. non_compliant_example:: :id: non_compl_ex_Hk3mNp5qRs7t From 7a9106b5090fe6254af295981c1b8429c6723ebd Mon Sep 17 00:00:00 2001 From: "Robert C. Seacord" Date: Fri, 2 Jan 2026 21:08:00 -0500 Subject: [PATCH 5/9] Update guidelines on unsafe attribute usage in Rust Clarify issues with using #[export_name] and #[link_section] attributes without unsafe wrappers in Rust 2024. --- .../attributes/gui_ZDLZzjeOwLSU.rst.inc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc index 144cda085..6b120a158 100644 --- a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc +++ b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc @@ -128,9 +128,22 @@ The ``#[export_name]`` and ``#[link_section]`` attributes can cause undefined behavior if misused, as they affect symbol resolution and memory layout at link time. Without the ``unsafe`` keyword, these hazards are not visible to reviewers or tools. + + This noncompliant example has two problems. + First, it uses an ``#[export_name]`` attribute without an unsafe wrapper. + This attribute controls the symbol name used during linking. + If another symbol with the same name exists, it causes undefined behavior. + Rust 2024 requires it to be marked ``unsafe``. + + The second problem is that this noncompliant example uses a ``#[link_section]`` attribute without unsafe wrapper. + This attribute places the item in a specific linker section. + Incorrect section placement can cause undefined behavior + (e.g., placing mutable data in read-only sections, or interfering with special sections like ``.init``). + This noncompliant example requires Rust Edition 2021 or earlier to compile. .. rust-example:: + :compile_fail: // Missing unsafe marker - noncompliant in Rust 2024 #[export_name = "custom_symbol"] From eb5bdadcf56fda770a825724b8f90c2c314bf154 Mon Sep 17 00:00:00 2001 From: "Robert C. Seacord" Date: Sat, 3 Jan 2026 13:49:58 -0500 Subject: [PATCH 6/9] Refactor guidelines for unsafe operations in Rust Removed visibility section and updated examples for compliance with Rust Edition 2024. Clarified unsafe usage in function declarations and attributes. --- .../attributes/gui_ZDLZzjeOwLSU.rst.inc | 165 +++++++----------- 1 file changed, 67 insertions(+), 98 deletions(-) diff --git a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc index 6b120a158..15e00e02a 100644 --- a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc +++ b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc @@ -45,14 +45,10 @@ * Prevents accidental use of ``unsafe`` operations without conscious decision * Aligns with the principle of "defense in depth" in safety-critical systems - * Visibility - - * Encouraging visibility discourages hiding unsafe operations inside safe-looking abstractions without proper encapsulation - * Macros that expand to unsafe code should preserve the ``unsafe`` token visibility - * Static Analysis and Tooling - * Tools like ``cargo-geiger`` :cite:`gui_cD3eGh4iJk5l:CARGO-GEIGER`, ``unsafe-inspect``, and custom linters can automatically locate and count unsafe blocks + * Tools like ``cargo-geiger`` :cite:`gui_cD3eGh4iJk5l:CARGO-GEIGER`, ``unsafe-inspect``, + and custom linters can automatically locate and count unsafe blocks * Enables metrics like "unsafe density" for safety assessments * Supports qualification evidence required by certification standards @@ -68,23 +64,43 @@ The ``#[no_mangle]`` attribute is unsafe because it can be used to declare a function identifier that conflicts with an existing symbol. - This noncompliant example declares an unmangled function named 'malloc'. - This identifier may conflict with the 'malloc' function from C, - if the C library is linked with the executable. + This noncompliant example declares an unmangled function named 'convert'. + This symbol may conflict with another 'convert' symbol defined in a different crate at link time, + resulting in undefined behavior. + It is even possible for an unmangled symbol to conflict with a mangled symbol. This noncompliant example requires Rust Edition 2021 or earlier to compile. .. rust-example:: - :compile_fail: +.. :compile_fail: // Undefined behavior by the linker or loader is possible - // if another 'something' function is defined. + // if another 'convert' function is defined. #[no_mangle] - fn malloc() {} + fn convert() {} fn main() { // Call the unmangled function - malloc(); + convert(); + } + + .. compliant_example:: + :id: compl_ex_wR1FEyLRKmrr + :status: draft + + Rust Edition 2024 enforces that the ``no_mangle`` attribute requires an ``unsafe`` keyword, + as shown in this compliant example. + + NOTE: This code can still have undefined behavior if the 'convert' function symbol is define more than once. + + .. rust-example:: + + #[unsafe(no_mangle)] // compliant. + fn convert() {} + + fn main() { + // Call the no_mangle function (safe to call) + convert(); } .. non_compliant_example:: @@ -99,7 +115,7 @@ This noncompliant example requires Rust Edition 2021 or earlier to compile. .. rust-example:: - :compile_fail: +.. :compile_fail: use std::ffi; @@ -121,74 +137,21 @@ } } - .. non_compliant_example:: - :id: non_compl_ex_Hk3mNp5qRs7t - :status: draft - - The ``#[export_name]`` and ``#[link_section]`` attributes can cause undefined behavior if misused, - as they affect symbol resolution and memory layout at link time. - Without the ``unsafe`` keyword, these hazards are not visible to reviewers or tools. - - This noncompliant example has two problems. - First, it uses an ``#[export_name]`` attribute without an unsafe wrapper. - This attribute controls the symbol name used during linking. - If another symbol with the same name exists, it causes undefined behavior. - Rust 2024 requires it to be marked ``unsafe``. - - The second problem is that this noncompliant example uses a ``#[link_section]`` attribute without unsafe wrapper. - This attribute places the item in a specific linker section. - Incorrect section placement can cause undefined behavior - (e.g., placing mutable data in read-only sections, or interfering with special sections like ``.init``). - - This noncompliant example requires Rust Edition 2021 or earlier to compile. - - .. rust-example:: - :compile_fail: - - // Missing unsafe marker - noncompliant in Rust 2024 - #[export_name = "custom_symbol"] - pub fn my_function() {} - - // Missing unsafe marker - noncompliant in Rust 2024 - #[link_section = ".custom_section"] - static DATA: u32 = 42; - - .. non_compliant_example:: - :id: non_compl_ex_Jm4oQr6sUv8w - :status: draft - - Macros that generate unsafe code without preserving the ``unsafe`` token visibility - obscure safety-critical code from auditors and static analysis tools. - - .. rust-example:: - - // This macro hides the unsafe token from callers - noncompliant - macro_rules! hidden_unsafe_call { - ($ptr:expr) => { - unsafe { *$ptr } - }; - } - - fn main() { - let x = 42; - let ptr = &x as *const i32; - // The unsafe operation is hidden from the caller - let val = hidden_unsafe_call!(ptr); - } - .. compliant_example:: :id: compl_ex_wR1FEyLRKmrq :status: draft - Using at least Rust Edition 2024 enforces that these things that involve safety obligations require the ``unsafe`` token. + Rust Edition 2024 enforces that ``extern "C"`` blocks require an ``unsafe`` keyword, + as shown in this compliant example. + + NOTE: This code can still have undefined behavior if the declared 'malloc' function is incompatible with + the actual definition of the 'malloc' function. To eliminate this undefined behavior, the declaration for + ``malloc`` used in this compliant example has been correct to accept one argument of type ``usize``. .. rust-example:: use std::ffi; - #[unsafe(no_mangle)] - fn something() {} - unsafe extern "C" { // Here the assumption is that malloc is the one defined by C's stdlib.h // and that size_of::() == size_of::() @@ -197,9 +160,6 @@ } fn main() { - // Call the no_mangle function (safe to call) - something(); - // Call the extern functions (requires unsafe block) unsafe { let ptr = malloc(1024); @@ -210,43 +170,52 @@ } } - .. compliant_example:: - :id: compl_ex_xY2zAb3cDe4f + .. non_compliant_example:: + :id: non_compl_ex_Hk3mNp5qRs7t :status: draft - The ``#[export_name]`` and ``#[link_section]`` attributes must use the ``unsafe()`` wrapper - to make their safety implications visible. + The ``#[export_name]`` and ``#[link_section]`` attributes can cause undefined behavior if misused, + as they affect symbol resolution and memory layout at link time. + Without the ``unsafe`` keyword, these hazards are not visible to reviewers or tools. + + This noncompliant example has two separate problems. + First, it uses an ``#[export_name]`` attribute without an unsafe wrapper. + This attribute controls the symbol name used during linking. + If another symbol with the same name exists, it causes undefined behavior. + Rust 2024 requires it to be marked ``unsafe``. + + The second problem is that this noncompliant example uses a ``#[link_section]`` attribute without unsafe wrapper. + This attribute places the item in a specific linker section. + Incorrect section placement can cause undefined behavior + (e.g., placing mutable data in read-only sections, or interfering with special sections like ``.init``). + + This noncompliant example requires Rust Edition 2021 or earlier to compile. .. rust-example:: + :compile_fail: - #[unsafe(export_name = "custom_symbol")] - pub fn my_function() {} + // Missing unsafe marker - noncompliant in Rust 2024 + #[export_name = "custom_symbol"] // error: unsafe attribute used without unsafe + pub fn my_function() {} - #[unsafe(link_section = ".custom_section")] + // Missing unsafe marker - noncompliant in Rust 2024 + #[link_section = ".custom_section"] // error: unsafe attribute used without unsafe static DATA: u32 = 42; .. compliant_example:: - :id: compl_ex_gH5iJk6lMn7o + :id: compl_ex_xY2zAb3cDe4f :status: draft - Macros that involve unsafe operations should require the caller to provide the ``unsafe`` - token, preserving visibility for auditors and tools. + The ``#[export_name]`` and ``#[link_section]`` attributes must use the ``unsafe()`` wrapper + to make their safety implications visible. .. rust-example:: - // This macro requires the caller to acknowledge the unsafe operation - compliant - macro_rules! unsafe_deref { - ($ptr:expr) => { - *$ptr - }; - } + #[unsafe(export_name = "custom_symbol")] + pub fn my_function() {} - fn main() { - let x = 42; - let ptr = &x as *const i32; - // The unsafe operation is visible at the call site - let val = unsafe { unsafe_deref!(ptr) }; - } + #[unsafe(link_section = ".custom_section")] + static DATA: u32 = 42; .. enforcement:: :id: enf_pQ8rSt9uVw0x From a6703e8d5dd945feadfe3b76ba1dd3553dad6820 Mon Sep 17 00:00:00 2001 From: "Robert C. Seacord" Date: Sat, 3 Jan 2026 19:42:59 -0500 Subject: [PATCH 7/9] Update guidelines for unsafe attributes in Rust Removed exceptions section and added safety notes for unsafe attributes. --- .../attributes/gui_ZDLZzjeOwLSU.rst.inc | 55 ++++++++----------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc index 15e00e02a..1d80cd1c3 100644 --- a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc +++ b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc @@ -81,7 +81,7 @@ fn main() { // Call the unmangled function - convert(); + convert() } .. compliant_example:: @@ -100,7 +100,7 @@ fn main() { // Call the no_mangle function (safe to call) - convert(); + convert() } .. non_compliant_example:: @@ -194,13 +194,17 @@ .. rust-example:: :compile_fail: - // Missing unsafe marker - noncompliant in Rust 2024 - #[export_name = "custom_symbol"] // error: unsafe attribute used without unsafe - pub fn my_function() {} + // Collides with the C library 'printf' function + #[export_name = "printf"] // noncompliant // Missing unsafe marker - noncompliant in Rust 2024 - #[link_section = ".custom_section"] // error: unsafe attribute used without unsafe - static DATA: u32 = 42; + #[unsafe(link_section = ".init_array")] // noncompliant + static DATA: u32 = 42; // Corrupts initialization table! + + fn main() { + printf("Hello, World"); + println!("DATA = {DATA}"); + } .. compliant_example:: :id: compl_ex_xY2zAb3cDe4f @@ -211,11 +215,22 @@ .. rust-example:: + // SAFETY: 'custom_symbol' does not conflict with any other symbol #[unsafe(export_name = "custom_symbol")] pub fn my_function() {} - #[unsafe(link_section = ".custom_section")] - static DATA: u32 = 42; + // SAFETY: Placing data in a specific section for embedded systems + #[unsafe(link_section = ".noinit")] + static mut PERSISTENT_DATA: [u8; 256] = [0; 256]; + + // SAFETY: Custom section for shared memory + #[unsafe(link_section = ".shared")] + static SHARED_BUFFER: [u8; 4096] = [0; 4096]; + + fn main() { + my_function(); + println!("DATA = {DATA}"); + } .. enforcement:: :id: enf_pQ8rSt9uVw0x @@ -241,28 +256,6 @@ * **Code Review**: Manual review of all code containing ``unsafe`` tokens should be part of the development process, with documented justification for each usage. - .. exceptions:: - :id: exc_yZ1aAb2cDe3f - :status: draft - - Deviations from this guideline may be permitted under the following conditions: - - * **Legacy Code Migration**: When migrating pre-2024 code, a documented migration plan - with timeline for compliance is acceptable. - - * **Third-Party Dependencies**: Dependencies not under project control that violate this - guideline must be documented in the safety case with risk assessment. - - * **Performance-Critical Sections**: Where the ``unsafe`` wrapper syntax causes measurable - compilation overhead, document the deviation with benchmarks. - - All deviations require: - - 1. Written justification documenting why the deviation is necessary - 2. Risk assessment of the safety implications - 3. Approval from the project's safety authority - 4. Tracking in the project's deviation log - .. related_guidelines:: :id: rel_gH4iJk5lMn6o :status: draft From e1044d54635587f961c0624d7e8e12c5d5d1cf26 Mon Sep 17 00:00:00 2001 From: Pete LeVasseur Date: Mon, 2 Feb 2026 07:30:52 +0900 Subject: [PATCH 8/9] fix: make unsafe attribute example 2024 compile-fail --- .../attributes/gui_ZDLZzjeOwLSU.rst.inc | 109 +++++++++--------- 1 file changed, 53 insertions(+), 56 deletions(-) diff --git a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc index 1d80cd1c3..d158266d1 100644 --- a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc +++ b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc @@ -2,16 +2,16 @@ SPDX-FileCopyrightText: The Coding Guidelines Subcommittee Contributors .. guideline:: Assure visibility of ``unsafe`` keyword in unsafe code - :id: gui_ZDLZzjeOwLSU - :category: required - :status: draft - :release: 1.85-latest - :fls: fls_8kqo952gjhaf - :decidability: decidable - :scope: crate - :tags: readability, reduce-human-error - - Mark all code that may violate safety guarantees with a visible ``unsafe`` keyword :cite:`gui_jK6lMn7oPq8r:RUST-REF-UNSAFE-KEYWORD`. + :id: gui_ZDLZzjeOwLSU + :category: required + :status: draft + :release: 1.85-latest + :fls: fls_8kqo952gjhaf + :decidability: decidable + :scope: crate + :tags: readability, reduce-human-error + + Mark all code that may violate safety guarantees with a visible ``unsafe`` keyword :cite:`gui_ZDLZzjeOwLSU:RUST-REF-UNSAFE-KEYWORD`. The following constructs require explicit ``unsafe`` visibility: @@ -33,8 +33,8 @@ * Auditability and Review - * ``unsafe`` blocks create clear audit boundaries where reviewers can focus on code that may violate Rust's safety guarantees :cite:`gui_bC2dEf3gHi4j:RUSTNOMICON-MEET-SAFE` - * Safety-critical standards like ISO 26262 :cite:`gui_kL5mNo6pQr7s:ISO-26262` and DO-178C :cite:`gui_tU8vWx9yZa0b:DO-178C` require traceability of hazardous operations + * ``unsafe`` blocks create clear audit boundaries where reviewers can focus on code that may violate Rust's safety guarantees :cite:`gui_ZDLZzjeOwLSU:RUSTNOMICON-MEET-SAFE` + * Safety-critical standards like ISO 26262 :cite:`gui_ZDLZzjeOwLSU:ISO-26262` and DO-178C :cite:`gui_ZDLZzjeOwLSU:DO-178C` require traceability of hazardous operations * Helps enumerate and document all places where safety requirements must be manually upheld * Satisfies ISO 26262 Part 6, Table 1, objective 1c (use of language subsets) * Satisfies DO-178C Section 6.3.4.f (source code traceability) @@ -47,7 +47,7 @@ * Static Analysis and Tooling - * Tools like ``cargo-geiger`` :cite:`gui_cD3eGh4iJk5l:CARGO-GEIGER`, ``unsafe-inspect``, + * Tools like ``cargo-geiger`` :cite:`gui_ZDLZzjeOwLSU:CARGO-GEIGER`, ``unsafe-inspect``, and custom linters can automatically locate and count unsafe blocks * Enables metrics like "unsafe density" for safety assessments * Supports qualification evidence required by certification standards @@ -70,9 +70,9 @@ It is even possible for an unmangled symbol to conflict with a mangled symbol. This noncompliant example requires Rust Edition 2021 or earlier to compile. + In Rust Edition 2024, missing ``unsafe`` wrappers cause compilation errors. .. rust-example:: -.. :compile_fail: // Undefined behavior by the linker or loader is possible // if another 'convert' function is defined. @@ -94,6 +94,7 @@ NOTE: This code can still have undefined behavior if the 'convert' function symbol is define more than once. .. rust-example:: + :miri: #[unsafe(no_mangle)] // compliant. fn convert() {} @@ -115,7 +116,7 @@ This noncompliant example requires Rust Edition 2021 or earlier to compile. .. rust-example:: -.. :compile_fail: + :miri: use std::ffi; @@ -149,6 +150,7 @@ ``malloc`` used in this compliant example has been correct to accept one argument of type ``usize``. .. rust-example:: + :miri: use std::ffi; @@ -192,17 +194,17 @@ This noncompliant example requires Rust Edition 2021 or earlier to compile. .. rust-example:: - :compile_fail: + :compile_fail: + :edition: 2024 // Collides with the C library 'printf' function #[export_name = "printf"] // noncompliant // Missing unsafe marker - noncompliant in Rust 2024 - #[unsafe(link_section = ".init_array")] // noncompliant + #[link_section = ".init_array"] // noncompliant static DATA: u32 = 42; // Corrupts initialization table! fn main() { - printf("Hello, World"); println!("DATA = {DATA}"); } @@ -214,6 +216,7 @@ to make their safety implications visible. .. rust-example:: + :miri: // SAFETY: 'custom_symbol' does not conflict with any other symbol #[unsafe(export_name = "custom_symbol")] @@ -232,41 +235,35 @@ println!("DATA = {DATA}"); } - .. enforcement:: - :id: enf_pQ8rSt9uVw0x - :status: draft - - This guideline can be enforced through the following mechanisms: + **Enforcement** + This guideline can be enforced through the following mechanisms: - * **Rust Edition 2024**: Migrating to Rust Edition 2024 makes violations of this guideline - compilation errors for ``extern`` blocks and unsafe attributes. + * **Rust Edition 2024**: Migrating to Rust Edition 2024 makes violations of this guideline + compilation errors for ``extern`` blocks and unsafe attributes. - * **Compiler Lints**: Enable the following lints: + * **Compiler Lints**: Enable the following lints: - * ``#![deny(unsafe_code)]`` - Denies all unsafe code (use ``#[allow(unsafe_code)]`` for justified exceptions) - * ``#![deny(unsafe_op_in_unsafe_fn)]`` - Requires explicit unsafe blocks within unsafe functions - * ``#![warn(unsafe_attr_outside_unsafe)]`` - Warns about unsafe attributes without the ``unsafe()`` wrapper (pre-2024) + * ``#![deny(unsafe_code)]`` - Denies all unsafe code (use ``#[allow(unsafe_code)]`` for justified exceptions) + * ``#![deny(unsafe_op_in_unsafe_fn)]`` - Requires explicit unsafe blocks within unsafe functions + * ``#![warn(unsafe_attr_outside_unsafe)]`` - Warns about unsafe attributes without the ``unsafe()`` wrapper (pre-2024) - * **Static Analysis Tools**: + * **Static Analysis Tools**: - * ``cargo-geiger`` - Counts and reports unsafe code usage - * ``cargo-audit`` - Checks for known vulnerabilities in dependencies - * Custom Clippy lints for project-specific requirements + * ``cargo-geiger`` - Counts and reports unsafe code usage + * ``cargo-audit`` - Checks for known vulnerabilities in dependencies + * Custom Clippy lints for project-specific requirements - * **Code Review**: Manual review of all code containing ``unsafe`` tokens should be - part of the development process, with documented justification for each usage. - - .. related_guidelines:: - :id: rel_gH4iJk5lMn6o - :status: draft + * **Code Review**: Manual review of all code containing ``unsafe`` tokens should be + part of the development process, with documented justification for each usage. - * Minimize the scope of unsafe blocks - * Document safety invariants for all unsafe code with ``// SAFETY:`` comments - * Prefer safe abstractions over raw unsafe code - * Use ``#![forbid(unsafe_code)]`` at crate level where possible, with explicit exceptions + **Related guidelines** + * Minimize the scope of unsafe blocks + * Document safety invariants for all unsafe code with ``// SAFETY:`` comments + * Prefer safe abstractions over raw unsafe code + * Use ``#![forbid(unsafe_code)]`` at crate level where possible, with explicit exceptions .. bibliography:: - :id: bib_WNCi5njUWLuZ + :id: bib_ZDLZzjeOwLSU :status: draft .. list-table:: @@ -274,38 +271,38 @@ :widths: auto :class: bibliography-table - * - :bibentry:`gui_aB3cDe4fGh5i:RUST-EDITION-GUIDE` + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-EDITION-GUIDE` - The Rust Edition Guide. "Rust 2024." https://doc.rust-lang.org/edition-guide/rust-2024/index.html. - * - :bibentry:`gui_jK6lMn7oPq8r:RUST-REF-UNSAFE-KEYWORD` + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-REF-UNSAFE-KEYWORD` - The Rust Reference. "Unsafe Keyword." https://doc.rust-lang.org/reference/unsafe-keyword.html. - * - :bibentry:`gui_sT9uVw0xYz1a:RUST-LINT-UNSAFE` + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-LINT-UNSAFE` - Rust Compiler Lint Documentation. "unsafe_code." https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unsafe-code. - * - :bibentry:`gui_bC2dEf3gHi4j:RUSTNOMICON-MEET-SAFE` + * - :bibentry:`gui_ZDLZzjeOwLSU:RUSTNOMICON-MEET-SAFE` - The Rustonomicon. "Meet Safe and Unsafe." https://doc.rust-lang.org/nomicon/meet-safe-and-unsafe.html. - * - :bibentry:`gui_kL5mNo6pQr7s:ISO-26262` + * - :bibentry:`gui_ZDLZzjeOwLSU:ISO-26262` - International Organization for Standardization. "ISO 26262 - Road vehicles - Functional safety." https://www.iso.org/standard/68383.html. - * - :bibentry:`gui_tU8vWx9yZa0b:DO-178C` + * - :bibentry:`gui_ZDLZzjeOwLSU:DO-178C` - RTCA, Inc. "DO-178C: Software Considerations in Airborne Systems and Equipment Certification." https://store.accuristech.com/standards/rtca-do-178c. - * - :bibentry:`gui_cD3eGh4iJk5l:CARGO-GEIGER` + * - :bibentry:`gui_ZDLZzjeOwLSU:CARGO-GEIGER` - cargo-geiger contributors. "cargo-geiger: Detects usage of unsafe Rust." https://github.com/geiger-rs/cargo-geiger. - * - :bibentry:`gui_mN6oQp7rSt8u:RUST-REF-EXTERN` + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-REF-EXTERN` - The Rust Reference. "External blocks." https://doc.rust-lang.org/reference/items/external-blocks.html. - * - :bibentry:`gui_vW9xYz0aAb1c:RUST-REF-UNSAFE-ATTR` + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-REF-UNSAFE-ATTR` - The Rust Reference. "Unsafe attributes." https://doc.rust-lang.org/reference/attributes.html#unsafe-attributes. - * - :bibentry:`gui_dE2fGh3iJk4l:FERROCENE-SPEC` + * - :bibentry:`gui_ZDLZzjeOwLSU:FERROCENE-SPEC` - Ferrocene GmbH. "Ferrocene Language Specification." https://spec.ferrocene.dev/. - * - :bibentry:`gui_eF3gHi4jKl5m:RUST-REF-UNION` + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-REF-UNION` - The Rust Reference. "Unions." https://doc.rust-lang.org/reference/items/unions.html. - * - :bibentry:`gui_fG4hIj5kLm6n:UCG-VALIDITY` + * - :bibentry:`gui_ZDLZzjeOwLSU:UCG-VALIDITY` - Rust Unsafe Code Guidelines. "Validity and Safety Invariant." https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#validity-and-safety-invariant. From fe6c44f72fb21ab8ede13360a6a13a30c128a3e7 Mon Sep 17 00:00:00 2001 From: Pete LeVasseur Date: Mon, 2 Feb 2026 08:45:04 +0900 Subject: [PATCH 9/9] fix: convert unsafe keyword guideline to .rst --- .../attributes/gui_ZDLZzjeOwLSU.rst | 299 +++++++++++++++++ .../attributes/gui_ZDLZzjeOwLSU.rst.inc | 308 ------------------ src/coding-guidelines/attributes/index.rst | 7 +- 3 files changed, 305 insertions(+), 309 deletions(-) create mode 100644 src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst delete mode 100644 src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc diff --git a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst new file mode 100644 index 000000000..925c6c702 --- /dev/null +++ b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst @@ -0,0 +1,299 @@ +.. SPDX-License-Identifier: MIT OR Apache-2.0 + SPDX-FileCopyrightText: The Coding Guidelines Subcommittee Contributors + +.. default-domain:: coding-guidelines + +Assure visibility of ``unsafe`` keyword in unsafe code +====================================================== + +.. guideline:: Assure visibility of ``unsafe`` keyword in unsafe code + :id: gui_ZDLZzjeOwLSU + :category: required + :status: draft + :release: 1.85-latest + :fls: fls_8kqo952gjhaf + :decidability: decidable + :scope: crate + :tags: readability, reduce-human-error + + Mark all code that may violate safety guarantees with a visible ``unsafe`` keyword + :cite:`gui_ZDLZzjeOwLSU:RUST-REF-UNSAFE-KEYWORD`. + + The following constructs require explicit ``unsafe`` visibility: + + * ``extern`` blocks must be declared as ``unsafe extern`` + * The ``#[no_mangle]`` attribute must be written as ``#[unsafe(no_mangle)]`` + * The ``#[export_name]`` attribute must be written as ``#[unsafe(export_name)]`` + * The ``#[link_section]`` attribute must be written as ``#[unsafe(link_section)]`` + + .. note:: + + Starting with Rust Edition 2024, the use of ``unsafe`` is required in these contexts. + The ``#[link]`` and ``#[link_ordinal]`` attributes are implicitly covered by the + ``unsafe extern`` requirement, as they must appear on ``extern`` blocks. + See rust-lang/rust#82499 for the tracking issue on unsafe attributes. + + .. rationale:: + :id: rat_eQV3s9ggNegr + :status: draft + + * Auditability and review + + * ``unsafe`` blocks create clear audit boundaries where reviewers can focus on code + that may violate Rust's safety guarantees :cite:`gui_ZDLZzjeOwLSU:RUSTNOMICON-MEET-SAFE` + * Safety-critical standards like ISO 26262 :cite:`gui_ZDLZzjeOwLSU:ISO-26262` and + DO-178C :cite:`gui_ZDLZzjeOwLSU:DO-178C` require traceability of hazardous operations + * Helps enumerate and document all places where safety requirements must be manually upheld + * Satisfies ISO 26262 Part 6, Table 1, objective 1c (use of language subsets) + * Satisfies DO-178C Section 6.3.4.f (source code traceability) + + * Explicit acknowledgment of responsibility + + * The ``unsafe`` keyword signals that the programmer is taking responsibility for + upholding invariants the compiler cannot verify + * Prevents accidental use of ``unsafe`` operations without conscious decision + * Aligns with the principle of defense in depth in safety-critical systems + + * Static analysis and tooling + + * Tools like ``cargo-geiger`` :cite:`gui_ZDLZzjeOwLSU:CARGO-GEIGER`, ``unsafe-inspect``, + and custom linters can automatically locate and count unsafe blocks + * Enables metrics like "unsafe density" for safety assessments + * Supports qualification evidence required by certification standards + + * Traceability for certification + + * Safety-critical certifications require demonstrating that hazardous operations are + identified and controlled + * Visible ``unsafe`` tokens provide direct linkage to safety cases and hazard analyses + * Facilitates the required documentation that each unsafe operation has been reviewed + and justified + + .. non_compliant_example:: + :id: non_compl_ex_FdmuPXGZr4EP + :status: draft + + The ``#[no_mangle]`` attribute is unsafe because it can be used to declare a function + identifier that conflicts with an existing symbol. This noncompliant example declares an + unmangled function named ``convert`` that is missing the required unsafe wrapper in Rust 2024. + + This noncompliant example requires Rust Edition 2021 or earlier to compile. + In Rust Edition 2024, missing ``unsafe`` wrappers cause compilation errors. + + .. rust-example:: + :compile_fail: + :edition: 2024 + + // Undefined behavior by the linker or loader is possible + // if another 'convert' function is defined. + #[no_mangle] + fn convert() {} + + fn main() { + convert(); + } + + .. compliant_example:: + :id: compl_ex_wR1FEyLRKmrr + :status: draft + + Rust Edition 2024 enforces that the ``no_mangle`` attribute requires an ``unsafe`` keyword, + as shown in this compliant example. + + NOTE: This code can still have undefined behavior if the ``convert`` function symbol is + defined more than once. + + .. rust-example:: + :miri: skip + :edition: 2024 + + #[unsafe(no_mangle)] // compliant + fn convert() {} + + fn main() { + convert(); + } + + .. non_compliant_example:: + :id: non_compl_ex_FdmuPXGZr4EO + :status: draft + + This noncompliant example misdeclares the ``malloc`` function in an ``extern "C"`` block + by specifying the type of the ``size`` parameter as ``f32`` instead of ``usize``. + + An ``extern`` block is unsafe because undefined behavior can occur if types or functions are + misdeclared. This is true even if the declarations are not used. This noncompliant example + requires Rust Edition 2021 or earlier to compile. + + .. rust-example:: + :compile_fail: + :edition: 2024 + + use std::ffi; + + extern "C" { + // If 'malloc' is otherwise defined with a 'usize' argument, the compiler + // may generate code for calls to this function using this incompatible declaration, + // resulting in undefined behavior. + fn malloc(size: f32) -> *mut ffi::c_void; + } + + fn main() {} + + .. compliant_example:: + :id: compl_ex_wR1FEyLRKmrq + :status: draft + + Rust Edition 2024 enforces that ``extern "C"`` blocks require an ``unsafe`` keyword, + as shown in this compliant example. + + NOTE: This code can still have undefined behavior if the declared ``malloc`` function is + incompatible with the actual definition. To eliminate this undefined behavior, the + declaration for ``malloc`` used in this compliant example accepts one argument of type ``usize``. + + .. rust-example:: + :miri: skip + :edition: 2024 + + use std::ffi; + + unsafe extern "C" { + // Here the assumption is that malloc is the one defined by C's stdlib.h + // and that size_of::() == size_of::() + fn malloc(size: usize) -> *mut ffi::c_void; + fn free(ptr: *mut ffi::c_void); + } + + fn main() { + unsafe { + let ptr = malloc(1024); + if !ptr.is_null() { + free(ptr); + } + } + } + + .. non_compliant_example:: + :id: non_compl_ex_Hk3mNp5qRs7t + :status: draft + + The ``#[export_name]`` and ``#[link_section]`` attributes can cause undefined behavior if + misused, as they affect symbol resolution and memory layout at link time. Without the + ``unsafe`` keyword, these hazards are not visible to reviewers or tools. + + This noncompliant example has two separate problems. First, it uses an ``#[export_name]`` + attribute without an unsafe wrapper. This attribute controls the symbol name used during + linking. If another symbol with the same name exists, it causes undefined behavior. + Rust 2024 requires it to be marked ``unsafe``. + + The second problem is that this noncompliant example uses a ``#[link_section]`` attribute + without an unsafe wrapper. This attribute places the item in a specific linker section. + Incorrect section placement can cause undefined behavior (e.g., placing mutable data in + read-only sections, or interfering with special sections like ``.init``). + + This noncompliant example requires Rust Edition 2021 or earlier to compile. + + .. rust-example:: + :compile_fail: + :edition: 2024 + + // Collides with the C library 'printf' function + #[export_name = "printf"] // noncompliant + + // Missing unsafe marker - noncompliant in Rust 2024 + #[link_section = ".init_array"] // noncompliant + static DATA: u32 = 42; // Corrupts initialization table! + + fn main() { + println!("DATA = {DATA}"); + } + + .. compliant_example:: + :id: compl_ex_xY2zAb3cDe4f + :status: draft + + The ``#[export_name]`` and ``#[link_section]`` attributes must use the ``unsafe()`` wrapper + to make their safety implications visible. + + .. rust-example:: + :miri: skip + :edition: 2024 + + // SAFETY: 'custom_symbol' does not conflict with any other symbol + #[unsafe(export_name = "custom_symbol")] + pub fn my_function() {} + + // SAFETY: Placing data in a specific section for embedded systems + #[unsafe(link_section = ".noinit")] + static mut PERSISTENT_DATA: [u8; 256] = [0; 256]; + + // SAFETY: Custom section for shared memory + #[unsafe(link_section = ".shared")] + static SHARED_BUFFER: [u8; 4096] = [0; 4096]; + + fn main() { + my_function(); + println!("shared buffer size = {}", SHARED_BUFFER.len()); + unsafe { let _ = PERSISTENT_DATA[0]; } + } + + **Enforcement** + This guideline can be enforced through the following mechanisms: + + * **Rust Edition 2024**: Migrating to Rust Edition 2024 makes violations of this guideline + compilation errors for ``extern`` blocks and unsafe attributes. + + * **Compiler Lints**: Enable the following lints: + + * ``#![deny(unsafe_code)]`` - Denies all unsafe code (use ``#[allow(unsafe_code)]`` for justified exceptions) + * ``#![deny(unsafe_op_in_unsafe_fn)]`` - Requires explicit unsafe blocks within unsafe functions + * ``#![warn(unsafe_attr_outside_unsafe)]`` - Warns about unsafe attributes without the ``unsafe()`` wrapper (pre-2024) + + * **Static Analysis Tools**: + + * ``cargo-geiger`` - Counts and reports unsafe code usage + * ``cargo-audit`` - Checks for known vulnerabilities in dependencies + * Custom Clippy lints for project-specific requirements + + * **Code Review**: Manual review of all code containing ``unsafe`` tokens should be + part of the development process, with documented justification for each usage. + + **Related guidelines** + * Minimize the scope of unsafe blocks + * Document safety invariants for all unsafe code with ``// SAFETY:`` comments + * Prefer safe abstractions over raw unsafe code + * Use ``#![forbid(unsafe_code)]`` at crate level where possible, with explicit exceptions + + .. bibliography:: + :id: bib_n8YJHvQf4mWx + :status: draft + + .. list-table:: + :header-rows: 0 + :widths: auto + :class: bibliography-table + + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-EDITION-GUIDE` + - The Rust Edition Guide. "Rust 2024." https://doc.rust-lang.org/edition-guide/rust-2024/index.html. + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-REF-UNSAFE-KEYWORD` + - The Rust Reference. "Unsafe Keyword." https://doc.rust-lang.org/reference/unsafe-keyword.html. + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-LINT-UNSAFE` + - Rust Compiler Lint Documentation. "unsafe_code." https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unsafe-code. + * - :bibentry:`gui_ZDLZzjeOwLSU:RUSTNOMICON-MEET-SAFE` + - The Rustonomicon. "Meet Safe and Unsafe." https://doc.rust-lang.org/nomicon/meet-safe-and-unsafe.html. + * - :bibentry:`gui_ZDLZzjeOwLSU:ISO-26262` + - International Organization for Standardization. "ISO 26262 - Road vehicles - Functional safety." https://www.iso.org/standard/68383.html. + * - :bibentry:`gui_ZDLZzjeOwLSU:DO-178C` + - RTCA, Inc. "DO-178C: Software Considerations in Airborne Systems and Equipment Certification." https://store.accuristech.com/standards/rtca-do-178c. + * - :bibentry:`gui_ZDLZzjeOwLSU:CARGO-GEIGER` + - cargo-geiger contributors. "cargo-geiger: Detects usage of unsafe Rust." https://github.com/geiger-rs/cargo-geiger. + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-REF-EXTERN` + - The Rust Reference. "External blocks." https://doc.rust-lang.org/reference/items/external-blocks.html. + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-REF-UNSAFE-ATTR` + - The Rust Reference. "Unsafe attributes." https://doc.rust-lang.org/reference/attributes.html#unsafe-attributes. + * - :bibentry:`gui_ZDLZzjeOwLSU:FERROCENE-SPEC` + - Ferrocene GmbH. "Ferrocene Language Specification." https://spec.ferrocene.dev/. + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-REF-UNION` + - The Rust Reference. "Unions." https://doc.rust-lang.org/reference/items/unions.html. + * - :bibentry:`gui_ZDLZzjeOwLSU:UCG-VALIDITY` + - Rust Unsafe Code Guidelines. "Validity and Safety Invariant." https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#validity-and-safety-invariant. diff --git a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc b/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc deleted file mode 100644 index d158266d1..000000000 --- a/src/coding-guidelines/attributes/gui_ZDLZzjeOwLSU.rst.inc +++ /dev/null @@ -1,308 +0,0 @@ -.. SPDX-License-Identifier: MIT OR Apache-2.0 - SPDX-FileCopyrightText: The Coding Guidelines Subcommittee Contributors - -.. guideline:: Assure visibility of ``unsafe`` keyword in unsafe code - :id: gui_ZDLZzjeOwLSU - :category: required - :status: draft - :release: 1.85-latest - :fls: fls_8kqo952gjhaf - :decidability: decidable - :scope: crate - :tags: readability, reduce-human-error - - Mark all code that may violate safety guarantees with a visible ``unsafe`` keyword :cite:`gui_ZDLZzjeOwLSU:RUST-REF-UNSAFE-KEYWORD`. - - The following constructs require explicit ``unsafe`` visibility: - - * ``extern`` blocks must be declared as ``unsafe extern`` - * The ``#[no_mangle]`` attribute must be written as ``#[unsafe(no_mangle)]`` - * The ``#[export_name]`` attribute must be written as ``#[unsafe(export_name)]`` - * The ``#[link_section]`` attribute must be written as ``#[unsafe(link_section)]`` - - .. note:: - - Starting with Rust Edition 2024, the use of ``unsafe`` is required in these contexts. - The ``#[link]`` and ``#[link_ordinal]`` attributes are implicitly covered by the - ``unsafe extern`` requirement, as they must appear on ``extern`` blocks. - See rust-lang/rust#82499 for the tracking issue on unsafe attributes. - - .. rationale:: - :id: rat_eQV3s9ggNegr - :status: draft - - * Auditability and Review - - * ``unsafe`` blocks create clear audit boundaries where reviewers can focus on code that may violate Rust's safety guarantees :cite:`gui_ZDLZzjeOwLSU:RUSTNOMICON-MEET-SAFE` - * Safety-critical standards like ISO 26262 :cite:`gui_ZDLZzjeOwLSU:ISO-26262` and DO-178C :cite:`gui_ZDLZzjeOwLSU:DO-178C` require traceability of hazardous operations - * Helps enumerate and document all places where safety requirements must be manually upheld - * Satisfies ISO 26262 Part 6, Table 1, objective 1c (use of language subsets) - * Satisfies DO-178C Section 6.3.4.f (source code traceability) - - * Explicit Acknowledgment of Responsibility - - * The ``unsafe`` keyword signals that the programmer is taking responsibility for upholding invariants the compiler cannot verify - * Prevents accidental use of ``unsafe`` operations without conscious decision - * Aligns with the principle of "defense in depth" in safety-critical systems - - * Static Analysis and Tooling - - * Tools like ``cargo-geiger`` :cite:`gui_ZDLZzjeOwLSU:CARGO-GEIGER`, ``unsafe-inspect``, - and custom linters can automatically locate and count unsafe blocks - * Enables metrics like "unsafe density" for safety assessments - * Supports qualification evidence required by certification standards - - * Traceability for Certification - - * Safety-critical certifications require demonstrating that hazardous operations are identified and controlled - * Visible ``unsafe`` tokens provide direct linkage to safety cases and hazard analyses - * Facilitates the required documentation that each unsafe operation has been reviewed and justified - - .. non_compliant_example:: - :id: non_compl_ex_FdmuPXGZr4EP - :status: draft - - The ``#[no_mangle]`` attribute is unsafe because it can be used to declare a - function identifier that conflicts with an existing symbol. - This noncompliant example declares an unmangled function named 'convert'. - This symbol may conflict with another 'convert' symbol defined in a different crate at link time, - resulting in undefined behavior. - It is even possible for an unmangled symbol to conflict with a mangled symbol. - - This noncompliant example requires Rust Edition 2021 or earlier to compile. - In Rust Edition 2024, missing ``unsafe`` wrappers cause compilation errors. - - .. rust-example:: - - // Undefined behavior by the linker or loader is possible - // if another 'convert' function is defined. - #[no_mangle] - fn convert() {} - - fn main() { - // Call the unmangled function - convert() - } - - .. compliant_example:: - :id: compl_ex_wR1FEyLRKmrr - :status: draft - - Rust Edition 2024 enforces that the ``no_mangle`` attribute requires an ``unsafe`` keyword, - as shown in this compliant example. - - NOTE: This code can still have undefined behavior if the 'convert' function symbol is define more than once. - - .. rust-example:: - :miri: - - #[unsafe(no_mangle)] // compliant. - fn convert() {} - - fn main() { - // Call the no_mangle function (safe to call) - convert() - } - - .. non_compliant_example:: - :id: non_compl_ex_FdmuPXGZr4EO - :status: draft - - This noncompliant example misdeclares the ``malloc`` function in the ``extern "C"`` block - specifying the type of ``size`` parameter as ``f32`` instead of ``usize``. - - An ``extern`` block is unsafe because undefined behavior can occur if types or functions are misdeclared. - This is true even if these types or functions are not used. - This noncompliant example requires Rust Edition 2021 or earlier to compile. - - .. rust-example:: - :miri: - - use std::ffi; - - extern "C" { - // If 'malloc' is otherwise defined with a 'usize' argument, the compiler - // may generate code for calls to this function using this incompatible declaration, - // resulting in undefined behavior. - fn malloc(size: f32) -> *mut ffi::c_void; - } - - fn main() { - // Call the extern "C" function (requires an 'unsafe' block) - unsafe { - let ptr = malloc(1024.0); - if !ptr.is_null() { - // Use the allocated memory then free it with 'libc::free' - println!("malloc returned: {:?}", ptr); - } - } - } - - .. compliant_example:: - :id: compl_ex_wR1FEyLRKmrq - :status: draft - - Rust Edition 2024 enforces that ``extern "C"`` blocks require an ``unsafe`` keyword, - as shown in this compliant example. - - NOTE: This code can still have undefined behavior if the declared 'malloc' function is incompatible with - the actual definition of the 'malloc' function. To eliminate this undefined behavior, the declaration for - ``malloc`` used in this compliant example has been correct to accept one argument of type ``usize``. - - .. rust-example:: - :miri: - - use std::ffi; - - unsafe extern "C" { - // Here the assumption is that malloc is the one defined by C's stdlib.h - // and that size_of::() == size_of::() - fn malloc(size: usize) -> *mut ffi::c_void; - fn free(ptr: *mut ffi::c_void); - } - - fn main() { - // Call the extern functions (requires unsafe block) - unsafe { - let ptr = malloc(1024); - if !ptr.is_null() { - // Use the allocated memory... - free(ptr); - } - } - } - - .. non_compliant_example:: - :id: non_compl_ex_Hk3mNp5qRs7t - :status: draft - - The ``#[export_name]`` and ``#[link_section]`` attributes can cause undefined behavior if misused, - as they affect symbol resolution and memory layout at link time. - Without the ``unsafe`` keyword, these hazards are not visible to reviewers or tools. - - This noncompliant example has two separate problems. - First, it uses an ``#[export_name]`` attribute without an unsafe wrapper. - This attribute controls the symbol name used during linking. - If another symbol with the same name exists, it causes undefined behavior. - Rust 2024 requires it to be marked ``unsafe``. - - The second problem is that this noncompliant example uses a ``#[link_section]`` attribute without unsafe wrapper. - This attribute places the item in a specific linker section. - Incorrect section placement can cause undefined behavior - (e.g., placing mutable data in read-only sections, or interfering with special sections like ``.init``). - - This noncompliant example requires Rust Edition 2021 or earlier to compile. - - .. rust-example:: - :compile_fail: - :edition: 2024 - - // Collides with the C library 'printf' function - #[export_name = "printf"] // noncompliant - - // Missing unsafe marker - noncompliant in Rust 2024 - #[link_section = ".init_array"] // noncompliant - static DATA: u32 = 42; // Corrupts initialization table! - - fn main() { - println!("DATA = {DATA}"); - } - - .. compliant_example:: - :id: compl_ex_xY2zAb3cDe4f - :status: draft - - The ``#[export_name]`` and ``#[link_section]`` attributes must use the ``unsafe()`` wrapper - to make their safety implications visible. - - .. rust-example:: - :miri: - - // SAFETY: 'custom_symbol' does not conflict with any other symbol - #[unsafe(export_name = "custom_symbol")] - pub fn my_function() {} - - // SAFETY: Placing data in a specific section for embedded systems - #[unsafe(link_section = ".noinit")] - static mut PERSISTENT_DATA: [u8; 256] = [0; 256]; - - // SAFETY: Custom section for shared memory - #[unsafe(link_section = ".shared")] - static SHARED_BUFFER: [u8; 4096] = [0; 4096]; - - fn main() { - my_function(); - println!("DATA = {DATA}"); - } - - **Enforcement** - This guideline can be enforced through the following mechanisms: - - * **Rust Edition 2024**: Migrating to Rust Edition 2024 makes violations of this guideline - compilation errors for ``extern`` blocks and unsafe attributes. - - * **Compiler Lints**: Enable the following lints: - - * ``#![deny(unsafe_code)]`` - Denies all unsafe code (use ``#[allow(unsafe_code)]`` for justified exceptions) - * ``#![deny(unsafe_op_in_unsafe_fn)]`` - Requires explicit unsafe blocks within unsafe functions - * ``#![warn(unsafe_attr_outside_unsafe)]`` - Warns about unsafe attributes without the ``unsafe()`` wrapper (pre-2024) - - * **Static Analysis Tools**: - - * ``cargo-geiger`` - Counts and reports unsafe code usage - * ``cargo-audit`` - Checks for known vulnerabilities in dependencies - * Custom Clippy lints for project-specific requirements - - * **Code Review**: Manual review of all code containing ``unsafe`` tokens should be - part of the development process, with documented justification for each usage. - - **Related guidelines** - * Minimize the scope of unsafe blocks - * Document safety invariants for all unsafe code with ``// SAFETY:`` comments - * Prefer safe abstractions over raw unsafe code - * Use ``#![forbid(unsafe_code)]`` at crate level where possible, with explicit exceptions - - .. bibliography:: - :id: bib_ZDLZzjeOwLSU - :status: draft - - .. list-table:: - :header-rows: 0 - :widths: auto - :class: bibliography-table - - * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-EDITION-GUIDE` - - The Rust Edition Guide. "Rust 2024." https://doc.rust-lang.org/edition-guide/rust-2024/index.html. - - * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-REF-UNSAFE-KEYWORD` - - The Rust Reference. "Unsafe Keyword." https://doc.rust-lang.org/reference/unsafe-keyword.html. - - * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-LINT-UNSAFE` - - Rust Compiler Lint Documentation. "unsafe_code." https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unsafe-code. - - * - :bibentry:`gui_ZDLZzjeOwLSU:RUSTNOMICON-MEET-SAFE` - - The Rustonomicon. "Meet Safe and Unsafe." https://doc.rust-lang.org/nomicon/meet-safe-and-unsafe.html. - - * - :bibentry:`gui_ZDLZzjeOwLSU:ISO-26262` - - International Organization for Standardization. "ISO 26262 - Road vehicles - Functional safety." https://www.iso.org/standard/68383.html. - - * - :bibentry:`gui_ZDLZzjeOwLSU:DO-178C` - - RTCA, Inc. "DO-178C: Software Considerations in Airborne Systems and Equipment Certification." https://store.accuristech.com/standards/rtca-do-178c. - - * - :bibentry:`gui_ZDLZzjeOwLSU:CARGO-GEIGER` - - cargo-geiger contributors. "cargo-geiger: Detects usage of unsafe Rust." https://github.com/geiger-rs/cargo-geiger. - - * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-REF-EXTERN` - - The Rust Reference. "External blocks." https://doc.rust-lang.org/reference/items/external-blocks.html. - - * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-REF-UNSAFE-ATTR` - - The Rust Reference. "Unsafe attributes." https://doc.rust-lang.org/reference/attributes.html#unsafe-attributes. - - * - :bibentry:`gui_ZDLZzjeOwLSU:FERROCENE-SPEC` - - Ferrocene GmbH. "Ferrocene Language Specification." https://spec.ferrocene.dev/. - - * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-REF-UNION` - - The Rust Reference. "Unions." https://doc.rust-lang.org/reference/items/unions.html. - - * - :bibentry:`gui_ZDLZzjeOwLSU:UCG-VALIDITY` - - Rust Unsafe Code Guidelines. "Validity and Safety Invariant." https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#validity-and-safety-invariant. diff --git a/src/coding-guidelines/attributes/index.rst b/src/coding-guidelines/attributes/index.rst index 3d825b326..9f5608b9c 100644 --- a/src/coding-guidelines/attributes/index.rst +++ b/src/coding-guidelines/attributes/index.rst @@ -6,4 +6,9 @@ Attributes ========== -.. include:: gui_ZDLZzjeOwLSU.rst.inc +.. toctree:: + :maxdepth: 1 + :titlesonly: + :glob: + + gui_*