ipc_message_utils_unittest.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. // Copyright (c) 2012 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 "ipc/ipc_message_utils.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <memory>
  8. #include "base/files/file_path.h"
  9. #include "base/json/json_reader.h"
  10. #include "base/memory/ptr_util.h"
  11. #include "base/test/test_shared_memory_util.h"
  12. #include "base/unguessable_token.h"
  13. #include "build/build_config.h"
  14. #include "ipc/ipc_channel_handle.h"
  15. #include "ipc/ipc_message.h"
  16. #include "testing/gtest/include/gtest/gtest.h"
  17. #if BUILDFLAG(IS_WIN)
  18. #include <windows.h>
  19. #endif
  20. namespace IPC {
  21. namespace {
  22. // Tests nesting of messages as parameters to other messages.
  23. TEST(IPCMessageUtilsTest, NestedMessages) {
  24. int32_t nested_routing = 12;
  25. uint32_t nested_type = 78;
  26. int nested_content = 456789;
  27. Message::PriorityValue nested_priority = Message::PRIORITY_HIGH;
  28. Message nested_msg(nested_routing, nested_type, nested_priority);
  29. nested_msg.set_sync();
  30. ParamTraits<int>::Write(&nested_msg, nested_content);
  31. // Outer message contains the nested one as its parameter.
  32. int32_t outer_routing = 91;
  33. uint32_t outer_type = 88;
  34. Message::PriorityValue outer_priority = Message::PRIORITY_NORMAL;
  35. Message outer_msg(outer_routing, outer_type, outer_priority);
  36. ParamTraits<Message>::Write(&outer_msg, nested_msg);
  37. // Read back the nested message.
  38. base::PickleIterator iter(outer_msg);
  39. IPC::Message result_msg;
  40. ASSERT_TRUE(ParamTraits<Message>::Read(&outer_msg, &iter, &result_msg));
  41. // Verify nested message headers.
  42. EXPECT_EQ(nested_msg.routing_id(), result_msg.routing_id());
  43. EXPECT_EQ(nested_msg.type(), result_msg.type());
  44. EXPECT_EQ(nested_msg.priority(), result_msg.priority());
  45. EXPECT_EQ(nested_msg.flags(), result_msg.flags());
  46. // Verify nested message content
  47. base::PickleIterator nested_iter(nested_msg);
  48. int result_content = 0;
  49. ASSERT_TRUE(ParamTraits<int>::Read(&nested_msg, &nested_iter,
  50. &result_content));
  51. EXPECT_EQ(nested_content, result_content);
  52. // Try reading past the ends for both messages and make sure it fails.
  53. IPC::Message dummy;
  54. ASSERT_FALSE(ParamTraits<Message>::Read(&outer_msg, &iter, &dummy));
  55. ASSERT_FALSE(ParamTraits<int>::Read(&nested_msg, &nested_iter,
  56. &result_content));
  57. }
  58. // Tests that detection of various bad parameters is working correctly.
  59. TEST(IPCMessageUtilsTest, ParameterValidation) {
  60. base::FilePath::StringType ok_string(FILE_PATH_LITERAL("hello"), 5);
  61. base::FilePath::StringType bad_string(FILE_PATH_LITERAL("hel\0o"), 5);
  62. // Change this if ParamTraits<FilePath>::Write() changes.
  63. IPC::Message message;
  64. ParamTraits<base::FilePath::StringType>::Write(&message, ok_string);
  65. ParamTraits<base::FilePath::StringType>::Write(&message, bad_string);
  66. base::PickleIterator iter(message);
  67. base::FilePath ok_path;
  68. base::FilePath bad_path;
  69. ASSERT_TRUE(ParamTraits<base::FilePath>::Read(&message, &iter, &ok_path));
  70. ASSERT_FALSE(ParamTraits<base::FilePath>::Read(&message, &iter, &bad_path));
  71. }
  72. TEST(IPCMessageUtilsTest, StackVector) {
  73. static const size_t stack_capacity = 5;
  74. base::StackVector<double, stack_capacity> stack_vector;
  75. for (size_t i = 0; i < 2 * stack_capacity; i++)
  76. stack_vector->push_back(i * 2.0);
  77. IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
  78. IPC::WriteParam(&msg, stack_vector);
  79. base::StackVector<double, stack_capacity> output;
  80. base::PickleIterator iter(msg);
  81. EXPECT_TRUE(IPC::ReadParam(&msg, &iter, &output));
  82. for (size_t i = 0; i < 2 * stack_capacity; i++)
  83. EXPECT_EQ(stack_vector[i], output[i]);
  84. }
  85. TEST(IPCMessageUtilsTest, MojoChannelHandle) {
  86. mojo::MessagePipe message_pipe;
  87. IPC::ChannelHandle channel_handle(message_pipe.handle0.release());
  88. IPC::Message message;
  89. IPC::WriteParam(&message, channel_handle);
  90. base::PickleIterator iter(message);
  91. IPC::ChannelHandle result_handle;
  92. EXPECT_TRUE(IPC::ReadParam(&message, &iter, &result_handle));
  93. EXPECT_EQ(channel_handle.mojo_handle, result_handle.mojo_handle);
  94. }
  95. TEST(IPCMessageUtilsTest, OptionalUnset) {
  96. absl::optional<int> opt;
  97. base::Pickle pickle;
  98. IPC::WriteParam(&pickle, opt);
  99. std::string log;
  100. IPC::LogParam(opt, &log);
  101. EXPECT_EQ("(unset)", log);
  102. absl::optional<int> unserialized_opt;
  103. base::PickleIterator iter(pickle);
  104. EXPECT_TRUE(IPC::ReadParam(&pickle, &iter, &unserialized_opt));
  105. EXPECT_FALSE(unserialized_opt);
  106. }
  107. TEST(IPCMessageUtilsTest, OptionalSet) {
  108. absl::optional<int> opt(10);
  109. base::Pickle pickle;
  110. IPC::WriteParam(&pickle, opt);
  111. std::string log;
  112. IPC::LogParam(opt, &log);
  113. EXPECT_EQ("10", log);
  114. absl::optional<int> unserialized_opt;
  115. base::PickleIterator iter(pickle);
  116. EXPECT_TRUE(IPC::ReadParam(&pickle, &iter, &unserialized_opt));
  117. EXPECT_TRUE(unserialized_opt);
  118. EXPECT_EQ(opt.value(), unserialized_opt.value());
  119. }
  120. template <typename SharedMemoryRegionType>
  121. class SharedMemoryRegionTypedTest : public ::testing::Test {};
  122. typedef ::testing::Types<base::WritableSharedMemoryRegion,
  123. base::UnsafeSharedMemoryRegion,
  124. base::ReadOnlySharedMemoryRegion>
  125. AllSharedMemoryRegionTypes;
  126. TYPED_TEST_SUITE(SharedMemoryRegionTypedTest, AllSharedMemoryRegionTypes);
  127. TYPED_TEST(SharedMemoryRegionTypedTest, WriteAndRead) {
  128. const size_t size = 2314;
  129. auto [pre_pickle, pre_mapping] = base::CreateMappedRegion<TypeParam>(size);
  130. const size_t pre_size = pre_pickle.GetSize();
  131. const std::string content = "Hello, world!";
  132. memcpy(pre_mapping.memory(), content.data(), content.size());
  133. IPC::Message message;
  134. IPC::WriteParam(&message, pre_pickle);
  135. EXPECT_FALSE(pre_pickle.IsValid());
  136. TypeParam post_pickle;
  137. base::PickleIterator iter(message);
  138. EXPECT_TRUE(IPC::ReadParam(&message, &iter, &post_pickle));
  139. EXPECT_EQ(pre_size, post_pickle.GetSize());
  140. typename TypeParam::MappingType post_mapping = post_pickle.Map();
  141. EXPECT_EQ(pre_mapping.guid(), post_mapping.guid());
  142. EXPECT_EQ(0, memcmp(pre_mapping.memory(), post_mapping.memory(),
  143. post_pickle.GetSize()));
  144. }
  145. TYPED_TEST(SharedMemoryRegionTypedTest, InvalidRegion) {
  146. TypeParam pre_pickle;
  147. EXPECT_FALSE(pre_pickle.IsValid());
  148. IPC::Message message;
  149. IPC::WriteParam(&message, pre_pickle);
  150. TypeParam post_pickle;
  151. base::PickleIterator iter(message);
  152. EXPECT_TRUE(IPC::ReadParam(&message, &iter, &post_pickle));
  153. EXPECT_FALSE(post_pickle.IsValid());
  154. }
  155. TEST(IPCMessageUtilsTest, UnguessableTokenTest) {
  156. base::UnguessableToken token = base::UnguessableToken::Create();
  157. base::Pickle pickle;
  158. IPC::WriteParam(&pickle, token);
  159. std::string log;
  160. IPC::LogParam(token, &log);
  161. EXPECT_EQ(token.ToString(), log);
  162. base::UnguessableToken deserialized_token;
  163. base::PickleIterator iter(pickle);
  164. EXPECT_TRUE(IPC::ReadParam(&pickle, &iter, &deserialized_token));
  165. EXPECT_EQ(token, deserialized_token);
  166. }
  167. TEST(IPCMessageUtilsTest, FlatMap) {
  168. base::flat_map<std::string, int> input;
  169. input["foo"] = 42;
  170. input["bar"] = 96;
  171. base::Pickle pickle;
  172. IPC::WriteParam(&pickle, input);
  173. base::PickleIterator iter(pickle);
  174. base::flat_map<std::string, int> output;
  175. EXPECT_TRUE(IPC::ReadParam(&pickle, &iter, &output));
  176. EXPECT_EQ(input, output);
  177. }
  178. TEST(IPCMessageUtilsTest, StrongAlias) {
  179. using TestType = base::StrongAlias<class Tag, int>;
  180. TestType input(42);
  181. base::Pickle pickle;
  182. IPC::WriteParam(&pickle, input);
  183. base::PickleIterator iter(pickle);
  184. TestType output;
  185. EXPECT_TRUE(IPC::ReadParam(&pickle, &iter, &output));
  186. EXPECT_EQ(input, output);
  187. }
  188. TEST(IPCMessageUtilsTest, LegacyDictValueConversion) {
  189. base::DictionaryValue dict_value;
  190. dict_value.GetDict().Set("path1", 42);
  191. dict_value.GetDict().Set("path2", 84);
  192. base::ListValue subvalue;
  193. subvalue.Append(1234);
  194. subvalue.Append(5678);
  195. dict_value.SetKey("path3", std::move(subvalue));
  196. IPC::Message message;
  197. ParamTraits<base::DictionaryValue>::Write(&message, dict_value);
  198. base::PickleIterator iter(message);
  199. base::DictionaryValue read_value;
  200. ASSERT_TRUE(
  201. ParamTraits<base::DictionaryValue>::Read(&message, &iter, &read_value));
  202. EXPECT_EQ(dict_value, read_value);
  203. }
  204. TEST(IPCMessageUtilsTest, DictValueConversion) {
  205. base::Value::Dict dict_value;
  206. dict_value.Set("path1", 42);
  207. dict_value.Set("path2", 84);
  208. base::Value::List subvalue;
  209. subvalue.Append(1234);
  210. subvalue.Append(5678);
  211. dict_value.Set("path3", std::move(subvalue));
  212. IPC::Message message;
  213. ParamTraits<base::Value::Dict>::Write(&message, dict_value);
  214. base::PickleIterator iter(message);
  215. base::Value::Dict read_value;
  216. ASSERT_TRUE(
  217. ParamTraits<base::Value::Dict>::Read(&message, &iter, &read_value));
  218. EXPECT_EQ(dict_value, read_value);
  219. }
  220. TEST(IPCMessageUtilsTest, LegacyListValueConversion) {
  221. base::ListValue list_value;
  222. list_value.Append(42);
  223. list_value.Append(84);
  224. IPC::Message message;
  225. ParamTraits<base::ListValue>::Write(&message, list_value);
  226. base::PickleIterator iter(message);
  227. base::ListValue read_value;
  228. ASSERT_TRUE(ParamTraits<base::ListValue>::Read(&message, &iter, &read_value));
  229. EXPECT_EQ(list_value, read_value);
  230. }
  231. TEST(IPCMessageUtilsTest, ListValueConversion) {
  232. base::Value::List list_value;
  233. list_value.Append(42);
  234. list_value.Append(84);
  235. IPC::Message message;
  236. ParamTraits<base::Value::List>::Write(&message, list_value);
  237. base::PickleIterator iter(message);
  238. base::Value::List read_value;
  239. ASSERT_TRUE(
  240. ParamTraits<base::Value::List>::Read(&message, &iter, &read_value));
  241. EXPECT_EQ(list_value, read_value);
  242. }
  243. #if BUILDFLAG(IS_WIN)
  244. TEST(IPCMessageUtilsTest, ScopedHandle) {
  245. HANDLE raw_dupe_handle;
  246. ASSERT_TRUE(::DuplicateHandle(::GetCurrentProcess(), ::GetCurrentProcess(),
  247. ::GetCurrentProcess(), &raw_dupe_handle, 0,
  248. FALSE, DUPLICATE_SAME_ACCESS));
  249. base::win::ScopedHandle dupe_handle(raw_dupe_handle);
  250. Message message(0, 0, Message::PRIORITY_LOW);
  251. WriteParam(&message, dupe_handle);
  252. base::PickleIterator iter(message);
  253. base::win::ScopedHandle read_handle;
  254. EXPECT_TRUE(ReadParam(&message, &iter, &read_handle));
  255. EXPECT_TRUE(read_handle.IsValid());
  256. }
  257. #endif // BUILDFLAG(IS_WIN)
  258. } // namespace
  259. } // namespace IPC