diff options
author | Xianzhu Wang <wangxianzhu@chromium.org> | 2019-05-20 22:25:25 +0000 |
---|---|---|
committer | Michal Klocek <michal.klocek@qt.io> | 2019-07-25 06:19:42 +0000 |
commit | 09c99945defd3319acfe15aac4564d4df2205233 (patch) | |
tree | 1f9f9f444dc75875ed656f2f428ecc89ddee1c06 /chromium/third_party | |
parent | d42e2e2bc4415af05451183808e46b55938229c9 (diff) | |
download | qtwebengine-chromium-09c99945defd3319acfe15aac4564d4df2205233.tar.gz |
[Backport] Security bug 964795
Harden first line background image observer registration
Background image observer registration/unregistration is required to be
strictly paired, and any object being destroyed must unregister it as
image observer if it has registered itself as one.
First line style complicates background image observer registration,
because LayoutObject::GetCachedPseudoStyle() can return a different
value after the DOM tree changed, so it's unreliable to depend on the
old style's first line pseudo style to unregister a LayoutObject as
an image observer.
Add a bit to indicate whether the LayoutObject has registered itself
as a first line image observer, and a static map to store the first
line style based on which the object registered. In
UpdateFirstLineImageObservers(), unregister based on these information
instead of old style's cached first line pseudo style.
Also let FirstLineStyleForCachedUncachedType() return nullptr when
:before/:after is getting the first line style before inserted into
the tree to avoid churn of first line style.
Bug: 964795
Change-Id: Iede3e835c67dfba8e18ad220ebc2efd4b892e9e8
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party')
-rw-r--r-- | chromium/third_party/blink/renderer/core/layout/layout_object.cc | 53 | ||||
-rw-r--r-- | chromium/third_party/blink/renderer/core/layout/layout_object.h | 9 |
2 files changed, 44 insertions, 18 deletions
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_object.cc b/chromium/third_party/blink/renderer/core/layout/layout_object.cc index 33be8a2e95b..c5c3ea1f32e 100644 --- a/chromium/third_party/blink/renderer/core/layout/layout_object.cc +++ b/chromium/third_party/blink/renderer/core/layout/layout_object.cc @@ -2156,26 +2156,30 @@ void LayoutObject::UpdateImageObservers(const ComputedStyle* old_style, UpdateCursorImages(old_style ? old_style->Cursors() : nullptr, new_style ? new_style->Cursors() : nullptr); - UpdateFirstLineImageObservers(old_style, new_style); + UpdateFirstLineImageObservers(new_style); } void LayoutObject::UpdateFirstLineImageObservers( - const ComputedStyle* old_style, const ComputedStyle* new_style) { - bool has_old_first_line_style = - old_style && old_style->HasPseudoStyle(kPseudoIdFirstLine); bool has_new_first_line_style = new_style && new_style->HasPseudoStyle(kPseudoIdFirstLine); - if (!has_old_first_line_style && !has_new_first_line_style) + if (!bitfields_.RegisteredAsFirstLineImageObserver() && + !has_new_first_line_style) return; + using FirstLineStyleMap = + HashMap<const LayoutObject*, scoped_refptr<const ComputedStyle>>; + DEFINE_STATIC_LOCAL(FirstLineStyleMap, first_line_style_map, ()); + DCHECK_EQ(bitfields_.RegisteredAsFirstLineImageObserver(), + first_line_style_map.Contains(this)); + const auto* old_first_line_style = + bitfields_.RegisteredAsFirstLineImageObserver() + ? first_line_style_map.at(this) + : nullptr; + // Don't call CacheFirstLineStyle() which will update the cache, because this // function can be called when the object has not been inserted into the tree // and we can't update the pseudo style cache which may depend on ancestors. - const auto* cached_old_first_line_style = - has_old_first_line_style - ? old_style->GetCachedPseudoStyle(kPseudoIdFirstLine) - : nullptr; const auto* cached_new_first_line_style = has_new_first_line_style ? new_style->GetCachedPseudoStyle(kPseudoIdFirstLine) @@ -2189,13 +2193,26 @@ void LayoutObject::UpdateFirstLineImageObservers( !cached_new_first_line_style); } - if (cached_old_first_line_style || cached_new_first_line_style) { - UpdateFillImages(cached_old_first_line_style - ? &cached_old_first_line_style->BackgroundLayers() + if (cached_new_first_line_style && + !cached_new_first_line_style->HasBackgroundImage()) + cached_new_first_line_style = nullptr; + + if (old_first_line_style || cached_new_first_line_style) { + UpdateFillImages(old_first_line_style + ? &old_first_line_style->BackgroundLayers() : nullptr, cached_new_first_line_style ? &cached_new_first_line_style->BackgroundLayers() : nullptr); + if (cached_new_first_line_style) { + bitfields_.SetRegisteredAsFirstLineImageObserver(true); + first_line_style_map.Set(this, cached_new_first_line_style); + } else { + bitfields_.SetRegisteredAsFirstLineImageObserver(false); + first_line_style_map.erase(this); + } + DCHECK_EQ(bitfields_.RegisteredAsFirstLineImageObserver(), + first_line_style_map.Contains(this)); } } @@ -3230,8 +3247,9 @@ void LayoutObject::WillBeDestroyed() { if (style_ && !IsText()) UpdateImageObservers(style_.get(), nullptr); -#if DCHECK_IS_ON() // We must have removed all image observers. + SECURITY_CHECK(!bitfields_.RegisteredAsFirstLineImageObserver()); +#if DCHECK_IS_ON() SECURITY_DCHECK(as_image_observer_count_ == 0u); #endif @@ -3568,9 +3586,13 @@ static scoped_refptr<const ComputedStyle> FirstLineStyleForCachedUncachedType( const LayoutObject* layout_object, const ComputedStyle* style) { DCHECK(layout_object); + const LayoutObject* layout_object_for_first_line_style = layout_object; - if (layout_object->IsBeforeOrAfterContent()) + if (layout_object->IsBeforeOrAfterContent()) { + if (!layout_object->Parent()) + return nullptr; layout_object_for_first_line_style = layout_object->Parent(); + } if (layout_object_for_first_line_style->BehavesLikeBlockContainer()) { if (const LayoutBlock* first_line_block = @@ -3656,8 +3678,7 @@ const ComputedStyle* LayoutObject::GetCachedPseudoStyle( bitfields_.PendingUpdateFirstLineImageObservers()) { // Update image observers now after we have updated the first line // style cache. - const_cast<LayoutObject*>(this)->UpdateFirstLineImageObservers(nullptr, - Style()); + const_cast<LayoutObject*>(this)->UpdateFirstLineImageObservers(Style()); } return cached_pseudo_style; } diff --git a/chromium/third_party/blink/renderer/core/layout/layout_object.h b/chromium/third_party/blink/renderer/core/layout/layout_object.h index 86c9d68434a..a903916ea1a 100644 --- a/chromium/third_party/blink/renderer/core/layout/layout_object.h +++ b/chromium/third_party/blink/renderer/core/layout/layout_object.h @@ -2450,8 +2450,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver, void UpdateImageObservers(const ComputedStyle* old_style, const ComputedStyle* new_style); - void UpdateFirstLineImageObservers(const ComputedStyle* old_style, - const ComputedStyle* new_style); + void UpdateFirstLineImageObservers(const ComputedStyle* new_style); void ApplyPseudoStyleChanges(const ComputedStyle* old_style); void ApplyFirstLineChanges(const ComputedStyle* old_style); @@ -2581,6 +2580,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver, is_effective_root_scroller_(false), is_global_root_scroller_(false), pending_update_first_line_image_observers_(false), + registered_as_first_line_image_observer_(false), positioned_state_(kIsStaticallyPositioned), selection_state_(static_cast<unsigned>(SelectionState::kNone)), background_obscuration_state_(kBackgroundObscurationStatusInvalid), @@ -2823,6 +2823,11 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver, ADD_BOOLEAN_BITFIELD(pending_update_first_line_image_observers_, PendingUpdateFirstLineImageObservers); + // Indicates whether this object has been added as a first line image + // observer. + ADD_BOOLEAN_BITFIELD(registered_as_first_line_image_observer_, + RegisteredAsFirstLineImageObserver); + private: // This is the cached 'position' value of this object // (see ComputedStyle::position). |