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