Bug 1417417 - use UniquePtr for bufferCopy to prevent memory leak when treeOp is null. r=hsivonen
authorAndi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
Wed, 15 Nov 2017 16:50:58 +0200
changeset 391917 34e43107b2f6ba30504815614c6c769228e62da8
parent 391916 5a31594501ba143897ed841c3104c7e5f35e6a0a
child 391918 40afac82ba8170e32100b4de73a2625c0dfd7848
push id32908
push usercbrindusan@mozilla.com
push dateWed, 15 Nov 2017 22:22:51 +0000
treeherdermozilla-central@60b9fa15e427 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershsivonen
bugs1417417
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1417417 - use UniquePtr for bufferCopy to prevent memory leak when treeOp is null. r=hsivonen MozReview-Commit-ID: HBI7CWjtS80
parser/html/nsHtml5TreeBuilderCppSupplement.h
--- a/parser/html/nsHtml5TreeBuilderCppSupplement.h
+++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h
@@ -71,18 +71,18 @@ nsIContentHandle*
 nsHtml5TreeBuilder::createElement(int32_t aNamespace,
                                   nsAtom* aName,
                                   nsHtml5HtmlAttributes* aAttributes,
                                   nsIContentHandle* aIntendedParent,
                                   nsHtml5ContentCreatorFunction aCreator)
 {
   NS_PRECONDITION(aAttributes, "Got null attributes.");
   NS_PRECONDITION(aName, "Got null name.");
-  NS_PRECONDITION(aNamespace == kNameSpaceID_XHTML || 
-                  aNamespace == kNameSpaceID_SVG || 
+  NS_PRECONDITION(aNamespace == kNameSpaceID_XHTML ||
+                  aNamespace == kNameSpaceID_SVG ||
                   aNamespace == kNameSpaceID_MathML,
                   "Bogus namespace.");
 
   if (mBuilder) {
     RefPtr<nsAtom> name = nsHtml5TreeOperation::Reget(aName);
 
     nsIContent* intendedParent = aIntendedParent ?
       static_cast<nsIContent*>(aIntendedParent) : nullptr;
@@ -362,17 +362,17 @@ nsHtml5TreeBuilder::createElement(int32_
     } else if (nsGkAtoms::script == aName) {
       nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
       if (MOZ_UNLIKELY(!treeOp)) {
         MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
         return nullptr;
       }
       treeOp->Init(eTreeOpSetScriptLineNumberAndFreeze, content, tokenizer->getLineNumber());
       if (aNamespace == kNameSpaceID_XHTML) {
-        mCurrentHtmlScriptIsAsyncOrDefer = 
+        mCurrentHtmlScriptIsAsyncOrDefer =
           aAttributes->contains(nsHtml5AttributeName::ATTR_SRC) &&
           (aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC) ||
            aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER));
       }
     } else if (aNamespace == kNameSpaceID_XHTML) {
       if (nsGkAtoms::html == aName) {
         nsHtml5String url =
           aAttributes->getValue(nsHtml5AttributeName::ATTR_MANIFEST);
@@ -391,23 +391,23 @@ nsHtml5TreeBuilder::createElement(int32_
         } else {
           treeOp->Init(eTreeOpProcessOfflineManifest, EmptyString());
         }
       } else if (nsGkAtoms::base == aName && mViewSource) {
         nsHtml5String url =
           aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
         if (url) {
           mViewSource->AddBase(url);
-        } 
+        }
       }
     }
   }
 
   // End wall of code for speculative loading
-  
+
   return content;
 }
 
 nsIContentHandle*
 nsHtml5TreeBuilder::createElement(int32_t aNamespace,
                                   nsAtom* aName,
                                   nsHtml5HtmlAttributes* aAttributes,
                                   nsIContentHandle* aFormElement,
@@ -590,33 +590,33 @@ nsHtml5TreeBuilder::insertFosterParented
       static_cast<nsIContent*>(aTable),
       mBuilder);
     if (NS_FAILED(rv)) {
       MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
     }
     return;
   }
 
-  char16_t* bufferCopy = new (mozilla::fallible) char16_t[aLength];
+  auto bufferCopy = MakeUniqueFallible<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));
+  memcpy(bufferCopy.get(), aBuffer, aLength * sizeof(char16_t));
 
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
   if (MOZ_UNLIKELY(!treeOp)) {
     MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
-  treeOp->Init(eTreeOpFosterParentText, bufferCopy, aLength, aStackParent, aTable);
+  treeOp->Init(eTreeOpFosterParentText, bufferCopy.release(), aLength, aStackParent, aTable);
 }
 
 void
 nsHtml5TreeBuilder::insertFosterParentedChild(nsIContentHandle* aChild, nsIContentHandle* aTable, nsIContentHandle* aStackParent)
 {
   NS_PRECONDITION(aChild, "Null child");
   NS_PRECONDITION(aTable, "Null table");
   NS_PRECONDITION(aStackParent, "Null stack parent");
@@ -656,33 +656,33 @@ nsHtml5TreeBuilder::appendCharacters(nsI
                                deepTreeSurrogateParent : aParent),
       mBuilder);
     if (NS_FAILED(rv)) {
       MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
     }
     return;
   }
 
-  char16_t* bufferCopy = new (mozilla::fallible) char16_t[aLength];
+  auto bufferCopy = MakeUniqueFallible<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));
+  memcpy(bufferCopy.get(), aBuffer, aLength * sizeof(char16_t));
 
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
   if (MOZ_UNLIKELY(!treeOp)) {
     MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
-  treeOp->Init(eTreeOpAppendText, bufferCopy, aLength,
+  treeOp->Init(eTreeOpAppendText, bufferCopy.release(), aLength,
       deepTreeSurrogateParent ? deepTreeSurrogateParent : aParent);
 }
 
 void
 nsHtml5TreeBuilder::appendComment(nsIContentHandle* aParent, char16_t* aBuffer, int32_t aStart, int32_t aLength)
 {
   NS_PRECONDITION(aBuffer, "Null buffer");
   NS_PRECONDITION(aParent, "Null parent");
@@ -699,33 +699,33 @@ nsHtml5TreeBuilder::appendComment(nsICon
       aLength,
       mBuilder);
     if (NS_FAILED(rv)) {
       MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
     }
     return;
   }
 
-  char16_t* bufferCopy = new (mozilla::fallible) char16_t[aLength];
+  auto bufferCopy = MakeUniqueFallible<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));
+  memcpy(bufferCopy.get(), aBuffer, aLength * sizeof(char16_t));
 
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
   if (MOZ_UNLIKELY(!treeOp)) {
     MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
-  treeOp->Init(eTreeOpAppendComment, bufferCopy, aLength, aParent);
+  treeOp->Init(eTreeOpAppendComment, bufferCopy.release(), aLength, aParent);
 }
 
 void
 nsHtml5TreeBuilder::appendCommentToDocument(char16_t* aBuffer, int32_t aStart, int32_t aLength)
 {
   NS_PRECONDITION(aBuffer, "Null buffer");
   MOZ_ASSERT(!aStart, "aStart must always be zero.");
 
@@ -735,33 +735,33 @@ nsHtml5TreeBuilder::appendCommentToDocum
       aLength,
       mBuilder);
     if (NS_FAILED(rv)) {
       MarkAsBrokenAndRequestSuspensionWithBuilder(rv);
     }
     return;
   }
 
-  char16_t* bufferCopy = new (mozilla::fallible) char16_t[aLength];
+  auto bufferCopy = MakeUniqueFallible<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));
+  memcpy(bufferCopy.get(), aBuffer, aLength * sizeof(char16_t));
 
   nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
   if (MOZ_UNLIKELY(!treeOp)) {
     MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
-  treeOp->Init(eTreeOpAppendCommentToDocument, bufferCopy, aLength);
+  treeOp->Init(eTreeOpAppendCommentToDocument, bufferCopy.release(), aLength);
 }
 
 void
 nsHtml5TreeBuilder::addAttributesToElement(nsIContentHandle* aElement, nsHtml5HtmlAttributes* aAttributes)
 {
   NS_PRECONDITION(aElement, "Null element");
   NS_PRECONDITION(aAttributes, "Null attributes");
 
@@ -953,24 +953,24 @@ nsHtml5TreeBuilder::elementPopped(int32_
       }
       mOpQueue.AppendElement()->Init(eTreeOpPreventScriptExecution, aElement);
       return;
     }
     if (mBuilder) {
       return;
     }
     if (mCurrentHtmlScriptIsAsyncOrDefer) {
-      NS_ASSERTION(aNamespace == kNameSpaceID_XHTML, 
+      NS_ASSERTION(aNamespace == kNameSpaceID_XHTML,
                    "Only HTML scripts may be async/defer.");
       nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
       if (MOZ_UNLIKELY(!treeOp)) {
         MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
         return;
       }
-      treeOp->Init(eTreeOpRunScriptAsyncDefer, aElement);      
+      treeOp->Init(eTreeOpRunScriptAsyncDefer, aElement);
       mCurrentHtmlScriptIsAsyncOrDefer = false;
       return;
     }
     requestSuspension();
     nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(mozilla::fallible);
     if (MOZ_UNLIKELY(!treeOp)) {
       MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY);
       return;
@@ -1186,17 +1186,17 @@ nsHtml5TreeBuilder::FlushLoads()
     return;
   }
   if (!mSpeculativeLoadQueue.IsEmpty()) {
     mSpeculativeLoadStage->MoveSpeculativeLoadsFrom(mSpeculativeLoadQueue);
   }
 }
 
 void
-nsHtml5TreeBuilder::SetDocumentCharset(NotNull<const Encoding*> aEncoding, 
+nsHtml5TreeBuilder::SetDocumentCharset(NotNull<const Encoding*> aEncoding,
                                        int32_t aCharsetSource)
 {
   if (mBuilder) {
     mBuilder->SetDocumentCharsetAndSource(aEncoding, aCharsetSource);
   } else if (mSpeculativeLoadStage) {
     nsAutoCString charset;
     aEncoding->Name(charset);
     mSpeculativeLoadQueue.AppendElement()->InitSetDocumentCharset(