Tighten TextIterator::handleTextNode run-renderer mapping logic.
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 18 May 2017 00:29:07 +0000 (00:29 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 18 May 2017 00:29:07 +0000 (00:29 +0000)
https://bugs.webkit.org/show_bug.cgi?id=172174

Reviewed by Antti Koivisto.

Source/WebCore:

This patch ensure that when runs and renderers are getting out of sync
we don't run into problems like webkit.org/b/172113 (where we end up
using incorrect content start/end positions).

* editing/TextIterator.cpp:
(WebCore::TextIterator::handleTextNode):

LayoutTests:

* fast/shadow-dom/slot-crash-expected.txt:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@217019 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
Source/WebCore/ChangeLog
Source/WebCore/editing/TextIterator.cpp
Source/WebCore/rendering/SimpleLineLayoutFlowContents.h
Source/WebCore/rendering/SimpleLineLayoutFunctions.cpp
Source/WebCore/rendering/SimpleLineLayoutFunctions.h

index 068db43..2d4f4c2 100644 (file)
@@ -1,3 +1,12 @@
+2017-05-17  Zalan Bujtas  <zalan@apple.com>
+
+        Tighten TextIterator::handleTextNode run-renderer mapping logic.
+        https://bugs.webkit.org/show_bug.cgi?id=172174
+
+        Reviewed by Antti Koivisto.
+
+        * fast/shadow-dom/slot-crash-expected.txt:
+
 2017-05-17  John Wilander  <wilander@apple.com>
 
         Resource Load Statistics: Grandfather domains for existing data records
index 2a876e0..61d32f2 100644 (file)
@@ -1,3 +1,17 @@
+2017-05-17  Zalan Bujtas  <zalan@apple.com>
+
+        Tighten TextIterator::handleTextNode run-renderer mapping logic.
+        https://bugs.webkit.org/show_bug.cgi?id=172174
+
+        Reviewed by Antti Koivisto.
+
+        This patch ensure that when runs and renderers are getting out of sync
+        we don't run into problems like webkit.org/b/172113 (where we end up
+        using incorrect content start/end positions).
+
+        * editing/TextIterator.cpp:
+        (WebCore::TextIterator::handleTextNode):
+
 2017-05-17  John Wilander  <wilander@apple.com>
 
         Resource Load Statistics: Grandfather domains for existing data records
index 63233db..2f5163d 100644 (file)
@@ -648,7 +648,8 @@ bool TextIterator::handleTextNode()
         auto range = m_flowRunResolverCache->rangeForRenderer(renderer);
         auto it = range.begin();
         auto end = range.end();
-        while (it != end && (*it).end() <= (static_cast<unsigned>(m_offset) + m_accumulatedSimpleTextLengthInFlow))
+        auto startPosition = static_cast<unsigned>(m_offset) + m_accumulatedSimpleTextLengthInFlow;
+        while (it != end && (*it).end() <= startPosition)
             ++it;
         if (m_nextRunNeedsWhitespace && rendererText[m_offset - 1] == '\n') {
             emitCharacter(' ', textNode, nullptr, m_offset, m_offset + 1);
@@ -664,7 +665,17 @@ bool TextIterator::handleTextNode()
             emitCharacter(' ', textNode, nullptr, m_offset, m_offset + 1);
             return false;
         }
-        const auto run = *it;
+        // If the position we are looking for is to the left of the renderer's first run, it could mean that
+        // the runs and the renderers are out of sync (e.g. we skipped a renderer in between).
+        // Better bail out at this point.
+        auto run = *it;
+        if (run.start() > startPosition) {
+            ASSERT(m_flowRunResolverCache);
+            if (&(rendererForPosition(m_flowRunResolverCache->flowContents(), startPosition)) != &renderer) {
+                ASSERT_NOT_REACHED();
+                return true;
+            }
+        }
         ASSERT(run.end() - run.start() <= rendererText.length());
         // contentStart skips leading whitespace.
         unsigned contentStart = std::max<unsigned>(m_offset, run.start() - m_accumulatedSimpleTextLengthInFlow);
index 1a7d655..6a594fa 100644 (file)
@@ -50,6 +50,7 @@ public:
         bool canUseSimplifiedTextMeasuring;
     };
     const Segment& segmentForRun(unsigned start, unsigned end) const;
+    const Segment& segmentForPosition(unsigned) const;
 
     typedef Vector<Segment, 8>::const_iterator Iterator;
     Iterator begin() const { return m_segments.begin(); }
@@ -70,5 +71,14 @@ inline const FlowContents::Segment& FlowContents::segmentForRun(unsigned start,
     return m_segments[segmentIndexForRunSlow(start, end)];
 }
 
+inline const FlowContents::Segment& FlowContents::segmentForPosition(unsigned position) const
+{
+    auto it = std::lower_bound(m_segments.begin(), m_segments.end(), position, [](const Segment& segment, unsigned position) {
+        return segment.end <= position;
+    });
+    ASSERT(it != m_segments.end());
+    return m_segments[it - m_segments.begin()];
+}
+
 }
 }
index 410d505..83b12f1 100644 (file)
@@ -40,6 +40,7 @@
 #include "RenderText.h"
 #include "RenderView.h"
 #include "Settings.h"
+#include "SimpleLineLayoutFlowContents.h"
 #include "SimpleLineLayoutResolver.h"
 #include "Text.h"
 #include "TextDecorationPainter.h"
@@ -254,6 +255,11 @@ Vector<FloatQuad> collectAbsoluteQuadsForRange(const RenderObject& renderer, uns
     return quads;
 }
 
+const RenderObject& rendererForPosition(const FlowContents& flowContents, unsigned position)
+{
+    return flowContents.segmentForPosition(position).renderer;
+}
+
 #if ENABLE(TREE_DEBUGGING)
 static void printPrefix(int& printedCharacters, int depth)
 {
index 615e9d5..fbbe365 100644 (file)
@@ -39,6 +39,7 @@ class RenderBlockFlow;
 struct PaintInfo;
 
 namespace SimpleLineLayout {
+class FlowContents;
 
 LayoutUnit computeFlowHeight(const RenderBlockFlow&, const Layout&);
 LayoutUnit computeFlowFirstLineBaseline(const RenderBlockFlow&, const Layout&);
@@ -64,6 +65,8 @@ Vector<FloatQuad> collectAbsoluteQuadsForRange(const RenderObject&, unsigned sta
 LayoutUnit lineHeightFromFlow(const RenderBlockFlow&);
 LayoutUnit baselineFromFlow(const RenderBlockFlow&);
 
+const RenderObject& rendererForPosition(const FlowContents&, unsigned);
+
 #if ENABLE(TREE_DEBUGGING)
 void showLineLayoutForFlow(const RenderBlockFlow&, const Layout&, int depth);
 #endif