[go: nahoru, domu]

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