← Chrome — 2026-W32

c319604d382409129f78d2f7a3da118a5bee259f  [M151] Sanitize presentation attribute cache hash using EnsureValidHash

severity low class UAF CVSS 8.1 signal score 3.8 third_party/blink/renderer/core/ patch-now AI review CONFIRMED
Structural signals: area:third_party/blink/renderer/core/ (+2.5), surgical (+1.3)

The bug at a glance

A hash collision with the HashTraits DeletedValue sentinel (0xFFFFFFFF) causes an Oilpan HeapHashMap bucket to be treated as deleted and skipped during tracing, so a live CSSPropertyValueSet is swept while still referenced, yielding a use-after-free returned from a web-reachable cache lookup. High because presentation attributes are fully web-content reachable, tempered from critical by the probabilistic hash condition.

An attacker crafts elements/attributes so ComputePresentationAttributeCacheHash produces 0xFFFFFFFF, poisoning the presentation-attribute cache bucket so a later lookup for the same key returns a freed CSSPropertyValueSet the renderer then uses.

Root cause

ComputePresentationAttributeCacheHash returned HashInts(…) directly, without routing through EnsureValidHash which maps the HashTraits sentinel values 0 and 0xFFFFFFFF to safe ones. When the computed hash equals 0xFFFFFFFF (the DeletedValue sentinel), the entry is stored in a HeapHashMap bucket that Oilpan treats as deleted; GC then skips tracing that bucket, so the referenced CSSPropertyValueSet is swept even though the map still holds a Member to it. A subsequent cache lookup for the same element key returns the dangling (freed) CSSPropertyValueSet pointer, a use-after-free. The fix wraps the result in EnsureValidHash, matching ElementDataCache and MatchedPropertiesCache.

Key code

Filter sentinel hashes (0 / 0xFFFFFFFF) via EnsureValidHash

-  return HashInts(key.tag_name->ExistingHash(), attribute_hash);
+  return EnsureValidHash(
+      HashInts(key.tag_name->ExistingHash(), attribute_hash));

Patch walkthrough

  • third_party/blink/renderer/core/dom/presentation_attribute_style.cc — Wraps the presentation-attribute cache hash in EnsureValidHash and includes hash_traits.h, preventing the hash from equaling the HashTraits empty(0)/deleted(0xFFFFFFFF) sentinels that would make a HeapHashMap bucket be treated as deleted and skipped by Oilpan tracing, which would otherwise free a still-referenced CSSPropertyValueSet and cause a UAF on the next lookup.

Background

Presentation attribute cache — A HeapHashMap cache mapping element presentation-attribute keys to computed CSSPropertyValueSet style objects.

EnsureValidHash — WTF helper that remaps the reserved HashTraits sentinel hashes (0 empty, 0xFFFFFFFF deleted) to valid non-sentinel values.

Oilpan HeapHashMap tracing — Garbage collection traces live buckets; buckets whose hash equals the deleted sentinel are treated as deleted and not traced, so their referents can be swept.

CSSPropertyValueSet — Oilpan-managed object holding parsed CSS declarations; here cached per element presentation-attribute signature.

Vulnerability window

  1. Reachability — A page sets presentation attributes on elements, populating the presentation-attribute style cache.
  2. Trigger — Attributes are chosen so ComputePresentationAttributeCacheHash yields 0xFFFFFFFF, storing the entry in a bucket Oilpan treats as deleted.
  3. Primitive — GC skips tracing the poisoned bucket and sweeps the still-referenced CSSPropertyValueSet, leaving a dangling Member; a later lookup returns the freed pointer (use-after-free).
  4. Escalation — Reclaiming the freed CSSPropertyValueSet allocation could enable type confusion or a write primitive toward renderer compromise (inferred).

Proof of concept

Conceptually: create elements whose tag name and presentation-attribute set hash to 0xFFFFFFFF so the cache bucket is marked deleted, force a garbage collection to sweep the referenced style object, then re-query the same element/attribute signature so the cache returns the freed CSSPropertyValueSet. Finding the colliding attribute set is the main effort; no weaponized trigger is provided.

Exploitation

  1. Hash grind — Search for a tag/attribute combination whose computed hash equals the 0xFFFFFFFF deleted sentinel (inferred).
  2. Poison cache — Insert that element to place its CSSPropertyValueSet in a bucket Oilpan will treat as deleted.
  3. Sweep — Trigger GC so the still-referenced style object is swept, creating a dangling Member.
  4. Use — Re-trigger a cache lookup for the same key and leverage the returned freed pointer (inferred).

Detection & hunting

For defenders and detection engineers:

  • grep for HashInts(…) returns feeding HeapHashMap keys without EnsureValidHash — Audit cache hash computations in blink that store Oilpan Member values; any unfiltered hash can hit the 0/0xFFFFFFFF sentinels.
  • ASAN/Oilpan UAF on CSSPropertyValueSet from presentation-attribute style lookups — Fuzz elements with varied presentation attributes plus forced GC and watch for swept-while-referenced style objects.

Audit directions

  • Other blink HeapHashMap caches keyed by a custom hash — Verify each hash passes through EnsureValidHash before use, as ElementDataCache and MatchedPropertiesCache do.
  • Custom HashTraits with sentinel 0/0xFFFFFFFF over Oilpan Members — Confirm no code path can produce a key hash colliding with the empty/deleted sentinels and silently drop tracing.

Before / after

Loading diff…