mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1176681 - Make character buffer allocations in the HTML5 tree builder fallible. r=wchen.
This commit is contained in:
parent
02d517f7ac
commit
e743fa6a9c
@ -374,6 +374,9 @@ nsHtml5Parser::Parse(const nsAString& aSourceBuffer,
|
||||
return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
mLastWasCR = mTokenizer->tokenizeBuffer(&stackBuffer);
|
||||
if (NS_FAILED((rv = mTreeBuilder->IsBroken()))) {
|
||||
return mExecutor->MarkAsBroken(rv);
|
||||
}
|
||||
|
||||
if (inRootContext) {
|
||||
mRootContextLineNumber = mTokenizer->getLineNumber();
|
||||
@ -485,6 +488,10 @@ nsHtml5Parser::Parse(const nsAString& aSourceBuffer,
|
||||
}
|
||||
mDocWriteSpeculativeLastWasCR =
|
||||
mDocWriteSpeculativeTokenizer->tokenizeBuffer(&stackBuffer);
|
||||
nsresult rv;
|
||||
if (NS_FAILED((rv = mDocWriteSpeculativeTreeBuilder->IsBroken()))) {
|
||||
return mExecutor->MarkAsBroken(rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -625,7 +632,11 @@ nsHtml5Parser::ParseUntilBlocked()
|
||||
"This should only happen with script-created parser.");
|
||||
if (NS_SUCCEEDED((rv = mExecutor->IsBroken()))) {
|
||||
mTokenizer->eof();
|
||||
mTreeBuilder->StreamEnded();
|
||||
if (NS_FAILED((rv = mTreeBuilder->IsBroken()))) {
|
||||
mExecutor->MarkAsBroken(rv);
|
||||
} else {
|
||||
mTreeBuilder->StreamEnded();
|
||||
}
|
||||
}
|
||||
mTreeBuilder->Flush();
|
||||
mExecutor->FlushDocumentWrite();
|
||||
@ -676,12 +687,16 @@ nsHtml5Parser::ParseUntilBlocked()
|
||||
return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
mLastWasCR = mTokenizer->tokenizeBuffer(mFirstBuffer);
|
||||
nsresult rv;
|
||||
if (NS_FAILED((rv = mTreeBuilder->IsBroken()))) {
|
||||
return mExecutor->MarkAsBroken(rv);
|
||||
}
|
||||
if (inRootContext) {
|
||||
mRootContextLineNumber = mTokenizer->getLineNumber();
|
||||
}
|
||||
if (mTreeBuilder->HasScript()) {
|
||||
mTreeBuilder->Flush();
|
||||
nsresult rv = mExecutor->FlushDocumentWrite();
|
||||
rv = mExecutor->FlushDocumentWrite();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
if (mBlocked) {
|
||||
|
@ -1369,9 +1369,14 @@ nsHtml5StreamParser::ParseAvailableData()
|
||||
}
|
||||
if (NS_SUCCEEDED(mTreeBuilder->IsBroken())) {
|
||||
mTokenizer->eof();
|
||||
mTreeBuilder->StreamEnded();
|
||||
if (mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML) {
|
||||
mTokenizer->EndViewSource();
|
||||
nsresult rv;
|
||||
if (NS_FAILED((rv = mTreeBuilder->IsBroken()))) {
|
||||
MarkAsBroken(rv);
|
||||
} else {
|
||||
mTreeBuilder->StreamEnded();
|
||||
if (mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML) {
|
||||
mTokenizer->EndViewSource();
|
||||
}
|
||||
}
|
||||
}
|
||||
FlushTreeOpsAndDisarmTimer();
|
||||
@ -1394,6 +1399,11 @@ nsHtml5StreamParser::ParseAvailableData()
|
||||
return;
|
||||
}
|
||||
mLastWasCR = mTokenizer->tokenizeBuffer(mFirstBuffer);
|
||||
nsresult rv;
|
||||
if (NS_FAILED((rv = mTreeBuilder->IsBroken()))) {
|
||||
MarkAsBroken(rv);
|
||||
return;
|
||||
}
|
||||
// At this point, internalEncodingDeclaration() may have called
|
||||
// Terminate, but that never happens together with script.
|
||||
// Can't assert that here, though, because it's possible that the main
|
||||
|
@ -501,7 +501,15 @@ nsHtml5TreeBuilder::insertFosterParentedCharacters(char16_t* aBuffer, int32_t aS
|
||||
return;
|
||||
}
|
||||
|
||||
char16_t* bufferCopy = new char16_t[aLength];
|
||||
char16_t* bufferCopy = new (mozilla::fallible) char16_t[aLength];
|
||||
if (!bufferCopy) {
|
||||
// Just assigning mBroken instead of generating tree op. The caller
|
||||
// of tokenizeBuffer() will call MarkAsBroken() as appropriate.
|
||||
mBroken = NS_ERROR_OUT_OF_MEMORY;
|
||||
requestSuspension();
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(bufferCopy, aBuffer, aLength * sizeof(char16_t));
|
||||
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
@ -553,7 +561,15 @@ nsHtml5TreeBuilder::appendCharacters(nsIContentHandle* aParent, char16_t* aBuffe
|
||||
return;
|
||||
}
|
||||
|
||||
char16_t* bufferCopy = new char16_t[aLength];
|
||||
char16_t* bufferCopy = new (mozilla::fallible) char16_t[aLength];
|
||||
if (!bufferCopy) {
|
||||
// Just assigning mBroken instead of generating tree op. The caller
|
||||
// of tokenizeBuffer() will call MarkAsBroken() as appropriate.
|
||||
mBroken = NS_ERROR_OUT_OF_MEMORY;
|
||||
requestSuspension();
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(bufferCopy, aBuffer, aLength * sizeof(char16_t));
|
||||
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
@ -605,7 +621,15 @@ nsHtml5TreeBuilder::appendComment(nsIContentHandle* aParent, char16_t* aBuffer,
|
||||
return;
|
||||
}
|
||||
|
||||
char16_t* bufferCopy = new char16_t[aLength];
|
||||
char16_t* bufferCopy = new (mozilla::fallible) char16_t[aLength];
|
||||
if (!bufferCopy) {
|
||||
// Just assigning mBroken instead of generating tree op. The caller
|
||||
// of tokenizeBuffer() will call MarkAsBroken() as appropriate.
|
||||
mBroken = NS_ERROR_OUT_OF_MEMORY;
|
||||
requestSuspension();
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(bufferCopy, aBuffer, aLength * sizeof(char16_t));
|
||||
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
@ -630,7 +654,15 @@ nsHtml5TreeBuilder::appendCommentToDocument(char16_t* aBuffer, int32_t aStart, i
|
||||
return;
|
||||
}
|
||||
|
||||
char16_t* bufferCopy = new char16_t[aLength];
|
||||
char16_t* bufferCopy = new (mozilla::fallible) char16_t[aLength];
|
||||
if (!bufferCopy) {
|
||||
// Just assigning mBroken instead of generating tree op. The caller
|
||||
// of tokenizeBuffer() will call MarkAsBroken() as appropriate.
|
||||
mBroken = NS_ERROR_OUT_OF_MEMORY;
|
||||
requestSuspension();
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(bufferCopy, aBuffer, aLength * sizeof(char16_t));
|
||||
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
@ -984,20 +1016,30 @@ nsHtml5TreeBuilder::Flush(bool aDiscretionary)
|
||||
MOZ_ASSERT_UNREACHABLE("Must never flush with builder.");
|
||||
return false;
|
||||
}
|
||||
if (!aDiscretionary ||
|
||||
!(charBufferLen &&
|
||||
currentPtr >= 0 &&
|
||||
stack[currentPtr]->isFosterParenting())) {
|
||||
// Don't flush text on discretionary flushes if the current element on
|
||||
// the stack is a foster-parenting element and there's pending text,
|
||||
// because flushing in that case would make the tree shape dependent on
|
||||
// where the flush points fall.
|
||||
flushCharacters();
|
||||
if (NS_SUCCEEDED(mBroken)) {
|
||||
if (!aDiscretionary ||
|
||||
!(charBufferLen &&
|
||||
currentPtr >= 0 &&
|
||||
stack[currentPtr]->isFosterParenting())) {
|
||||
// Don't flush text on discretionary flushes if the current element on
|
||||
// the stack is a foster-parenting element and there's pending text,
|
||||
// because flushing in that case would make the tree shape dependent on
|
||||
// where the flush points fall.
|
||||
flushCharacters();
|
||||
}
|
||||
FlushLoads();
|
||||
}
|
||||
FlushLoads();
|
||||
if (mOpSink) {
|
||||
bool hasOps = !mOpQueue.IsEmpty();
|
||||
if (hasOps) {
|
||||
// If the builder is broken and mOpQueue is not empty, there must be
|
||||
// one op and it must be eTreeOpMarkAsBroken.
|
||||
if (NS_FAILED(mBroken)) {
|
||||
MOZ_ASSERT(mOpQueue.Length() == 1,
|
||||
"Tree builder is broken with a non-empty op queue whose length isn't 1.");
|
||||
MOZ_ASSERT(mOpQueue[0].IsMarkAsBroken(),
|
||||
"Tree builder is broken but the op in queue is not marked as broken.");
|
||||
}
|
||||
mOpSink->MoveOpsFrom(mOpQueue);
|
||||
}
|
||||
return hasOps;
|
||||
|
@ -476,6 +476,11 @@ class nsHtml5TreeOperation {
|
||||
return mOpCode == eTreeOpRunScript;
|
||||
}
|
||||
|
||||
inline bool IsMarkAsBroken()
|
||||
{
|
||||
return mOpCode == eTreeOpMarkAsBroken;
|
||||
}
|
||||
|
||||
inline void SetSnapshot(nsAHtml5TreeBuilderState* aSnapshot, int32_t aLine)
|
||||
{
|
||||
NS_ASSERTION(IsRunScript(),
|
||||
|
Loading…
Reference in New Issue
Block a user