CVE-2025-6555
Overview
Background
- `InterpolationType`
- A Blink animation class (subclassed as
CSSNumberInterpolationType,CSSColorInterpolationType, etc.) describing how a given CSS property’s values are converted and interpolated during animations and transitions. - `InterpolationTypesMap`
- A per-property registry, queried via
map.Get(property), that returns the list ofInterpolationTypes applicable to a property. - Active interpolation / `TransitionInterpolation`
- A running transition holds a reference to the
InterpolationTypeit was built with (e.g., viaTypedInterpolationValue) and keeps using it while the transition is live. - `PropertyRegistry::RemoveDeclaredProperties` / Oilpan GC
- CSS custom-property registrations can be removed at runtime, which previously deleted the associated
InterpolationTypes;MakeGarbageCollected/GarbageCollectedplaces objects on Blink’s Oilpan heap so they live as long as any reference remains.
Root Cause Analysis
Active interpolations retained raw pointers to InterpolationType objects, but those types could be destroyed out from under them by PropertyRegistry::RemoveDeclaredProperties (per the commit message), leaving the running transition with a dangling transition_type pointer. In CSSAnimations, map.Get(property) returned a container of owning smart pointers whose lifetime was tied to the registry, and the code captured interpolation_type.get() / passed *transition_type by reference into TypedInterpolationValue, so a later registry update could free the type still referenced by the transition.
The fix makes InterpolationType garbage-collected (adding interpolation_type.cc to the build and using MakeGarbageCollected), so map.Get(property) now returns a pointer to a traced collection and callers hold Member-style references (interpolation_type.Get(), passing transition_type rather than *transition_type). Because Oilpan keeps the old InterpolationType alive as long as any active interpolation references it, an interpolation can safely keep using its type even after the registry replaces or removes the declared property, eliminating the use-after-free. The underlying_value_owner.Set(this, value) conversions (dropping the *this dereference) propagate the pointer-based ownership through the many per-property interpolation types.
InterpolationTypes whose lifetime was controlled by the mutable property registry; making InterpolationType garbage-collected ties its lifetime to its live references so it cannot be freed while still in use.Attack Path
- Start a transition using a registered property
Cause a CSS transition/animation to begin so an active interpolation captures an
InterpolationTypeobtained fromInterpolationTypesMap::Get(transition_type). - Invalidate the property registration
From script/CSS, remove or redeclare the custom property so
PropertyRegistry::RemoveDeclaredPropertiesdeletes the previously registeredInterpolationTypethe transition still points to. - Dangling type pointer
The active interpolation now holds a freed
InterpolationType*, since ownership lived with the registry rather than the interpolation. - Access during animation update
The next animation tick uses the stale
transition_type(e.g., when buildingTransitionKeyframe/TypedInterpolationValue), dereferencing freed memory — a use-after-free in the renderer. Converting this into a controlled primitive is not shown by the patch (inferred).
Impact Assessment
InterpolationType that a live interpolation still references, producing a use-after-free in the Blink renderer process. The advisory classifies this as a use-after-free in Animation (bug 407328533); it does not report in-the-wild exploitation, and escalation beyond the dangling access to memory disclosure or code execution is (inferred), not demonstrated by the patch. The precondition is only attacker-controlled HTML/CSS/JS that can register/animate and then remove a declared property.Changed Functions
| Function | Change | Notes |
|---|---|---|
ifthird_party/blink/renderer/core/animation/css/css_animations.cc |
modified |
Files Changed
third_party/blink/renderer/core/animation/BUILD.gnthird_party/blink/renderer/core/animation/animation_test.ccthird_party/blink/renderer/core/animation/css/css_animations.ccthird_party/blink/renderer/core/animation/css_aspect_ratio_interpolation_type.ccthird_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.ccthird_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.ccthird_party/blink/renderer/core/animation/css_clip_interpolation_type.ccthird_party/blink/renderer/core/animation/css_color_interpolation_type.ccthird_party/blink/renderer/core/animation/css_content_visibility_interpolation_type.ccthird_party/blink/renderer/core/animation/css_custom_list_interpolation_type.cc
Audit Directions
- Registry-owned objects referenced by long-lived stateLook for classes whose instances are owned by a mutable registry/map but whose raw pointers are cached by longer-lived objects (animations, observers, timers) that outlive registry mutation.
- Mutation APIs that delete shared typesReview
PropertyRegistry-style “Remove”/“Redeclare” paths for other subsystems that keep pointers to the removed entries without lifetime guarantees.
Patch
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"
Regression Test / PoC
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));
Original Bug Report
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:
- Open crash.html.
- Open devtools.
- Turn on the device toolbar.
- Wait a few seconds, turn the device toolbar off.
- 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:
- Open crash.html.
- Resize Chrome[1].
- 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)