Bug 1409327 - NS_NewBufferedInputStream should take the ownership of the inputStream, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Thu, 19 Oct 2017 11:39:30 +0200
changeset 437895 23e2e65211f5c7787d45f56da9ea56bcf5f73a94
parent 437894 47bb399c0621cf47178dbb2360dabeda70dc5eb6
child 437896 007b32ba8b07089a562ae19477d6f9d2d149d2be
push id8114
push userjlorenzo@mozilla.com
push dateThu, 02 Nov 2017 16:33:21 +0000
treeherdermozilla-beta@73e0d89a540f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1409327
milestone58.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 1409327 - NS_NewBufferedInputStream should take the ownership of the inputStream, r=smaug
dom/base/DOMParser.cpp
dom/base/nsSyncLoadService.cpp
dom/base/nsSyncLoadService.h
dom/cache/FileUtils.cpp
dom/html/HTMLFormSubmission.cpp
dom/quota/ActorsParent.cpp
dom/webbrowserpersist/nsWebBrowserPersist.cpp
dom/workers/FileReaderSync.cpp
dom/workers/FileReaderSync.h
dom/xbl/nsXBLService.cpp
dom/xhr/XMLHttpRequestMainThread.cpp
dom/xhr/XMLHttpRequestMainThread.h
gfx/thebes/gfxSVGGlyphs.cpp
image/ImageOps.cpp
image/ImageOps.h
image/imgTools.cpp
image/test/fuzzing/TestDecoders.cpp
image/test/gtest/Common.cpp
image/test/gtest/TestDecodeToSurface.cpp
layout/style/Loader.cpp
netwerk/base/nsInputStreamPump.cpp
netwerk/base/nsNetUtil.cpp
netwerk/base/nsNetUtil.h
netwerk/protocol/http/HttpBaseChannel.cpp
netwerk/protocol/http/nsHttpTransaction.cpp
parser/xml/nsSAXXMLReader.cpp
rdf/base/nsRDFXMLDataSource.cpp
toolkit/components/places/FaviconHelpers.cpp
toolkit/components/url-classifier/HashStore.cpp
toolkit/components/url-classifier/VariableLengthPrefixSet.cpp
toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp
tools/fuzzing/interface/FuzzingInterface.cpp
xpcom/tests/gtest/TestCloneInputStream.cpp
--- a/dom/base/DOMParser.cpp
+++ b/dom/base/DOMParser.cpp
@@ -191,45 +191,46 @@ DOMParser::ParseFromStream(nsIInputStrea
                                   aContentLength,
                                   StringFromSupportedType(aType),
                                   getter_AddRefs(domDocument));
   nsCOMPtr<nsIDocument> document(do_QueryInterface(domDocument));
   return document.forget();
 }
 
 NS_IMETHODIMP
-DOMParser::ParseFromStream(nsIInputStream *stream,
-                           const char *charset,
-                           int32_t contentLength,
-                           const char *contentType,
-                           nsIDOMDocument **aResult)
+DOMParser::ParseFromStream(nsIInputStream* aStream,
+                           const char* aCharset,
+                           int32_t aContentLength,
+                           const char* aContentType,
+                           nsIDOMDocument** aResult)
 {
-  NS_ENSURE_ARG(stream);
-  NS_ENSURE_ARG(contentType);
+  NS_ENSURE_ARG(aStream);
+  NS_ENSURE_ARG(aContentType);
   NS_ENSURE_ARG_POINTER(aResult);
   *aResult = nullptr;
 
-  bool svg = nsCRT::strcmp(contentType, "image/svg+xml") == 0;
+  bool svg = nsCRT::strcmp(aContentType, "image/svg+xml") == 0;
 
   // For now, we can only create XML documents.
   //XXXsmaug Should we create an HTMLDocument (in XHTML mode)
   //         for "application/xhtml+xml"?
-  if ((nsCRT::strcmp(contentType, "text/xml") != 0) &&
-      (nsCRT::strcmp(contentType, "application/xml") != 0) &&
-      (nsCRT::strcmp(contentType, "application/xhtml+xml") != 0) &&
+  if ((nsCRT::strcmp(aContentType, "text/xml") != 0) &&
+      (nsCRT::strcmp(aContentType, "application/xml") != 0) &&
+      (nsCRT::strcmp(aContentType, "application/xhtml+xml") != 0) &&
       !svg)
     return NS_ERROR_NOT_IMPLEMENTED;
 
   nsresult rv;
 
   // Put the nsCOMPtr out here so we hold a ref to the stream as needed
-  nsCOMPtr<nsIInputStream> bufferedStream;
+  nsCOMPtr<nsIInputStream> stream = aStream;
   if (!NS_InputStreamIsBuffered(stream)) {
-    rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream,
-                                   4096);
+    nsCOMPtr<nsIInputStream> bufferedStream;
+    rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
+                                   stream.forget(), 4096);
     NS_ENSURE_SUCCESS(rv, rv);
 
     stream = bufferedStream;
   }
 
   nsCOMPtr<nsIDOMDocument> domDocument;
   rv = SetUpDocument(svg ? DocumentFlavorSVG : DocumentFlavorLegacyGuess,
                      getter_AddRefs(domDocument));
@@ -238,21 +239,21 @@ DOMParser::ParseFromStream(nsIInputStrea
   // Create a fake channel
   nsCOMPtr<nsIChannel> parserChannel;
   NS_NewInputStreamChannel(getter_AddRefs(parserChannel),
                            mDocumentURI,
                            nullptr, // aStream
                            mPrincipal,
                            nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
                            nsIContentPolicy::TYPE_OTHER,
-                           nsDependentCString(contentType));
+                           nsDependentCString(aContentType));
   NS_ENSURE_STATE(parserChannel);
 
-  if (charset) {
-    parserChannel->SetContentCharset(nsDependentCString(charset));
+  if (aCharset) {
+    parserChannel->SetContentCharset(nsDependentCString(aCharset));
   }
 
   // Tell the document to start loading
   nsCOMPtr<nsIStreamListener> listener;
 
   // Have to pass false for reset here, else the reset will remove
   // our event listener.  Should that listener addition move to later
   // than this call?
@@ -279,17 +280,17 @@ DOMParser::ParseFromStream(nsIInputStrea
 
   rv = listener->OnStartRequest(parserChannel, nullptr);
   if (NS_FAILED(rv))
     parserChannel->Cancel(rv);
   parserChannel->GetStatus(&status);
 
   if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
     rv = listener->OnDataAvailable(parserChannel, nullptr, stream, 0,
-                                   contentLength);
+                                   aContentLength);
     if (NS_FAILED(rv))
       parserChannel->Cancel(rv);
     parserChannel->GetStatus(&status);
   }
 
   rv = listener->OnStopRequest(parserChannel, nullptr, status);
   // Failure returned from OnStopRequest does not affect the final status of
   // the channel, so we do not need to call Cancel(rv) as we do above.
--- a/dom/base/nsSyncLoadService.cpp
+++ b/dom/base/nsSyncLoadService.cpp
@@ -247,17 +247,18 @@ nsSyncLoader::PushAsyncStream(nsIStreamL
 nsresult
 nsSyncLoader::PushSyncStream(nsIStreamListener* aListener)
 {
     nsCOMPtr<nsIInputStream> in;
     nsresult rv = mChannel->Open2(getter_AddRefs(in));
     NS_ENSURE_SUCCESS(rv, rv);
 
     mLoading = true;
-    rv = nsSyncLoadService::PushSyncStreamToListener(in, aListener, mChannel);
+    rv = nsSyncLoadService::PushSyncStreamToListener(in.forget(), aListener,
+                                                     mChannel);
     mLoading = false;
 
     return rv;
 }
 
 NS_IMETHODIMP
 nsSyncLoader::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
 {
@@ -333,57 +334,59 @@ nsSyncLoadService::LoadDocument(nsIURI *
        (NS_SUCCEEDED(aURI->SchemeIs("resource", &isResource)) && isResource));
     RefPtr<nsSyncLoader> loader = new nsSyncLoader();
     return loader->LoadDocument(channel, isSync, aForceToXML,
                                 aReferrerPolicy, aResult);
 }
 
 /* static */
 nsresult
-nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
+nsSyncLoadService::PushSyncStreamToListener(already_AddRefed<nsIInputStream> aIn,
                                             nsIStreamListener* aListener,
                                             nsIChannel* aChannel)
 {
+    nsCOMPtr<nsIInputStream> in = Move(aIn);
+
     // Set up buffering stream
     nsresult rv;
     nsCOMPtr<nsIInputStream> bufferedStream;
-    if (!NS_InputStreamIsBuffered(aIn)) {
+    if (!NS_InputStreamIsBuffered(in)) {
         int64_t chunkSize;
         rv = aChannel->GetContentLength(&chunkSize);
         if (NS_FAILED(rv) || chunkSize < 1) {
             chunkSize = 4096;
         }
         chunkSize = std::min(int64_t(UINT16_MAX), chunkSize);
 
-        rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), aIn,
-                                       chunkSize);
+        rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
+                                       in.forget(), chunkSize);
         NS_ENSURE_SUCCESS(rv, rv);
 
-        aIn = bufferedStream;
+        in = bufferedStream;
     }
 
     // Load
     rv = aListener->OnStartRequest(aChannel, nullptr);
     if (NS_SUCCEEDED(rv)) {
         uint64_t sourceOffset = 0;
         while (1) {
             uint64_t readCount = 0;
-            rv = aIn->Available(&readCount);
+            rv = in->Available(&readCount);
             if (NS_FAILED(rv) || !readCount) {
                 if (rv == NS_BASE_STREAM_CLOSED) {
                     // End of file, but not an error
                     rv = NS_OK;
                 }
                 break;
             }
 
             if (readCount > UINT32_MAX)
                 readCount = UINT32_MAX;
 
-            rv = aListener->OnDataAvailable(aChannel, nullptr, aIn,
+            rv = aListener->OnDataAvailable(aChannel, nullptr, in,
                                             (uint32_t)std::min(sourceOffset, (uint64_t)UINT32_MAX),
                                             (uint32_t)readCount);
             if (NS_FAILED(rv)) {
                 break;
             }
             sourceOffset += readCount;
         }
     }
--- a/dom/base/nsSyncLoadService.h
+++ b/dom/base/nsSyncLoadService.h
@@ -46,20 +46,20 @@ public:
                                  nsILoadGroup *aLoadGroup,
                                  bool aForceToXML,
                                  mozilla::net::ReferrerPolicy aReferrerPolicy,
                                  nsIDOMDocument** aResult);
 
     /**
      * Read input stream aIn in chunks and deliver synchronously to aListener.
      *
-     * @param aIn The stream to be read.
+     * @param aIn The stream to be read. The ownership of this stream is taken.
      * @param aListener The listener that will receive
      *                  OnStartRequest/OnDataAvailable/OnStopRequest
      *                  notifications.
      * @param aChannel The channel that aIn was opened from.
      */
-    static nsresult PushSyncStreamToListener(nsIInputStream* aIn,
+    static nsresult PushSyncStreamToListener(already_AddRefed<nsIInputStream> aIn,
                                              nsIStreamListener* aListener,
                                              nsIChannel* aChannel);
 };
 
 #endif // nsSyncLoadService_h__
--- a/dom/cache/FileUtils.cpp
+++ b/dom/cache/FileUtils.cpp
@@ -732,17 +732,18 @@ LockedDirectoryPaddingGet(nsIFile* aBase
   rv = file->Append(NS_LITERAL_STRING(PADDING_FILE_NAME));
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   nsCOMPtr<nsIInputStream> stream;
   rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), file);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   nsCOMPtr<nsIInputStream> bufferedStream;
-  rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream, 512);
+  rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream.forget(),
+                                 512);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   nsCOMPtr<nsIObjectInputStream> objectStream =
     NS_NewObjectInputStream(bufferedStream);
 
   uint64_t paddingSize = 0;
   rv = objectStream->Read64(&paddingSize);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
--- a/dom/html/HTMLFormSubmission.cpp
+++ b/dom/html/HTMLFormSubmission.cpp
@@ -524,17 +524,17 @@ FSMultipartFormData::AddNameBlobOrNullPa
       error.SuppressException();
       fileStream = nullptr;
     }
 
     if (fileStream) {
       // Create buffered stream (for efficiency)
       nsCOMPtr<nsIInputStream> bufferedStream;
       rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
-                                     fileStream, 8192);
+                                     fileStream.forget(), 8192);
       NS_ENSURE_SUCCESS(rv, rv);
 
       fileStream = bufferedStream;
     }
   } else {
     contentType.AssignLiteral("application/octet-stream");
   }
 
--- a/dom/quota/ActorsParent.cpp
+++ b/dom/quota/ActorsParent.cpp
@@ -2449,17 +2449,18 @@ GetBinaryInputStream(nsIFile* aDirectory
 
   nsCOMPtr<nsIInputStream> stream;
   rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), file);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   nsCOMPtr<nsIInputStream> bufferedStream;
-  rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream, 512);
+  rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
+                                 stream.forget(), 512);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   nsCOMPtr<nsIBinaryInputStream> binaryStream =
     do_CreateInstance("@mozilla.org/binaryinputstream;1");
   if (NS_WARN_IF(!binaryStream)) {
     return NS_ERROR_FAILURE;
--- a/dom/webbrowserpersist/nsWebBrowserPersist.cpp
+++ b/dom/webbrowserpersist/nsWebBrowserPersist.cpp
@@ -1486,17 +1486,18 @@ nsresult nsWebBrowserPersist::SaveChanne
     nsCOMPtr<nsIFileURL> fu(do_QueryInterface(aFile));
 
     if (fc && !fu) {
         nsCOMPtr<nsIInputStream> fileInputStream, bufferedInputStream;
         nsresult rv = NS_MaybeOpenChannelUsingOpen2(aChannel,
                         getter_AddRefs(fileInputStream));
         NS_ENSURE_SUCCESS(rv, rv);
         rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedInputStream),
-                                       fileInputStream, BUFFERED_OUTPUT_SIZE);
+                                       fileInputStream.forget(),
+                                       BUFFERED_OUTPUT_SIZE);
         NS_ENSURE_SUCCESS(rv, rv);
         nsAutoCString contentType;
         aChannel->GetContentType(contentType);
         return StartUpload(bufferedInputStream, aFile, contentType);
     }
 
     // Mark save channel as throttleable.
     nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(aChannel));
--- a/dom/workers/FileReaderSync.cpp
+++ b/dom/workers/FileReaderSync.cpp
@@ -210,17 +210,17 @@ FileReaderSync::ReadAsText(Blob& aBlob,
   }
 
   uint64_t blobSize = aBlob.GetSize(aRv);
   if (NS_WARN_IF(aRv.Failed())){
     return;
   }
 
   nsCOMPtr<nsIInputStream> syncStream;
-  aRv = ConvertAsyncToSyncStream(blobSize - sniffBuf.Length(), stream,
+  aRv = ConvertAsyncToSyncStream(blobSize - sniffBuf.Length(), stream.forget(),
                                  getter_AddRefs(syncStream));
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   // ConvertAsyncToSyncStream returns a null syncStream if the stream has been
   // already closed or there is nothing to read.
   if (syncStream) {
@@ -264,17 +264,18 @@ FileReaderSync::ReadAsDataURL(Blob& aBlo
   }
 
   uint64_t blobSize = aBlob.GetSize(aRv);
   if (NS_WARN_IF(aRv.Failed())){
     return;
   }
 
   nsCOMPtr<nsIInputStream> syncStream;
-  aRv = ConvertAsyncToSyncStream(blobSize, stream, getter_AddRefs(syncStream));
+  aRv = ConvertAsyncToSyncStream(blobSize, stream.forget(),
+                                 getter_AddRefs(syncStream));
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   MOZ_ASSERT(syncStream);
 
   uint64_t size;
   aRv = syncStream->Available(&size);
@@ -470,33 +471,35 @@ FileReaderSync::SyncRead(nsIInputStream*
   }
 
   // Now, we can try to read again.
   return SyncRead(aStream, aBuffer, aBufferSize, aRead);
 }
 
 nsresult
 FileReaderSync::ConvertAsyncToSyncStream(uint64_t aStreamSize,
-                                         nsIInputStream* aAsyncStream,
+                                         already_AddRefed<nsIInputStream> aAsyncStream,
                                          nsIInputStream** aSyncStream)
 {
+  nsCOMPtr<nsIInputStream> asyncInputStream = Move(aAsyncStream);
+
   // If the stream is not async, we just need it to be bufferable.
-  nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aAsyncStream);
+  nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(asyncInputStream);
   if (!asyncStream) {
-    return NS_NewBufferedInputStream(aSyncStream, aAsyncStream, 4096);
+    return NS_NewBufferedInputStream(aSyncStream, asyncInputStream.forget(), 4096);
   }
 
   nsAutoCString buffer;
   if (!buffer.SetLength(aStreamSize, fallible)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   uint32_t read;
   nsresult rv =
-    SyncRead(aAsyncStream, buffer.BeginWriting(), aStreamSize, &read);
+    SyncRead(asyncInputStream, buffer.BeginWriting(), aStreamSize, &read);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (read != aStreamSize) {
     return NS_ERROR_FAILURE;
   }
 
--- a/dom/workers/FileReaderSync.h
+++ b/dom/workers/FileReaderSync.h
@@ -28,17 +28,17 @@ private:
   ~FileReaderSync()
   {
   }
 
   nsresult ConvertStream(nsIInputStream *aStream, const char *aCharset,
                          nsAString &aResult);
 
   nsresult ConvertAsyncToSyncStream(uint64_t aStreamSize,
-                                    nsIInputStream* aAsyncStream,
+                                    already_AddRefed<nsIInputStream> aAsyncStream,
                                     nsIInputStream** aSyncStream);
 
   nsresult SyncRead(nsIInputStream* aStream, char* aBuffer,
                     uint32_t aBufferSize, uint32_t* aRead);
 
 public:
   static already_AddRefed<FileReaderSync>
   Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
--- a/dom/xbl/nsXBLService.cpp
+++ b/dom/xbl/nsXBLService.cpp
@@ -1111,15 +1111,16 @@ nsXBLService::FetchBindingDocument(nsICo
                               xblSink);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Now do a blocking synchronous parse of the file.
   nsCOMPtr<nsIInputStream> in;
   rv = channel->Open2(getter_AddRefs(in));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = nsSyncLoadService::PushSyncStreamToListener(in, listener, channel);
+  rv = nsSyncLoadService::PushSyncStreamToListener(in.forget(), listener,
+                                                   channel);
   NS_ENSURE_SUCCESS(rv, rv);
 
   doc.swap(*aResult);
 
   return NS_OK;
 }
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -2556,21 +2556,22 @@ XMLHttpRequestMainThread::MaybeLowerChan
 
   nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(mChannel);
   if (p) {
     p->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
   }
 }
 
 nsresult
-XMLHttpRequestMainThread::InitiateFetch(nsIInputStream* aUploadStream,
+XMLHttpRequestMainThread::InitiateFetch(already_AddRefed<nsIInputStream> aUploadStream,
                                         int64_t aUploadLength,
                                         nsACString& aUploadContentType)
 {
   nsresult rv;
+  nsCOMPtr<nsIInputStream> uploadStream = Move(aUploadStream);
 
   // nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active, which
   // in turn keeps STOP button from becoming active.  If the consumer passed in
   // a progress event handler we must load with nsIRequest::LOAD_NORMAL or
   // necko won't generate any progress notifications.
   if (HasListenersFor(nsGkAtoms::onprogress) ||
       (mUpload && mUpload->HasListenersFor(nsGkAtoms::onprogress))) {
     nsLoadFlags loadFlags;
@@ -2610,47 +2611,47 @@ XMLHttpRequestMainThread::InitiateFetch(
       if (consoleService) {
         consoleService->LogStringMessage(
           u"Http channel implementation doesn't support nsIUploadChannel2. "
           "An extension has supplied a non-functional http protocol handler. "
           "This will break behavior and in future releases not work at all.");
       }
     }
 
-    if (aUploadStream) {
+    if (uploadStream) {
       // If necessary, wrap the stream in a buffered stream so as to guarantee
       // support for our upload when calling ExplicitSetUploadStream.
-      nsCOMPtr<nsIInputStream> bufferedStream;
-      if (!NS_InputStreamIsBuffered(aUploadStream)) {
+      if (!NS_InputStreamIsBuffered(uploadStream)) {
+        nsCOMPtr<nsIInputStream> bufferedStream;
         rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
-                                       aUploadStream, 4096);
+                                       uploadStream.forget(), 4096);
         NS_ENSURE_SUCCESS(rv, rv);
 
-        aUploadStream = bufferedStream;
+        uploadStream = bufferedStream;
       }
 
       // We want to use a newer version of the upload channel that won't
       // ignore the necessary headers for an empty Content-Type.
       nsCOMPtr<nsIUploadChannel2> uploadChannel2(do_QueryInterface(httpChannel));
       // This assertion will fire if buggy extensions are installed
       NS_ASSERTION(uploadChannel2, "http must support nsIUploadChannel2");
       if (uploadChannel2) {
-          uploadChannel2->ExplicitSetUploadStream(aUploadStream,
+          uploadChannel2->ExplicitSetUploadStream(uploadStream,
                                                   aUploadContentType,
                                                   mUploadTotal, mRequestMethod,
                                                   false);
       } else {
         // The http channel doesn't support the new nsIUploadChannel2.
         // Emulate it as best we can using nsIUploadChannel.
         if (aUploadContentType.IsEmpty()) {
           aUploadContentType.AssignLiteral("application/octet-stream");
         }
         nsCOMPtr<nsIUploadChannel> uploadChannel =
           do_QueryInterface(httpChannel);
-        uploadChannel->SetUploadStream(aUploadStream, aUploadContentType,
+        uploadChannel->SetUploadStream(uploadStream, aUploadContentType,
                                        mUploadTotal);
         // Reset the method to its original value
         rv = httpChannel->SetRequestMethod(mRequestMethod);
         MOZ_ASSERT(NS_SUCCEEDED(rv));
       }
     }
   }
 
@@ -3048,17 +3049,17 @@ XMLHttpRequestMainThread::SendInternal(c
     if (NS_SUCCEEDED(rv)) {
       uri->GetScheme(scheme);
       if (scheme.LowerCaseEqualsLiteral("jar")) {
         mIsMappedArrayBuffer = true;
       }
     }
   }
 
-  rv = InitiateFetch(uploadStream, mUploadTotal, uploadContentType);
+  rv = InitiateFetch(uploadStream.forget(), mUploadTotal, uploadContentType);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Start our timeout
   mRequestSentTime = PR_Now();
   StartTimeoutTimer();
 
   mWaitingForOnStopRequest = true;
 
--- a/dom/xhr/XMLHttpRequestMainThread.h
+++ b/dom/xhr/XMLHttpRequestMainThread.h
@@ -256,17 +256,17 @@ public:
 
   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(XMLHttpRequestEventTarget)
 
   // states
   virtual uint16_t ReadyState() const override;
 
   // request
   nsresult CreateChannel();
-  nsresult InitiateFetch(nsIInputStream* aUploadStream,
+  nsresult InitiateFetch(already_AddRefed<nsIInputStream> aUploadStream,
                          int64_t aUploadLength,
                          nsACString& aUploadContentType);
 
   virtual void
   Open(const nsACString& aMethod, const nsAString& aUrl,
        ErrorResult& aRv) override;
 
   virtual void
--- a/gfx/thebes/gfxSVGGlyphs.cpp
+++ b/gfx/thebes/gfxSVGGlyphs.cpp
@@ -328,17 +328,18 @@ CreateBufferedStream(const uint8_t *aBuf
     nsCOMPtr<nsIInputStream> stream;
     nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
                                         reinterpret_cast<const char *>(aBuffer),
                                         aBufLen, NS_ASSIGNMENT_DEPEND);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIInputStream> aBufferedStream;
     if (!NS_InputStreamIsBuffered(stream)) {
-        rv = NS_NewBufferedInputStream(getter_AddRefs(aBufferedStream), stream, 4096);
+        rv = NS_NewBufferedInputStream(getter_AddRefs(aBufferedStream),
+                                       stream.forget(), 4096);
         NS_ENSURE_SUCCESS(rv, rv);
         stream = aBufferedStream;
     }
 
     aResult = stream;
 
     return NS_OK;
 }
--- a/image/ImageOps.cpp
+++ b/image/ImageOps.cpp
@@ -95,30 +95,30 @@ protected:
     return sourceBuffer.forget();
   }
 
 private:
   RefPtr<SourceBuffer> mSourceBuffer;
 };
 
 /* static */ already_AddRefed<ImageOps::ImageBuffer>
-ImageOps::CreateImageBuffer(nsIInputStream* aInputStream)
+ImageOps::CreateImageBuffer(already_AddRefed<nsIInputStream> aInputStream)
 {
-  MOZ_ASSERT(aInputStream);
+  nsCOMPtr<nsIInputStream> inputStream = Move(aInputStream);
+  MOZ_ASSERT(inputStream);
 
   nsresult rv;
 
   // Prepare the input stream.
-  nsCOMPtr<nsIInputStream> inputStream = aInputStream;
-  if (!NS_InputStreamIsBuffered(aInputStream)) {
+  if (!NS_InputStreamIsBuffered(inputStream)) {
     nsCOMPtr<nsIInputStream> bufStream;
     rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
-                                   aInputStream, 1024);
-    if (NS_SUCCEEDED(rv)) {
-      inputStream = bufStream;
+                                   inputStream.forget(), 1024);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return nullptr;
     }
   }
 
   // Figure out how much data we've been passed.
   uint64_t length;
   rv = inputStream->Available(&length);
   if (NS_FAILED(rv) || length > UINT32_MAX) {
     return nullptr;
@@ -140,21 +140,22 @@ ImageOps::CreateImageBuffer(nsIInputStre
   }
   sourceBuffer->Complete(NS_OK);
 
   RefPtr<ImageBuffer> imageBuffer = new ImageBufferImpl(sourceBuffer.forget());
   return imageBuffer.forget();
 }
 
 /* static */ nsresult
-ImageOps::DecodeMetadata(nsIInputStream* aInputStream,
+ImageOps::DecodeMetadata(already_AddRefed<nsIInputStream> aInputStream,
                          const nsACString& aMimeType,
                          ImageMetadata& aMetadata)
 {
-  RefPtr<ImageBuffer> buffer = CreateImageBuffer(aInputStream);
+  nsCOMPtr<nsIInputStream> inputStream = Move(aInputStream);
+  RefPtr<ImageBuffer> buffer = CreateImageBuffer(inputStream.forget());
   return DecodeMetadata(buffer, aMimeType, aMetadata);
 }
 
 /* static */ nsresult
 ImageOps::DecodeMetadata(ImageBuffer* aBuffer,
                          const nsACString& aMimeType,
                          ImageMetadata& aMetadata)
 {
@@ -188,22 +189,23 @@ ImageOps::DecodeMetadata(ImageBuffer* aB
   if (aMetadata.GetNativeSizes().IsEmpty() && aMetadata.HasSize()) {
     aMetadata.AddNativeSize(aMetadata.GetSize());
   }
 
   return NS_OK;
 }
 
 /* static */ already_AddRefed<gfx::SourceSurface>
-ImageOps::DecodeToSurface(nsIInputStream* aInputStream,
+ImageOps::DecodeToSurface(already_AddRefed<nsIInputStream> aInputStream,
                           const nsACString& aMimeType,
                           uint32_t aFlags,
                           const Maybe<IntSize>& aSize /* = Nothing() */)
 {
-  RefPtr<ImageBuffer> buffer = CreateImageBuffer(aInputStream);
+  nsCOMPtr<nsIInputStream> inputStream = Move(aInputStream);
+  RefPtr<ImageBuffer> buffer = CreateImageBuffer(inputStream.forget());
   return DecodeToSurface(buffer, aMimeType, aFlags, aSize);
 }
 
 /* static */ already_AddRefed<gfx::SourceSurface>
 ImageOps::DecodeToSurface(ImageBuffer* aBuffer,
                           const nsACString& aMimeType,
                           uint32_t aFlags,
                           const Maybe<IntSize>& aSize /* = Nothing() */)
--- a/image/ImageOps.h
+++ b/image/ImageOps.h
@@ -88,33 +88,35 @@ public:
   static already_AddRefed<imgIContainer>
   CreateFromDrawable(gfxDrawable* aDrawable);
 
   /**
    * Create a buffer to be used with DecodeMetadata and DecodeToSurface. Reusing
    * an ImageBuffer representing the given input stream is more efficient if one
    * has multiple Decode* calls to make on that stream.
    *
-   * @param aInputStream An input stream containing an encoded image.
+   * @param aInputStream An input stream containing an encoded image. The
+   * ownership is taken.
    * @return An image buffer derived from the input stream.
    */
   static already_AddRefed<ImageBuffer>
-  CreateImageBuffer(nsIInputStream* aInputStream);
+  CreateImageBuffer(already_AddRefed<nsIInputStream> aInputStream);
 
   /**
    * Decodes an image's metadata from an nsIInputStream into the given
    * structure. This function may be called off-main-thread.
    *
-   * @param aInputStream An input stream containing an encoded image.
+   * @param aInputStream An input stream containing an encoded image. Ownership
+   * is taken.
    * @param aMimeType The MIME type of the image.
    * @param aMetadata Where the image metadata is stored upon success.
    * @return The status of the operation.
    */
   static nsresult
-  DecodeMetadata(nsIInputStream* aInputStream,
+  DecodeMetadata(already_AddRefed<nsIInputStream> aInputStream,
                  const nsACString& aMimeType,
                  ImageMetadata& aMetadata);
 
   /**
    * Same as above but takes an ImageBuffer instead of nsIInputStream.
    */
   static nsresult
   DecodeMetadata(ImageBuffer* aBuffer,
@@ -122,24 +124,25 @@ public:
                  ImageMetadata& aMetadata);
 
   /**
    * Decodes an image from an nsIInputStream directly into a SourceSurface,
    * without ever creating an Image or imgIContainer (which are mostly
    * main-thread-only). That means that this function may be called
    * off-main-thread.
    *
-   * @param aInputStream An input stream containing an encoded image.
+   * @param aInputStream An input stream containing an encoded image. The
+   * ownership is taken.
    * @param aMimeType The MIME type of the image.
    * @param aFlags Flags of the imgIContainer::FLAG_DECODE_* variety.
    * @return A SourceSurface containing the first frame of the image at its
    *         intrinsic size, or nullptr if the image cannot be decoded.
    */
   static already_AddRefed<gfx::SourceSurface>
-  DecodeToSurface(nsIInputStream* aInputStream,
+  DecodeToSurface(already_AddRefed<nsIInputStream> aInputStream,
                   const nsACString& aMimeType,
                   uint32_t aFlags,
                   const Maybe<gfx::IntSize>& aSize = Nothing());
 
   /**
    * Same as above but takes an ImageBuffer instead of nsIInputStream.
    */
   static already_AddRefed<gfx::SourceSurface>
--- a/image/imgTools.cpp
+++ b/image/imgTools.cpp
@@ -56,17 +56,18 @@ imgTools::DecodeImage(nsIInputStream* aI
   nsresult rv;
 
   NS_ENSURE_ARG_POINTER(aInStr);
 
   // Prepare the input stream.
   nsCOMPtr<nsIInputStream> inStream = aInStr;
   if (!NS_InputStreamIsBuffered(aInStr)) {
     nsCOMPtr<nsIInputStream> bufStream;
-    rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), aInStr, 1024);
+    rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
+                                   inStream.forget(), 1024);
     if (NS_SUCCEEDED(rv)) {
       inStream = bufStream;
     }
   }
 
   // Figure out how much data we've been passed.
   uint64_t length;
   rv = inStream->Available(&length);
--- a/image/test/fuzzing/TestDecoders.cpp
+++ b/image/test/fuzzing/TestDecoders.cpp
@@ -47,17 +47,17 @@ public:
   {
     Go();
     return NS_OK;
   }
 
   void Go()
   {
     mSurface =
-      ImageOps::DecodeToSurface(mInputStream,
+      ImageOps::DecodeToSurface(mInputStream.forget(),
                                 nsDependentCString(mimeType.c_str()),
                                 imgIContainer::DECODE_FLAGS_DEFAULT);
     if (!mSurface)
       return;
 
     if (mSurface->GetType() == SurfaceType::DATA) {
       if (mSurface->GetFormat() == SurfaceFormat::B8G8R8X8 ||
           mSurface->GetFormat() == SurfaceFormat::B8G8R8A8) {
--- a/image/test/gtest/Common.cpp
+++ b/image/test/gtest/Common.cpp
@@ -120,17 +120,17 @@ LoadFile(const char* aRelativePath)
   nsCOMPtr<nsIInputStream> inputStream;
   rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), file);
   ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr);
 
   // Ensure the resulting input stream is buffered.
   if (!NS_InputStreamIsBuffered(inputStream)) {
     nsCOMPtr<nsIInputStream> bufStream;
     rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
-                                   inputStream, 1024);
+                                   inputStream.forget(), 1024);
     ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr);
     inputStream = bufStream;
   }
 
   return inputStream.forget();
 }
 
 bool
--- a/image/test/gtest/TestDecodeToSurface.cpp
+++ b/image/test/gtest/TestDecodeToSurface.cpp
@@ -52,17 +52,17 @@ public:
     if (mImageBuffer) {
       mSurface =
         ImageOps::DecodeToSurface(mImageBuffer,
                                   nsDependentCString(mTestCase.mMimeType),
                                   imgIContainer::DECODE_FLAGS_DEFAULT,
                                   outputSize);
     } else {
       mSurface =
-        ImageOps::DecodeToSurface(mInputStream,
+        ImageOps::DecodeToSurface(mInputStream.forget(),
                                   nsDependentCString(mTestCase.mMimeType),
                                   imgIContainer::DECODE_FLAGS_DEFAULT,
                                   outputSize);
     }
     ASSERT_TRUE(mSurface != nullptr);
 
     EXPECT_TRUE(mSurface->IsDataSourceSurface());
     EXPECT_TRUE(mSurface->GetFormat() == SurfaceFormat::B8G8R8X8 ||
@@ -139,31 +139,31 @@ TEST_F(ImageDecodeToSurface, AnimatedPNG
 TEST_F(ImageDecodeToSurface, Corrupt)
 {
   ImageTestCase testCase = CorruptTestCase();
 
   nsCOMPtr<nsIInputStream> inputStream = LoadFile(testCase.mPath);
   ASSERT_TRUE(inputStream != nullptr);
 
   RefPtr<SourceSurface> surface =
-    ImageOps::DecodeToSurface(inputStream,
+    ImageOps::DecodeToSurface(inputStream.forget(),
                               nsDependentCString(testCase.mMimeType),
                               imgIContainer::DECODE_FLAGS_DEFAULT);
   EXPECT_TRUE(surface == nullptr);
 }
 
 TEST_F(ImageDecodeToSurface, ICOMultipleSizes)
 {
   ImageTestCase testCase = GreenMultipleSizesICOTestCase();
 
   nsCOMPtr<nsIInputStream> inputStream = LoadFile(testCase.mPath);
   ASSERT_TRUE(inputStream != nullptr);
 
   RefPtr<ImageOps::ImageBuffer> buffer =
-    ImageOps::CreateImageBuffer(inputStream);
+    ImageOps::CreateImageBuffer(inputStream.forget());
   ASSERT_TRUE(buffer != nullptr);
 
   ImageMetadata metadata;
   nsresult rv = ImageOps::DecodeMetadata(buffer,
                                          nsDependentCString(testCase.mMimeType),
                                          metadata);
   EXPECT_TRUE(NS_SUCCEEDED(rv));
   ASSERT_TRUE(metadata.HasSize());
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -1399,17 +1399,17 @@ Loader::LoadSheet(SheetLoadData* aLoadDa
     // XXX this is only necessary because the default in
     // SheetLoadData::OnDetermineCharset is wrong (bug 521039).
     channel->SetContentCharset(NS_LITERAL_CSTRING("UTF-8"));
 
     // Manually feed the streamloader the contents of the stream.
     // This will call back into OnStreamComplete
     // and thence to ParseSheet.  Regardless of whether this fails,
     // SheetComplete has been called.
-    return nsSyncLoadService::PushSyncStreamToListener(stream,
+    return nsSyncLoadService::PushSyncStreamToListener(stream.forget(),
                                                        streamLoader,
                                                        channel);
   }
 
   SheetLoadData* existingData = nullptr;
 
   URIPrincipalReferrerPolicyAndCORSModeHashKey key(aLoadData->mURI,
                                      aLoadData->mLoaderPrincipal,
--- a/netwerk/base/nsInputStreamPump.cpp
+++ b/netwerk/base/nsInputStreamPump.cpp
@@ -722,18 +722,19 @@ nsInputStreamPump::CreateBufferedStreamI
   // ReadSegments is not available for any nsIAsyncInputStream. In order to use
   // it, we wrap a nsIBufferedInputStream around it, if needed.
 
   if (NS_InputStreamIsBuffered(mAsyncStream)) {
     mBufferedStream = mAsyncStream;
     return NS_OK;
   }
 
+  nsCOMPtr<nsIAsyncInputStream> stream = mAsyncStream;
   nsresult rv = NS_NewBufferedInputStream(getter_AddRefs(mBufferedStream),
-                                          mAsyncStream, 4096);
+                                          stream.forget(), 4096);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsIThreadRetargetableRequest
 //-----------------------------------------------------------------------------
--- a/netwerk/base/nsNetUtil.cpp
+++ b/netwerk/base/nsNetUtil.cpp
@@ -1365,65 +1365,52 @@ NS_BufferOutputStream(nsIOutputStream *a
     if (NS_SUCCEEDED(rv))
         return bos.forget();
 
     bos = aOutputStream;
     return bos.forget();
 }
 
 MOZ_MUST_USE nsresult
-NS_NewBufferedInputStream(nsIInputStream **result,
-                          nsIInputStream  *str,
-                          uint32_t         bufferSize)
+NS_NewBufferedInputStream(nsIInputStream** aResult,
+                          already_AddRefed<nsIInputStream> aInputStream,
+                          uint32_t aBufferSize)
 {
+    nsCOMPtr<nsIInputStream> inputStream = Move(aInputStream);
+
     nsresult rv;
     nsCOMPtr<nsIBufferedInputStream> in =
         do_CreateInstance(NS_BUFFEREDINPUTSTREAM_CONTRACTID, &rv);
     if (NS_SUCCEEDED(rv)) {
-        rv = in->Init(str, bufferSize);
+        rv = in->Init(inputStream, aBufferSize);
         if (NS_SUCCEEDED(rv)) {
-            in.forget(result);
+            in.forget(aResult);
         }
     }
     return rv;
 }
 
-already_AddRefed<nsIInputStream>
-NS_BufferInputStream(nsIInputStream *aInputStream,
-                      uint32_t aBufferSize)
-{
-    NS_ASSERTION(aInputStream, "No input stream given!");
-
-    nsCOMPtr<nsIInputStream> bis;
-    nsresult rv = NS_NewBufferedInputStream(getter_AddRefs(bis), aInputStream,
-                                            aBufferSize);
-    if (NS_SUCCEEDED(rv))
-        return bis.forget();
-
-    bis = aInputStream;
-    return bis.forget();
-}
-
 nsresult
 NS_NewPostDataStream(nsIInputStream  **result,
                      bool              isFile,
                      const nsACString &data)
 {
     nsresult rv;
 
     if (isFile) {
         nsCOMPtr<nsIFile> file;
         nsCOMPtr<nsIInputStream> fileStream;
 
         rv = NS_NewNativeLocalFile(data, false, getter_AddRefs(file));
         if (NS_SUCCEEDED(rv)) {
             rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream), file);
             if (NS_SUCCEEDED(rv)) {
                 // wrap the file stream with a buffered input stream
-                rv = NS_NewBufferedInputStream(result, fileStream, 8192);
+                rv = NS_NewBufferedInputStream(result, fileStream.forget(),
+                                               8192);
             }
         }
         return rv;
     }
 
     // otherwise, create a string stream for the data (copies)
     nsCOMPtr<nsIStringInputStream> stream
         (do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv));
--- a/netwerk/base/nsNetUtil.h
+++ b/netwerk/base/nsNetUtil.h
@@ -506,19 +506,19 @@ nsresult NS_NewSafeLocalFileOutputStream
 
 nsresult NS_NewLocalFileStream(nsIFileStream **result,
                                nsIFile        *file,
                                int32_t         ioFlags       = -1,
                                int32_t         perm          = -1,
                                int32_t         behaviorFlags = 0);
 
 MOZ_MUST_USE nsresult
-NS_NewBufferedInputStream(nsIInputStream **result,
-                          nsIInputStream  *str,
-                          uint32_t         bufferSize);
+NS_NewBufferedInputStream(nsIInputStream** aResult,
+                          already_AddRefed<nsIInputStream> aInputStream,
+                          uint32_t aBufferSize);
 
 // note: the resulting stream can be QI'ed to nsISafeOutputStream iff the
 // provided stream supports it.
 nsresult NS_NewBufferedOutputStream(nsIOutputStream **result,
                                     nsIOutputStream  *str,
                                     uint32_t          bufferSize);
 
 /**
@@ -530,19 +530,16 @@ nsresult NS_NewBufferedOutputStream(nsIO
  * @param aBufferSize
  *        The size of the buffer for the buffered output stream.
  * @returns an nsIOutputStream that is buffered with the specified buffer size,
  *          or is aOutputStream if creating the new buffered stream failed.
  */
 already_AddRefed<nsIOutputStream>
 NS_BufferOutputStream(nsIOutputStream *aOutputStream,
                       uint32_t aBufferSize);
-already_AddRefed<nsIInputStream>
-NS_BufferInputStream(nsIInputStream *aInputStream,
-                      uint32_t aBufferSize);
 
 // returns an input stream compatible with nsIUploadChannel::SetUploadStream()
 nsresult NS_NewPostDataStream(nsIInputStream  **result,
                               bool              isFile,
                               const nsACString &data);
 
 nsresult NS_ReadInputStreamToBuffer(nsIInputStream *aInputStream,
                                     void **aDest,
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -924,17 +924,18 @@ HttpBaseChannel::EnsureUploadStreamIsClo
   nsCOMPtr<nsIOutputStream> sink;
   rv = storageStream->GetOutputStream(0, getter_AddRefs(sink));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIInputStream> source;
   if (NS_InputStreamIsBuffered(mUploadStream)) {
     source = mUploadStream;
   } else {
-    rv = NS_NewBufferedInputStream(getter_AddRefs(source), mUploadStream, 4096);
+    rv = NS_NewBufferedInputStream(getter_AddRefs(source),
+                                   mUploadStream.forget(), 4096);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsCOMPtr<nsIEventTarget> target =
     do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
 
   mUploadCloneableCallback = aCallback;
 
--- a/netwerk/protocol/http/nsHttpTransaction.cpp
+++ b/netwerk/protocol/http/nsHttpTransaction.cpp
@@ -378,17 +378,18 @@ nsHttpTransaction::Init(uint32_t caps,
 
         rv = multi->AppendStream(requestBody);
         if (NS_FAILED(rv)) return rv;
 
         // wrap the multiplexed input stream with a buffered input stream, so
         // that we write data in the largest chunks possible.  this is actually
         // necessary to workaround some common server bugs (see bug 137155).
         nsCOMPtr<nsIInputStream> stream(do_QueryInterface(multi));
-        rv = NS_NewBufferedInputStream(getter_AddRefs(mRequestStream), stream,
+        rv = NS_NewBufferedInputStream(getter_AddRefs(mRequestStream),
+                                       stream.forget(),
                                        nsIOService::gDefaultSegmentSize);
         if (NS_FAILED(rv)) return rv;
     } else {
         mRequestStream = headers;
     }
 
     nsCOMPtr<nsIThrottledInputChannel> throttled = do_QueryInterface(mChannel);
     nsIInputChannelThrottleQueue* queue;
--- a/parser/xml/nsSAXXMLReader.cpp
+++ b/parser/xml/nsSAXXMLReader.cpp
@@ -469,47 +469,48 @@ nsSAXXMLReader::ParseFromString(const ns
   nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
                                       data.get(), data.Length(),
                                       NS_ASSIGNMENT_DEPEND);
   NS_ENSURE_SUCCESS(rv, rv);
   return ParseFromStream(stream, "UTF-8", aContentType);
 }
 
 NS_IMETHODIMP
-nsSAXXMLReader::ParseFromStream(nsIInputStream *aStream,
+nsSAXXMLReader::ParseFromStream(nsIInputStream *aStreamPtr,
                                 const char *aCharset,
                                 const char *aContentType)
 {
   // Don't call this in the middle of an async parse
   NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE);
 
-  NS_ENSURE_ARG(aStream);
+  NS_ENSURE_ARG(aStreamPtr);
   NS_ENSURE_ARG(aContentType);
 
   // Put the nsCOMPtr out here so we hold a ref to the stream as needed
   nsresult rv;
-  nsCOMPtr<nsIInputStream> bufferedStream;
-  if (!NS_InputStreamIsBuffered(aStream)) {
+  nsCOMPtr<nsIInputStream> stream = aStreamPtr;
+  if (!NS_InputStreamIsBuffered(stream)) {
+    nsCOMPtr<nsIInputStream> bufferedStream;
     rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
-                                   aStream, 4096);
+                                   stream.forget(), 4096);
     NS_ENSURE_SUCCESS(rv, rv);
-    aStream = bufferedStream;
+    stream = bufferedStream;
   }
  
   rv = EnsureBaseURI();
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIPrincipal> nullPrincipal = NullPrincipal::Create();
 
   // The following channel is never openend, so it does not matter what
   // securityFlags we pass; let's follow the principle of least privilege.
   nsCOMPtr<nsIChannel> parserChannel;
   rv = NS_NewInputStreamChannel(getter_AddRefs(parserChannel),
                                 mBaseURI,
-                                aStream,
+                                stream,
                                 nullPrincipal,
                                 nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
                                 nsIContentPolicy::TYPE_OTHER,
                                 nsDependentCString(aContentType));
   if (!parserChannel || NS_FAILED(rv))
     return NS_ERROR_FAILURE;
 
   if (aCharset)
@@ -531,33 +532,33 @@ nsSAXXMLReader::ParseFromStream(nsIInput
   mPublicId.Truncate();
 
   nsresult status;
   parserChannel->GetStatus(&status);
   
   uint64_t offset = 0;
   while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
     uint64_t available;
-    rv = aStream->Available(&available);
+    rv = stream->Available(&available);
     if (rv == NS_BASE_STREAM_CLOSED) {
       rv = NS_OK;
       available = 0;
     }
     if (NS_FAILED(rv)) {
       parserChannel->Cancel(rv);
       break;
     }
     if (! available)
       break; // blocking input stream has none available when done
 
     if (available > UINT32_MAX)
       available = UINT32_MAX;
 
     rv = mListener->OnDataAvailable(parserChannel, nullptr,
-                                    aStream,
+                                    stream,
                                     offset,
                                     (uint32_t)available);
     if (NS_SUCCEEDED(rv))
       offset += available;
     else
       parserChannel->Cancel(rv);
     parserChannel->GetStatus(&status);
   }
--- a/rdf/base/nsRDFXMLDataSource.cpp
+++ b/rdf/base/nsRDFXMLDataSource.cpp
@@ -492,17 +492,17 @@ RDFXMLDataSourceImpl::BlockingParse(nsIU
     if (! in) {
         NS_ERROR("no input stream");
         return NS_ERROR_FAILURE;
     }
 
     // Wrap the channel's input stream in a buffered stream to ensure that
     // ReadSegments is implemented (which OnDataAvailable expects).
     nsCOMPtr<nsIInputStream> bufStream;
-    rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), in,
+    rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), in.forget(),
                                    4096 /* buffer size */);
     if (NS_FAILED(rv)) return rv;
 
     // Notify load observers
     int32_t i;
     for (i = mObservers.Count() - 1; i >= 0; --i) {
         // Make sure to hold a strong reference to the observer so
         // that it doesn't go away in this call if it removes itself
--- a/toolkit/components/places/FaviconHelpers.cpp
+++ b/toolkit/components/places/FaviconHelpers.cpp
@@ -1290,17 +1290,17 @@ FetchAndConvertUnsupportedPayloads::Conv
   nsCOMPtr<nsIInputStream> stream;
   nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
                 aPayload.get(), aPayload.Length(),
                 NS_ASSIGNMENT_DEPEND);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Decode the input stream to a surface.
   RefPtr<gfx::SourceSurface> surface =
-      image::ImageOps::DecodeToSurface(stream,
+      image::ImageOps::DecodeToSurface(stream.forget(),
                                        aMimeType,
                                        imgIContainer::DECODE_FLAGS_DEFAULT);
   NS_ENSURE_STATE(surface);
   RefPtr<gfx::DataSourceSurface> dataSurface = surface->GetDataSurface();
   NS_ENSURE_STATE(dataSurface);
 
   // Read the current size and set an appropriate final width.
   int32_t width = dataSurface->GetSize().width;
--- a/toolkit/components/url-classifier/HashStore.cpp
+++ b/toolkit/components/url-classifier/HashStore.cpp
@@ -334,17 +334,19 @@ HashStore::Open()
   rv = storeFile->GetFileSize(&fileSize);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (fileSize < 0 || fileSize > UINT32_MAX) {
     return NS_ERROR_FAILURE;
   }
 
   mFileSize = static_cast<uint32_t>(fileSize);
-  mInputStream = NS_BufferInputStream(origStream, mFileSize);
+  rv = NS_NewBufferedInputStream(getter_AddRefs(mInputStream),
+                                 origStream.forget(), mFileSize);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   rv = ReadHeader();
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = SanityCheck();
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
--- a/toolkit/components/url-classifier/VariableLengthPrefixSet.cpp
+++ b/toolkit/components/url-classifier/VariableLengthPrefixSet.cpp
@@ -234,17 +234,20 @@ VariableLengthPrefixSet::LoadFromFile(ns
   if (fileSize < 0 || fileSize > UINT32_MAX) {
     return NS_ERROR_FAILURE;
   }
 
   uint32_t bufferSize = std::min<uint32_t>(static_cast<uint32_t>(fileSize),
                                            MAX_BUFFER_SIZE);
 
   // Convert to buffered stream
-  nsCOMPtr<nsIInputStream> in = NS_BufferInputStream(localInFile, bufferSize);
+  nsCOMPtr<nsIInputStream> in;
+  rv = NS_NewBufferedInputStream(getter_AddRefs(in), localInFile.forget(),
+                                 bufferSize);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   rv = mFixedPrefixSet->LoadPrefixes(in);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = LoadPrefixes(in);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;;
--- a/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierPrefixSet.cpp
@@ -347,17 +347,20 @@ nsUrlClassifierPrefixSet::LoadFromFile(n
   if (fileSize < 0 || fileSize > UINT32_MAX) {
     return NS_ERROR_FAILURE;
   }
 
   uint32_t bufferSize = std::min<uint32_t>(static_cast<uint32_t>(fileSize),
                                            MAX_BUFFER_SIZE);
 
   // Convert to buffered stream
-  nsCOMPtr<nsIInputStream> in = NS_BufferInputStream(localInFile, bufferSize);
+  nsCOMPtr<nsIInputStream> in;
+  rv = NS_NewBufferedInputStream(getter_AddRefs(in), localInFile.forget(),
+                                 bufferSize);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   rv = LoadPrefixes(in);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/tools/fuzzing/interface/FuzzingInterface.cpp
+++ b/tools/fuzzing/interface/FuzzingInterface.cpp
@@ -26,17 +26,17 @@ void afl_interface_stream(const char* te
     file->AppendNative(nsDependentCString(testFile));
     while(__AFL_LOOP(1000)) {
       nsCOMPtr<nsIInputStream> inputStream;
       rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), file);
       MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
       if (!NS_InputStreamIsBuffered(inputStream)) {
         nsCOMPtr<nsIInputStream> bufStream;
         rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
-                                       inputStream, 1024);
+                                       inputStream.forget(), 1024);
         MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
         inputStream = bufStream;
       }
       testFunc(inputStream.forget());
     }
 }
 
 void afl_interface_raw(const char* testFile, FuzzingTestFuncRaw testFunc) {
--- a/xpcom/tests/gtest/TestCloneInputStream.cpp
+++ b/xpcom/tests/gtest/TestCloneInputStream.cpp
@@ -49,17 +49,17 @@ TEST(CloneInputStream, NonCloneableInput
   nsCOMPtr<nsIInputStream> base;
   nsresult rv = NS_NewCStringInputStream(getter_AddRefs(base), inputString);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 
   // Take advantage of nsBufferedInputStream being non-cloneable right
   // now.  If this changes in the future, then we need a different stream
   // type in this test.
   nsCOMPtr<nsIInputStream> stream;
-  rv = NS_NewBufferedInputStream(getter_AddRefs(stream), base, 4096);
+  rv = NS_NewBufferedInputStream(getter_AddRefs(stream), base.forget(), 4096);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 
   nsCOMPtr<nsICloneableInputStream> cloneable = do_QueryInterface(stream);
   ASSERT_TRUE(cloneable == nullptr);
 
   nsCOMPtr<nsIInputStream> clone;
   rv = NS_CloneInputStream(stream, getter_AddRefs(clone));
   ASSERT_TRUE(NS_FAILED(rv));
@@ -77,17 +77,17 @@ TEST(CloneInputStream, NonCloneableInput
   nsCOMPtr<nsIInputStream> base;
   nsresult rv = NS_NewCStringInputStream(getter_AddRefs(base), inputString);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 
   // Take advantage of nsBufferedInputStream being non-cloneable right
   // now.  If this changes in the future, then we need a different stream
   // type in this test.
   nsCOMPtr<nsIInputStream> stream;
-  rv = NS_NewBufferedInputStream(getter_AddRefs(stream), base, 4096);
+  rv = NS_NewBufferedInputStream(getter_AddRefs(stream), base.forget(), 4096);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 
   nsCOMPtr<nsICloneableInputStream> cloneable = do_QueryInterface(stream);
   ASSERT_TRUE(cloneable == nullptr);
 
   nsCOMPtr<nsIInputStream> clone;
   nsCOMPtr<nsIInputStream> replacement;
   rv = NS_CloneInputStream(stream, getter_AddRefs(clone),