Skip to content

Commit dd5ce85

Browse files
authored
Revise guideline on unsafe code in macros
Updated guideline on unsafe code in macros to clarify the importance of preserving 'unsafe' token visibility. Added examples of compliant and non-compliant macro implementations.
1 parent 48e18ea commit dd5ce85

1 file changed

Lines changed: 55 additions & 37 deletions

File tree

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,70 @@
11
.. SPDX-License-Identifier: MIT OR Apache-2.0
22
SPDX-FileCopyrightText: The Coding Guidelines Subcommittee Contributors
33

4-
.. default-domain:: coding-guidelines
4+
.. guideline:: Do not hide unsafe code in macros
5+
:id: gui_yQC2tSE2Qeii
6+
:category: advisory
7+
:status: draft
8+
:release: unclear-latest
9+
:fls: fls_4vjbkm4ceymk
10+
:decidability: decidable
11+
:scope: module
12+
:tags: safety, reduce-human-error
513

6-
.. guideline:: Do not hide unsafe blocks within macro expansions
7-
:id: gui_FRLaMIMb4t3S
8-
:category: required
9-
:status: draft
10-
:release: todo
11-
:fls: fls_4vjbkm4ceymk
12-
:decidability: todo
13-
:scope: todo
14-
:tags: reduce-human-error
14+
Do not hide unsafe code in macro definitions.
15+
Macros that expand to unsafe code should preserve the ``unsafe`` token visibility.
1516

16-
Description of the guideline goes here.
17+
.. rationale::
18+
:id: rat_s7ffMlPUFt77
19+
:status: draft
1720

18-
.. rationale::
19-
:id: rat_WJubG7KuUDLW
20-
:status: draft
21+
Macros that generate unsafe code obscure safety-critical code, making the code more difficult to review and audit.
2122

22-
Explanation of why this guideline is important.
23+
.. non_compliant_example::
24+
:id: non_compl_ex_YNX7AnWENTu7
25+
:status: draft
2326

24-
.. non_compliant_example::
25-
:id: non_compl_ex_AyFnP0lJLHxi
26-
:status: draft
27+
Macros that generate unsafe code without preserving the ``unsafe`` token visibility obscure safety-critical code.
28+
This noncompliant example defines a ``deref_ptr`` macro that performs an unsafe poitner deference.
2729

28-
Explanation of code example.
30+
.. rust-example::
2931

30-
.. rust-example::
32+
// This macro hides the unsafe token from callers - noncompliant
33+
macro_rules! deref_ptr {
34+
($ptr:expr) => {
35+
unsafe { *$ptr }
36+
};
37+
}
3138

32-
#[allow(dead_code)]
33-
fn example_function() {
34-
// Non-compliant implementation
35-
}
36-
#
37-
# fn main() {}
39+
fn main() {
40+
let x = 42;
41+
let ptr = &x as *const i32;
42+
// The unsafe operation is hidden from the caller
43+
println!("val = {}", deref_ptr!(ptr));
44+
}
3845

39-
.. compliant_example::
40-
:id: compl_ex_pO5gP1aj2v4F
41-
:status: draft
4246

43-
Explanation of code example.
47+
.. compliant_example::
48+
:id: compl_ex_nBkfzueTWvTA
49+
:status: draft
4450

45-
.. rust-example::
51+
This compliant example requires the caller to wrap the macro invocation in an ``unsafe`` block,
52+
making the use of unsafe code obvious at the call site.
53+
Visibility can be further improved by prefixing the identifier for each unsafe macro with the string “unsafe\_”
4654

47-
#[allow(dead_code)]
48-
fn example_function() {
49-
// Compliant implementation
50-
}
51-
#
52-
# fn main() {}
55+
.. rust-example::
56+
57+
// This macro requires the caller to acknowledge the unsafe operation - compliant
58+
macro_rules! unsafe_deref_ptr {
59+
($ptr:expr) => {
60+
*$ptr
61+
};
62+
}
63+
64+
fn main() {
65+
let x = 42;
66+
let ptr = &x as *const i32;
67+
// The unsafe operation is visible at the call site
68+
let val = unsafe { unsafe_deref_ptr!(ptr) };
69+
println!("val = {}", val);
70+
}

0 commit comments

Comments
 (0)