diff --git a/layout/generic/crashtests/606642.xhtml b/layout/generic/crashtests/606642.xhtml
new file mode 100644
index 00000000000..9113b7d7182
--- /dev/null
+++ b/layout/generic/crashtests/606642.xhtml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/layout/generic/crashtests/crashtests.list b/layout/generic/crashtests/crashtests.list
index 6b575fe8b8d..923619da973 100644
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -383,6 +383,7 @@ load 603510-1.html
load 604314-1.html
load 604843.html
load 605340.html
+load 606642.xhtml
load 621424-1.html
load 621841-1.html
load 645072-1.html
diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp
index 4605c6e9dd8..80a0be5777b 100644
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -216,6 +216,27 @@ nsContainerFrame::DestroyAbsoluteFrames(nsIFrame* aDestructRoot)
}
}
+void
+nsContainerFrame::SafelyDestroyFrameListProp(nsIFrame* aDestructRoot,
+ FramePropertyTable* aPropTable,
+ const FramePropertyDescriptor* aProp)
+{
+ // Note that the last frame can be removed through another route and thus
+ // delete the property -- that's why we fetch the property again before
+ // removing each frame rather than fetching it once and iterating the list.
+ while (nsFrameList* frameList =
+ static_cast(aPropTable->Get(this, aProp))) {
+ nsIFrame* frame = frameList->RemoveFirstChild();
+ if (MOZ_LIKELY(frame)) {
+ frame->DestroyFrom(aDestructRoot);
+ } else {
+ aPropTable->Remove(this, aProp);
+ delete frameList;
+ return;
+ }
+ }
+}
+
void
nsContainerFrame::DestroyFrom(nsIFrame* aDestructRoot)
{
@@ -235,15 +256,11 @@ nsContainerFrame::DestroyFrom(nsIFrame* aDestructRoot)
DestroyOverflowList(prescontext, aDestructRoot);
if (IsFrameOfType(nsIFrame::eCanContainOverflowContainers)) {
- nsFrameList* frameList =
- RemovePropTableFrames(prescontext, OverflowContainersProperty());
- if (frameList)
- frameList->DestroyFrom(aDestructRoot);
-
- frameList = RemovePropTableFrames(prescontext,
- ExcessOverflowContainersProperty());
- if (frameList)
- frameList->DestroyFrom(aDestructRoot);
+ FramePropertyTable* props = prescontext->PropertyTable();
+ SafelyDestroyFrameListProp(aDestructRoot, props,
+ OverflowContainersProperty());
+ SafelyDestroyFrameListProp(aDestructRoot, props,
+ ExcessOverflowContainersProperty());
}
// Destroy the frame and remove the flow pointers
diff --git a/layout/generic/nsContainerFrame.h b/layout/generic/nsContainerFrame.h
index 5880f1df89e..b1b7eb56a2e 100644
--- a/layout/generic/nsContainerFrame.h
+++ b/layout/generic/nsContainerFrame.h
@@ -25,6 +25,9 @@
#define NS_FRAME_INVALIDATE_ON_MOVE 0x0010
class nsOverflowContinuationTracker;
+namespace mozilla {
+class FramePropertyTable;
+}
// Some macros for container classes to do sanity checking on
// width/height/x/y values computed during reflow.
@@ -514,6 +517,16 @@ protected:
nsresult SetPropTableFrames(nsPresContext* aPresContext,
nsFrameList* aFrameList,
const FramePropertyDescriptor* aProperty);
+
+ /**
+ * Safely destroy the frames on the nsFrameList stored on aProp for this
+ * frame then remove the property and delete the frame list.
+ * Nothing happens if the property doesn't exist.
+ */
+ void SafelyDestroyFrameListProp(nsIFrame* aDestructRoot,
+ mozilla::FramePropertyTable* aPropTable,
+ const FramePropertyDescriptor* aProp);
+
// ==========================================================================
nsFrameList mFrames;
diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h
index f7742bf7da4..2f950500b2e 100644
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -618,6 +618,7 @@ protected:
virtual void DestroyFrom(nsIFrame* aDestructRoot) = 0;
friend class nsFrameList; // needed to pass aDestructRoot through to children
friend class nsLineBox; // needed to pass aDestructRoot through to children
+ friend class nsContainerFrame; // needed to pass aDestructRoot through to children
public:
/**