MiraclePtr (BackupRefPtr)
A one-time architectural or governance choice whose consequences still govern current work.
The decision to wrap many non-owning C++ pointer fields in raw_ptr<T>, whose BackupRefPtr implementation uses PartitionAlloc metadata to keep freed allocations unavailable while dangling references still exist.
The names are easy to blur. MiraclePtr is the umbrella project name, BackupRefPtr is the shipped allocator-backed algorithm, and raw_ptr<T> is the type a Chromium contributor writes in code. The entry’s security claim depends on keeping those three levels separate.
Use-after-free bugs remain useful to attackers after Chromium’s process model has done its job. A renderer compromise is contained by the renderer sandbox; a browser-process use-after-free can sit on the privileged side of that split, close to cookies, profile data, file-system brokering, and IPC handlers. MiraclePtr is the Chromium project’s decision to make that bug class less exploitable in the existing C++ codebase without waiting for a full rewrite.
Decision Statement
Chromium chose to mitigate a large share of use-after-free bugs in existing C++ by replacing many unowned raw pointer fields with raw_ptr<T>. The type is a non-owning smart pointer whose BackupRefPtr implementation stores reference-count metadata in PartitionAlloc and quarantines freed allocations while any raw_ptr<T> still points at them.
Context
Temporal memory safety is the property that an address still refers to the object the program believes it refers to. A use-after-free violates that property: code frees an object, leaves a pointer behind, and later reads or writes through the stale pointer after the allocator has reused the memory for something else. In a browser, that stale pointer can become an attacker-shaped type confusion, a fake vtable, or a wrong object header at exactly the point where the privileged browser process is handling renderer-supplied data.
The long-term answer is to write less memory-unsafe C++. Chromium is doing that through Rust adoption, spanification of unsafe buffers, V8-specific containment, and process isolation. None of those removes the existing browser-process C++ heap. The project needed a retrofit: something deployable across millions of lines, compatible with ordinary C++ class fields, and narrow enough that the team could roll it out in the codebase while Chrome kept shipping on its four-week stable cadence.
The first major stable rollout enabled BackupRefPtr for the browser process on Windows and Android in Chrome 102. The current raw_ptr<T> reference documents protection as default-on in non-renderer processes on Android, Windows, ChromeOS, macOS, Linux, and Fuchsia, with exceptions for iOS and Linux CastOS. Renderer-only code remains the hardest boundary because the renderer is hot, attacker-influenced, and performance-sensitive.
Alternatives Considered
| Alternative | Description | Reason rejected |
|---|---|---|
Keep raw T* fields plus review discipline | Continue using ordinary non-owning C++ pointers and rely on code review, tests, fuzzing, and AddressSanitizer-style discovery to catch lifetime errors. | Review finds individual bugs; it doesn’t change the exploitability of the class. A large C++ codebase keeps creating new lifetime edges, and a privileged browser-process use-after-free remains a high-value link in an exploit chain. |
| *Scan heap quarantine | Put freed memory in quarantine, scan the heap for remaining references, and release a block only after the scanner finds no pointers into it. | The May 2022 Google Security blog experiment found meaningful memory cost in renderer-process tests: about 12 percent memory regression for *Scan without hardware help. The scanner also has race and scheduling complexity because it has to inspect a mutating heap. |
| Hardware Memory Tagging Extension | Use ARM MTE tags to detect stale pointers when the pointer tag no longer matches the allocation tag. | MTE depends on hardware support that Chromium cannot assume across its installed base. The published prototype results were promising, but the project still needed a software mechanism for devices without MTE and for platforms outside that hardware family. |
BackupRefPtr through raw_ptr<T> (chosen) | Add ref-count metadata to PartitionAlloc allocations, replace eligible non-owning pointer fields with raw_ptr<T>, and quarantine freed memory while dangling references remain. | It required no new hardware, fit existing C++ field declarations, could be enforced by tooling, and gave the project a measurable reduction in exploitability while preserving most call-site behavior. The cost moved into memory overhead and pointer construction, assignment, and destruction rather than into every dereference. |
Rationale
The chosen design changed the outcome of the bug class without pretending to solve ownership. raw_ptr<T> is still non-owning. The owner still frees the object at the correct time, and dereferencing a dangling raw_ptr<T> is still undefined behavior. The security gain is narrower: when the owner frees a PartitionAlloc-backed object and a raw_ptr<T> still points at it, BackupRefPtr keeps the allocation out of reuse and poisons it with the 0xEF pattern. The stale access is more likely to crash or leak memory than to become a controlled write into a new attacker-shaped object.
That narrowness is why the retrofit worked. In most class and struct fields, the code change is a type replacement: T* member_ becomes raw_ptr<T> member_. The type keeps the pointer-sized representation, supports ordinary dereference and arrow access, and avoids adding cost to the dereference itself. The cost appears when the pointer is constructed, assigned, moved, or destroyed, because BackupRefPtr has to maintain allocator-side metadata and check that pointer arithmetic stays within the allocation.
The decision also kept the rollout enforceable. Chromium’s style guide and Clang plugin steer eligible class and struct fields toward raw_ptr<T>, with named escape hatches such as RAW_PTR_EXCLUSION for cases that cannot compile, point outside protected memory, sit in renderer-only paths, or have measured performance regressions. An escape hatch is not a second design path. It is a documented exception that reviewers can audit.
Ongoing Consequences
For Chromium contributors, the rule is now visible in code review. A non-owning class or struct field in non-renderer Chromium C++ is expected to use raw_ptr<T> unless one of the documented exceptions applies. Function pointers, Objective-C object pointers, pointers into stack memory, shared memory, mmap regions, V8 heaps, Oilpan heaps, Java heaps, and other non-PartitionAlloc-managed memory are not protected by BackupRefPtr and may need a different representation or a documented exclusion. The pointer’s ownership story still has to be correct; MiraclePtr doesn’t turn a borrower into an owner.
For security response, the change lowers the value of a browser-process use-after-free. The September 2022 Google Security blog post described MiraclePtr as protecting roughly half of known exploitable use-after-free issues against exploitation. That doesn’t mean half of lifetime bugs disappeared. It means many stale accesses that would once have reached attacker-controlled replacement memory instead hit quarantined or poisoned memory and crash in a way the project can debug.
For performance and memory budgets, the decision spends some of the savings PartitionAlloc produced elsewhere. The 2022 rollout account reported browser-process memory increases in the low single digits, with the Google post naming about 4.5 to 6.5 percent on Windows and about 3.5 to 5 percent on Android. The same post notes that PartitionAlloc work had recently produced larger memory savings, so the project spent part of that budget on temporal safety. That exchange matters for downstream products: on memory-constrained fleets, MiraclePtr’s cost lives beside Memory Pressure Response, tab discard rate, and process-consolidation thresholds.
For exploit-chain reasoning, MiraclePtr mostly hardens the browser-process link. A renderer-side V8 bug still has its own containment story in the V8 Heap Sandbox, trusted-space partitioning, CFI, and site/process isolation. A browser-process use-after-free in a Mojo handler is different. It is close to the third link of the Sandbox Escape Chain, the point where a renderer primitive tries to cross into privileged code. MiraclePtr makes that link harder to turn into controlled memory reuse.
For downstream Chromium consumers, the decision is inherited only when the product consumes the relevant Chromium version, build flags, allocator configuration, and process class. A fork that carries custom browser-process C++ with ordinary T* fields can reintroduce the older exposure even while upstream has moved. An Electron, WebView2, enterprise-browser, or embedded-runtime team auditing custom code should treat RAW_PTR_EXCLUSION and RawPtrManualPathsToIgnore.h entries as security debt unless the exception is mechanical and documented.
The decision also creates a debugging obligation. A crash inside RawPtrBackupRefImpl::AcquireInternal() or ReleaseInternal() is not noise to be papered over with a cast or an exclusion. It is often the runtime signal that a pointer lifetime assumption was false. The right response is to fix the lifetime model or use the documented short-lived adapter for an in-out argument, not to restore a raw pointer because the raw pointer compiled.
Reversal Conditions
The decision could be revisited if a stronger temporal-safety mechanism became deployable across Chromium’s supported platforms at lower cost. Universal hardware memory tagging with deterministic properties would qualify, but today’s MTE story is platform-bound and still needs software fallback. A memory-safe rewrite of the browser-process C++ surface would also qualify, but that is a multi-year migration rather than a replacement for a retrofit.
The decision could also be narrowed if its overhead stopped fitting the product budget. That would require a measured regression severe enough that the project could not recover the cost through allocator work, process tuning, or targeted exceptions. The current direction points the other way: Chromium’s 2026 quarterly security updates describe continuing memory-safety work around PartitionAlloc, Skia, Rust, and Safe Buffers rather than a retreat from MiraclePtr.
What should not trigger reversal is a single false positive or a local compile problem. The raw_ptr<T> reference already documents recoverable compile-time problems, kMayDangle aliases for known legacy patterns, and explicit exclusions for unsupported cases. Those are local escape valves around a standing decision, not reasons to abandon the decision.
Notes for Agent Context
When editing Chromium C++ outside renderer-only paths, use raw_ptr<T> for non-owning class and struct fields that point to PartitionAlloc-managed heap objects. Don’t use raw_ptr<T> to express ownership: use std::unique_ptr, scoped_refptr, or another owning type when the field owns the object, and keep lifetime analysis explicit because raw_ptr<T> doesn’t free the pointee. Don’t add RAW_PTR_EXCLUSION, RawPtrManualPathsToIgnore.h, DisableDanglingPtrDetection, or DanglingUntriaged unless the documented exception applies and the reason is written next to the field. When an API needs a T** or T*& out parameter, don’t take the address of a raw_ptr<T> directly; refactor the callee to accept raw_ptr<T>* or use AsEphemeralRawAddr() only for the one full expression the reference permits.
Related Articles
Sources
The canonical implementation reference is Chromium’s own base/memory/raw_ptr.md, whose current title names the type as raw_ptr<T> and the aliases MiraclePtr, BackupRefPtr, and BRP. It documents the quick rules, the non-owning semantics, the BackupRefPtr quarantine-and-poison mechanism, the default process coverage, and the documented exception paths.
The public decision record is the Google Online Security Blog post Use-after-freedom: MiraclePtr by Adrian Taylor, Bartek Nowierski, and Kentaro Hara on behalf of the MiraclePtr team, published September 13, 2022. It records the Chrome 102 browser-process rollout on Windows and Android, the rough use-after-free coverage target, the memory-overhead tradeoff, and the browser-process focus.
The main rejected-alternative record is the Google Online Security Blog post Retrofitting Temporal Memory Safety on C++ by Anton Bikineev, Michael Lippautz, and Hannes Payer, published May 26, 2022. It explains the *Scan heap-scanning family, the renderer-process memory regression observed in experiments, and the MTE prototype results that made hardware tagging promising but insufficient as the general rollout answer.
Chromium’s Security Quarterly Updates provide the current deployment ledger. The Q4 2025 and Q1 2026 entries place MiraclePtr beside spanification, Rust migration, V8 sandbox hardening, and PartitionAlloc adoption in dependencies such as Skia. That ledger is useful because MiraclePtr is a living mitigation, not a one-time blog post.
Technical Drill-Down
base/memory/raw_ptr.md(pinnedd009a0e) — the contributor-facing reference forraw_ptr<T>usage, exceptions, performance notes, and dangling-pointer detection.base/memory/raw_ptr.h(pinnedd009a0e) — the wrapper type and trait surface Chromium code includes.build_overrides/partition_alloc.gni(pinnedd009a0e) — one of the build-argument sources theraw_ptr<T>reference names for BackupRefPtr support and feature-flag state.base/allocator/partition_allocator/partition_alloc.gni(pinnedd009a0e) — allocator build configuration for the PartitionAlloc features BackupRefPtr depends on.tools/clang/raw_ptr_plugin/RawPtrManualPathsToIgnore.h(pinnedd009a0e) — the directory-level exclusion mechanism; any use here should be treated as a reviewable exception, not a default.docs/dangling_ptr.md(pinnedd009a0e) — the dangling-pointer detection guide referenced byraw_ptr<T>forkMayDangleand related aliases.- Google Online Security Blog: Use-after-freedom: MiraclePtr, September 2022 — public rollout rationale, coverage claim, and memory-overhead tradeoff.
- Google Online Security Blog: Retrofitting Temporal Memory Safety on C++, May 2022 — *Scan and MTE experimental context, including why heap scanning and hardware tagging did not become the general retrofit on their own.
- Chromium Security Quarterly Updates — ongoing deployment ledger for memory-safety work around PartitionAlloc, Skia, Rust, Safe Buffers, and V8 hardening.