Movatterモバイル変換


[0]ホーム

URL:


Google Git
Sign in
chromium /chromium /src /refs/heads/main /. /ipc /ipc_channel_reader_unittest.cc
blob: 2a61e0050334b249a9bdfc02e24f4e40a4b062e5 [file] [log] [blame] [edit]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/390223051): Remove C-library calls to fix the errors.
#pragma allow_unsafe_libc_calls
#endif
#include"base/memory/raw_ptr.h"
#include"build/build_config.h"
#include<stddef.h>
#include<stdint.h>
#include<limits>
#include<memory>
#include<set>
#include"base/run_loop.h"
#include"ipc/ipc_channel_reader.h"
#include"testing/gtest/include/gtest/gtest.h"
namespace IPC{
namespace internal{
namespace{
classMockChannelReader:publicChannelReader{
public:
MockChannelReader()
:ChannelReader(nullptr), last_dispatched_message_(nullptr){}
ReadStateReadData(char* buffer,int buffer_len,int* bytes_read) override{
if(data_.empty())
return READ_PENDING;
size_t read_len= std::min(static_cast<size_t>(buffer_len), data_.size());
memcpy(buffer, data_.data(), read_len);
*bytes_read=static_cast<int>(read_len);
data_.erase(0, read_len);
return READ_SUCCEEDED;
}
boolShouldDispatchInputMessage(Message* msg) override{returntrue;}
boolGetAttachments(Message* msg) override{returntrue;}
boolDidEmptyInputBuffers() override{returntrue;}
voidHandleInternalMessage(constMessage& msg) override{}
voidDispatchMessage(Message* m) override{ last_dispatched_message_= m;}
Message* get_last_dispatched_message(){return last_dispatched_message_;}
voidAppendData(constvoid* data,size_t size){
data_.append(static_cast<constchar*>(data), size);
}
voidAppendMessageData(constMessage& message){
AppendData(message.data(), message.size());
}
private:
raw_ptr<Message> last_dispatched_message_;
std::string data_;
};
classExposedMessage:publicMessage{
public:
usingMessage::Header;
usingMessage::header;
};
// Payload that makes messages large
constsize_tLargePayloadSize=Channel::kMaximumReadBufferSize*3/2;
}// namespace
// We can determine message size from its header (and hence resize the buffer)
// only when attachment broker is not used, see IPC::Message::FindNext().
TEST(ChannelReaderTest,ResizeOverflowBuffer){
MockChannelReader reader;
ExposedMessage::Header header={};
header.payload_size=128*1024;
EXPECT_LT(reader.input_overflow_buf_.capacity(), header.payload_size);
EXPECT_TRUE(reader.TranslateInputData(
reinterpret_cast<constchar*>(&header),sizeof(header)));
// Once message header is available we resize overflow buffer to
// fit the entire message.
EXPECT_GE(reader.input_overflow_buf_.capacity(), header.payload_size);
}
TEST(ChannelReaderTest,InvalidMessageSize){
MockChannelReader reader;
ExposedMessage::Header header={};
size_t capacity_before= reader.input_overflow_buf_.capacity();
// Message is slightly larger than maximum allowed size
header.payload_size=Channel::kMaximumMessageSize+1;
EXPECT_FALSE(reader.TranslateInputData(
reinterpret_cast<constchar*>(&header),sizeof(header)));
EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before);
// Payload size is negative, overflow is detected by Pickle::PeekNext()
header.payload_size=static_cast<uint32_t>(-1);
EXPECT_FALSE(reader.TranslateInputData(
reinterpret_cast<constchar*>(&header),sizeof(header)));
EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before);
// Payload size is maximum int32_t value
header.payload_size= std::numeric_limits<int32_t>::max();
EXPECT_FALSE(reader.TranslateInputData(
reinterpret_cast<constchar*>(&header),sizeof(header)));
EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before);
}
TEST(ChannelReaderTest,TrimBuffer){
// ChannelReader uses std::string as a buffer, and calls reserve()
// to trim it to kMaximumReadBufferSize. However, an implementation
// is free to actually reserve a larger amount.
size_t trimmed_buffer_size;
{
std::string buf;
buf.reserve(Channel::kMaximumReadBufferSize);
trimmed_buffer_size= buf.capacity();
}
// Buffer is trimmed after message is processed.
{
MockChannelReader reader;
Message message;
message.WriteString(std::string(LargePayloadSize,'X'));
// Sanity check
EXPECT_TRUE(message.size()> trimmed_buffer_size);
// Initially buffer is small
EXPECT_LE(reader.input_overflow_buf_.capacity(), trimmed_buffer_size);
// Write and process large message
reader.AppendMessageData(message);
EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
reader.ProcessIncomingMessages());
// After processing large message buffer is trimmed
EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size);
}
// Buffer is trimmed only after entire message is processed.
{
MockChannelReader reader;
ExposedMessage message;
message.WriteString(std::string(LargePayloadSize,'X'));
// Write and process message header
reader.AppendData(message.header(),sizeof(ExposedMessage::Header));
EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
reader.ProcessIncomingMessages());
// We determined message size for the message from its header, so
// we resized the buffer to fit.
EXPECT_GE(reader.input_overflow_buf_.capacity(), message.size());
// Write and process payload
reader.AppendData(message.payload_bytes().data(),
message.payload_bytes().size());
EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
reader.ProcessIncomingMessages());
// But once we process the message, we trim the buffer
EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size);
}
// Buffer is not trimmed if the next message is also large.
{
MockChannelReader reader;
// Write large message
Message message1;
message1.WriteString(std::string(LargePayloadSize*2,'X'));
reader.AppendMessageData(message1);
// Write header for the next large message
ExposedMessage message2;
message2.WriteString(std::string(LargePayloadSize,'Y'));
reader.AppendData(message2.header(),sizeof(ExposedMessage::Header));
// Process messages
EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
reader.ProcessIncomingMessages());
// We determined message size for the second (partial) message, so
// we resized the buffer to fit.
EXPECT_GE(reader.input_overflow_buf_.capacity(), message1.size());
}
// Buffer resized appropriately if next message is larger than the first.
// (Similar to the test above except for the order of messages.)
{
MockChannelReader reader;
// Write large message
Message message1;
message1.WriteString(std::string(LargePayloadSize,'Y'));
reader.AppendMessageData(message1);
// Write header for the next even larger message
ExposedMessage message2;
message2.WriteString(std::string(LargePayloadSize*2,'X'));
reader.AppendData(message2.header(),sizeof(ExposedMessage::Header));
// Process messages
EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
reader.ProcessIncomingMessages());
// We determined message size for the second (partial) message, and
// resized the buffer to fit it.
EXPECT_GE(reader.input_overflow_buf_.capacity(), message2.size());
}
// Buffer is not trimmed if we've just resized it to accommodate large
// incoming message.
{
MockChannelReader reader;
// Write small message
Message message1;
message1.WriteString(std::string(11,'X'));
reader.AppendMessageData(message1);
// Write header for the next large message
ExposedMessage message2;
message2.WriteString(std::string(LargePayloadSize,'Y'));
reader.AppendData(message2.header(),sizeof(ExposedMessage::Header));
EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
reader.ProcessIncomingMessages());
// We determined message size for the second (partial) message, so
// we resized the buffer to fit.
EXPECT_GE(reader.input_overflow_buf_.capacity(), message2.size());
}
}
}// namespace internal
}// namespace IPC

[8]ページ先頭

©2009-2025 Movatter.jp