Bug 1462912 - Fixed BufferList::Extract to handle the case where the call consumes the entirety of the BufferList. r=froydnj, a=RyanVM
authorAlex Gaynor <agaynor@mozilla.com>
Tue, 22 May 2018 13:04:59 -0400
changeset 473416 cef7f526b60ef27abc881356d12a10805ab730c9
parent 473415 fbd069ce4e4dc5e2c724f1bc5b8d3ae7d34f0fa3
child 473417 0411d00f9dcf2ae6bf20d93b64dd172b36cbe371
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj, RyanVM
bugs1462912
milestone61.0
Bug 1462912 - Fixed BufferList::Extract to handle the case where the call consumes the entirety of the BufferList. r=froydnj, a=RyanVM 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;
 }