ipc_channel_reader_unittest.cc 7.9 KB

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