Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update UB #659

Merged
merged 16 commits into from
Sep 5, 2019
56 changes: 34 additions & 22 deletions src/behavior-considered-undefined.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,44 +23,56 @@ code.
</div>

* Data races.
* Dereferencing a null or dangling raw pointer.
* Unaligned pointer reading and writing outside of [`read_unaligned`]
Centril marked this conversation as resolved.
Show resolved Hide resolved
and [`write_unaligned`].
* Reads of [undef] \(uninitialized) memory.
* Breaking the [pointer aliasing rules] on accesses through raw pointers;
Centril marked this conversation as resolved.
Show resolved Hide resolved
a subset of the rules used by C.
* `&mut T` and `&T` follow LLVM’s scoped [noalias] model, except if the `&T`
contains an [`UnsafeCell<U>`].
* Mutating non-mutable data &mdash; that is, data reached through a shared
* Dereferencing (using the `*` operator on) a dangling or unaligned raw pointer.
* Breaking the [pointer aliasing rules]. `&mut T` and `&T` follow LLVM’s scoped
[noalias] model, except if the `&T` contains an [`UnsafeCell<U>`].
* Mutating non-mutable data (that is, data reached through a shared
reference or data owned by a `let` binding), unless that data is contained
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
within an [`UnsafeCell<U>`].
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
* Invoking undefined behavior via compiler intrinsics:
* Indexing outside of the bounds of an object with [`offset`] with
the exception of one byte past the end of the object.
* Using [`std::ptr::copy_nonoverlapping_memory`], a.k.a. the `memcpy32`and
`memcpy64` intrinsics, on overlapping buffers.
* Invalid values in primitive types, even in private fields and locals:
* Dangling or null references and boxes.
* Invoking undefined behavior via compiler intrinsics.
* Executing code compiled with platform features that the current platform
does not support (see [`target_feature`]).
* Unwinding into another language.
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
* Producing an invalid value, even in private fields and locals. "Producing" a
value happens any time a value is assigned, passed to a function/primitive
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
operation or returned from a function/primitive operation.
The following values are invalid (at their respective type):
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
* A value other than `false` (`0`) or `true` (`1`) in a `bool`.
* A discriminant in an `enum` not included in the type definition.
* A null `fn` pointer.
* A value in a `char` which is a surrogate or above `char::MAX`.
* A `!` (all values are invalid for this type).
* A dangling or unaligned reference or `Box`, or one that points to an invalid value.
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
* Invalid metadata in a wide reference, `Box` or raw pointer:
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
* slice metadata is invalid if the slice has a total size larger than
`isize::MAX` bytes in memory.
* `dyn Trait` metadata is invalid if it is not a pointer to a vtable for
`Trait` that matches the actual dynamic trait the reference points to.
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
* Non-UTF-8 byte sequences in a `str`.
* Executing code compiled with platform features that the current platform
does not support (see [`target_feature`]).
* [Uninitialized memory][undef] in the value of an integer (`i*`/`u*`),
floating point value (`f*`), or raw pointer.
Centril marked this conversation as resolved.
Show resolved Hide resolved
* Invalid values for a type with a custom definition of invalid values, such
as a `NonNull` that is null. (Requesting custom invalid values is an
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
Centril marked this conversation as resolved.
Show resolved Hide resolved
unstable feature, but some stable libstd types, like `NonNull`, make use of
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
it.)

> **Note**: Undefined behavior affects the entire program. For example, calling
> a function in C that exhibits undefined behavior of C means your entire
> program contains undefined behaviour that can also affect the Rust code. And
> vice versa, undefined behavior in Rust can cause adverse affects on code
> executed by any FFI calls to other languages.

A reference/pointer is "dangling" if it is null or not all of the bytes it
points to are part of the same allocation (so in particular they all have to be
part of *some* allocation). The span of bytes it points to is determined by the
pointer value and the size of the pointee type. As a consequence, if the span is
empty, "dangling" is the same as "non-null". Note that slices point to their
entire range, so it is very important that the length metadata is never too
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
large.

[noalias]: http://llvm.org/docs/LangRef.html#noalias
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
[pointer aliasing rules]: http://llvm.org/docs/LangRef.html#pointer-aliasing-rules
[undef]: http://llvm.org/docs/LangRef.html#undefined-values
[`offset`]: ../std/primitive.pointer.html#method.offset
[`std::ptr::copy_nonoverlapping_memory`]: ../std/ptr/fn.copy_nonoverlapping.html
[`target_feature`]: attributes/codegen.md#the-target_feature-attribute
[`UnsafeCell<U>`]: ../std/cell/struct.UnsafeCell.html
[`read_unaligned`]: ../std/ptr/fn.read_unaligned.html
[`write_unaligned`]: ../std/ptr/fn.write_unaligned.html
[Rustonomicon]: ../nomicon/index.html