|
2 | 2 | SPDX-FileCopyrightText: The Coding Guidelines Subcommittee Contributors |
3 | 3 |
|
4 | 4 | .. guideline:: Assure visibility of ``unsafe`` keyword in unsafe code |
5 | | - :id: gui_ZDLZzjeOwLSU |
6 | | - :category: required |
7 | | - :status: draft |
8 | | - :release: 1.85-latest |
9 | | - :fls: fls_8kqo952gjhaf |
10 | | - :decidability: decidable |
11 | | - :scope: crate |
12 | | - :tags: readability, reduce-human-error |
13 | | - |
14 | | - Mark all code that may violate safety guarantees with a visible ``unsafe`` keyword :cite:`gui_jK6lMn7oPq8r:RUST-REF-UNSAFE-KEYWORD`. |
| 5 | + :id: gui_ZDLZzjeOwLSU |
| 6 | + :category: required |
| 7 | + :status: draft |
| 8 | + :release: 1.85-latest |
| 9 | + :fls: fls_8kqo952gjhaf |
| 10 | + :decidability: decidable |
| 11 | + :scope: crate |
| 12 | + :tags: readability, reduce-human-error |
| 13 | + |
| 14 | + Mark all code that may violate safety guarantees with a visible ``unsafe`` keyword :cite:`gui_ZDLZzjeOwLSU:RUST-REF-UNSAFE-KEYWORD`. |
15 | 15 |
|
16 | 16 | The following constructs require explicit ``unsafe`` visibility: |
17 | 17 |
|
|
33 | 33 |
|
34 | 34 | * Auditability and Review |
35 | 35 |
|
36 | | - * ``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` |
37 | | - * Safety-critical standards like ISO 26262 :cite:`gui_kL5mNo6pQr7s:ISO-26262` and DO-178C :cite:`gui_tU8vWx9yZa0b:DO-178C` require traceability of hazardous operations |
| 36 | + * ``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` |
| 37 | + * Safety-critical standards like ISO 26262 :cite:`gui_ZDLZzjeOwLSU:ISO-26262` and DO-178C :cite:`gui_ZDLZzjeOwLSU:DO-178C` require traceability of hazardous operations |
38 | 38 | * Helps enumerate and document all places where safety requirements must be manually upheld |
39 | 39 | * Satisfies ISO 26262 Part 6, Table 1, objective 1c (use of language subsets) |
40 | 40 | * Satisfies DO-178C Section 6.3.4.f (source code traceability) |
|
47 | 47 |
|
48 | 48 | * Static Analysis and Tooling |
49 | 49 |
|
50 | | - * Tools like ``cargo-geiger`` :cite:`gui_cD3eGh4iJk5l:CARGO-GEIGER`, ``unsafe-inspect``, |
| 50 | + * Tools like ``cargo-geiger`` :cite:`gui_ZDLZzjeOwLSU:CARGO-GEIGER`, ``unsafe-inspect``, |
51 | 51 | and custom linters can automatically locate and count unsafe blocks |
52 | 52 | * Enables metrics like "unsafe density" for safety assessments |
53 | 53 | * Supports qualification evidence required by certification standards |
|
70 | 70 | It is even possible for an unmangled symbol to conflict with a mangled symbol. |
71 | 71 |
|
72 | 72 | This noncompliant example requires Rust Edition 2021 or earlier to compile. |
| 73 | + In Rust Edition 2024, missing ``unsafe`` wrappers cause compilation errors. |
73 | 74 |
|
74 | 75 | .. rust-example:: |
75 | | -.. :compile_fail: |
76 | 76 |
|
77 | 77 | // Undefined behavior by the linker or loader is possible |
78 | 78 | // if another 'convert' function is defined. |
|
94 | 94 | NOTE: This code can still have undefined behavior if the 'convert' function symbol is define more than once. |
95 | 95 |
|
96 | 96 | .. rust-example:: |
| 97 | + :miri: |
97 | 98 |
|
98 | 99 | #[unsafe(no_mangle)] // compliant. |
99 | 100 | fn convert() {} |
|
115 | 116 | This noncompliant example requires Rust Edition 2021 or earlier to compile. |
116 | 117 |
|
117 | 118 | .. rust-example:: |
118 | | -.. :compile_fail: |
| 119 | + :miri: |
119 | 120 |
|
120 | 121 | use std::ffi; |
121 | 122 |
|
|
149 | 150 | ``malloc`` used in this compliant example has been correct to accept one argument of type ``usize``. |
150 | 151 |
|
151 | 152 | .. rust-example:: |
| 153 | + :miri: |
152 | 154 |
|
153 | 155 | use std::ffi; |
154 | 156 |
|
|
192 | 194 | This noncompliant example requires Rust Edition 2021 or earlier to compile. |
193 | 195 |
|
194 | 196 | .. rust-example:: |
195 | | - :compile_fail: |
| 197 | + :compile_fail: |
| 198 | + :edition: 2024 |
196 | 199 |
|
197 | 200 | // Collides with the C library 'printf' function |
198 | 201 | #[export_name = "printf"] // noncompliant |
199 | 202 |
|
200 | 203 | // Missing unsafe marker - noncompliant in Rust 2024 |
201 | | - #[unsafe(link_section = ".init_array")] // noncompliant |
| 204 | + #[link_section = ".init_array"] // noncompliant |
202 | 205 | static DATA: u32 = 42; // Corrupts initialization table! |
203 | 206 |
|
204 | 207 | fn main() { |
205 | | - printf("Hello, World"); |
206 | 208 | println!("DATA = {DATA}"); |
207 | 209 | } |
208 | 210 |
|
|
214 | 216 | to make their safety implications visible. |
215 | 217 |
|
216 | 218 | .. rust-example:: |
| 219 | + :miri: |
217 | 220 |
|
218 | 221 | // SAFETY: 'custom_symbol' does not conflict with any other symbol |
219 | 222 | #[unsafe(export_name = "custom_symbol")] |
|
232 | 235 | println!("DATA = {DATA}"); |
233 | 236 | } |
234 | 237 |
|
235 | | - .. enforcement:: |
236 | | - :id: enf_pQ8rSt9uVw0x |
237 | | - :status: draft |
238 | | - |
239 | | - This guideline can be enforced through the following mechanisms: |
| 238 | + **Enforcement** |
| 239 | + This guideline can be enforced through the following mechanisms: |
240 | 240 |
|
241 | | - * **Rust Edition 2024**: Migrating to Rust Edition 2024 makes violations of this guideline |
242 | | - compilation errors for ``extern`` blocks and unsafe attributes. |
| 241 | + * **Rust Edition 2024**: Migrating to Rust Edition 2024 makes violations of this guideline |
| 242 | + compilation errors for ``extern`` blocks and unsafe attributes. |
243 | 243 |
|
244 | | - * **Compiler Lints**: Enable the following lints: |
| 244 | + * **Compiler Lints**: Enable the following lints: |
245 | 245 |
|
246 | | - * ``#![deny(unsafe_code)]`` - Denies all unsafe code (use ``#[allow(unsafe_code)]`` for justified exceptions) |
247 | | - * ``#![deny(unsafe_op_in_unsafe_fn)]`` - Requires explicit unsafe blocks within unsafe functions |
248 | | - * ``#![warn(unsafe_attr_outside_unsafe)]`` - Warns about unsafe attributes without the ``unsafe()`` wrapper (pre-2024) |
| 246 | + * ``#![deny(unsafe_code)]`` - Denies all unsafe code (use ``#[allow(unsafe_code)]`` for justified exceptions) |
| 247 | + * ``#![deny(unsafe_op_in_unsafe_fn)]`` - Requires explicit unsafe blocks within unsafe functions |
| 248 | + * ``#![warn(unsafe_attr_outside_unsafe)]`` - Warns about unsafe attributes without the ``unsafe()`` wrapper (pre-2024) |
249 | 249 |
|
250 | | - * **Static Analysis Tools**: |
| 250 | + * **Static Analysis Tools**: |
251 | 251 |
|
252 | | - * ``cargo-geiger`` - Counts and reports unsafe code usage |
253 | | - * ``cargo-audit`` - Checks for known vulnerabilities in dependencies |
254 | | - * Custom Clippy lints for project-specific requirements |
| 252 | + * ``cargo-geiger`` - Counts and reports unsafe code usage |
| 253 | + * ``cargo-audit`` - Checks for known vulnerabilities in dependencies |
| 254 | + * Custom Clippy lints for project-specific requirements |
255 | 255 |
|
256 | | - * **Code Review**: Manual review of all code containing ``unsafe`` tokens should be |
257 | | - part of the development process, with documented justification for each usage. |
258 | | - |
259 | | - .. related_guidelines:: |
260 | | - :id: rel_gH4iJk5lMn6o |
261 | | - :status: draft |
| 256 | + * **Code Review**: Manual review of all code containing ``unsafe`` tokens should be |
| 257 | + part of the development process, with documented justification for each usage. |
262 | 258 |
|
263 | | - * Minimize the scope of unsafe blocks |
264 | | - * Document safety invariants for all unsafe code with ``// SAFETY:`` comments |
265 | | - * Prefer safe abstractions over raw unsafe code |
266 | | - * Use ``#![forbid(unsafe_code)]`` at crate level where possible, with explicit exceptions |
| 259 | + **Related guidelines** |
| 260 | + * Minimize the scope of unsafe blocks |
| 261 | + * Document safety invariants for all unsafe code with ``// SAFETY:`` comments |
| 262 | + * Prefer safe abstractions over raw unsafe code |
| 263 | + * Use ``#![forbid(unsafe_code)]`` at crate level where possible, with explicit exceptions |
267 | 264 |
|
268 | 265 | .. bibliography:: |
269 | | - :id: bib_WNCi5njUWLuZ |
| 266 | + :id: bib_ZDLZzjeOwLSU |
270 | 267 | :status: draft |
271 | 268 |
|
272 | 269 | .. list-table:: |
273 | 270 | :header-rows: 0 |
274 | 271 | :widths: auto |
275 | 272 | :class: bibliography-table |
276 | 273 |
|
277 | | - * - :bibentry:`gui_aB3cDe4fGh5i:RUST-EDITION-GUIDE` |
| 274 | + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-EDITION-GUIDE` |
278 | 275 | - The Rust Edition Guide. "Rust 2024." https://doc.rust-lang.org/edition-guide/rust-2024/index.html. |
279 | 276 |
|
280 | | - * - :bibentry:`gui_jK6lMn7oPq8r:RUST-REF-UNSAFE-KEYWORD` |
| 277 | + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-REF-UNSAFE-KEYWORD` |
281 | 278 | - The Rust Reference. "Unsafe Keyword." https://doc.rust-lang.org/reference/unsafe-keyword.html. |
282 | 279 |
|
283 | | - * - :bibentry:`gui_sT9uVw0xYz1a:RUST-LINT-UNSAFE` |
| 280 | + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-LINT-UNSAFE` |
284 | 281 | - Rust Compiler Lint Documentation. "unsafe_code." https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unsafe-code. |
285 | 282 |
|
286 | | - * - :bibentry:`gui_bC2dEf3gHi4j:RUSTNOMICON-MEET-SAFE` |
| 283 | + * - :bibentry:`gui_ZDLZzjeOwLSU:RUSTNOMICON-MEET-SAFE` |
287 | 284 | - The Rustonomicon. "Meet Safe and Unsafe." https://doc.rust-lang.org/nomicon/meet-safe-and-unsafe.html. |
288 | 285 |
|
289 | | - * - :bibentry:`gui_kL5mNo6pQr7s:ISO-26262` |
| 286 | + * - :bibentry:`gui_ZDLZzjeOwLSU:ISO-26262` |
290 | 287 | - International Organization for Standardization. "ISO 26262 - Road vehicles - Functional safety." https://www.iso.org/standard/68383.html. |
291 | 288 |
|
292 | | - * - :bibentry:`gui_tU8vWx9yZa0b:DO-178C` |
| 289 | + * - :bibentry:`gui_ZDLZzjeOwLSU:DO-178C` |
293 | 290 | - RTCA, Inc. "DO-178C: Software Considerations in Airborne Systems and Equipment Certification." https://store.accuristech.com/standards/rtca-do-178c. |
294 | 291 |
|
295 | | - * - :bibentry:`gui_cD3eGh4iJk5l:CARGO-GEIGER` |
| 292 | + * - :bibentry:`gui_ZDLZzjeOwLSU:CARGO-GEIGER` |
296 | 293 | - cargo-geiger contributors. "cargo-geiger: Detects usage of unsafe Rust." https://github.com/geiger-rs/cargo-geiger. |
297 | 294 |
|
298 | | - * - :bibentry:`gui_mN6oQp7rSt8u:RUST-REF-EXTERN` |
| 295 | + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-REF-EXTERN` |
299 | 296 | - The Rust Reference. "External blocks." https://doc.rust-lang.org/reference/items/external-blocks.html. |
300 | 297 |
|
301 | | - * - :bibentry:`gui_vW9xYz0aAb1c:RUST-REF-UNSAFE-ATTR` |
| 298 | + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-REF-UNSAFE-ATTR` |
302 | 299 | - The Rust Reference. "Unsafe attributes." https://doc.rust-lang.org/reference/attributes.html#unsafe-attributes. |
303 | 300 |
|
304 | | - * - :bibentry:`gui_dE2fGh3iJk4l:FERROCENE-SPEC` |
| 301 | + * - :bibentry:`gui_ZDLZzjeOwLSU:FERROCENE-SPEC` |
305 | 302 | - Ferrocene GmbH. "Ferrocene Language Specification." https://spec.ferrocene.dev/. |
306 | 303 |
|
307 | | - * - :bibentry:`gui_eF3gHi4jKl5m:RUST-REF-UNION` |
| 304 | + * - :bibentry:`gui_ZDLZzjeOwLSU:RUST-REF-UNION` |
308 | 305 | - The Rust Reference. "Unions." https://doc.rust-lang.org/reference/items/unions.html. |
309 | 306 |
|
310 | | - * - :bibentry:`gui_fG4hIj5kLm6n:UCG-VALIDITY` |
| 307 | + * - :bibentry:`gui_ZDLZzjeOwLSU:UCG-VALIDITY` |
311 | 308 | - Rust Unsafe Code Guidelines. "Validity and Safety Invariant." https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#validity-and-safety-invariant. |
0 commit comments