docs: Add notes on behaviours which Rust considers undefined.

This commit is contained in:
Isis Lovecruft 2017-08-31 01:12:45 +00:00 committed by Nick Mathewson
parent 12cf04646c
commit 1645c5503d
1 changed files with 41 additions and 2 deletions

View File

@ -44,8 +44,8 @@ If your Rust code must call out to parts of Tor's C code, you must
declare the functions you are calling in the `external` crate, located
at `.../src/rust/external`.
XXX get better examples of how to declare these externs, when/how they
XXX are unsafe, what they are expected to do —isis
<!-- XXX get better examples of how to declare these externs, when/how they -->
<!-- XXX are unsafe, what they are expected to do —isis -->
Modules should strive to be below 500 lines (tests excluded). Single
responsibility and limited dependencies should be a guiding standard.
@ -170,6 +170,45 @@ before attempting to write FFI or any other unsafe code.
Here are some additional bits of advice and rules:
0. Any behaviours which Rust considers to be undefined are forbidden
From https://doc.rust-lang.org/reference/behavior-considered-undefined.html:
> Behavior considered undefined
>
> The following is a list of behavior which is forbidden in all Rust code,
> including within unsafe blocks and unsafe functions. Type checking provides the
> guarantee that these issues are never caused by safe code.
>
> * Data races
> * Dereferencing a null/dangling raw pointer
> * Reads of [undef](http://llvm.org/docs/LangRef.html#undefined-values)
> (uninitialized) memory
> * Breaking the
> [pointer aliasing rules](http://llvm.org/docs/LangRef.html#pointer-aliasing-rules)
> with raw pointers (a subset of the rules used by C)
> * `&mut T` and `&T` follow LLVMs scoped noalias model, except if the `&T`
> contains an `UnsafeCell<U>`. Unsafe code must not violate these aliasing
> guarantees.
> * Mutating non-mutable data (that is, data reached through a shared
> reference or data owned by a `let` binding), unless that data is
> contained within an `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:
> - Dangling/null references or boxes
> - A value other than `false` (0) or `true` (1) in a `bool`
> - A discriminant in an `enum` not included in the 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. Rust's failure system is not compatible with exception handling in other
> languages. Unwinding must be caught and handled at FFI boundaries.
1. `unwrap()`
If you call `unwrap()`, anywhere, even in a test, you MUST include