зеркало из https://github.com/mozilla/gecko-dev.git
Bug 855898 - Limit ProcessChildren recursion depth to avoid exhausting stack space and crashing. r=bzbarsky
This commit is contained in:
Родитель
72dcb9d7c9
Коммит
57ed7b1c58
|
@ -11,11 +11,11 @@
|
||||||
|
|
||||||
#include "nsCSSFrameConstructor.h"
|
#include "nsCSSFrameConstructor.h"
|
||||||
|
|
||||||
|
#include "mozilla/AutoRestore.h"
|
||||||
#include "mozilla/DebugOnly.h"
|
#include "mozilla/DebugOnly.h"
|
||||||
#include "mozilla/dom/HTMLSelectElement.h"
|
#include "mozilla/dom/HTMLSelectElement.h"
|
||||||
#include "mozilla/Likely.h"
|
#include "mozilla/Likely.h"
|
||||||
#include "mozilla/LinkedList.h"
|
#include "mozilla/LinkedList.h"
|
||||||
|
|
||||||
#include "nsAbsoluteContainingBlock.h"
|
#include "nsAbsoluteContainingBlock.h"
|
||||||
#include "nsCRT.h"
|
#include "nsCRT.h"
|
||||||
#include "nsIAtom.h"
|
#include "nsIAtom.h"
|
||||||
|
@ -1415,6 +1415,7 @@ nsCSSFrameConstructor::nsCSSFrameConstructor(nsIDocument *aDocument,
|
||||||
, mDocElementContainingBlock(nullptr)
|
, mDocElementContainingBlock(nullptr)
|
||||||
, mGfxScrollFrame(nullptr)
|
, mGfxScrollFrame(nullptr)
|
||||||
, mPageSequenceFrame(nullptr)
|
, mPageSequenceFrame(nullptr)
|
||||||
|
, mCurrentDepth(0)
|
||||||
, mUpdateCount(0)
|
, mUpdateCount(0)
|
||||||
, mQuotesDirty(false)
|
, mQuotesDirty(false)
|
||||||
, mCountersDirty(false)
|
, mCountersDirty(false)
|
||||||
|
@ -9841,6 +9842,12 @@ nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
|
||||||
NS_PRECONDITION(aFrame->GetContentInsertionFrame() == aFrame,
|
NS_PRECONDITION(aFrame->GetContentInsertionFrame() == aFrame,
|
||||||
"Parent frame in ProcessChildren should be its own "
|
"Parent frame in ProcessChildren should be its own "
|
||||||
"content insertion frame");
|
"content insertion frame");
|
||||||
|
const uint32_t kMaxDepth = 2 * MAX_REFLOW_DEPTH;
|
||||||
|
MOZ_STATIC_ASSERT(kMaxDepth <= UINT16_MAX, "mCurrentDepth type is too narrow");
|
||||||
|
AutoRestore<uint16_t> savedDepth(mCurrentDepth);
|
||||||
|
if (mCurrentDepth != UINT16_MAX) {
|
||||||
|
++mCurrentDepth;
|
||||||
|
}
|
||||||
|
|
||||||
if (!aPossiblyLeafFrame) {
|
if (!aPossiblyLeafFrame) {
|
||||||
aPossiblyLeafFrame = aFrame;
|
aPossiblyLeafFrame = aFrame;
|
||||||
|
@ -9938,6 +9945,11 @@ nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
|
||||||
itemsToConstruct);
|
itemsToConstruct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool addChildItems = MOZ_LIKELY(mCurrentDepth < kMaxDepth);
|
||||||
|
if (!addChildItems) {
|
||||||
|
NS_WARNING("ProcessChildren max depth exceeded");
|
||||||
|
}
|
||||||
|
|
||||||
ChildIterator iter, last;
|
ChildIterator iter, last;
|
||||||
for (ChildIterator::Init(aContent, &iter, &last);
|
for (ChildIterator::Init(aContent, &iter, &last);
|
||||||
iter != last;
|
iter != last;
|
||||||
|
@ -9948,8 +9960,12 @@ nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
|
||||||
if (child->IsElement()) {
|
if (child->IsElement()) {
|
||||||
child->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS);
|
child->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS);
|
||||||
}
|
}
|
||||||
AddFrameConstructionItems(aState, child, iter.XBLInvolved(), aFrame,
|
if (addChildItems) {
|
||||||
itemsToConstruct);
|
AddFrameConstructionItems(aState, child, iter.XBLInvolved(), aFrame,
|
||||||
|
itemsToConstruct);
|
||||||
|
} else {
|
||||||
|
ClearLazyBits(child, child->GetNextSibling());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
itemsToConstruct.SetParentHasNoXBLChildren(!iter.XBLInvolved());
|
itemsToConstruct.SetParentHasNoXBLChildren(!iter.XBLInvolved());
|
||||||
|
|
||||||
|
|
|
@ -1878,6 +1878,8 @@ private:
|
||||||
nsIFrame* mPageSequenceFrame;
|
nsIFrame* mPageSequenceFrame;
|
||||||
nsQuoteList mQuoteList;
|
nsQuoteList mQuoteList;
|
||||||
nsCounterManager mCounterManager;
|
nsCounterManager mCounterManager;
|
||||||
|
// Current ProcessChildren depth.
|
||||||
|
uint16_t mCurrentDepth;
|
||||||
uint16_t mUpdateCount;
|
uint16_t mUpdateCount;
|
||||||
bool mQuotesDirty : 1;
|
bool mQuotesDirty : 1;
|
||||||
bool mCountersDirty : 1;
|
bool mCountersDirty : 1;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче