Exploring Rust's Unsafe Operations

RustRustBeginner
Practice Now

This tutorial is from open-source community. Access the source code

Introduction

In this lab, we will explore unsafe operations in Rust, which are used to bypass compiler protections and are typically used for dereferencing raw pointers, calling unsafe functions, accessing or modifying static mutable variables, and implementing unsafe traits. These operations should be minimized in a code base to ensure safety.

Note: If the lab does not specify a file name, you can use any file name you want. For example, you can use main.rs, compile and run it with rustc main.rs && ./main.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("`Rust`")) -.-> rust/BasicConceptsGroup(["`Basic Concepts`"]) rust(("`Rust`")) -.-> rust/DataTypesGroup(["`Data Types`"]) rust(("`Rust`")) -.-> rust/FunctionsandClosuresGroup(["`Functions and Closures`"]) rust(("`Rust`")) -.-> rust/DataStructuresandEnumsGroup(["`Data Structures and Enums`"]) rust(("`Rust`")) -.-> rust/AdvancedTopicsGroup(["`Advanced Topics`"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("`Variable Declarations`") rust/BasicConceptsGroup -.-> rust/constants_usage("`Constants Usage`") rust/DataTypesGroup -.-> rust/integer_types("`Integer Types`") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("`Function Syntax`") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("`Expressions and Statements`") rust/DataStructuresandEnumsGroup -.-> rust/method_syntax("`Method Syntax`") rust/AdvancedTopicsGroup -.-> rust/unsafe_rust("`Unsafe Rust`") subgraph Lab Skills rust/variable_declarations -.-> lab-99286{{"`Exploring Rust's Unsafe Operations`"}} rust/constants_usage -.-> lab-99286{{"`Exploring Rust's Unsafe Operations`"}} rust/integer_types -.-> lab-99286{{"`Exploring Rust's Unsafe Operations`"}} rust/function_syntax -.-> lab-99286{{"`Exploring Rust's Unsafe Operations`"}} rust/expressions_statements -.-> lab-99286{{"`Exploring Rust's Unsafe Operations`"}} rust/method_syntax -.-> lab-99286{{"`Exploring Rust's Unsafe Operations`"}} rust/unsafe_rust -.-> lab-99286{{"`Exploring Rust's Unsafe Operations`"}} end

Unsafe Operations

As an introduction to this section, to borrow from the official docs, "one should try to minimize the amount of unsafe code in a code base." With that in mind, let's get started! Unsafe annotations in Rust are used to bypass protections put in place by the compiler; specifically, there are four primary things that unsafe is used for:

  • dereferencing raw pointers
  • calling functions or methods which are unsafe (including calling a function over FFI, see [a previous chapter of the book)
  • accessing or modifying static mutable variables
  • implementing unsafe traits

Raw Pointers

Raw pointers * and references &T function similarly, but references are always safe because they are guaranteed to point to valid data due to the borrow checker. Dereferencing a raw pointer can only be done through an unsafe block.

fn main() {
    let raw_p: *const u32 = &10;

    unsafe {
        assert!(*raw_p == 10);
    }
}

Calling Unsafe Functions

Some functions can be declared as unsafe, meaning it is the programmer's responsibility to ensure correctness instead of the compiler's. One example of this is [std::slice::from_raw_parts] which will create a slice given a pointer to the first element and a length.

use std::slice;

fn main() {
    let some_vector = vec![1, 2, 3, 4];

    let pointer = some_vector.as_ptr();
    let length = some_vector.len();

    unsafe {
        let my_slice: &[u32] = slice::from_raw_parts(pointer, length);

        assert_eq!(some_vector.as_slice(), my_slice);
    }
}

For slice::from_raw_parts, one of the assumptions which must be upheld is that the pointer passed in points to valid memory and that the memory pointed to is of the correct type. If these invariants aren't upheld then the program's behaviour is undefined and there is no knowing what will happen.

Summary

Congratulations! You have completed the Unsafe Operations lab. You can practice more labs in LabEx to improve your skills.

Other Rust Tutorials you may like