1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
% Unsafe
Rust’s main draw is its powerful static guarantees about behavior. But safety
checks are conservative by nature: there are some programs that are actually
safe, but the compiler is not able to verify this is true. To write these kinds
of programs, we need to tell the compiler to relax its restrictions a bit. For
this, Rust has a keyword, `unsafe`. Code using `unsafe` has less restrictions
than normal code does.
Let’s go over the syntax, and then we’ll talk semantics. `unsafe` is used in
four contexts. The first one is to mark a function as unsafe:
```rust
unsafe fn danger_will_robinson() {
// scary stuff
}
```
All functions called from [FFI][ffi] must be marked as `unsafe`, for example.
The second use of `unsafe` is an unsafe block:
[ffi]: ffi.html
```rust
unsafe {
// scary stuff
}
```
The third is for unsafe traits:
```rust
unsafe trait Scary { }
```
And the fourth is for `impl`ementing one of those traits:
```rust
# unsafe trait Scary { }
unsafe impl Scary for i32 {}
```
It’s important to be able to explicitly delineate code that may have bugs that
cause big problems. If a Rust program segfaults, you can be sure it’s somewhere
in the sections marked `unsafe`.
# What does ‘safe’ mean?
Safe, in the context of Rust, means ‘doesn’t do anything unsafe’. It’s also
important to know that there are certain behaviors that are probably not
desirable in your code, but are expressly _not_ unsafe:
* Deadlocks
* Leaks of memory or other resources
* Exiting without calling destructors
* Integer overflow
Rust cannot prevent all kinds of software problems. Buggy code can and will be
written in Rust. These things aren’t great, but they don’t qualify as `unsafe`
specifically.
In addition, the following are all undefined behaviors in Rust, and must be
avoided, even when writing `unsafe` code:
* Data races
* Dereferencing a null/dangling raw pointer
* Reads of [undef][undef] (uninitialized) memory
* Breaking the [pointer aliasing rules][aliasing] with raw pointers.
* `&mut T` and `&T` follow LLVM’s scoped [noalias][noalias] model, except if
the `&T` contains an `UnsafeCell<U>`. Unsafe code must not violate these
aliasing guarantees.
* Mutating an immutable value/reference without `UnsafeCell<U>`
* Invoking undefined behavior via compiler intrinsics:
* Indexing outside of the bounds of an object with `std::ptr::offset`
(`offset` intrinsic), with
the exception of one byte past the end which is permitted.
* Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64`
intrinsics) on overlapping buffers
* Invalid values in primitive types, even in private fields/locals:
* Null/dangling references or boxes
* A value other than `false` (0) or `true` (1) in a `bool`
* A discriminant in an `enum` not included in its type definition
* A value in a `char` which is a surrogate or above `char::MAX`
* Non-UTF-8 byte sequences in a `str`
* Unwinding into Rust from foreign code or unwinding from Rust into foreign
code.
[noalias]: http://llvm.org/docs/LangRef.html#noalias
[undef]: http://llvm.org/docs/LangRef.html#undefined-values
[aliasing]: http://llvm.org/docs/LangRef.html#pointer-aliasing-rules
# Unsafe Superpowers
In both unsafe functions and unsafe blocks, Rust will let you do three things
that you normally can not do. Just three. Here they are:
1. Access or update a [static mutable variable][static].
2. Dereference a raw pointer.
3. Call unsafe functions. This is the most powerful ability.
That’s it. It’s important that `unsafe` does not, for example, ‘turn off the
borrow checker’. Adding `unsafe` to some random Rust code doesn’t change its
semantics, it won’t just start accepting anything. But it will let you write
things that _do_ break some of the rules.
You will also encounter the `unsafe` keyword when writing bindings to foreign
(non-Rust) interfaces. You're encouraged to write a safe, native Rust interface
around the methods provided by the library.
Let’s go over the basic three abilities listed, in order.
## Access or update a `static mut`
Rust has a feature called ‘`static mut`’ which allows for mutable global state.
Doing so can cause a data race, and as such is inherently not safe. For more
details, see the [static][static] section of the book.
[static]: const-and-static.html#static
## Dereference a raw pointer
Raw pointers let you do arbitrary pointer arithmetic, and can cause a number of
different memory safety and security issues. In some senses, the ability to
dereference an arbitrary pointer is one of the most dangerous things you can
do. For more on raw pointers, see [their section of the book][rawpointers].
[rawpointers]: raw-pointers.html
## Call unsafe functions
This last ability works with both aspects of `unsafe`: you can only call
functions marked `unsafe` from inside an unsafe block.
This ability is powerful and varied. Rust exposes some [compiler
intrinsics][intrinsics] as unsafe functions, and some unsafe functions bypass
safety checks, trading safety for speed.
I’ll repeat again: even though you _can_ do arbitrary things in unsafe blocks
and functions doesn’t mean you should. The compiler will act as though you’re
upholding its invariants, so be careful!
[intrinsics]: intrinsics.html
|