Commit 1810df13 authored by Xiaocheng Hu's avatar Xiaocheng Hu Committed by Commit Bot

Stop InlineContents iteration when reaching document boundary

This patch stops a crash in InlineContents previous/next iteration by
terminating the iteration at document boundary, so that subsequent
operations don't proceed with invalid parameters.

Bug: 903723
Change-Id: Iaed2ac1d5d74d3ab59da3a2f0db2d4f8150fb21b
Reviewed-on: https://chromium-review.googlesource.com/c/1331571Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Reviewed-by: default avatarYoichi Osato <yoichio@chromium.org>
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607499}
parent 68ea9d19
...@@ -328,35 +328,53 @@ EphemeralRangeInFlatTree TextOffsetMapping::InlineContents::GetRange() const { ...@@ -328,35 +328,53 @@ EphemeralRangeInFlatTree TextOffsetMapping::InlineContents::GetRange() const {
PositionInFlatTree PositionInFlatTree
TextOffsetMapping::InlineContents::LastPositionBeforeBlockFlow() const { TextOffsetMapping::InlineContents::LastPositionBeforeBlockFlow() const {
DCHECK(block_flow_); DCHECK(block_flow_);
if (const Node* node = block_flow_->NonPseudoNode()) if (const Node* node = block_flow_->NonPseudoNode()) {
if (!FlatTreeTraversal::Parent(*node)) {
// Reached start of document.
return PositionInFlatTree();
}
return PositionInFlatTree::BeforeNode(*node); return PositionInFlatTree::BeforeNode(*node);
}
DCHECK(first_); DCHECK(first_);
DCHECK(first_->NonPseudoNode()); DCHECK(first_->NonPseudoNode());
DCHECK(FlatTreeTraversal::Parent(*first_->NonPseudoNode()));
return PositionInFlatTree::BeforeNode(*first_->NonPseudoNode()); return PositionInFlatTree::BeforeNode(*first_->NonPseudoNode());
} }
PositionInFlatTree PositionInFlatTree
TextOffsetMapping::InlineContents::FirstPositionAfterBlockFlow() const { TextOffsetMapping::InlineContents::FirstPositionAfterBlockFlow() const {
DCHECK(block_flow_); DCHECK(block_flow_);
if (const Node* node = block_flow_->NonPseudoNode()) if (const Node* node = block_flow_->NonPseudoNode()) {
if (!FlatTreeTraversal::Parent(*node)) {
// Reached end of document.
return PositionInFlatTree();
}
return PositionInFlatTree::AfterNode(*node); return PositionInFlatTree::AfterNode(*node);
}
DCHECK(last_); DCHECK(last_);
DCHECK(last_->NonPseudoNode()); DCHECK(last_->NonPseudoNode());
DCHECK(FlatTreeTraversal::Parent(*last_->NonPseudoNode()));
return PositionInFlatTree::AfterNode(*last_->NonPseudoNode()); return PositionInFlatTree::AfterNode(*last_->NonPseudoNode());
} }
// static // static
TextOffsetMapping::InlineContents TextOffsetMapping::InlineContents::NextOf( TextOffsetMapping::InlineContents TextOffsetMapping::InlineContents::NextOf(
const InlineContents& inline_contents) { const InlineContents& inline_contents) {
return TextOffsetMapping::FindForwardInlineContents( const PositionInFlatTree position_after =
inline_contents.FirstPositionAfterBlockFlow()); inline_contents.FirstPositionAfterBlockFlow();
if (position_after.IsNull())
return InlineContents();
return TextOffsetMapping::FindForwardInlineContents(position_after);
} }
// static // static
TextOffsetMapping::InlineContents TextOffsetMapping::InlineContents::PreviousOf( TextOffsetMapping::InlineContents TextOffsetMapping::InlineContents::PreviousOf(
const InlineContents& inline_contents) { const InlineContents& inline_contents) {
return TextOffsetMapping::FindBackwardInlineContents( const PositionInFlatTree position_before =
inline_contents.LastPositionBeforeBlockFlow()); inline_contents.LastPositionBeforeBlockFlow();
if (position_before.IsNull())
return InlineContents();
return TextOffsetMapping::FindBackwardInlineContents(position_before);
} }
std::ostream& operator<<( std::ostream& operator<<(
......
...@@ -369,4 +369,20 @@ TEST_P(ParameterizedTextOffsetMappingTest, GetPositionAfter) { ...@@ -369,4 +369,20 @@ TEST_P(ParameterizedTextOffsetMappingTest, GetPositionAfter) {
// We hit DCHECK for offset 8, because we walk on "012 456". // We hit DCHECK for offset 8, because we walk on "012 456".
} }
// https://crbug.com/903723
TEST_P(ParameterizedTextOffsetMappingTest, InlineContentsWithDocumentBoundary) {
InsertStyleElement("*{position:fixed}");
SetBodyContent("");
const PositionInFlatTree position =
PositionInFlatTree::FirstPositionInNode(*GetDocument().body());
const TextOffsetMapping::InlineContents inline_contents =
TextOffsetMapping::FindForwardInlineContents(position);
EXPECT_TRUE(inline_contents.IsNotNull());
// Should not crash when previous/next iteration reaches document boundary.
EXPECT_TRUE(
TextOffsetMapping::InlineContents::PreviousOf(inline_contents).IsNull());
EXPECT_TRUE(
TextOffsetMapping::InlineContents::NextOf(inline_contents).IsNull());
}
} // namespace blink } // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment