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