Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in Animation
DescriptionUse after free in Animation
ComponentAnimation
Bug ClassUAF
Tracker407328533
Fix commit3dc8b5b36eaa (chromium/src) +357/-252
CISA KEVNot listed
CreditedLyra Rebane (rebane2001)
Disclosed2025-06-24

Changed Functions

FunctionChangeNotes
if
third_party/blink/renderer/core/animation/css/css_animations.cc
modified

Files Changed

  • third_party/blink/renderer/core/animation/BUILD.gn
  • third_party/blink/renderer/core/animation/animation_test.cc
  • third_party/blink/renderer/core/animation/css/css_animations.cc
  • third_party/blink/renderer/core/animation/css_aspect_ratio_interpolation_type.cc
  • third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc
  • third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc
  • third_party/blink/renderer/core/animation/css_clip_interpolation_type.cc
  • third_party/blink/renderer/core/animation/css_color_interpolation_type.cc
  • third_party/blink/renderer/core/animation/css_content_visibility_interpolation_type.cc
  • third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc
From 3dc8b5b36eaa1d68f5caa5e36444fcb3e204d460 Mon Sep 17 00:00:00 2001
From: Robert Flack <[email protected]>
Date: Wed, 07 May 2025 05:39:51 -0700
Subject: [PATCH] Make InterpolationType GarbageCollected.

Active interpolations keep pointers to the InterpolationType
however the referenced type can be deleted by calls to
blink::PropertyRegistry::RemoveDeclaredProperties.
Instead, we make InterpolationType garbage collected
so that active interpolations can safely use the old
interpolation type until it is updated.

Bug: 407328533
Change-Id: Ifb7661a4c663cbefadb9216221e679ad0e9eab97
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6511917
Reviewed-by: Kevin Ellis <[email protected]>
Reviewed-by: Anders Hartvoll Ruud <[email protected]>
Commit-Queue: Robert Flack <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1456895}
---

diff --git a/third_party/blink/renderer/core/animation/BUILD.gn b/third_party/blink/renderer/core/animation/BUILD.gn
index 2d3b681..7fc03e4a 100644
--- a/third_party/blink/renderer/core/animation/BUILD.gn
+++ b/third_party/blink/renderer/core/animation/BUILD.gn
@@ -232,6 +232,7 @@
     "interpolation.h",
     "interpolation_effect.cc",
     "interpolation_effect.h",
+    "interpolation_type.cc",
     "interpolation_type.h",
     "interpolation_types_map.cc",
     "interpolation_types_map.h",
diff --git a/third_party/blink/renderer/core/animation/animation_test.cc b/third_party/blink/renderer/core/animation/animation_test.cc
index e3d8321..ee03a2f7 100644
--- a/third_party/blink/renderer/core/animation/animation_test.cc
+++ b/third_party/blink/renderer/core/animation/animation_test.cc
@@ -113,7 +113,9 @@
 
   KeyframeEffectModelBase* MakeSimpleEffectModel() {
     PropertyHandle PropertyHandleOpacity(GetCSSPropertyOpacity());
-    static CSSNumberInterpolationType opacity_type(PropertyHandleOpacity);
+    CSSNumberInterpolationType* opacity_type(
+        MakeGarbageCollected<CSSNumberInterpolationType>(
+            PropertyHandleOpacity));
     TransitionKeyframe* start_keyframe =
         MakeGarbageCollected<TransitionKeyframe>(PropertyHandleOpacity);
     start_keyframe->SetValue(MakeGarbageCollected<TypedInterpolationValue>(
diff --git a/third_party/blink/renderer/core/animation/css/css_animations.cc b/third_party/blink/renderer/core/animation/css/css_animations.cc
index 6e7c888..baaad0a 100644
--- a/third_party/blink/renderer/core/animation/css/css_animations.cc
+++ b/third_party/blink/renderer/core/animation/css/css_animations.cc
@@ -2523,9 +2523,9 @@
   InterpolationValue end = nullptr;
   bool discrete_interpolation = true;
 
-  for (const auto& interpolation_type : map.Get(property)) {
+  for (const auto& interpolation_type : *map.Get(property)) {
     start = interpolation_type->MaybeConvertUnderlyingValue(old_environment);
-    transition_type = interpolation_type.get();
+    transition_type = interpolation_type.Get();
     if (!start) {
       continue;
     }
@@ -2624,7 +2624,7 @@
   TransitionKeyframe* start_keyframe =
       MakeGarbageCollected<TransitionKeyframe>(property);
   start_keyframe->SetValue(MakeGarbageCollected<TypedInterpolationValue>(
-      *transition_type, start.interpolable_value->Clone(),
+      transition_type, start.interpolable_value->Clone(),
       start.non_interpolable_value));
   start_keyframe->SetOffset(0);
   keyframes.push_back(start_keyframe);
@@ -2632,7 +2632,7 @@
   TransitionKeyframe* end_keyframe =
       MakeGarbageCollected<TransitionKeyframe>(property);
   end_keyframe->SetValue(MakeGarbageCollected<TypedInterpolationValue>(
-      *transition_type, end.interpolable_value->Clone(),
+      transition_type, end.interpolable_value->Clone(),
       end.non_interpolable_value));
   end_keyframe->SetOffset(1);
   keyframes.push_back(end_keyframe);
diff --git a/third_party/blink/renderer/core/animation/css_aspect_ratio_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_aspect_ratio_interpolation_type.cc
index cd918d0..e915847f 100644
--- a/third_party/blink/renderer/core/animation/css_aspect_ratio_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_aspect_ratio_interpolation_type.cc
@@ -9,6 +9,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "third_party/blink/renderer/core/animation/interpolable_aspect_ratio.h"
+#include "third_party/blink/renderer/core/animation/underlying_value_owner.h"
 #include "third_party/blink/renderer/core/css/resolver/style_builder_converter.h"
 #include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
 #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
diff --git a/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc
index 192d5cc..39060f0 100644
--- a/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc
@@ -10,6 +10,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/values_equivalent.h"
 #include "third_party/blink/renderer/core/animation/basic_shape_interpolation_functions.h"
+#include "third_party/blink/renderer/core/animation/underlying_value_owner.h"
 #include "third_party/blink/renderer/core/css/css_property_names.h"
 #include "third_party/blink/renderer/core/css/css_value_list.h"
 #include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
@@ -207,7 +208,7 @@
   if (!basic_shape_interpolation_functions::ShapesAreCompatible(
           *underlying_value_owner.Value().non_interpolable_value,
           *value.non_interpolable_value)) {
-    underlying_value_owner.Set(*this, value);
+    underlying_value_owner.Set(this, value);
     return;
   }
 
diff --git a/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc
index ac7d09d..59cd9a3f 100644
--- a/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/core/animation/interpolable_length.h"
 #include "third_party/blink/renderer/core/animation/list_interpolation_functions.h"
 #include "third_party/blink/renderer/core/animation/side_index.h"
+#include "third_party/blink/renderer/core/animation/underlying_value_owner.h"
 #include "third_party/blink/renderer/core/css/css_identifier_value.h"
 #include "third_party/blink/renderer/core/css/css_math_function_value.h"
 #include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
@@ -375,7 +376,7 @@
     const InterpolationValue& value,
     double interpolation_fraction) const {
   ListInterpolationFunctions::Composite(
-      underlying_value_owner, underlying_fraction, *this, value,
+      underlying_value_owner, underlying_fraction, this, value,
       ListInterpolationFunctions::LengthMatchingStrategy::kEqual,
       ListInterpolationFunctions::InterpolableValuesKnownCompatible,
       NonInterpolableSidesAreCompatible, CompositeSide);
diff --git a/third_party/blink/renderer/core/animation/css_clip_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_clip_interpolation_type.cc
index 03f3060..3330d88 100644
--- a/third_party/blink/renderer/core/animation/css_clip_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_clip_interpolation_type.cc
@@ -9,6 +9,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "third_party/blink/renderer/core/animation/interpolable_length.h"
+#include "third_party/blink/renderer/core/animation/underlying_value_owner.h"
 #include "third_party/blink/renderer/core/css/css_identifier_value.h"
 #include "third_party/blink/renderer/core/css/css_quad_value.h"
 #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
@@ -272,7 +273,7 @@
     underlying_value_owner.MutableValue().interpolable_value->ScaleAndAdd(
         underlying_fraction, *value.interpolable_value);
   else
-    underlying_value_owner.Set(*this, value);
+    underlying_value_owner.Set(this, value);
 }
 
 void CSSClipInterpolationType::ApplyStandardPropertyValue(
diff --git a/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc
index 2f2eb63..e7ea00e 100644
--- a/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/core/animation/color_property_functions.h"
 #include "third_party/blink/renderer/core/animation/interpolable_color.h"
 #include "third_party/blink/renderer/core/animation/interpolable_value.h"
+#include "third_party/blink/renderer/core/animation/underlying_value_owner.h"
 #include "third_party/blink/renderer/core/css/css_color.h"
 #include "third_party/blink/renderer/core/css/css_identifier_value.h"
 #include "third_party/blink/renderer/core/css/resolver/style_builder_converter.h"
diff --git a/third_party/blink/renderer/core/animation/css_content_visibility_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_content_visibility_interpolation_type.cc
index 83d6e976..e50ca54 100644
--- a/third_party/blink/renderer/core/animation/css_content_visibility_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_content_visibility_interpolation_type.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/memory/ptr_util.h"
+#include "third_party/blink/renderer/core/animation/underlying_value_owner.h"
 #include "third_party/blink/renderer/core/css/css_identifier_value_mappings.h"
 #include "third_party/blink/renderer/core/css/css_to_length_conversion_data.h"
 #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
@@ -201,7 +202,7 @@
     double underlying_fraction,
     const InterpolationValue& value,
     double interpolation_fraction) const {
-  underlying_value_owner.Set(*this, value);
+  underlying_value_owner.Set(this, value);
 }
 
 void CSSContentVisibilityInterpolationType::ApplyStandardPropertyValue(
diff --git a/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc
index d4ec374..636f986 100644
--- a/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc
@@ -6,6 +6,7 @@
 
 #include "third_party/blink/renderer/core/animation/interpolable_length.h"
 #include "third_party/blink/renderer/core/animation/underlying_length_checker.h"
+#include "third_party/blink/renderer/core/animation/underlying_value_owner.h"
 #include "third_party/blink/renderer/core/css/css_primitive_value.h"
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/third_party/blink/renderer/core/animation/animation_test.cc b/third_party/blink/renderer/core/animation/animation_test.cc
index e3d8321..ee03a2f7 100644
--- a/third_party/blink/renderer/core/animation/animation_test.cc
+++ b/third_party/blink/renderer/core/animation/animation_test.cc
@@ -113,7 +113,9 @@
 
   KeyframeEffectModelBase* MakeSimpleEffectModel() {
     PropertyHandle PropertyHandleOpacity(GetCSSPropertyOpacity());
-    static CSSNumberInterpolationType opacity_type(PropertyHandleOpacity);
+    CSSNumberInterpolationType* opacity_type(
+        MakeGarbageCollected<CSSNumberInterpolationType>(
+            PropertyHandleOpacity));
     TransitionKeyframe* start_keyframe =
         MakeGarbageCollected<TransitionKeyframe>(PropertyHandleOpacity);
     start_keyframe->SetValue(MakeGarbageCollected<TypedInterpolationValue>(
diff --git a/third_party/blink/renderer/core/animation/css_dynamic_range_limit_interpolation_type_test.cc b/third_party/blink/renderer/core/animation/css_dynamic_range_limit_interpolation_type_test.cc
index a4f22ad..6828138d 100644
--- a/third_party/blink/renderer/core/animation/css_dynamic_range_limit_interpolation_type_test.cc
+++ b/third_party/blink/renderer/core/animation/css_dynamic_range_limit_interpolation_type_test.cc
@@ -25,13 +25,14 @@
 
 class CSSDynamicRangeLimitInterpolationTypeTest : public PageTestBase {
  protected:
-  std::unique_ptr<CSSDynamicRangeLimitInterpolationType>
+  CSSDynamicRangeLimitInterpolationType*
   CreateDynamicRangeLimitInterpolationType() {
     ScopedCSSDynamicRangeLimitForTest scoped_feature(true);
     const CSSProperty& css_property =
         CSSProperty::Get(CSSPropertyID::kDynamicRangeLimit);
     PropertyHandle property = PropertyHandle(css_property);
-    return std::make_unique<CSSDynamicRangeLimitInterpolationType>(property);
+    return MakeGarbageCollected<CSSDynamicRangeLimitInterpolationType>(
+        property);
   }
 };
 
@@ -51,7 +52,7 @@
   StyleResolverState state(document, *element, nullptr,
                            StyleRequest(element->GetComputedStyle()));
 
-  std::unique_ptr<CSSDynamicRangeLimitInterpolationType>
+  CSSDynamicRangeLimitInterpolationType*
       dynamic_range_limit_interpolation_type =
           CreateDynamicRangeLimitInterpolationType();
 
@@ -68,7 +69,7 @@
 }
 
 TEST_F(CSSDynamicRangeLimitInterpolationTypeTest, MaybeConvertValue) {
-  std::unique_ptr<CSSDynamicRangeLimitInterpolationType>
+  CSSDynamicRangeLimitInterpolationType*
       dynamic_range_limit_interpolation_type =
           CreateDynamicRangeLimitInterpolationType();
   CSSDynamicRangeLimitInterpolationType::ConversionCheckers conversion_checkers;
diff --git a/third_party/blink/renderer/core/animation/css_font_palette_interpolation_type_test.cc b/third_party/blink/renderer/core/animation/css_font_palette_interpolation_type_test.cc
index 22a4ce6..36616d2f 100644
--- a/third_party/blink/renderer/core/animation/css_font_palette_interpolation_type_test.cc
+++ b/third_party/blink/renderer/core/animation/css_font_palette_interpolation_type_test.cc
@@ -25,12 +25,11 @@
 
 class CSSFontPaletteInterpolationTypeTest : public PageTestBase {
  protected:
-  std::unique_ptr<CSSFontPaletteInterpolationType>
-  CreateFontPaletteInterpolationType() {
+  CSSFontPaletteInterpolationType* CreateFontPaletteInterpolationType() {
     const CSSProperty& css_property =
         CSSProperty::Get(CSSPropertyID::kFontPalette);
     PropertyHandle property = PropertyHandle(css_property);
-    return std::make_unique<CSSFontPaletteInterpolationType>(property);
+    return MakeGarbageCollected<CSSFontPaletteInterpolationType>(property);
   }
 };
 
@@ -52,8 +51,8 @@
   StyleResolverState state(document, *element, nullptr,
                            StyleRequest(element->GetComputedStyle()));
 
-  std::unique_ptr<CSSFontPaletteInterpolationType>
-      font_palette_interpolation_type = CreateFontPaletteInterpolationType();
+  CSSFontPaletteInterpolationType* font_palette_interpolation_type =
+      CreateFontPaletteInterpolationType();
 
   InterpolationValue result = font_palette_interpolation_type
                                   ->MaybeConvertStandardPropertyUnderlyingValue(
@@ -68,8 +67,8 @@
 }
 
 TEST_F(CSSFontPaletteInterpolationTypeTest, MaybeConvertValue) {
-  std::unique_ptr<CSSFontPaletteInterpolationType>
-      font_palette_interpolation_type = CreateFontPaletteInterpolationType();
+  CSSFontPaletteInterpolationType* font_palette_interpolation_type =
+      CreateFontPaletteInterpolationType();
   CSSFontPaletteInterpolationType::ConversionCheckers conversion_checkers;
   CSSValue* value =
       MakeGarbageCollected<CSSCustomIdentValue>(AtomicString("--palette"));
diff --git a/third_party/blink/renderer/core/animation/interpolable_value_test.cc b/third_party/blink/renderer/core/animation/interpolable_value_test.cc
index 18ea596..22b02815 100644
--- a/third_party/blink/renderer/core/animation/interpolable_value_test.cc
+++ b/third_party/blink/renderer/core/animation/interpolable_value_test.cc
@@ -30,7 +30,8 @@
     // suffices for this, and also means we can ignore the AnimatableValues for
     // the compositor (as z-index isn't compositor-compatible).
     PropertyHandle property_handle(GetCSSPropertyZIndex());
-    CSSNumberInterpolationType interpolation_type(property_handle);
+    CSSNumberInterpolationType* interpolation_type(
+        MakeGarbageCollected<CSSNumberInterpolationType>(property_handle));
     InterpolationValue start(MakeGarbageCollected<InterpolableNumber>(a));
     InterpolationValue end(MakeGarbageCollected<InterpolableNumber>(b));
     TransitionInterpolation* i = MakeGarbageCollected<TransitionInterpolation>(
diff --git a/third_party/blink/renderer/core/animation/interpolation_effect_test.cc b/third_party/blink/renderer/core/animation/interpolation_effect_test.cc
index 28ecd696..88231a9 100644
--- a/third_party/blink/renderer/core/animation/interpolation_effect_test.cc
+++ b/third_party/blink/renderer/core/animation/interpolation_effect_test.cc
@@ -31,7 +31,8 @@
   // suffices for this, and also means we can ignore the AnimatableValues for
   // the compositor (as z-index isn't compositor-compatible).
   PropertyHandle property_handle(GetCSSPropertyZIndex());
-  CSSNumberInterpolationType interpolation_type(property_handle);
+  CSSNumberInterpolationType* interpolation_type(
+      MakeGarbageCollected<CSSNumberInterpolationType>(property_handle));
   InterpolationValue start(MakeGarbageCollected<InterpolableNumber>(from));
   InterpolationValue end(MakeGarbageCollected<InterpolableNumber>(to));
   return MakeGarbageCollected<TransitionInterpolation>(
diff --git a/third_party/blink/renderer/core/animation/interpolation_types_map_test.cc b/third_party/blink/renderer/core/animation/interpolation_types_map_test.cc
index a944bf08..1d2000b5 100644
--- a/third_party/blink/renderer/core/animation/interpolation_types_map_test.cc
+++ b/third_party/blink/renderer/core/animation/interpolation_types_map_test.cc
@@ -38,13 +38,13 @@
   InterpolationTypesMap map2(registry, *document2);
 
   PropertyHandle handle(property_name);
-  auto& types1 = map1.Get(handle);
-  auto& types2 = map2.Get(handle);
-  EXPECT_NE(&types1, &types2);
-  EXPECT_EQ(types1.size(), 1u);
+  const auto* types1 = map1.Get(handle);
+  const auto* types2 = map2.Get(handle);
+  EXPECT_NE(types1, types2);
+  EXPECT_EQ(types1->size(), 1u);
 
-  auto& types1_1 = map1.Get(handle);
-  EXPECT_EQ(&types1, &types1_1);
+  const auto* types1_1 = map1.Get(handle);
+  EXPECT_EQ(types1, types1_1);
 
   execution_context->NotifyContextDestroyed();
 }
diff --git a/third_party/blink/renderer/core/animation/list_interpolation_functions_test.cc b/third_party/blink/renderer/core/animation/list_interpolation_functions_test.cc
index 2bd232a..c29cade 100644
--- a/third_party/blink/renderer/core/animation/list_interpolation_functions_test.cc
+++ b/third_party/blink/renderer/core/animation/list_interpolation_functions_test.cc
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/core/animation/css_number_interpolation_type.h"
 #include "third_party/blink/renderer/core/animation/interpolation_value.h"
 #include "third_party/blink/renderer/core/animation/underlying_value.h"
+#include "third_party/blink/renderer/core/animation/underlying_value_owner.h"
 #include "third_party/blink/renderer/core/css/properties/longhands.h"
 #include "third_party/blink/renderer/platform/testing/task_environment.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -208,7 +209,8 @@
   auto list2 = CreateInterpolableList({{1.0, 1}, {2.0, 2}, {3.0, 3}});
 
   PropertyHandle property_handle(GetCSSPropertyZIndex());
-  CSSNumberInterpolationType interpolation_type(property_handle);
+  CSSNumberInterpolationType* interpolation_type(
+      MakeGarbageCollected<CSSNumberInterpolationType>(property_handle));
   UnderlyingValueOwner owner;
   owner.Set(interpolation_type, std::move(list1));
 
@@ -235,7 +237,8 @@
   auto list2 = CreateInterpolableList({4.0, 5.0});
 
   PropertyHandle property_handle(GetCSSPropertyZIndex());
-  CSSNumberInterpolationType interpolation_type(property_handle);
+  CSSNumberInterpolationType* interpolation_type(
+      MakeGarbageCollected<CSSNumberInterpolationType>(property_handle));
   UnderlyingValueOwner owner;
   owner.Set(interpolation_type, std::move(list1));
 
@@ -264,7 +267,8 @@
       {true, false, true});
 
   PropertyHandle property_handle(GetCSSPropertyZIndex());
-  CSSNumberInterpolationType interpolation_type(property_handle);
+  CSSNumberInterpolationType* interpolation_type(
+      MakeGarbageCollected<CSSNumberInterpolationType>(property_handle));
   UnderlyingValueOwner owner;
   owner.Set(interpolation_type, std::move(list1));
 
@@ -294,7 +298,8 @@
   auto list2 = CreateInterpolableList({{4.0, 1}, {5.0, 4}, {6.0, 3}});
 
   PropertyHandle property_handle(GetCSSPropertyZIndex());
-  CSSNumberInterpolationType interpolation_type(property_handle);
+  CSSNumberInterpolationType* interpolation_type(
+      MakeGarbageCollected<CSSNumberInterpolationType>(property_handle));
   UnderlyingValueOwner owner;
   owner.Set(interpolation_type, std::move(list1));
Loading diff…

Original Bug Report

reported by [email protected]

Security: heap-use-after-free in blink::TransitionInterpolation on CSS custom properties

VULNERABILITY DETAILS When transitioning a custom property with @starting-style, heap-use-after-free tab crashes in blink::TransitionInterpolation seem to be likely. I am not exactly sure what triggers the heap-uaf and how/whether it could be used, but I have found a reliable repro for this.

I am not sure whether this is an exploitable security bug, but since it is an uaf read I figured I’d report it anyways.

VERSION Chrome Version: 136.0.7091.2 Dev Operating System: Windows, Android

REPRODUCTION CASE Condensed down:

@property --crash {
  syntax: '<integer>';
  initial-value: 0;
  inherits: false;
}
* {
  transition: --crash 1000s;
  @starting-style {
    --crash: 1000000;
  }
}

I have also added a viewport in the included crash.html just in case.

This bug is reliably reproducible through DevTools:

  1. Open crash.html.
  2. Open devtools.
  3. Turn on the device toolbar.
  4. Wait a few seconds, turn the device toolbar off.
  5. Resize the devtools panel. Note that only the steps 1-3 are necessary for a crash, but steps 4-5 make the repro reliable.

On Android it can be reproduced as such:

  1. Open crash.html.
  2. Resize Chrome[1].
  3. Wait for a while Repro on Android is not reliable and takes a while, but doesn’t require DevTools or unrealistic user actions.

[1] I am not sure what types of resizes trigger the crash and which do not. Closing my folding phone does trigger the crash, as does resizing a window in my phone’s multi-window mode. I am not sure of whether simply rotating the screen is enough though.

FOR CRASHES, PLEASE INCLUDE THE FOLLOWING ADDITIONAL INFORMATION Type of crash: tab Crash State: see asan.log The asan report was captured with –single-process, I’m not sure how I’d get asan logs for the tab otherwise. The tab crash happens without the flag too, of course.

CREDIT INFORMATION Externally reported security bugs may appear in Chrome release notes. If this bug is included, how would you like to be credited? Reporter credit: Lyra Rebane (rebane2001)

View on issue tracker