1*6777b538SAndroid Build Coastguard Worker // Copyright 2015 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
6*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
7*6777b538SAndroid Build Coastguard Worker
8*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
9*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker #include <limits>
12*6777b538SAndroid Build Coastguard Worker #include <memory>
13*6777b538SAndroid Build Coastguard Worker #include <set>
14*6777b538SAndroid Build Coastguard Worker
15*6777b538SAndroid Build Coastguard Worker #include "base/run_loop.h"
16*6777b538SAndroid Build Coastguard Worker #include "ipc/ipc_channel_reader.h"
17*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker namespace IPC {
20*6777b538SAndroid Build Coastguard Worker namespace internal {
21*6777b538SAndroid Build Coastguard Worker
22*6777b538SAndroid Build Coastguard Worker namespace {
23*6777b538SAndroid Build Coastguard Worker
24*6777b538SAndroid Build Coastguard Worker class MockChannelReader : public ChannelReader {
25*6777b538SAndroid Build Coastguard Worker public:
MockChannelReader()26*6777b538SAndroid Build Coastguard Worker MockChannelReader()
27*6777b538SAndroid Build Coastguard Worker : ChannelReader(nullptr), last_dispatched_message_(nullptr) {}
28*6777b538SAndroid Build Coastguard Worker
ReadData(char * buffer,int buffer_len,int * bytes_read)29*6777b538SAndroid Build Coastguard Worker ReadState ReadData(char* buffer, int buffer_len, int* bytes_read) override {
30*6777b538SAndroid Build Coastguard Worker if (data_.empty())
31*6777b538SAndroid Build Coastguard Worker return READ_PENDING;
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard Worker size_t read_len = std::min(static_cast<size_t>(buffer_len), data_.size());
34*6777b538SAndroid Build Coastguard Worker memcpy(buffer, data_.data(), read_len);
35*6777b538SAndroid Build Coastguard Worker *bytes_read = static_cast<int>(read_len);
36*6777b538SAndroid Build Coastguard Worker data_.erase(0, read_len);
37*6777b538SAndroid Build Coastguard Worker return READ_SUCCEEDED;
38*6777b538SAndroid Build Coastguard Worker }
39*6777b538SAndroid Build Coastguard Worker
ShouldDispatchInputMessage(Message * msg)40*6777b538SAndroid Build Coastguard Worker bool ShouldDispatchInputMessage(Message* msg) override { return true; }
41*6777b538SAndroid Build Coastguard Worker
GetAttachments(Message * msg)42*6777b538SAndroid Build Coastguard Worker bool GetAttachments(Message* msg) override { return true; }
43*6777b538SAndroid Build Coastguard Worker
DidEmptyInputBuffers()44*6777b538SAndroid Build Coastguard Worker bool DidEmptyInputBuffers() override { return true; }
45*6777b538SAndroid Build Coastguard Worker
HandleInternalMessage(const Message & msg)46*6777b538SAndroid Build Coastguard Worker void HandleInternalMessage(const Message& msg) override {}
47*6777b538SAndroid Build Coastguard Worker
DispatchMessage(Message * m)48*6777b538SAndroid Build Coastguard Worker void DispatchMessage(Message* m) override { last_dispatched_message_ = m; }
49*6777b538SAndroid Build Coastguard Worker
get_last_dispatched_message()50*6777b538SAndroid Build Coastguard Worker Message* get_last_dispatched_message() { return last_dispatched_message_; }
51*6777b538SAndroid Build Coastguard Worker
AppendData(const void * data,size_t size)52*6777b538SAndroid Build Coastguard Worker void AppendData(const void* data, size_t size) {
53*6777b538SAndroid Build Coastguard Worker data_.append(static_cast<const char*>(data), size);
54*6777b538SAndroid Build Coastguard Worker }
55*6777b538SAndroid Build Coastguard Worker
AppendMessageData(const Message & message)56*6777b538SAndroid Build Coastguard Worker void AppendMessageData(const Message& message) {
57*6777b538SAndroid Build Coastguard Worker AppendData(message.data(), message.size());
58*6777b538SAndroid Build Coastguard Worker }
59*6777b538SAndroid Build Coastguard Worker
60*6777b538SAndroid Build Coastguard Worker private:
61*6777b538SAndroid Build Coastguard Worker raw_ptr<Message> last_dispatched_message_;
62*6777b538SAndroid Build Coastguard Worker std::string data_;
63*6777b538SAndroid Build Coastguard Worker };
64*6777b538SAndroid Build Coastguard Worker
65*6777b538SAndroid Build Coastguard Worker class ExposedMessage: public Message {
66*6777b538SAndroid Build Coastguard Worker public:
67*6777b538SAndroid Build Coastguard Worker using Message::Header;
68*6777b538SAndroid Build Coastguard Worker using Message::header;
69*6777b538SAndroid Build Coastguard Worker };
70*6777b538SAndroid Build Coastguard Worker
71*6777b538SAndroid Build Coastguard Worker // Payload that makes messages large
72*6777b538SAndroid Build Coastguard Worker const size_t LargePayloadSize = Channel::kMaximumReadBufferSize * 3 / 2;
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Worker } // namespace
75*6777b538SAndroid Build Coastguard Worker
76*6777b538SAndroid Build Coastguard Worker // We can determine message size from its header (and hence resize the buffer)
77*6777b538SAndroid Build Coastguard Worker // only when attachment broker is not used, see IPC::Message::FindNext().
78*6777b538SAndroid Build Coastguard Worker
TEST(ChannelReaderTest,ResizeOverflowBuffer)79*6777b538SAndroid Build Coastguard Worker TEST(ChannelReaderTest, ResizeOverflowBuffer) {
80*6777b538SAndroid Build Coastguard Worker MockChannelReader reader;
81*6777b538SAndroid Build Coastguard Worker
82*6777b538SAndroid Build Coastguard Worker ExposedMessage::Header header = {};
83*6777b538SAndroid Build Coastguard Worker
84*6777b538SAndroid Build Coastguard Worker header.payload_size = 128 * 1024;
85*6777b538SAndroid Build Coastguard Worker EXPECT_LT(reader.input_overflow_buf_.capacity(), header.payload_size);
86*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(reader.TranslateInputData(
87*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&header), sizeof(header)));
88*6777b538SAndroid Build Coastguard Worker
89*6777b538SAndroid Build Coastguard Worker // Once message header is available we resize overflow buffer to
90*6777b538SAndroid Build Coastguard Worker // fit the entire message.
91*6777b538SAndroid Build Coastguard Worker EXPECT_GE(reader.input_overflow_buf_.capacity(), header.payload_size);
92*6777b538SAndroid Build Coastguard Worker }
93*6777b538SAndroid Build Coastguard Worker
TEST(ChannelReaderTest,InvalidMessageSize)94*6777b538SAndroid Build Coastguard Worker TEST(ChannelReaderTest, InvalidMessageSize) {
95*6777b538SAndroid Build Coastguard Worker MockChannelReader reader;
96*6777b538SAndroid Build Coastguard Worker
97*6777b538SAndroid Build Coastguard Worker ExposedMessage::Header header = {};
98*6777b538SAndroid Build Coastguard Worker
99*6777b538SAndroid Build Coastguard Worker size_t capacity_before = reader.input_overflow_buf_.capacity();
100*6777b538SAndroid Build Coastguard Worker
101*6777b538SAndroid Build Coastguard Worker // Message is slightly larger than maximum allowed size
102*6777b538SAndroid Build Coastguard Worker header.payload_size = Channel::kMaximumMessageSize + 1;
103*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(reader.TranslateInputData(
104*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&header), sizeof(header)));
105*6777b538SAndroid Build Coastguard Worker EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before);
106*6777b538SAndroid Build Coastguard Worker
107*6777b538SAndroid Build Coastguard Worker // Payload size is negative, overflow is detected by Pickle::PeekNext()
108*6777b538SAndroid Build Coastguard Worker header.payload_size = static_cast<uint32_t>(-1);
109*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(reader.TranslateInputData(
110*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&header), sizeof(header)));
111*6777b538SAndroid Build Coastguard Worker EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before);
112*6777b538SAndroid Build Coastguard Worker
113*6777b538SAndroid Build Coastguard Worker // Payload size is maximum int32_t value
114*6777b538SAndroid Build Coastguard Worker header.payload_size = std::numeric_limits<int32_t>::max();
115*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(reader.TranslateInputData(
116*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const char*>(&header), sizeof(header)));
117*6777b538SAndroid Build Coastguard Worker EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before);
118*6777b538SAndroid Build Coastguard Worker }
119*6777b538SAndroid Build Coastguard Worker
TEST(ChannelReaderTest,TrimBuffer)120*6777b538SAndroid Build Coastguard Worker TEST(ChannelReaderTest, TrimBuffer) {
121*6777b538SAndroid Build Coastguard Worker // ChannelReader uses std::string as a buffer, and calls reserve()
122*6777b538SAndroid Build Coastguard Worker // to trim it to kMaximumReadBufferSize. However, an implementation
123*6777b538SAndroid Build Coastguard Worker // is free to actually reserve a larger amount.
124*6777b538SAndroid Build Coastguard Worker size_t trimmed_buffer_size;
125*6777b538SAndroid Build Coastguard Worker {
126*6777b538SAndroid Build Coastguard Worker std::string buf;
127*6777b538SAndroid Build Coastguard Worker buf.reserve(Channel::kMaximumReadBufferSize);
128*6777b538SAndroid Build Coastguard Worker trimmed_buffer_size = buf.capacity();
129*6777b538SAndroid Build Coastguard Worker }
130*6777b538SAndroid Build Coastguard Worker
131*6777b538SAndroid Build Coastguard Worker // Buffer is trimmed after message is processed.
132*6777b538SAndroid Build Coastguard Worker {
133*6777b538SAndroid Build Coastguard Worker MockChannelReader reader;
134*6777b538SAndroid Build Coastguard Worker
135*6777b538SAndroid Build Coastguard Worker Message message;
136*6777b538SAndroid Build Coastguard Worker message.WriteString(std::string(LargePayloadSize, 'X'));
137*6777b538SAndroid Build Coastguard Worker
138*6777b538SAndroid Build Coastguard Worker // Sanity check
139*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(message.size() > trimmed_buffer_size);
140*6777b538SAndroid Build Coastguard Worker
141*6777b538SAndroid Build Coastguard Worker // Initially buffer is small
142*6777b538SAndroid Build Coastguard Worker EXPECT_LE(reader.input_overflow_buf_.capacity(), trimmed_buffer_size);
143*6777b538SAndroid Build Coastguard Worker
144*6777b538SAndroid Build Coastguard Worker // Write and process large message
145*6777b538SAndroid Build Coastguard Worker reader.AppendMessageData(message);
146*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
147*6777b538SAndroid Build Coastguard Worker reader.ProcessIncomingMessages());
148*6777b538SAndroid Build Coastguard Worker
149*6777b538SAndroid Build Coastguard Worker // After processing large message buffer is trimmed
150*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size);
151*6777b538SAndroid Build Coastguard Worker }
152*6777b538SAndroid Build Coastguard Worker
153*6777b538SAndroid Build Coastguard Worker // Buffer is trimmed only after entire message is processed.
154*6777b538SAndroid Build Coastguard Worker {
155*6777b538SAndroid Build Coastguard Worker MockChannelReader reader;
156*6777b538SAndroid Build Coastguard Worker
157*6777b538SAndroid Build Coastguard Worker ExposedMessage message;
158*6777b538SAndroid Build Coastguard Worker message.WriteString(std::string(LargePayloadSize, 'X'));
159*6777b538SAndroid Build Coastguard Worker
160*6777b538SAndroid Build Coastguard Worker // Write and process message header
161*6777b538SAndroid Build Coastguard Worker reader.AppendData(message.header(), sizeof(ExposedMessage::Header));
162*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
163*6777b538SAndroid Build Coastguard Worker reader.ProcessIncomingMessages());
164*6777b538SAndroid Build Coastguard Worker
165*6777b538SAndroid Build Coastguard Worker // We determined message size for the message from its header, so
166*6777b538SAndroid Build Coastguard Worker // we resized the buffer to fit.
167*6777b538SAndroid Build Coastguard Worker EXPECT_GE(reader.input_overflow_buf_.capacity(), message.size());
168*6777b538SAndroid Build Coastguard Worker
169*6777b538SAndroid Build Coastguard Worker // Write and process payload
170*6777b538SAndroid Build Coastguard Worker reader.AppendData(message.payload_bytes().data(),
171*6777b538SAndroid Build Coastguard Worker message.payload_bytes().size());
172*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
173*6777b538SAndroid Build Coastguard Worker reader.ProcessIncomingMessages());
174*6777b538SAndroid Build Coastguard Worker
175*6777b538SAndroid Build Coastguard Worker // But once we process the message, we trim the buffer
176*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size);
177*6777b538SAndroid Build Coastguard Worker }
178*6777b538SAndroid Build Coastguard Worker
179*6777b538SAndroid Build Coastguard Worker // Buffer is not trimmed if the next message is also large.
180*6777b538SAndroid Build Coastguard Worker {
181*6777b538SAndroid Build Coastguard Worker MockChannelReader reader;
182*6777b538SAndroid Build Coastguard Worker
183*6777b538SAndroid Build Coastguard Worker // Write large message
184*6777b538SAndroid Build Coastguard Worker Message message1;
185*6777b538SAndroid Build Coastguard Worker message1.WriteString(std::string(LargePayloadSize * 2, 'X'));
186*6777b538SAndroid Build Coastguard Worker reader.AppendMessageData(message1);
187*6777b538SAndroid Build Coastguard Worker
188*6777b538SAndroid Build Coastguard Worker // Write header for the next large message
189*6777b538SAndroid Build Coastguard Worker ExposedMessage message2;
190*6777b538SAndroid Build Coastguard Worker message2.WriteString(std::string(LargePayloadSize, 'Y'));
191*6777b538SAndroid Build Coastguard Worker reader.AppendData(message2.header(), sizeof(ExposedMessage::Header));
192*6777b538SAndroid Build Coastguard Worker
193*6777b538SAndroid Build Coastguard Worker // Process messages
194*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
195*6777b538SAndroid Build Coastguard Worker reader.ProcessIncomingMessages());
196*6777b538SAndroid Build Coastguard Worker
197*6777b538SAndroid Build Coastguard Worker // We determined message size for the second (partial) message, so
198*6777b538SAndroid Build Coastguard Worker // we resized the buffer to fit.
199*6777b538SAndroid Build Coastguard Worker EXPECT_GE(reader.input_overflow_buf_.capacity(), message1.size());
200*6777b538SAndroid Build Coastguard Worker }
201*6777b538SAndroid Build Coastguard Worker
202*6777b538SAndroid Build Coastguard Worker // Buffer resized appropriately if next message is larger than the first.
203*6777b538SAndroid Build Coastguard Worker // (Similar to the test above except for the order of messages.)
204*6777b538SAndroid Build Coastguard Worker {
205*6777b538SAndroid Build Coastguard Worker MockChannelReader reader;
206*6777b538SAndroid Build Coastguard Worker
207*6777b538SAndroid Build Coastguard Worker // Write large message
208*6777b538SAndroid Build Coastguard Worker Message message1;
209*6777b538SAndroid Build Coastguard Worker message1.WriteString(std::string(LargePayloadSize, 'Y'));
210*6777b538SAndroid Build Coastguard Worker reader.AppendMessageData(message1);
211*6777b538SAndroid Build Coastguard Worker
212*6777b538SAndroid Build Coastguard Worker // Write header for the next even larger message
213*6777b538SAndroid Build Coastguard Worker ExposedMessage message2;
214*6777b538SAndroid Build Coastguard Worker message2.WriteString(std::string(LargePayloadSize * 2, 'X'));
215*6777b538SAndroid Build Coastguard Worker reader.AppendData(message2.header(), sizeof(ExposedMessage::Header));
216*6777b538SAndroid Build Coastguard Worker
217*6777b538SAndroid Build Coastguard Worker // Process messages
218*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
219*6777b538SAndroid Build Coastguard Worker reader.ProcessIncomingMessages());
220*6777b538SAndroid Build Coastguard Worker
221*6777b538SAndroid Build Coastguard Worker // We determined message size for the second (partial) message, and
222*6777b538SAndroid Build Coastguard Worker // resized the buffer to fit it.
223*6777b538SAndroid Build Coastguard Worker EXPECT_GE(reader.input_overflow_buf_.capacity(), message2.size());
224*6777b538SAndroid Build Coastguard Worker }
225*6777b538SAndroid Build Coastguard Worker
226*6777b538SAndroid Build Coastguard Worker // Buffer is not trimmed if we've just resized it to accommodate large
227*6777b538SAndroid Build Coastguard Worker // incoming message.
228*6777b538SAndroid Build Coastguard Worker {
229*6777b538SAndroid Build Coastguard Worker MockChannelReader reader;
230*6777b538SAndroid Build Coastguard Worker
231*6777b538SAndroid Build Coastguard Worker // Write small message
232*6777b538SAndroid Build Coastguard Worker Message message1;
233*6777b538SAndroid Build Coastguard Worker message1.WriteString(std::string(11, 'X'));
234*6777b538SAndroid Build Coastguard Worker reader.AppendMessageData(message1);
235*6777b538SAndroid Build Coastguard Worker
236*6777b538SAndroid Build Coastguard Worker // Write header for the next large message
237*6777b538SAndroid Build Coastguard Worker ExposedMessage message2;
238*6777b538SAndroid Build Coastguard Worker message2.WriteString(std::string(LargePayloadSize, 'Y'));
239*6777b538SAndroid Build Coastguard Worker reader.AppendData(message2.header(), sizeof(ExposedMessage::Header));
240*6777b538SAndroid Build Coastguard Worker
241*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
242*6777b538SAndroid Build Coastguard Worker reader.ProcessIncomingMessages());
243*6777b538SAndroid Build Coastguard Worker
244*6777b538SAndroid Build Coastguard Worker // We determined message size for the second (partial) message, so
245*6777b538SAndroid Build Coastguard Worker // we resized the buffer to fit.
246*6777b538SAndroid Build Coastguard Worker EXPECT_GE(reader.input_overflow_buf_.capacity(), message2.size());
247*6777b538SAndroid Build Coastguard Worker }
248*6777b538SAndroid Build Coastguard Worker }
249*6777b538SAndroid Build Coastguard Worker
250*6777b538SAndroid Build Coastguard Worker } // namespace internal
251*6777b538SAndroid Build Coastguard Worker } // namespace IPC
252