← Chrome — 2026-W40

fa43f625042ace39040e4caebdcc520fc8c2ba53  [M155] Reinsert PatternData into pattern map after reconstruction

severity high class UAF confidence 0.9 signal score 6.8 third_party/blink/renderer/core/ patch-now AI review CONFIRMED
Primitive: dangling unique_ptr& slot in pattern_map_ cleared during BuildPatternData
Triage note: Identical to 67f6fef1e4, M155 cherry-pick: the unique_ptr<PatternData>& into pattern_map_ is invalidated when BuildPatternData() clears the map, then written through. Fix re-inserts via Set(). SVG patterns web-reachable.
Structural signals: security_assert (+3.0), area:third_party/blink/renderer/core/ (+2.5), surgical (+1.3)

The bug at a glance

Use-after-free in Blink SVG paint-server layout, reachable from any page that renders an SVG . A dangling reference into a LayoutSVGResourcePattern::pattern_map_ hash-table slot was written through after BuildPatternData re-entrantly cleared/rehashed the map. UAF-write in the renderer is a strong exploitation primitive; High. M155 release-branch cherry-pick (identical code to the M154 pick 67f6fef1e4).

Same iterator/reference-invalidation UAF as 67f6fef1e4: pattern_map_.insert(&client, nullptr).stored_value->value handed out a std::unique_ptr& into a hash-table slot, and BuildPatternData() can re-enter and clear/rehash pattern_map_, invalidating it. This is the M155 release-branch (refs/branch-heads/8059) cherry-pick of the same main fix dedbd3f9dee8.

Root cause

Identical to 67f6fef1e4: a std::unique_ptr& bound to pattern_map_.insert(…).stored_value->value was written through after BuildPatternData could clear/rehash pattern_map_, a UAF write into a freed/moved bucket. The fix does find() up front, builds into a local new_pattern_data, CHECK()s it, and re-inserts via pattern_map_.Set(&client, std::move(new_pattern_data)) after reconstruction, so no reference spans the re-entrant mutation.

Key code

layout_svg_resource_pattern.cc: don’t hold a map-slot reference across BuildPatternData; Set() afterward

  auto iter = pattern_map_.find(&client);
  PatternData* pattern_data =
      (iter == pattern_map_.end() ? nullptr : iter->value.get());
  if (pattern_data && pattern_data->paint_flags != paint_flags) {
    pattern_data = nullptr;
  }
  if (!pattern_data) {
    auto new_pattern_data = BuildPatternData(reference_box, paint_flags);
    pattern_data = new_pattern_data.get();
    CHECK(pattern_data);
    pattern_map_.Set(&client, std::move(new_pattern_data));
    pattern_data->paint_flags = paint_flags;
  }

Patch walkthrough

  • third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc — The only code change; byte-identical to 67f6fef1e4. M155 branch cherry-pick of main commit dedbd3f9dee8 (Fixed: 565742179, branch bug 567399346).

Background

LayoutSVGResourcePattern / pattern_map_ — Blink layout object for an SVG paint server; pattern_map_ caches per-client std::unique_ptr.

WTF::HashMap AddResult / stored_value — insert() returns an AddResult whose stored_value points into the bucket; invalidated if the map is mutated before use.

BuildPatternData re-entrancy — Constructing pattern data can run layout/paint that clears pattern_map_, so a reference held across it may dangle.

Vulnerability window

  1. Main fix 2026-09-29 — dedbd3f9dee8 on main (CL 8464440), Fixed: 565742179.
  2. M155 cherry-pick — Cherry-picked to refs/branch-heads/8059 as fa43f62504 (CL 8485527, branch bug 567399346); identical code to the M154 pick 67f6fef1e4.

Proof of concept

No test or PoC ships in this cherry-pick diff. Conceptual trigger identical to 67f6fef1e4 (inferred): SVG painting where reconstruction re-enters and clears pattern_map_ while a reference into it is live. Web-reachable via ordinary SVG markup/CSS/script.

Exploitation

  1. Trigger — Paint an element using an SVG paint server and cause reconstruction to re-enter/clear pattern_map_ during BuildPatternData (inferred).
  2. Free / invalidate — The clear/rehash frees/moves the bucket the held reference pointed at (inferred).
  3. UAF write — Writing through the stale reference corrupts freed/reallocated heap; grooming could yield a controlled write (inferred).

Detection & hunting

For defenders and detection engineers:

  • Reference/iterator into a WTF::HashMap held across a mutating call — Flag map-slot references kept live across non-trivial calls; re-look-up or Set() afterward.
  • ASan heap-use-after-free WRITE in layout/svg paint-server code — Watch for UAF writes in LayoutSVGResourcePattern during pattern painting.

Audit directions

  • Sibling SVG paint servers — Review LayoutSVGResourceGradient and other LayoutSVGResourceContainer subclasses for the same held-reference pattern.
  • HashMap AddResult lifetime across callbacks — Grep Blink for .insert(…).stored_value held across functions that can mutate the same map.

Before / after

Loading diff…