Bug 771873 part 1 - Check for reversed indices in Selection::GetIndicesForInterval; r=ehsan a=akeybl
authorAryeh Gregor <ayg@aryeh.name>
Thu, 12 Jul 2012 18:56:30 +0300
changeset 100382 268e31db5949cdfb8a709ca50d8d7c14162e6bdf
parent 100381 80000a1e4ea0cfa2b31ffdf84e8f961e8dfe26df
child 100383 0c9df0afa02ea6b51ad51aa4f3348cd70ae2cbb9
push id1190
push usereakhgari@mozilla.com
push dateMon, 30 Jul 2012 18:00:01 +0000
treeherdermozilla-beta@268e31db5949 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan, akeybl
bugs771873
milestone15.0
Bug 771873 part 1 - Check for reversed indices in Selection::GetIndicesForInterval; r=ehsan a=akeybl
layout/generic/nsSelection.cpp
layout/generic/nsTypedSelection.h
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -3503,19 +3503,22 @@ nsTypedSelection::AddItem(nsRange *aItem
     aItem->SetInSelection(true);
 
     if (aOutIndex)
       *aOutIndex = 0;
     return NS_OK;
   }
 
   PRInt32 startIndex, endIndex;
-  GetIndicesForInterval(aItem->GetStartParent(), aItem->StartOffset(),
-                        aItem->GetEndParent(), aItem->EndOffset(),
-                        false, &startIndex, &endIndex);
+  nsresult rv = GetIndicesForInterval(aItem->GetStartParent(),
+                                      aItem->StartOffset(),
+                                      aItem->GetEndParent(),
+                                      aItem->EndOffset(), false,
+                                      &startIndex, &endIndex);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   if (endIndex == -1) {
     // All ranges start after the given range. We can insert our range at
     // position 0, knowing there are no overlaps (handled below)
     startIndex = 0;
     endIndex = 0;
   } else if (startIndex == -1) {
     // All ranges end before the given range. We can insert our range at
@@ -3569,20 +3572,19 @@ nsTypedSelection::AddItem(nsRange *aItem
   nsTArray<RangeData> temp;
   for (PRInt32 i = overlaps.Length() - 1; i >= 0; i--) {
     nsresult rv = SubtractRange(&overlaps[i], aItem, &temp);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Insert the new element into our "leftovers" array
   PRInt32 insertionPoint;
-  nsresult rv = FindInsertionPoint(&temp, aItem->GetStartParent(),
-                                   aItem->StartOffset(),
-                                   CompareToRangeStart,
-                                   &insertionPoint);
+  rv = FindInsertionPoint(&temp, aItem->GetStartParent(),
+                          aItem->StartOffset(), CompareToRangeStart,
+                          &insertionPoint);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!temp.InsertElementAt(insertionPoint, RangeData(aItem)))
     return NS_ERROR_OUT_OF_MEMORY;
 
   // Merge the leftovers back in to mRanges
   if (!mRanges.InsertElementsAt(startIndex, temp))
     return NS_ERROR_OUT_OF_MEMORY;
@@ -3767,18 +3769,20 @@ nsTypedSelection::GetRangesForInterval(n
 nsresult
 nsTypedSelection::GetRangesForIntervalArray(nsINode* aBeginNode, PRInt32 aBeginOffset,
                                             nsINode* aEndNode, PRInt32 aEndOffset,
                                             bool aAllowAdjacent,
                                             nsTArray<nsRange*>* aRanges)
 {
   aRanges->Clear();
   PRInt32 startIndex, endIndex;
-  GetIndicesForInterval(aBeginNode, aBeginOffset, aEndNode, aEndOffset,
-                        aAllowAdjacent, &startIndex, &endIndex);
+  nsresult res = GetIndicesForInterval(aBeginNode, aBeginOffset, aEndNode, aEndOffset,
+                                       aAllowAdjacent, &startIndex, &endIndex);
+  NS_ENSURE_SUCCESS(res, res);
+
   if (startIndex == -1 || endIndex == -1)
     return NS_OK;
 
   for (PRInt32 i = startIndex; i < endIndex; i++) {
     if (!aRanges->AppendElement(mRanges[i].mRange))
       return NS_ERROR_OUT_OF_MEMORY;
   }
 
@@ -3786,17 +3790,17 @@ nsTypedSelection::GetRangesForIntervalAr
 }
 
 // nsTypedSelection::GetIndicesForInterval
 //
 //    Works on the same principle as GetRangesForIntervalArray above, however
 //    instead this returns the indices into mRanges between which the
 //    overlapping ranges lie.
 
-void
+nsresult
 nsTypedSelection::GetIndicesForInterval(nsINode* aBeginNode,
                                         PRInt32 aBeginOffset,
                                         nsINode* aEndNode, PRInt32 aEndOffset,
                                         bool aAllowAdjacent,
                                         PRInt32 *aStartIndex,
                                         PRInt32 *aEndIndex)
 {
   PRInt32 startIndex;
@@ -3806,56 +3810,56 @@ nsTypedSelection::GetIndicesForInterval(
     aStartIndex = &startIndex;
   if (!aEndIndex)
     aEndIndex = &endIndex;
 
   *aStartIndex = -1;
   *aEndIndex = -1;
 
   if (mRanges.Length() == 0)
-    return;
+    return NS_OK;
 
   bool intervalIsCollapsed = aBeginNode == aEndNode &&
     aBeginOffset == aEndOffset;
 
   // Ranges that end before the given interval and begin after the given
   // interval can be discarded
   PRInt32 endsBeforeIndex;
   if (NS_FAILED(FindInsertionPoint(&mRanges, aEndNode, aEndOffset,
                                    &CompareToRangeStart,
                                    &endsBeforeIndex))) {
-    return;
+    return NS_OK;
   }
 
   if (endsBeforeIndex == 0) {
     nsRange* endRange = mRanges[endsBeforeIndex].mRange;
 
     // If the interval is strictly before the range at index 0, we can optimize
     // by returning now - all ranges start after the given interval
     if (!RangeMatchesBeginPoint(endRange, aEndNode, aEndOffset))
-      return;
+      return NS_OK;
 
     // We now know that the start point of mRanges[0].mRange equals the end of
     // the interval. Thus, when aAllowadjacent is true, the caller is always
     // interested in this range. However, when excluding adjacencies, we must
     // remember to include the range when both it and the given interval are
     // collapsed to the same point
     if (!aAllowAdjacent && !(endRange->Collapsed() && intervalIsCollapsed))
-      return;
+      return NS_OK;
   }
   *aEndIndex = endsBeforeIndex;
 
   PRInt32 beginsAfterIndex;
   if (NS_FAILED(FindInsertionPoint(&mRanges, aBeginNode, aBeginOffset,
                                    &CompareToRangeEnd,
                                    &beginsAfterIndex))) {
-    return;
+    return NS_OK;
   }
   if (beginsAfterIndex == (PRInt32) mRanges.Length())
-    return; // optimization: all ranges are strictly before us
+    return NS_OK; // optimization: all ranges are strictly before us
 
   if (aAllowAdjacent) {
     // At this point, one of the following holds:
     //   endsBeforeIndex == mRanges.Length(),
     //   endsBeforeIndex points to a range whose start point does not equal the
     //     given interval's start point
     //   endsBeforeIndex points to a range whose start point equals the given
     //     interval's start point
@@ -3905,19 +3909,23 @@ nsTypedSelection::GetIndicesForInterval(
     if (endsBeforeIndex < (PRInt32) mRanges.Length()) {
       nsRange* endRange = mRanges[endsBeforeIndex].mRange;
       if (RangeMatchesBeginPoint(endRange, aEndNode, aEndOffset) &&
           endRange->Collapsed())
         endsBeforeIndex++;
      }
   }
 
+  NS_ASSERTION(beginsAfterIndex <= endsBeforeIndex,
+               "Is mRanges not ordered?");
+  NS_ENSURE_STATE(beginsAfterIndex <= endsBeforeIndex);
+
   *aStartIndex = beginsAfterIndex;
   *aEndIndex = endsBeforeIndex;
-  return;
+  return NS_OK;
 }
 
 //utility method to get the primary frame of node or use the offset to get frame of child node
 
 #if 0
 NS_IMETHODIMP
 nsTypedSelection::GetPrimaryFrameForRangeEndpoint(nsIDOMNode *aNode, PRInt32 aOffset, bool aIsEndNode, nsIFrame **aReturnFrame)
 {
--- a/layout/generic/nsTypedSelection.h
+++ b/layout/generic/nsTypedSelection.h
@@ -181,20 +181,20 @@ private:
   nsresult FindInsertionPoint(
       nsTArray<RangeData>* aElementArray,
       nsINode* aPointNode, PRInt32 aPointOffset,
       nsresult (*aComparator)(nsINode*,PRInt32,nsRange*,PRInt32*),
       PRInt32* aPoint);
   bool EqualsRangeAtPoint(nsINode* aBeginNode, PRInt32 aBeginOffset,
                             nsINode* aEndNode, PRInt32 aEndOffset,
                             PRInt32 aRangeIndex);
-  void GetIndicesForInterval(nsINode* aBeginNode, PRInt32 aBeginOffset,
-                             nsINode* aEndNode, PRInt32 aEndOffset,
-                             bool aAllowAdjacent,
-                             PRInt32 *aStartIndex, PRInt32 *aEndIndex);
+  nsresult GetIndicesForInterval(nsINode* aBeginNode, PRInt32 aBeginOffset,
+                                 nsINode* aEndNode, PRInt32 aEndOffset,
+                                 bool aAllowAdjacent,
+                                 PRInt32 *aStartIndex, PRInt32 *aEndIndex);
   RangeData* FindRangeData(nsIDOMRange* aRange);
 
   // These are the ranges inside this selection. They are kept sorted in order
   // of DOM start position.
   //
   // This data structure is sorted by the range beginnings. As the ranges are
   // disjoint, it is also implicitly sorted by the range endings. This allows
   // us to perform binary searches when searching for existence of a range,