Bug 1361443 - FileReader should support ReadSegments() not returning the whole size, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Thu, 04 May 2017 14:45:34 +0200
changeset 572816 e9078bccc0a3cb05d7605fe7a270b6f240d27aac
parent 572815 122644e28040c3b43e5e6a04d72162e7c264dda4
child 572817 4ab091bdeda1baad4edf8c193260397fddb66016
push id57195
push userbmo:rbarker@mozilla.com
push dateThu, 04 May 2017 20:08:56 +0000
reviewerssmaug
bugs1361443
milestone55.0a1
Bug 1361443 - FileReader should support ReadSegments() not returning the whole size, r=smaug
dom/file/FileReader.cpp
--- a/dom/file/FileReader.cpp
+++ b/dom/file/FileReader.cpp
@@ -275,16 +275,18 @@ FileReader::DoAsyncWait()
   return NS_OK;
 }
 
 nsresult
 FileReader::DoReadData(uint64_t aCount)
 {
   MOZ_ASSERT(mAsyncStream);
 
+  uint32_t bytesRead = 0;
+
   if (mDataFormat == FILE_AS_BINARY) {
     //Continuously update our binary string as data comes in
     uint32_t oldLen = mResult.Length();
     MOZ_ASSERT(mResult.Length() == mDataLen, "unexpected mResult length");
     if (uint64_t(oldLen) + aCount > UINT32_MAX)
       return NS_ERROR_OUT_OF_MEMORY;
     char16_t *buf = nullptr;
     mResult.GetMutableData(&buf, oldLen + aCount, fallible);
@@ -296,53 +298,46 @@ FileReader::DoReadData(uint64_t aCount)
     // with a nsIAsyncInputStream, in content process, we need to wrap a
     // nsIBufferedInputStream around it.
     if (!mBufferedStream) {
       rv = NS_NewBufferedInputStream(getter_AddRefs(mBufferedStream),
                                      mAsyncStream, 8192);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
-    uint32_t bytesRead = 0;
     rv = mBufferedStream->ReadSegments(ReadFuncBinaryString, buf + oldLen,
                                        aCount, &bytesRead);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
-    MOZ_ASSERT(bytesRead == aCount, "failed to read data");
+    mResult.Truncate(oldLen + bytesRead);
   }
   else {
     CheckedInt<uint64_t> size = mDataLen;
     size += aCount;
 
     //Update memory buffer to reflect the contents of the file
     if (!size.isValid() ||
         // PR_Realloc doesn't support over 4GB memory size even if 64-bit OS
         size.value() > UINT32_MAX ||
         size.value() > mTotal) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    if (mDataFormat != FILE_AS_ARRAYBUFFER) {
-      mFileData = (char *) realloc(mFileData, mDataLen + aCount);
-      NS_ENSURE_TRUE(mFileData, NS_ERROR_OUT_OF_MEMORY);
-    }
+    MOZ_DIAGNOSTIC_ASSERT(mFileData);
+    MOZ_RELEASE_ASSERT((mDataLen + aCount) <= mTotal);
 
-    uint32_t bytesRead = 0;
-    MOZ_DIAGNOSTIC_ASSERT(mFileData);
     nsresult rv = mAsyncStream->Read(mFileData + mDataLen, aCount, &bytesRead);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
-
-    MOZ_ASSERT(bytesRead == aCount, "failed to read data");
   }
 
-  mDataLen += aCount;
+  mDataLen += bytesRead;
   return NS_OK;
 }
 
 // Helper methods
 
 void
 FileReader::ReadFileContent(Blob& aBlob,
                             const nsAString &aCharset,
@@ -411,18 +406,25 @@ FileReader::ReadFileContent(Blob& aBlob,
 
   MOZ_ASSERT(mAsyncStream);
 
   mTotal = mBlob->GetSize(aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
-  if (mDataFormat == FILE_AS_ARRAYBUFFER) {
-    mFileData = js_pod_malloc<char>(mTotal);
+  // Binary Format doesn't need a post-processing of the data. Everything is
+  // written directly into mResult.
+  if (mDataFormat != FILE_AS_BINARY) {
+    if (mDataFormat == FILE_AS_ARRAYBUFFER) {
+      mFileData = js_pod_malloc<char>(mTotal);
+    } else {
+      mFileData = (char *) malloc(mTotal);
+    }
+
     if (!mFileData) {
       NS_WARNING("Preallocation failed for ReadFileData");
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
   }
 
   aRv = DoAsyncWait();