Bug 1291082 ContentCacheInParent::GetUnionTextRects() shouldn't use mTextRectArray when it's empty r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 02 Aug 2016 12:02:14 +0900
changeset 396015 017c132f10e2d547cb72909f13104d92dfdb9c3c
parent 396014 39c869559883f654875c1e0dc0e8289eec5c0f3a
child 396094 d95c98d11cf96d2793516a58d0389948cef54023
push id24895
push usermasayuki@d-toybox.com
push dateWed, 03 Aug 2016 07:54:57 +0000
reviewersm_kato
bugs1291082
milestone51.0a1
Bug 1291082 ContentCacheInParent::GetUnionTextRects() shouldn't use mTextRectArray when it's empty r?m_kato This must be able to reproduce with some IMEs which creates 0 length composition string. In such case, mTextRectArray isn't available, but mTextRectArray.GetUnionRectAsFarAsPossible() always assumes that it's valid and has at least one rect. Therefore, it can meet this crash. Therefore, this patch makes that ContentCacheInParent::GetUnionTextRects() not use mTextRectArray when it's not valid nor doesn't have rects. MozReview-Commit-ID: 2yLMo4lxI3Z
widget/ContentCache.cpp
widget/ContentCache.h
--- a/widget/ContentCache.cpp
+++ b/widget/ContentCache.cpp
@@ -947,17 +947,17 @@ ContentCacheInParent::GetUnionTextRects(
   // in most cases.
 
   if (!aOffset && aOffset != mSelection.mAnchor &&
       aOffset != mSelection.mFocus && !mTextRectArray.InRange(aOffset)) {
     // The first character rect isn't cached.
     return false;
   }
 
-  if ((aRoundToExistingOffset && mTextRectArray.IsValid()) ||
+  if ((aRoundToExistingOffset && mTextRectArray.HasRects()) ||
       mTextRectArray.IsOverlappingWith(aOffset, aLength)) {
     aUnionTextRect =
       mTextRectArray.GetUnionRectAsFarAsPossible(aOffset, aLength,
                                                  aRoundToExistingOffset);
   } else {
     aUnionTextRect.SetEmpty();
   }
 
@@ -1306,16 +1306,18 @@ ContentCache::TextRectArray::GetUnionRec
 }
 
 LayoutDeviceIntRect
 ContentCache::TextRectArray::GetUnionRectAsFarAsPossible(
                                uint32_t aOffset,
                                uint32_t aLength,
                                bool aRoundToExistingOffset) const
 {
+  MOZ_ASSERT(HasRects());
+
   LayoutDeviceIntRect rect;
   if (!aRoundToExistingOffset && !IsOverlappingWith(aOffset, aLength)) {
     return rect;
   }
   uint32_t startOffset = std::max(aOffset, mStart);
   if (aRoundToExistingOffset && startOffset >= EndOffset()) {
     startOffset = EndOffset() - 1;
   }
--- a/widget/ContentCache.h
+++ b/widget/ContentCache.h
@@ -202,16 +202,20 @@ protected:
     {
       if (mStart == UINT32_MAX) {
         return false;
       }
       CheckedInt<uint32_t> endOffset =
         CheckedInt<uint32_t>(mStart) + mRects.Length();
       return endOffset.isValid();
     }
+    bool HasRects() const
+    {
+      return IsValid() && !mRects.IsEmpty();
+    }
     uint32_t StartOffset() const
     {
       NS_ASSERTION(IsValid(),
                    "The caller should check if the caret is valid");
       return mStart;
     }
     uint32_t EndOffset() const
     {