Bug 1462912 - fixed BufferList::Extract to handle the case where the call consumes the entirety of the BufferList; r?froydnj draft
authorAlex Gaynor <agaynor@mozilla.com>
Tue, 22 May 2018 13:04:59 -0400
changeset 798356 7964a32b784c0da91335880c63636f9d14d7a7b5
parent 798084 b75acf9652937ce79a9bf02de843c100db0e5ec7
push id110731
push userbmo:agaynor@mozilla.com
push dateTue, 22 May 2018 18:26:05 +0000
reviewersfroydnj
bugs1462912
milestone62.0a1
Bug 1462912 - fixed BufferList::Extract to handle the case where the call consumes the entirety of the BufferList; r?froydnj MozReview-Commit-ID: 1LWODn8JaNL
mfbt/BufferList.h
mfbt/tests/TestBufferList.cpp
--- a/mfbt/BufferList.h
+++ b/mfbt/BufferList.h
@@ -609,17 +609,24 @@ BufferList<AllocPolicy>::Extract(IterImp
     size_t segmentsToCopy = segmentsNeeded - lastSegmentSize.isSome();
     for (size_t i = 0; i < segmentsToCopy; ++i) {
       result.mSegments.infallibleAppend(
         Segment(mSegments[aIter.mSegment].mData,
                 mSegments[aIter.mSegment].mSize,
                 mSegments[aIter.mSegment].mCapacity));
       aIter.Advance(*this, aIter.RemainingInSegment());
     }
-    MOZ_RELEASE_ASSERT(aIter.mSegment == copyStart + segmentsToCopy);
+    // Due to the way IterImpl works, there are two cases here: (1) if we've
+    // consumed the entirety of the BufferList, then the iterator is pointed at
+    // the end of the final segment, (2) otherwise it is pointed at the start
+    // of the next segment. We want to verify that we really consumed all
+    // |segmentsToCopy| segments.
+    MOZ_RELEASE_ASSERT(
+      (aIter.mSegment == copyStart + segmentsToCopy) ||
+      (aIter.Done() && aIter.mSegment == copyStart + segmentsToCopy - 1));
     mSegments.erase(mSegments.begin() + copyStart,
                     mSegments.begin() + copyStart + segmentsToCopy);
 
     // Reset the iter's position for what we just deleted.
     aIter.mSegment -= segmentsToCopy;
 
     if (lastSegmentSize.isSome()) {
       // We called reserve() on result.mSegments so infallibleAppend is safe.
--- a/mfbt/tests/TestBufferList.cpp
+++ b/mfbt/tests/TestBufferList.cpp
@@ -274,10 +274,22 @@ int main(void)
   BufferList bl8(0, 0, 16);
   bl8.WriteBytes("abcdefgh12345678", 16);
   iter = bl8.Iter();
   BufferList bl9 = bl8.Extract(iter, 8, &success);
   MOZ_RELEASE_ASSERT(success);
   MOZ_RELEASE_ASSERT(bl9.Size() == 8);
   MOZ_RELEASE_ASSERT(!iter.Done());
 
+  BufferList bl10(0, 0, 8);
+  bl10.WriteBytes("abcdefgh", 8);
+  bl10.WriteBytes("12345678", 8);
+  iter = bl10.Iter();
+  BufferList bl11 = bl10.Extract(iter, 16, &success);
+  MOZ_RELEASE_ASSERT(success);
+  MOZ_RELEASE_ASSERT(bl11.Size() == 16);
+  MOZ_RELEASE_ASSERT(iter.Done());
+  iter = bl11.Iter();
+  MOZ_RELEASE_ASSERT(bl11.ReadBytes(iter, data, 16));
+  MOZ_RELEASE_ASSERT(memcmp(data, "abcdefgh12345678", 16) == 0);
+
   return 0;
 }