Reviewed by John
authorkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 2 Dec 2004 17:43:46 +0000 (17:43 +0000)
committerkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 2 Dec 2004 17:43:46 +0000 (17:43 +0000)
        Fix for this bug:

        <rdar://problem/3900996> Crash dragging past end of contentEditable DIV, at DOM::RangeImpl::pastEndNode() const + 24

        * khtml/xml/dom_position.cpp:
        (DOM::Position::equivalentRangeCompliantPosition): Fixed this function so that it constrains the offset
        of the position to be >= 0 and <= number of kids of its node. Not doing this constraining led to a DOM
        exception trying to use a Position returned from this function to set the boundary point of a Range (which
        eventually led to the crash). Since this crash happened, it seems like this function was failing in its
        contract to return a range-compliant position, hence the need for this fix.

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

WebCore/ChangeLog-2005-08-23
WebCore/khtml/xml/dom_position.cpp

index 2a944b3..b674941 100644 (file)
@@ -1,3 +1,18 @@
+2004-12-02  Ken Kocienda  <kocienda@apple.com>
+
+        Reviewed by John
+
+        Fix for this bug:
+        
+        <rdar://problem/3900996> Crash dragging past end of contentEditable DIV, at DOM::RangeImpl::pastEndNode() const + 24
+
+        * khtml/xml/dom_position.cpp:
+        (DOM::Position::equivalentRangeCompliantPosition): Fixed this function so that it constrains the offset
+        of the position to be >= 0 and <= number of kids of its node. Not doing this constraining led to a DOM
+        exception trying to use a Position returned from this function to set the boundary point of a Range (which
+        eventually led to the crash). Since this crash happened, it seems like this function was failing in its
+        contract to return a range-compliant position, hence the need for this fix.
+
 2004-12-01  Ken Kocienda  <kocienda@apple.com>
 
         Reviewed by me
index 6b931a0..d9659e7 100644 (file)
@@ -489,24 +489,33 @@ Position Position::downstream(EStayInBlock stayInBlock) const
 Position Position::equivalentRangeCompliantPosition() const
 {
     if (isNull())
-        return *this;
+        return Position();
+
+    // Make sure that 0 <= constrainedOffset <= num kids, otherwise using this Position
+    // in DOM calls can result in exceptions.
+    long maxOffset = node()->isTextNode() ? static_cast<TextImpl *>(node())->length(): node()->childNodeCount();
+    long constrainedOffset = offset() <= 0 ? 0 : kMin(maxOffset, offset());
 
     if (!node()->parentNode())
-        return *this;
+        return Position(node(), constrainedOffset);
 
     RenderObject *renderer = node()->renderer();
     if (!renderer)
-        return *this;
+        return Position(node(), constrainedOffset);
         
     if (!renderer->isReplaced() && !renderer->isBR())
-        return *this;
+        return Position(node(), constrainedOffset);
     
-    int o = 0;
+    long o = offset();
     const NodeImpl *n = node();
     while ((n = n->previousSibling()))
         o++;
     
-    return Position(node()->parentNode(), o + offset());
+    // Make sure that 0 <= constrainedOffset <= num kids, as above.
+    NodeImpl *parent = node()->parentNode();
+    maxOffset = parent->isTextNode() ? static_cast<TextImpl *>(parent)->length(): parent->childNodeCount();
+    constrainedOffset = o <= 0 ? 0 : kMin(maxOffset, o);
+    return Position(parent, constrainedOffset);
 }
 
 Position Position::equivalentDeepPosition() const