Part 2: Ownership, Borrowing, and Lifetimes - Rust's Memory Safety

Introduction

When building my WAF scanner, I needed to share an HTTP client across multiple concurrent tasks testing different payloads. In Python, I'd just pass the client around without thinking. In Rust, the compiler immediately complained about ownership. This forced me to understand Rust's most unique—and initially frustrating—feature: the ownership system.

Understanding ownership is crucial for writing Rust. It's what enables memory safety without garbage collection and prevents data races at compile time. This article explains ownership through real examples from simple-waf-scannerarrow-up-right.

Why Ownership Exists

The Memory Management Spectrum

Manual Memory Management (C/C++)

char* data = malloc(1024);  // Allocate
// Use data...
free(data);                  // Must remember to free!
// Later use of data = segfault or security vulnerability

Problems:

  • Use after free

  • Double free

  • Memory leaks

  • No thread safety guarantees

Garbage Collection (Python/Java/Go)

Problems:

  • Unpredictable pauses

  • Memory overhead

  • Runtime performance cost

Rust's Ownership

Benefits:

  • Memory safety without GC

  • Zero runtime cost

  • Thread safety enforced by compiler

The Three Ownership Rules

  1. Each value has a single owner

  2. When the owner goes out of scope, the value is dropped

  3. Ownership can be transferred (moved)

Rule 1: Single Owner

Rule 2: Automatic Cleanup

Rule 3: Move Semantics

Real Example: Payload Management

From my WAF scanner:

Borrowing - Using Without Owning

Immutable References (&T)

Mutable References (&mut T)

Borrowing Rules

  1. Multiple immutable borrows OR one mutable borrow (not both)

  2. References must always be valid (no dangling pointers)

Real Example: HTTP Client Sharing

Initial attempt (doesn't work):

Solution - use references:

Even better - use Arc for sharing across threads:

Clone vs Copy

Copy Types (Stack-only)

Clone Types (Explicit Copy)

In My Project

Lifetimes - Ensuring References Are Valid

The Problem Lifetimes Solve

Lifetime Annotations

Lifetime Elision (Compiler Infers Lifetimes)

These are equivalent:

Lifetimes in Structs

Real Example from My Scanner

Smart Pointers

Box - Heap Allocation

Rc - Reference Counted (Single-threaded)

Arc - Atomic Reference Counted (Thread-safe)

Real-World Pattern: Scanner Implementation

Complete example combining ownership concepts:

Common Ownership Patterns

Pattern 1: Taking Ownership for Consumption

Pattern 2: Borrowing for Inspection

Pattern 3: Borrowing Mutably for Modification

Pattern 4: Returning Owned Data

Fighting the Borrow Checker

Common Error: Multiple Mutable Borrows

Solution: Don't overlap mutable borrows:

Common Error: Borrowing Moved Value

Solution: Clone or borrow:

Iterator Ownership

Key Takeaways

  1. Ownership = automatic memory management: No GC needed

  2. One owner at a time: Prevents use-after-free

  3. Borrowing allows access without ownership: Read-only (&T) or mutable (&mut T)

  4. Only one mutable borrow OR many immutable borrows: Prevents data races

  5. Lifetimes ensure references are valid: No dangling pointers

  6. Arc for sharing across threads: Atomic reference counting

  7. Clone when you need separate ownership: Explicit copying

When to Use What

  • Move (take ownership): Consuming data, passing to async tasks

  • Borrow (&T): Reading without modification

  • Mutable borrow (&mut T): Modifying in place

  • Clone: When you need independent copies

  • Arc: Sharing across threads/async tasks

  • Rc: Sharing within single thread (rare in async code)

Next in Series

In Part 3: Error Handling and Result Types, we'll explore how Rust forces explicit error handling, preventing the silent failures common in other languages. We'll see how to handle HTTP errors, JSON parsing failures, and build robust error types for the scanner.


Based on implementing concurrent payload testing in simple-waf-scanner, where ownership and borrowing ensure thread-safe operation without data races.

Last updated