diff --git a/source/common/buffer/buffer_impl.cc b/source/common/buffer/buffer_impl.cc index f8e18b4f2e55..23e2bcdf91df 100644 --- a/source/common/buffer/buffer_impl.cc +++ b/source/common/buffer/buffer_impl.cc @@ -148,6 +148,11 @@ void OwnedImpl::drain(uint64_t size) { size = 0; } } + // Make sure to drain any zero byte fragments that might have been added as + // sentinels for flushed data. + while (!slices_.empty() && slices_.front()->dataSize() == 0) { + slices_.pop_front(); + } } uint64_t OwnedImpl::getRawSlices(RawSlice* out, uint64_t out_size) const { diff --git a/test/common/buffer/owned_impl_test.cc b/test/common/buffer/owned_impl_test.cc index 14fd7145e0ac..8be60ef91ae3 100644 --- a/test/common/buffer/owned_impl_test.cc +++ b/test/common/buffer/owned_impl_test.cc @@ -65,6 +65,24 @@ TEST_F(OwnedImplTest, AddBufferFragmentWithCleanup) { EXPECT_TRUE(release_callback_called_); } +TEST_F(OwnedImplTest, AddEmptyFragment) { + char input[] = "hello world"; + BufferFragmentImpl frag1(input, 11, [](const void*, size_t, const BufferFragmentImpl*) {}); + BufferFragmentImpl frag2("", 0, [this](const void*, size_t, const BufferFragmentImpl*) { + release_callback_called_ = true; + }); + Buffer::OwnedImpl buffer; + buffer.addBufferFragment(frag1); + EXPECT_EQ(11, buffer.length()); + + buffer.addBufferFragment(frag2); + EXPECT_EQ(11, buffer.length()); + + buffer.drain(11); + EXPECT_EQ(0, buffer.length()); + EXPECT_TRUE(release_callback_called_); +} + TEST_F(OwnedImplTest, AddBufferFragmentDynamicAllocation) { char input_stack[] = "hello world"; char* input = new char[11];