Skip to content

Commit 825ab84

Browse files
committed
Add guideline requiring wrapping unsafe in safe abstractions
1 parent 1d5d163 commit 825ab84

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

src/coding-guidelines/unsafety.rst

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,66 @@
55

66
Unsafety
77
========
8+
9+
.. guideline:: All unsafe code shall be contained inside a sound safe abstraction
10+
:id: gui_goekLVFUAjSM
11+
:category: required
12+
:status: draft
13+
:release: -
14+
:fls: fls_jep7p27kaqlp
15+
:decidability: undecidable
16+
:scope: module
17+
:tags: undefined-behavior
18+
19+
A safe abstraction is considered sound, when it is impossible to build a **safe** program using
20+
the safe abstraction that invokes undefined behavior.
21+
22+
Safe abstractions shall be kept as small as possible and only include features that cannot be built
23+
on top in safe Rust.
24+
25+
.. rationale::
26+
:id: rat_3FoizIv2mZ4Z
27+
:status: draft
28+
29+
Unsound safe abstractions leak the possibility for undefined behavior to safe Rust.
30+
With violations of this rule, it would no longer suffice to only focus on unsafe modules
31+
as the root cause of undefined behavior
32+
33+
Because safe abstractions are more difficult to review compared to safe code due to the
34+
subtle semantics of unsafe operations, their size need to be minimized.
35+
36+
.. non_compliant_example::
37+
:id: non_compl_ex_4Rj4YQkr1Nr4
38+
:status: draft
39+
40+
The following module with a safe API uses unsafe code and is therefore a safe abstraction.
41+
However, when passing a data slice with an index that is outside the range of the slice,
42+
the safe function will cause undefined behavior.
43+
44+
.. code-block:: rust
45+
46+
mod bad {
47+
fn get_value(data: &[i32], index: usize) -> i32 {
48+
unsafe {
49+
data.get_unchecked(usize)
50+
}
51+
}
52+
}
53+
54+
.. compliant_example::
55+
:id: compl_ex_aM7w7UbgSdvT
56+
:status: draft
57+
58+
This safe module checks that its argument are valid, (i.e., they satisfy the safety
59+
precondition of the unsafe operation) before performing the unsafe operation.
60+
61+
.. code-block:: rust
62+
63+
mod good {
64+
fn get_value(data: &[i32], index: usize) -> i32 {
65+
assert!(usize < data.len());
66+
unsafe {
67+
data.get_unchecked(usize)
68+
}
69+
}
70+
}

0 commit comments

Comments
 (0)