Skip to content

[Coding Guideline]: Do not hide unsafe code in macros #359

Description

@rcseacord

Chapter

Macros

Guideline Title

Do not hide unsafe code in macros

Category

Advisory

Status

Draft

Release Begin

unclear

Release End

latest

FLS Paragraph ID

fls_83182bfa9uqb

Decidability

Decidable

Scope

Module

Tags

safety

Amplification

Do not hide unsafe code in macro definitions.
Macros that expand to unsafe code should preserve the unsafe token visibility.

Exception(s)

No response

Rationale

Macros that generate unsafe code obscure safety-critical code, making the code more difficult to review and audit.

Non-Compliant Example 1 - Prose

Macros that generate unsafe code without preserving the unsafe token visibility obscure safety-critical code from auditors and static analysis tools.

Non-Compliant Example 1 - Code

            // This macro hides the unsafe token from callers - noncompliant
            macro_rules! deref_ptr {
                ($ptr:expr) => {
                    unsafe { *$ptr }
                };
            }

            fn main() {
                let x = 42;
                let ptr = &x as *const i32;
                // The unsafe operation is hidden from the caller
                println!("val = {}", deref_ptr!(ptr));
            }

Non-Compliant Example 2 - Prose (Optional)

No response

Non-Compliant Example 2 - Code (Optional)

No response

Non-Compliant Example 3 - Prose (Optional)

No response

Non-Compliant Example 3 - Code (Optional)

No response

Non-Compliant Example 4 - Prose (Optional)

No response

Non-Compliant Example 4 - Code (Optional)

No response

Compliant Example 1 - Prose

This compliant example requires the caller to wrap the macro invocation in an unsafe block, making the use of unsafe code obvious at the call site.
Visibility can be further improved by prefixing the identifier for each unsafe macro with the string "unsafe_"

Compliant Example 1 - Code

            // This macro requires the caller to acknowledge the unsafe operation - compliant
            macro_rules! unsafe_deref_ptr {
                ($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!(ptr) };
                println!("val = {}", val);
            }

Compliant Example 2 - Prose (Optional)

No response

Compliant Example 2 - Code (Optional)

No response

Compliant Example 3 - Prose (Optional)

No response

Compliant Example 3 - Code (Optional)

No response

Compliant Example 4 - Prose (Optional)

No response

Compliant Example 4 - Code (Optional)

No response

Bibliography

No response

Metadata

Metadata

Assignees

Labels

category: requiredA coding guideline with category requiredchapter: macroscoding guidelineAn issue related to a suggestion for a coding guidelinedecidability: decidableA coding guideline which can be checked automaticallyscope: moduleA coding guideline that can be determined applied at the module levelstatus: draft

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions