summaryrefslogtreecommitdiff
path: root/chromium/third_party
diff options
context:
space:
mode:
authorXianzhu Wang <wangxianzhu@chromium.org>2019-05-20 22:25:25 +0000
committerMichal Klocek <michal.klocek@qt.io>2019-07-25 06:19:42 +0000
commit09c99945defd3319acfe15aac4564d4df2205233 (patch)
tree1f9f9f444dc75875ed656f2f428ecc89ddee1c06 /chromium/third_party
parentd42e2e2bc4415af05451183808e46b55938229c9 (diff)
downloadqtwebengine-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.cc53
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object.h9
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).