Bug 1375131 - Part 1. Store ranges before using on loop. r?masayuki
This crash occurs that range is nullptr.
DeleteNonTableElements will update selection and range, so we shouldn't use range count before modifying selection. So we should save range data for loop.
MozReview-Commit-ID: C9c4TZqRvUc
--- a/editor/libeditor/EditorUtils.h
+++ b/editor/libeditor/EditorUtils.h
@@ -2,16 +2,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_EditorUtils_h
#define mozilla_EditorUtils_h
+#include "mozilla/dom/Selection.h"
#include "mozilla/EditorBase.h"
#include "mozilla/GuardObjects.h"
#include "nsCOMPtr.h"
#include "nsDebug.h"
#include "nsIDOMNode.h"
#include "nsIEditor.h"
#include "nscore.h"
@@ -21,20 +22,16 @@ class nsIDOMDocument;
class nsIDOMEvent;
class nsISimpleEnumerator;
class nsITransferable;
class nsRange;
namespace mozilla {
template <class T> class OwningNonNull;
-namespace dom {
-class Selection;
-} // namespace dom
-
/***************************************************************************
* EditActionResult is useful to return multiple results of an editor
* action handler without out params.
* Note that when you return an anonymous instance from a method, you should
* use EditActionIgnored(), EditActionHandled() or EditActionCanceled() for
* easier to read. In other words, EditActionResult should be used when
* declaring return type of a method, being an argument or defined as a local
* variable.
@@ -317,16 +314,33 @@ public:
}
}
protected:
EditorBase* mEditorBase;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
+class MOZ_STACK_CLASS AutoRangeArray final
+{
+public:
+ AutoRangeArray(dom::Selection* aSelection)
+ {
+ if (!aSelection) {
+ return;
+ }
+ uint32_t rangeCount = aSelection->RangeCount();
+ for (uint32_t i = 0; i < rangeCount; i++) {
+ mRanges.AppendElement(*aSelection->GetRangeAt(i));
+ }
+ }
+
+ AutoTArray<mozilla::OwningNonNull<nsRange>, 8> mRanges;
+};
+
/******************************************************************************
* some helper classes for iterating the dom tree
*****************************************************************************/
class BoolDomIterFunctor
{
public:
virtual bool operator()(nsINode* aNode) const = 0;
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -2447,20 +2447,18 @@ HTMLEditRules::WillDeleteSelection(Selec
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
// Else blocks not same type, or not siblings. Delete everything
// except table elements.
join = true;
- uint32_t rangeCount = aSelection->RangeCount();
- for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
- OwningNonNull<nsRange> range = *aSelection->GetRangeAt(rangeIdx);
-
+ AutoRangeArray arrayOfRanges(aSelection);
+ for (auto& range : arrayOfRanges.mRanges) {
// Build a list of nodes in the range
nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
TrivialFunctor functor;
DOMSubtreeIterator iter;
nsresult rv = iter.Init(*range);
NS_ENSURE_SUCCESS(rv, rv);
iter.AppendList(functor, arrayOfNodes);