How does Rust stop memory bugs? Ownership, borrowing and real Android data
TL;DR
Rust checks memory safety at compile time through ownership, borrowing and lifetimes, with no garbage collector. With about 5 million lines of Rust, Android saw roughly 1000× lower memory vulnerability density and 4× fewer rollbacks; unsafe code and logic bugs still need watching.
If 70% of serious vulnerabilities come from memory bugs, the natural question is: is there a language as fast as C/C++ without that bug class? Java, Go and C# are memory-safe thanks to garbage collection, but at the cost of a runtime and unpredictable latency, unsuitable for OS kernels or codecs. Rust takes a different path: memory safety is checked at compile time, with no garbage collector. And there is now large-scale real-world data showing how well that works.
Three core rules
| Rule | What it says | What it prevents |
|---|---|---|
| Ownership | Every value has exactly one owner; when the owner goes out of scope, memory is freed automatically | Double frees, forgotten frees |
| Borrowing | At any moment: either many read-only references or exactly one mutable reference | Data races, mutating data while it's being read |
| Lifetimes | A reference can't outlive the data it points to | Use-after-free, dangling pointers |
let s = String::from("hello");
let r = &s;
drop(s); // compile error: s is borrowed by r
println!("{}", r);
The equivalent C compiles and causes a use-after-free; in Rust, the compiler rejects it outright.
Other layers of protection
- Bounds checks: out-of-range array access panics (a controlled stop) instead of reading or writing stray memory.
- No null: possibly-absent values use
Option, which forces you to handle both cases. - Mandatory initialisation: you can't read a variable that hasn't been assigned.
- Thread safety: the type system (
Send,Sync) prevents unsafe sharing of data across threads.
Real-world data from Android
Google published these numbers after putting around 5 million lines of Rust into the Android platform:
| Metric | Rust vs C/C++ |
|---|---|
| Memory safety vulnerability density | About 0.2 vs about 1,000 per million lines: roughly a 1000× reduction |
| Rollback rate (medium and large changes) | About 4× lower |
| Time in code review | About 25% less |
| Revisions before approval | About 20% fewer |
The striking part: safer and faster, not a trade-off.
unsafe: a controlled escape hatch
Some things the compiler can't prove safe (calling C, touching hardware, special optimisations). Rust lets you mark an unsafe block. In Android, unsafe makes up about 4% of the code. Android's first Rust memory safety vulnerability (CVE-2025-48530, a buffer overflow in CrabbyAVIF) was in this kind of code; it was patched before release, and the Scudo allocator had made it non-exploitable. Google argues unsafe Rust is still less risky than C because unsafe blocks don't disable most checks, are encapsulated for local reasoning, and get extra review.
What Rust doesn't prevent
- Logic bugs, broken authorisation, injection.
- Memory leaks (considered "safe" by the language) and deadlocks.
- Panics on out-of-bounds access: not exploitable, but they can still take a service down.
- Bugs inside
unsafeblocks and in C libraries called through FFI.
How to apply it
- Dev: Learn ownership and borrowing first (chapter 4 of The Rust Book); it's where you "fight the compiler" at first, and it's the reason Rust is safe.
- Tech Lead: Set review rules for every
unsafeblock: a required comment explaining why it's sound, kept small and encapsulated. - PM: Use Android's data (fewer rollbacks, faster reviews) to see Rust as a productivity gain, not just a security cost.
Sources & references
- Rust in Android: move fast and fix things — Google Security Blog
- What is Ownership? (The Rust Programming Language) — Rust Project