Bug 1417417 - use UniquePtr for bufferCopy to prevent memory leak when treeOp is null. r?hsivonen draft
authorAndi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
Wed, 15 Nov 2017 16:50:58 +0200
changeset 698338 50668cf1c2e2249f4060197906266fcc3ddcf3e6
parent 697940 f0c0fb9182d695081edf170d8e3bcb8164f2c96a
child 740346 2ff1509e7df0197f06969fd516103f7a6c112676
push id89255
push userbmo:bpostelnicu@mozilla.com
push dateWed, 15 Nov 2017 14:51:48 +0000
reviewershsivonen
bugs1417417
milestone59.0a1
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(