What Unsafe Rust Can Do

The only things that are different in Unsafe Rust are that you can:

  • Dereference raw pointers
  • Call unsafe functions (including C functions, compiler intrinsics, and the raw allocator)
  • Implement unsafe traits
  • Mutate statics
  • Access fields of unions

That’s it. The reason these operations are relegated to Unsafe is that misusingany of these things will cause the ever dreaded Undefined Behavior. InvokingUndefined Behavior gives the compiler full rights to do arbitrarily bad thingsto your program. You definitely should not invoke Undefined Behavior.

Unlike C, Undefined Behavior is pretty limited in scope in Rust. All the corelanguage cares about is preventing the following things:

  • Dereferencing null, dangling, or unaligned pointers
  • Reading uninitialized memory
  • Breaking the pointer aliasing rules
  • Producing invalid primitive values:
    • dangling/null references
    • null fn pointers
    • a bool that isn’t 0 or 1
    • an undefined enum discriminant
    • a char outside the ranges [0x0, 0xD7FF] and [0xE000, 0x10FFFF]
    • A non-utf8 str
  • Unwinding into another language
  • Causing a data race

That’s it. That’s all the causes of Undefined Behavior baked into Rust. Ofcourse, unsafe functions and traits are free to declare arbitrary otherconstraints that a program must maintain to avoid Undefined Behavior. Forinstance, the allocator APIs declare that deallocating unallocated memory isUndefined Behavior.

However, violations of these constraints generally will just transitively lead to one ofthe above problems. Some additional constraints may also derive from compilerintrinsics that make special assumptions about how code can be optimized. For instance,Vec and Box make use of intrinsics that require their pointers to be non-null at all times.

Rust is otherwise quite permissive with respect to other dubious operations.Rust considers it “safe” to:

  • Deadlock
  • Have a race condition
  • Leak memory
  • Fail to call destructors
  • Overflow integers
  • Abort the program
  • Delete the production database

However any program that actually manages to do such a thing is probablyincorrect. Rust provides lots of tools to make these things rare, butthese problems are considered impractical to categorically prevent.