Skip to content

Commit 051d5d7

Browse files
committed
explain place alignment
1 parent b29823c commit 051d5d7

File tree

1 file changed

+33
-2
lines changed

1 file changed

+33
-2
lines changed

src/behavior-considered-undefined.md

+33-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ code.
2323
</div>
2424

2525
* Data races.
26-
* Accessing (loading from or storing to) a place that is [dangling] or unaligned.
26+
* Accessing (loading from or storing to) a place that is [dangling] or [based on
27+
a misaligned pointer].
2728
* Performing a place projection that violates the requirements of [in-bounds
2829
pointer arithmetic][offset]. A place projection is a [field
2930
expression][project-field], a [tuple index expression][project-tuple], or an
@@ -66,7 +67,7 @@ code.
6667
* A `!` (all values are invalid for this type).
6768
* An integer (`i*`/`u*`), floating point value (`f*`), or raw pointer obtained
6869
from [uninitialized memory][undef], or uninitialized memory in a `str`.
69-
* A reference or `Box<T>` that is [dangling], unaligned, or points to an invalid value.
70+
* A reference or `Box<T>` that is [dangling], misaligned, or points to an invalid value.
7071
* Invalid metadata in a wide reference, `Box<T>`, or raw pointer:
7172
* `dyn Trait` metadata is invalid if it is not a pointer to a vtable for
7273
`Trait` that matches the actual dynamic trait the pointer or reference points to.
@@ -100,6 +101,36 @@ reading uninitialized memory is permitted are inside `union`s and in "padding"
100101

101102
The span of bytes a pointer or reference "points to" is determined by the pointer value and the size of the pointee type (using `size_of_val`).
102103

104+
### Places based on misaligned pointers
105+
[based on a misaligned pointer]: #places-based-on-misaligned-pointers
106+
107+
A place is said to be "based on a misaligned pointer" if the last `*` projection
108+
during place computation was performed on a pointer that was not aligned for its
109+
type. (If there is no `*` projection in the place expression, then this is
110+
accessing the field of a local and rustc will guarantee proper alignment. If
111+
there are multiple `*` projection, then each of them incurs a load of the
112+
pointer-to-be-dereferenced itself from memory, and each of these loads is
113+
subject to the alignment constraint. Note that some `*` projections can be
114+
omitted in surface Rust syntax due to automatic dereferencing; we are
115+
considering the fully expanded place expression here.)
116+
117+
For instance, if `ptr` has type `*const S` where `S` has an alignment of 8, then
118+
`ptr` must be 8-aligned or else `(*ptr).f` is "based on an misaligned pointer".
119+
This is true even if the type of the field `f` is `u8` (i.e., a type with
120+
alignment 1). In other words, the alignment requirement derives from the type of
121+
the pointer that was dereferenced, *not* the type of the field that is being
122+
accessed.
123+
124+
Note that a place based on a misaligned pointer only leads to Undefined Behavior
125+
when it is loaded from or stored to. `addr_of!`/`addr_of_mut!` on such a place
126+
is allowed. `&`/`&mut` on a place requires the alignment of the field type (or
127+
else the program would be "producing an invalid value"), which generally is a
128+
less restrictive requirement than being based on an aligned pointer. Taking a
129+
reference will lead to a compiler error in cases where the field type might be
130+
more aligned than the type that contains it, i.e., `repr(packed)`. This means
131+
that being based on an aligned pointer is always sufficient to ensure that the
132+
new reference is aligned, but it is not always necessary.
133+
103134
### Dangling pointers
104135
[dangling]: #dangling-pointers
105136

0 commit comments

Comments
 (0)