Bug 1768077 - Fix math issue in DataPipeBase::ProcessSegments, r=asuth

This could lead to hangs or buffer overflow crashes when doing a partial read
which is spread across both ends of the ring buffer.

Differential Revision: https://phabricator.services.mozilla.com/D145670
This commit is contained in:
Nika Layzell 2022-05-05 22:53:58 +00:00
Родитель 1f32baf6d5
Коммит f6d92d7332
2 изменённых файлов: 54 добавлений и 1 удалений

Просмотреть файл

@ -328,7 +328,7 @@ nsresult DataPipeBase::ProcessSegmentsInternal(
// buffer which will be used .
char* start = static_cast<char*>(link->mShmem->memory()) + link->mOffset;
char* iter = start;
char* end = start + std::min({aCount, link->mAvailable,
char* end = start + std::min({aCount - *aProcessedCount, link->mAvailable,
link->mCapacity - link->mOffset});
// Record the consumed region from our segment when exiting this scope,
@ -373,6 +373,8 @@ nsresult DataPipeBase::ProcessSegmentsInternal(
}
}
}
MOZ_DIAGNOSTIC_ASSERT(*aProcessedCount == aCount,
"Must have processed exactly aCount");
return NS_OK;
}

Просмотреть файл

@ -10,6 +10,7 @@
#include "mozilla/ipc/DataPipe.h"
#include "nsIAsyncInputStream.h"
#include "nsIAsyncOutputStream.h"
#include "nsNetUtil.h"
#include "nsStreamUtils.h"
namespace mozilla::ipc {
@ -136,6 +137,56 @@ TEST(DataPipe, SegmentedReadWrite)
ConsumeAndValidateStream(reader, inputData2);
}
TEST(DataPipe, SegmentedPartialRead)
{
RefPtr<DataPipeReceiver> reader;
RefPtr<DataPipeSender> writer;
nsresult rv =
NewDataPipe(1024, getter_AddRefs(writer), getter_AddRefs(reader));
ASSERT_TRUE(NS_SUCCEEDED(rv));
nsCString inputData1;
CreateData(512, inputData1);
uint32_t numWritten = 0;
rv = writer->Write(inputData1.BeginReading(), inputData1.Length(),
&numWritten);
ASSERT_TRUE(NS_SUCCEEDED(rv));
EXPECT_EQ(numWritten, 512u);
uint64_t available = 0;
rv = reader->Available(&available);
EXPECT_EQ(available, 512u);
ConsumeAndValidateStream(reader, inputData1);
nsCString inputData2;
CreateData(1024, inputData2);
rv = writer->Write(inputData2.BeginReading(), inputData2.Length(),
&numWritten);
ASSERT_TRUE(NS_SUCCEEDED(rv));
EXPECT_EQ(numWritten, 1024u);
rv = reader->Available(&available);
EXPECT_EQ(available, 1024u);
nsAutoCString outputData;
rv = NS_ReadInputStreamToString(reader, outputData, 768);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(768u, outputData.Length());
ASSERT_TRUE(Substring(inputData2, 0, 768).Equals(outputData));
rv = reader->Available(&available);
EXPECT_EQ(available, 256u);
nsAutoCString outputData2;
rv = NS_ReadInputStreamToString(reader, outputData2, 256);
ASSERT_TRUE(NS_SUCCEEDED(rv));
ASSERT_EQ(256u, outputData2.Length());
ASSERT_TRUE(Substring(inputData2, 768).Equals(outputData2));
}
TEST(DataPipe, Write_AsyncWait)
{
RefPtr<DataPipeReceiver> reader;