Bug 448993 - Crash [@ nsRange::CutContents] using deleteContents after extractContents and GC, r+sr=sicking
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Wed, 03 Dec 2008 12:14:51 +0200
changeset 22216 245b7f2f782c2dc938b9bf46b637a38169a2add8
parent 22215 0d300ab7a8cfbec8739c0ba94e42ce9abc8e5307
child 22217 ed948f38134ffa90f02da73f7a610044d634e5ba
push idunknown
push userunknown
push dateunknown
bugs448993
milestone1.9.2a1pre
Bug 448993 - Crash [@ nsRange::CutContents] using deleteContents after extractContents and GC, r+sr=sicking
content/base/public/nsIRange.h
content/base/src/nsRange.cpp
content/base/src/nsRange.h
content/base/test/Makefile.in
content/base/test/test_bug448993.html
--- a/content/base/public/nsIRange.h
+++ b/content/base/public/nsIRange.h
@@ -107,17 +107,17 @@ public:
     mMaySpanAnonymousSubtrees = aMaySpanAnonymousSubtrees;
   }
 
   virtual nsINode* GetCommonAncestor() = 0;
 
   virtual void Reset() = 0;
 
 protected:
-  nsINode* mRoot;
+  nsCOMPtr<nsINode> mRoot;
   nsCOMPtr<nsINode> mStartParent;
   nsCOMPtr<nsINode> mEndParent;
   PRInt32 mStartOffset;
   PRInt32 mEndOffset;
 
   PRPackedBool mIsPositioned;
   PRPackedBool mIsDetached;
   PRPackedBool mMaySpanAnonymousSubtrees;
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -251,16 +251,17 @@ NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsRange)
   tmp->Reset();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsRange)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mStartParent)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEndParent)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRoot)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 /******************************************************
  * nsIMutationObserver implementation
  ******************************************************/
 
 void
 nsRange::CharacterDataChanged(nsIDocument* aDocument,
@@ -335,27 +336,16 @@ nsRange::ContentRemoved(nsIDocument* aDo
   }
   else if (nsContentUtils::ContentIsDescendantOf(mEndParent, aChild)) {
     mEndParent = container;
     mEndOffset = aIndexInContainer;
   }
 }
 
 void
-nsRange::NodeWillBeDestroyed(const nsINode* aNode)
-{
-  NS_ASSERTION(mIsPositioned, "shouldn't be notified if not positioned");
-
-  // No need to detach, but reset positions so that the endpoints don't
-  // end up disconnected from each other.
-  // An alternative solution would be to make mRoot a strong pointer.
-  DoSetRange(nsnull, 0, nsnull, 0, nsnull);
-}
-
-void
 nsRange::ParentChainChanged(nsIContent *aContent)
 {
   NS_ASSERTION(mRoot == aContent, "Wrong ParentChainChanged notification?");
   nsINode* newRoot = IsValidBoundary(mStartParent);
   NS_ASSERTION(newRoot, "No valid boundary or root found!");
   NS_ASSERTION(newRoot == IsValidBoundary(mEndParent),
                "Start parent and end parent give different root!");
   DoSetRange(mStartParent, mStartOffset, mEndParent, mEndOffset, newRoot);
--- a/content/base/src/nsRange.h
+++ b/content/base/src/nsRange.h
@@ -105,17 +105,16 @@ public:
   virtual void ContentInserted(nsIDocument* aDocument,
                                nsIContent* aContainer,
                                nsIContent* aChild,
                                PRInt32 aIndexInContainer);
   virtual void ContentRemoved(nsIDocument* aDocument,
                               nsIContent* aContainer,
                               nsIContent* aChild,
                               PRInt32 aIndexInContainer);
-  virtual void NodeWillBeDestroyed(const nsINode* aNode);
   virtual void ParentChainChanged(nsIContent *aContent);
 
 private:
   // no copy's or assigns
   nsRange(const nsRange&);
   nsRange& operator=(const nsRange&);
 
   nsINode* IsValidBoundary(nsINode* aNode);
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -236,16 +236,17 @@ include $(topsrcdir)/config/rules.mk
 		test_title.html \
 		test_bug453521.html \
 		test_bug391728.html \
 		file_bug391728.html \
 		test_bug454325.html \
 		file_bug391728_2.html \
 		test_bug456262.html \
 		test_bug368972.html \
+		test_bug448993.html \
 		test_bug450160.html \
 		test_bug454326.html \
 		test_bug457746.html \
 		bug457746.sjs \
 		test_CrossSiteXHR.html \
 		file_CrossSiteXHR_inner.html \
 		file_CrossSiteXHR_server.sjs \
 		test_CrossSiteXHR_cache.html \
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug448993.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=448993
+-->
+<head>
+  <title>Test for Bug 448993</title>
+  <script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=448993">Mozilla Bug 448993</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 448993 **/
+
+function gc() {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+        .getInterface(Components.interfaces.nsIDOMWindowUtils)
+        .garbageCollect();
+}
+
+function runTest() {
+  var a = document.getElementById("a");
+  var b = document.getElementById("b");
+  var c = document.getElementById("c")
+  var r = document.createRange();
+  r.setStart(b, 0); 
+  r.setEnd(a, 2); 
+  c.appendChild(b);
+  r.extractContents();
+  var s = document.createRange();
+  s.setEnd(b, 0); 
+  gc();
+  s.deleteContents();
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runTest);
+
+</script>
+</pre>
+<div id="a"><span id="b"></span><span id="c"></span></div>
+</body>
+</html>