System Design

MiraclePtr: how Chrome blocks use-after-free in C++

TL;DR

Half of Chrome's exploitable bugs are use-after-free. raw_ptr (MiraclePtr) holds back and poisons memory that still has dangling pointers, expected to block exploitation of about 50% of UAF bugs in the browser process for 3.5–6.5% more memory.

In Chrome, half of the known exploitable bugs are use-after-free (UAF): code keeps a pointer to memory that has already been freed, and an attacker refills that memory with their own data. Chrome has tens of millions of lines of C++ that cannot be rewritten in a few years. The Chrome security team took another route: replace raw pointers in class fields with a lightweight smart pointer, raw_ptr<T>, which implements the BackupRefPtr algorithm from the MiraclePtr project. The goal: make roughly 50% of UAF bugs in the browser process non-exploitable.

Mechanism: a hidden reference count and quarantine

  1. Hidden reference count: the PartitionAlloc allocator reserves extra space in each allocation for a counter. Whenever a raw_ptr<T> is constructed, destroyed or assigned, the counter goes up or down.
  2. Quarantine: if memory is freed while the count is still above zero (a dangling pointer exists), PartitionAlloc does not hand it back for reuse; it holds on to it.
  3. Poisoning: quarantined memory is overwritten with the pattern 0xEF..EF, so reads through a dangling pointer tend to crash, which helps find and fix the bug.
  4. Real release: only when the count reaches zero is the memory reused.

The clever part: exploiting a UAF requires the attacker to reclaim the freed memory. When that memory is held back and poisoned, the crucial step fails.

class Widget {
  raw_ptr<Delegate> delegate_;   // instead of Delegate* delegate_;
};

Cost: real numbers

ItemResult (Chrome 99–102)
Browser process memory+4.5–6.5% on Windows, +3.5–5% on Android
Quarantined memoryAbout 0.01% of browser process memory
Windows performanceNo statistically significant regression on most top-level metrics; main-thread contention up about 7%
Android performanceMain-thread contention +6%, First Input Delay +1%, First Contentful Paint +0.5%
Pointer sizeSame as a raw pointer; dereferencing costs nothing extra

Most of the memory cost comes from the 4-byte counter per allocation, which sometimes pushes an allocation into a larger bucket. The Chrome team offset it with earlier PartitionAlloc work that had saved 10–25% of memory.

Rollout at Chrome scale

  • More than 15,000 raw pointers were rewritten to raw_ptr<T>.
  • Enabled for the browser process on Windows and Android from Chrome 102; current documentation says it is on by default in non-renderer processes on Android, Windows, ChromeOS, macOS, Linux and Fuchsia.
  • Style rule: class/struct fields use raw_ptr<T> instead of T* (except renderer-only code), enforced automatically by Chromium's Clang plugin. Locals, parameters and return values stay raw.

Risks and limits

  • Not everything is covered: only class/struct fields are protected; local pointers, pointers in unions and memory outside PartitionAlloc (stack, V8 heap…) are not.
  • Still undefined behaviour: reading a dangling pointer is still a bug; MiraclePtr only makes it harder to exploit.
  • Quarantine leaks: per the Chromium docs, memory held back by dangling pointers has caused significant leaks a couple of times.
  • Bug bounty: at launch, Chrome said MiraclePtr would not factor into bug severity until it reached all users.

How to apply it

  • Dev: If your C++ project has many long-lived objects referencing each other, that is where UAF lives. Audit non-owning pointer fields and consider smart pointers or an allocator with quarantine.
  • Tech Lead: Copy Chrome's playbook: a clear rule (class fields use a safe type), automated enforcement, an exemption process with recorded reasons, and A/B performance testing before a broad rollout.
  • PM: Paying around 5% memory to remove exploitability from half of the most dangerous bug class is a good trade. Decide with measurements like Chrome did, not gut feeling.

Sources & references

  1. Use-after-freedom: MiraclePtr — Google Security Blog
  2. raw_ptr<T> (aka MiraclePtr, aka BackupRefPtr) — Chromium