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
--- 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
{