Unsafe Functions

Calling Unsafe Functions

A function or method can be marked unsafe if it has extra preconditions you must uphold to avoid undefined behaviour:

1. ```
   extern "C" {
   ```
2. ```
       fn abs(input: i32) -> i32;
   ```
3. ```
   }
   ```

5. ```
   fn main() {
   ```
6. ```
       let emojis = "🗻∈🌏";
   ```

8. ```
       // SAFETY: The indices are in the correct order, within the bounds of the
   ```
9. ```
       // string slice, and lie on UTF-8 sequence boundaries.
   ```
10. ```
        unsafe {
    ```
11. ```
            println!("emoji: {}", emojis.get_unchecked(0..4));
    ```
12. ```
            println!("emoji: {}", emojis.get_unchecked(4..7));
    ```
13. ```
            println!("emoji: {}", emojis.get_unchecked(7..11));
    ```
14. ```
        }
    ```

16. ```
        println!("char count: {}", count_chars(unsafe { emojis.get_unchecked(0..7) }));
    ```

18. ```
        // SAFETY: `abs` doesn't deal with pointers and doesn't have any safety
    ```
19. ```
        // requirements.
    ```
20. ```
        unsafe {
    ```
21. ```
            println!("Absolute value of -3 according to C: {}", abs(-3));
    ```
22. ```
        }
    ```

24. ```
        // Not upholding the UTF-8 encoding requirement breaks memory safety!
    ```
25. ```
        // println!("emoji: {}", unsafe { emojis.get_unchecked(0..3) });
    ```
26. ```
        // println!("char count: {}", count_chars(unsafe {
    ```
27. ```
        // emojis.get_unchecked(0..3) }));
    ```
28. ```
    }
    ```

30. ```
    fn count_chars(s: &str) -> usize {
    ```
31. ```
        s.chars().count()
    ```
32. ```
    }
    ```

Writing Unsafe Functions

You can mark your own functions as unsafe if they require particular conditions to avoid undefined behaviour.

1. ```
   /// Swaps the values pointed to by the given pointers.
   ```
2. ```
   ///
   ```
3. ```
   /// # Safety
   ```
4. ```
   ///
   ```
5. ```
   /// The pointers must be valid and properly aligned.
   ```
6. ```
   unsafe fn swap(a: *mut u8, b: *mut u8) {
   ```
7. ```
       let temp = *a;
   ```
8. ```
       *a = *b;
   ```
9. ```
       *b = temp;
   ```
10. ```
    }
    ```

12. ```
    fn main() {
    ```
13. ```
        let mut a = 42;
    ```
14. ```
        let mut b = 66;
    ```

16. ```
        // SAFETY: ...
    ```
17. ```
        unsafe {
    ```
18. ```
            swap(&mut a, &mut b);
    ```
19. ```
        }
    ```

21. ```
        println!("a = {}, b = {}", a, b);
    ```
22. ```
    }
    ```

This slide should take about 5 minutes.

Calling Unsafe Functions

get_unchecked, like most _unchecked functions, is unsafe, because it can create UB if the range is incorrect. abs is unsafe for a different reason: it is an external function (FFI). Calling external functions is usually only a problem when those functions do things with pointers which might violate Rust’s memory model, but in general any C function might have undefined behaviour under any arbitrary circumstances.

The "C" in this example is the ABI; other ABIs are available too.

Writing Unsafe Functions

We wouldn’t actually use pointers for a swap function - it can be done safely with references.

Note that unsafe code is allowed within an unsafe function without an unsafe block. We can prohibit this with #[deny(unsafe_op_in_unsafe_fn)]. Try adding it and see what happens. This will likely change in a future Rust edition.