Bug 1203680 P4 Fix bug in nsStorageStream with reading streams created before data is populated. r=froydnj
authorBen Kelly <ben@wanderview.com>
Tue, 15 Sep 2015 10:15:45 -0700
changeset 295227 0c0bfeb70612ef41aa093eb0158b840fc7ad1115
parent 295226 278ddd4793c39195bbf156bb70b6838d845ea04a
child 295228 52093388544adaa41d3abfe0413d60763a7f1a7d
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1203680
milestone43.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 1203680 P4 Fix bug in nsStorageStream with reading streams created before data is populated. r=froydnj
xpcom/io/nsStorageStream.cpp
xpcom/tests/gtest/TestStorageStream.cpp
--- a/xpcom/io/nsStorageStream.cpp
+++ b/xpcom/io/nsStorageStream.cpp
@@ -455,17 +455,25 @@ nsStorageInputStream::ReadSegments(nsWri
   while (remainingCapacity) {
     availableInSegment = mSegmentEnd - mReadCursor;
     if (!availableInSegment) {
       uint32_t available = mStorageStream->mLogicalLength - mLogicalCursor;
       if (!available) {
         goto out;
       }
 
-      mSegmentNum++;
+      // We have data in the stream, but if mSegmentEnd is zero, then we
+      // were likely constructed prior to any data being written into
+      // the stream.  Therefore, if mSegmentEnd is non-zero, we should
+      // move into the next segment; otherwise, we should stay in this
+      // segment so our input state can be updated and we can properly
+      // perform the initial read.
+      if (mSegmentEnd > 0) {
+        mSegmentNum++;
+      }
       mReadCursor = 0;
       mSegmentEnd = XPCOM_MIN(mSegmentSize, available);
       availableInSegment = mSegmentEnd;
     }
     const char* cur = mStorageStream->mSegmentedBuffer->GetSegment(mSegmentNum);
 
     count = XPCOM_MIN(availableInSegment, remainingCapacity);
     rv = aWriter(this, aClosure, cur + mReadCursor, aCount - remainingCapacity,
--- a/xpcom/tests/gtest/TestStorageStream.cpp
+++ b/xpcom/tests/gtest/TestStorageStream.cpp
@@ -9,27 +9,29 @@
 #include "Helpers.h"
 #include "nsCOMPtr.h"
 #include "nsICloneableInputStream.h"
 #include "nsIInputStream.h"
 #include "nsIOutputStream.h"
 #include "nsIStorageStream.h"
 
 namespace {
+
 void
 WriteData(nsIOutputStream* aOut, nsTArray<char>& aData, uint32_t aNumBytes,
           nsACString& aDataWritten)
 {
   uint32_t n;
   nsresult rv = aOut->Write(aData.Elements(), aNumBytes, &n);
   EXPECT_TRUE(NS_SUCCEEDED(rv));
   aDataWritten.Append(aData.Elements(), aNumBytes);
 }
 
 } // namespace
+
 TEST(StorageStreams, Main)
 {
   // generate some test data we will write in 4k chunks to the stream
   nsTArray<char> kData;
   testing::CreateData(4096, kData);
 
   // track how much data was written so we can compare at the end
   nsAutoCString dataWritten;
@@ -84,8 +86,45 @@ TEST(StorageStreams, Main)
 
   // now, read all
   rv = stor->NewInputStream(0, getter_AddRefs(in));
   EXPECT_TRUE(NS_SUCCEEDED(rv));
 
   testing::ConsumeAndValidateStream(in, dataWritten);
   in = nullptr;
 }
+
+TEST(StorageStreams, EarlyInputStream)
+{
+  // generate some test data we will write in 4k chunks to the stream
+  nsTArray<char> kData;
+  testing::CreateData(4096, kData);
+
+  // track how much data was written so we can compare at the end
+  nsAutoCString dataWritten;
+
+  nsresult rv;
+  nsCOMPtr<nsIStorageStream> stor;
+
+  rv = NS_NewStorageStream(kData.Length(), UINT32_MAX, getter_AddRefs(stor));
+  EXPECT_TRUE(NS_SUCCEEDED(rv));
+
+  // Get input stream before writing data into the output stream
+  nsCOMPtr<nsIInputStream> in;
+  rv = stor->NewInputStream(0, getter_AddRefs(in));
+  EXPECT_TRUE(NS_SUCCEEDED(rv));
+
+  // Write data to output stream
+  nsCOMPtr<nsIOutputStream> out;
+  rv = stor->GetOutputStream(0, getter_AddRefs(out));
+  EXPECT_TRUE(NS_SUCCEEDED(rv));
+
+  WriteData(out, kData, kData.Length(), dataWritten);
+  WriteData(out, kData, kData.Length(), dataWritten);
+
+  rv = out->Close();
+  EXPECT_TRUE(NS_SUCCEEDED(rv));
+  out = nullptr;
+
+  // Should be able to consume input stream
+  testing::ConsumeAndValidateStream(in, dataWritten);
+  in = nullptr;
+}