From 3a6cd65871172b14a5e5f3371f7952d613b997d7 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Tue, 29 Nov 2016 15:57:30 -0800 Subject: [PATCH] Bug 1321066 - Explicitly guard against reentrance in nsSMILTimeContainer. r=dholbert --- dom/smil/nsSMILTimeContainer.cpp | 12 ++++++++++++ dom/smil/nsSMILTimeContainer.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/dom/smil/nsSMILTimeContainer.cpp b/dom/smil/nsSMILTimeContainer.cpp index ac1f56518230..96c772ab9b96 100644 --- a/dom/smil/nsSMILTimeContainer.cpp +++ b/dom/smil/nsSMILTimeContainer.cpp @@ -9,6 +9,8 @@ #include "nsSMILTimedElement.h" #include +#include "mozilla/AutoRestore.h" + nsSMILTimeContainer::nsSMILTimeContainer() : mParent(nullptr), @@ -18,6 +20,7 @@ nsSMILTimeContainer::nsSMILTimeContainer() mNeedsPauseSample(false), mNeedsRewind(false), mIsSeeking(false), + mHoldingEntries(false), mPauseState(PAUSE_BEGIN) { } @@ -213,12 +216,14 @@ nsSMILTimeContainer::AddMilestone(const nsSMILMilestone& aMilestone, // time may change (e.g. if attributes are changed on the timed element in // between samples). If this happens, then we may do an unecessary sample // but that's pretty cheap. + MOZ_RELEASE_ASSERT(!mHoldingEntries); return mMilestoneEntries.Push(MilestoneEntry(aMilestone, aElement)); } void nsSMILTimeContainer::ClearMilestones() { + MOZ_RELEASE_ASSERT(!mHoldingEntries); mMilestoneEntries.Clear(); } @@ -259,6 +264,8 @@ nsSMILTimeContainer::PopMilestoneElementsAtMilestone( "Trying to pop off earliest times but we have earlier ones that " "were overlooked"); + MOZ_RELEASE_ASSERT(!mHoldingEntries); + bool gotOne = false; while (!mMilestoneEntries.IsEmpty() && mMilestoneEntries.Top().mMilestone == containerMilestone) @@ -273,6 +280,8 @@ nsSMILTimeContainer::PopMilestoneElementsAtMilestone( void nsSMILTimeContainer::Traverse(nsCycleCollectionTraversalCallback* aCallback) { + AutoRestore saveHolding(mHoldingEntries); + mHoldingEntries = true; const MilestoneEntry* p = mMilestoneEntries.Elements(); while (p < mMilestoneEntries.Elements() + mMilestoneEntries.Length()) { NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCallback, "mTimebase"); @@ -284,6 +293,7 @@ nsSMILTimeContainer::Traverse(nsCycleCollectionTraversalCallback* aCallback) void nsSMILTimeContainer::Unlink() { + MOZ_RELEASE_ASSERT(!mHoldingEntries); mMilestoneEntries.Clear(); } @@ -307,6 +317,8 @@ nsSMILTimeContainer::NotifyTimeChange() // milestone elements. This is because any timed element with dependents and // with significant transitions yet to fire should have their next milestone // registered. Other timed elements don't matter. + AutoRestore saveHolding(mHoldingEntries); + mHoldingEntries = true; const MilestoneEntry* p = mMilestoneEntries.Elements(); #if DEBUG uint32_t queueLength = mMilestoneEntries.Length(); diff --git a/dom/smil/nsSMILTimeContainer.h b/dom/smil/nsSMILTimeContainer.h index 8d0ec0385ebc..50c9709dbfc1 100644 --- a/dom/smil/nsSMILTimeContainer.h +++ b/dom/smil/nsSMILTimeContainer.h @@ -266,6 +266,8 @@ protected: bool mNeedsRewind; // Backwards seek performed bool mIsSeeking; // Currently in the middle of a seek operation + bool mHoldingEntries; // True if there's a raw pointer to mMilestoneEntries on the stack. + // A bitfield of the pause state for all pause requests uint32_t mPauseState;