• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors
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 "base/memory/raw_ptr.h"
6 #include "build/build_config.h"
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <limits>
12 #include <memory>
13 #include <set>
14 
15 #include "base/run_loop.h"
16 #include "ipc/ipc_channel_reader.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 
19 namespace IPC {
20 namespace internal {
21 
22 namespace {
23 
24 class MockChannelReader : public ChannelReader {
25  public:
MockChannelReader()26   MockChannelReader()
27       : ChannelReader(nullptr), last_dispatched_message_(nullptr) {}
28 
ReadData(char * buffer,int buffer_len,int * bytes_read)29   ReadState ReadData(char* buffer, int buffer_len, int* bytes_read) override {
30     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;
38   }
39 
ShouldDispatchInputMessage(Message * msg)40   bool ShouldDispatchInputMessage(Message* msg) override { return true; }
41 
GetAttachments(Message * msg)42   bool GetAttachments(Message* msg) override { return true; }
43 
DidEmptyInputBuffers()44   bool DidEmptyInputBuffers() override { return true; }
45 
HandleInternalMessage(const Message & msg)46   void HandleInternalMessage(const Message& msg) override {}
47 
DispatchMessage(Message * m)48   void DispatchMessage(Message* m) override { last_dispatched_message_ = m; }
49 
get_last_dispatched_message()50   Message* get_last_dispatched_message() { return last_dispatched_message_; }
51 
AppendData(const void * data,size_t size)52   void AppendData(const void* data, size_t size) {
53     data_.append(static_cast<const char*>(data), size);
54   }
55 
AppendMessageData(const Message & message)56   void AppendMessageData(const Message& message) {
57     AppendData(message.data(), message.size());
58   }
59 
60  private:
61   raw_ptr<Message> last_dispatched_message_;
62   std::string data_;
63 };
64 
65 class ExposedMessage: public Message {
66  public:
67   using Message::Header;
68   using Message::header;
69 };
70 
71 // Payload that makes messages large
72 const size_t LargePayloadSize = Channel::kMaximumReadBufferSize * 3 / 2;
73 
74 }  // namespace
75 
76 // 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 
TEST(ChannelReaderTest,ResizeOverflowBuffer)79 TEST(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 
TEST(ChannelReaderTest,InvalidMessageSize)94 TEST(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 
113   // Payload size is maximum int32_t value
114   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 
TEST(ChannelReaderTest,TrimBuffer)120 TEST(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 
165     // 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());
168 
169     // Write and process payload
170     reader.AppendData(message.payload(), message.payload_size());
171     EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
172               reader.ProcessIncomingMessages());
173 
174     // But once we process the message, we trim the buffer
175     EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size);
176   }
177 
178   // Buffer is not trimmed if the next message is also large.
179   {
180     MockChannelReader reader;
181 
182     // Write large message
183     Message message1;
184     message1.WriteString(std::string(LargePayloadSize * 2, 'X'));
185     reader.AppendMessageData(message1);
186 
187     // Write header for the next large message
188     ExposedMessage message2;
189     message2.WriteString(std::string(LargePayloadSize, 'Y'));
190     reader.AppendData(message2.header(), sizeof(ExposedMessage::Header));
191 
192     // Process messages
193     EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
194               reader.ProcessIncomingMessages());
195 
196     // We determined message size for the second (partial) message, so
197     // we resized the buffer to fit.
198     EXPECT_GE(reader.input_overflow_buf_.capacity(), message1.size());
199   }
200 
201   // Buffer resized appropriately if next message is larger than the first.
202   // (Similar to the test above except for the order of messages.)
203   {
204     MockChannelReader reader;
205 
206     // Write large message
207     Message message1;
208     message1.WriteString(std::string(LargePayloadSize, 'Y'));
209     reader.AppendMessageData(message1);
210 
211     // Write header for the next even larger message
212     ExposedMessage message2;
213     message2.WriteString(std::string(LargePayloadSize * 2, 'X'));
214     reader.AppendData(message2.header(), sizeof(ExposedMessage::Header));
215 
216     // Process messages
217     EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
218               reader.ProcessIncomingMessages());
219 
220     // We determined message size for the second (partial) message, and
221     // resized the buffer to fit it.
222     EXPECT_GE(reader.input_overflow_buf_.capacity(), message2.size());
223   }
224 
225   // Buffer is not trimmed if we've just resized it to accommodate large
226   // incoming message.
227   {
228     MockChannelReader reader;
229 
230     // Write small message
231     Message message1;
232     message1.WriteString(std::string(11, 'X'));
233     reader.AppendMessageData(message1);
234 
235     // Write header for the next large message
236     ExposedMessage message2;
237     message2.WriteString(std::string(LargePayloadSize, 'Y'));
238     reader.AppendData(message2.header(), sizeof(ExposedMessage::Header));
239 
240     EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
241               reader.ProcessIncomingMessages());
242 
243     // We determined message size for the second (partial) message, so
244     // we resized the buffer to fit.
245     EXPECT_GE(reader.input_overflow_buf_.capacity(), message2.size());
246   }
247 }
248 
249 }  // namespace internal
250 }  // namespace IPC
251