| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stdio.h> | 5 #include <stdio.h> |
| 6 #include <string> | 6 #include <string> |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
| 10 #include "base/strings/string16.h" |
| 11 #include "base/strings/utf_string_conversions.h" |
| 10 #include "base/threading/platform_thread.h" | 12 #include "base/threading/platform_thread.h" |
| 11 #include "ipc/ipc_test_base.h" | 13 #include "ipc/ipc_test_base.h" |
| 12 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
| 13 | 15 |
| 14 // IPC messages for testing ---------------------------------------------------- | 16 // IPC messages for testing ---------------------------------------------------- |
| 15 | 17 |
| 16 #define IPC_MESSAGE_IMPL | 18 #define IPC_MESSAGE_IMPL |
| 17 #include "ipc/ipc_message_macros.h" | 19 #include "ipc/ipc_message_macros.h" |
| 18 | 20 |
| 19 #define IPC_MESSAGE_START TestMsgStart | 21 #define IPC_MESSAGE_START TestMsgStart |
| 20 | 22 |
| 21 // Generic message class that is an int followed by a wstring. | 23 // Generic message class that is an int followed by a string16. |
| 22 IPC_MESSAGE_CONTROL2(MsgClassIS, int, std::wstring) | 24 IPC_MESSAGE_CONTROL2(MsgClassIS, int, base::string16) |
| 23 | 25 |
| 24 // Generic message class that is a wstring followed by an int. | 26 // Generic message class that is a string16 followed by an int. |
| 25 IPC_MESSAGE_CONTROL2(MsgClassSI, std::wstring, int) | 27 IPC_MESSAGE_CONTROL2(MsgClassSI, base::string16, int) |
| 26 | 28 |
| 27 // Message to create a mutex in the IPC server, using the received name. | 29 // Message to create a mutex in the IPC server, using the received name. |
| 28 IPC_MESSAGE_CONTROL2(MsgDoMutex, std::wstring, int) | 30 IPC_MESSAGE_CONTROL2(MsgDoMutex, base::string16, int) |
| 29 | 31 |
| 30 // Used to generate an ID for a message that should not exist. | 32 // Used to generate an ID for a message that should not exist. |
| 31 IPC_MESSAGE_CONTROL0(MsgUnhandled) | 33 IPC_MESSAGE_CONTROL0(MsgUnhandled) |
| 32 | 34 |
| 33 // ----------------------------------------------------------------------------- | 35 // ----------------------------------------------------------------------------- |
| 34 | 36 |
| 35 namespace { | 37 namespace { |
| 36 | 38 |
| 37 TEST(IPCMessageIntegrity, ReadBeyondBufferStr) { | 39 TEST(IPCMessageIntegrity, ReadBeyondBufferStr) { |
| 38 //This was BUG 984408. | 40 // This was BUG 984408. |
| 39 uint32 v1 = kuint32max - 1; | 41 uint32 v1 = kuint32max - 1; |
| 40 int v2 = 666; | 42 int v2 = 666; |
| 41 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); | 43 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); |
| 42 EXPECT_TRUE(m.WriteInt(v1)); | 44 EXPECT_TRUE(m.WriteInt(v1)); |
| 43 EXPECT_TRUE(m.WriteInt(v2)); | 45 EXPECT_TRUE(m.WriteInt(v2)); |
| 44 | 46 |
| 45 PickleIterator iter(m); | 47 PickleIterator iter(m); |
| 46 std::string vs; | 48 std::string vs; |
| 47 EXPECT_FALSE(iter.ReadString(&vs)); | 49 EXPECT_FALSE(iter.ReadString(&vs)); |
| 48 } | 50 } |
| 49 | 51 |
| 50 TEST(IPCMessageIntegrity, ReadBeyondBufferWStr) { | 52 TEST(IPCMessageIntegrity, ReadBeyondBufferStr16) { |
| 51 //This was BUG 984408. | 53 // This was BUG 984408. |
| 52 uint32 v1 = kuint32max - 1; | 54 uint32 v1 = kuint32max - 1; |
| 53 int v2 = 777; | 55 int v2 = 777; |
| 54 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); | 56 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); |
| 55 EXPECT_TRUE(m.WriteInt(v1)); | 57 EXPECT_TRUE(m.WriteInt(v1)); |
| 56 EXPECT_TRUE(m.WriteInt(v2)); | 58 EXPECT_TRUE(m.WriteInt(v2)); |
| 57 | 59 |
| 58 PickleIterator iter(m); | 60 PickleIterator iter(m); |
| 59 std::wstring vs; | 61 base::string16 vs; |
| 60 EXPECT_FALSE(iter.ReadWString(&vs)); | 62 EXPECT_FALSE(iter.ReadString16(&vs)); |
| 61 } | 63 } |
| 62 | 64 |
| 63 TEST(IPCMessageIntegrity, ReadBytesBadIterator) { | 65 TEST(IPCMessageIntegrity, ReadBytesBadIterator) { |
| 64 // This was BUG 1035467. | 66 // This was BUG 1035467. |
| 65 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); | 67 IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); |
| 66 EXPECT_TRUE(m.WriteInt(1)); | 68 EXPECT_TRUE(m.WriteInt(1)); |
| 67 EXPECT_TRUE(m.WriteInt(2)); | 69 EXPECT_TRUE(m.WriteInt(2)); |
| 68 | 70 |
| 69 PickleIterator iter(m); | 71 PickleIterator iter(m); |
| 70 const char* data = NULL; | 72 const char* data = NULL; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 IPC_END_MESSAGE_MAP() | 146 IPC_END_MESSAGE_MAP() |
| 145 if (pending_messages_) { | 147 if (pending_messages_) { |
| 146 // Probably a problem de-serializing the message. | 148 // Probably a problem de-serializing the message. |
| 147 ReplyMsgNotHandled(msg.type()); | 149 ReplyMsgNotHandled(msg.type()); |
| 148 } | 150 } |
| 149 } | 151 } |
| 150 return true; | 152 return true; |
| 151 } | 153 } |
| 152 | 154 |
| 153 private: | 155 private: |
| 154 void OnMsgClassISMessage(int value, const std::wstring& text) { | 156 void OnMsgClassISMessage(int value, const base::string16& text) { |
| 155 UseData(MsgClassIS::ID, value, text); | 157 UseData(MsgClassIS::ID, value, text); |
| 156 RoundtripAckReply(FUZZER_ROUTING_ID, MsgClassIS::ID, value); | 158 RoundtripAckReply(FUZZER_ROUTING_ID, MsgClassIS::ID, value); |
| 157 Cleanup(); | 159 Cleanup(); |
| 158 } | 160 } |
| 159 | 161 |
| 160 void OnMsgClassSIMessage(const std::wstring& text, int value) { | 162 void OnMsgClassSIMessage(const base::string16& text, int value) { |
| 161 UseData(MsgClassSI::ID, value, text); | 163 UseData(MsgClassSI::ID, value, text); |
| 162 RoundtripAckReply(FUZZER_ROUTING_ID, MsgClassSI::ID, value); | 164 RoundtripAckReply(FUZZER_ROUTING_ID, MsgClassSI::ID, value); |
| 163 Cleanup(); | 165 Cleanup(); |
| 164 } | 166 } |
| 165 | 167 |
| 166 bool RoundtripAckReply(int routing, uint32 type_id, int reply) { | 168 bool RoundtripAckReply(int routing, uint32 type_id, int reply) { |
| 167 IPC::Message* message = new IPC::Message(routing, type_id, | 169 IPC::Message* message = new IPC::Message(routing, type_id, |
| 168 IPC::Message::PRIORITY_NORMAL); | 170 IPC::Message::PRIORITY_NORMAL); |
| 169 message->WriteInt(reply + 1); | 171 message->WriteInt(reply + 1); |
| 170 message->WriteInt(reply); | 172 message->WriteInt(reply); |
| 171 return other_->Send(message); | 173 return other_->Send(message); |
| 172 } | 174 } |
| 173 | 175 |
| 174 void Cleanup() { | 176 void Cleanup() { |
| 175 --message_count_; | 177 --message_count_; |
| 176 --pending_messages_; | 178 --pending_messages_; |
| 177 if (0 == message_count_) | 179 if (0 == message_count_) |
| 178 base::MessageLoop::current()->Quit(); | 180 base::MessageLoop::current()->Quit(); |
| 179 } | 181 } |
| 180 | 182 |
| 181 void ReplyMsgNotHandled(uint32 type_id) { | 183 void ReplyMsgNotHandled(uint32 type_id) { |
| 182 RoundtripAckReply(FUZZER_ROUTING_ID, MsgUnhandled::ID, type_id); | 184 RoundtripAckReply(FUZZER_ROUTING_ID, MsgUnhandled::ID, type_id); |
| 183 Cleanup(); | 185 Cleanup(); |
| 184 } | 186 } |
| 185 | 187 |
| 186 void UseData(int caller, int value, const std::wstring& text) { | 188 void UseData(int caller, int value, const base::string16& text) { |
| 187 std::wostringstream wos; | 189 std::ostringstream os; |
| 188 wos << L"IPC fuzzer:" << caller << " [" << value << L" " << text << L"]\n"; | 190 os << "IPC fuzzer:" << caller << " [" << value << " " |
| 189 std::wstring output = wos.str(); | 191 << base::UTF16ToUTF8(text) << "]\n"; |
| 190 LOG(WARNING) << output.c_str(); | 192 std::string output = os.str(); |
| 191 }; | 193 LOG(WARNING) << output; |
| 194 } |
| 192 | 195 |
| 193 int message_count_; | 196 int message_count_; |
| 194 int pending_messages_; | 197 int pending_messages_; |
| 195 }; | 198 }; |
| 196 | 199 |
| 197 class FuzzerClientListener : public SimpleListener { | 200 class FuzzerClientListener : public SimpleListener { |
| 198 public: | 201 public: |
| 199 FuzzerClientListener() : last_msg_(NULL) { | 202 FuzzerClientListener() : last_msg_(NULL) { |
| 200 } | 203 } |
| 201 | 204 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 230 } | 233 } |
| 231 | 234 |
| 232 private: | 235 private: |
| 233 bool MsgHandlerInternal(uint32 type_id) { | 236 bool MsgHandlerInternal(uint32 type_id) { |
| 234 base::MessageLoop::current()->Run(); | 237 base::MessageLoop::current()->Run(); |
| 235 if (NULL == last_msg_) | 238 if (NULL == last_msg_) |
| 236 return false; | 239 return false; |
| 237 if (FUZZER_ROUTING_ID != last_msg_->routing_id()) | 240 if (FUZZER_ROUTING_ID != last_msg_->routing_id()) |
| 238 return false; | 241 return false; |
| 239 return (type_id == last_msg_->type()); | 242 return (type_id == last_msg_->type()); |
| 240 }; | 243 } |
| 241 | 244 |
| 242 IPC::Message* last_msg_; | 245 IPC::Message* last_msg_; |
| 243 }; | 246 }; |
| 244 | 247 |
| 245 // Runs the fuzzing server child mode. Returns when the preset number of | 248 // Runs the fuzzing server child mode. Returns when the preset number of |
| 246 // messages have been received. | 249 // messages have been received. |
| 247 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(FuzzServerClient) { | 250 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(FuzzServerClient) { |
| 248 base::MessageLoopForIO main_message_loop; | 251 base::MessageLoopForIO main_message_loop; |
| 249 FuzzerServerListener listener; | 252 FuzzerServerListener listener; |
| 250 scoped_ptr<IPC::Channel> channel(IPC::Channel::CreateClient( | 253 scoped_ptr<IPC::Channel> channel(IPC::Channel::CreateClient( |
| (...skipping 14 matching lines...) Expand all Loading... |
| 265 Init("FuzzServerClient"); | 268 Init("FuzzServerClient"); |
| 266 | 269 |
| 267 FuzzerClientListener listener; | 270 FuzzerClientListener listener; |
| 268 CreateChannel(&listener); | 271 CreateChannel(&listener); |
| 269 listener.Init(channel()); | 272 listener.Init(channel()); |
| 270 ASSERT_TRUE(ConnectChannel()); | 273 ASSERT_TRUE(ConnectChannel()); |
| 271 ASSERT_TRUE(StartClient()); | 274 ASSERT_TRUE(StartClient()); |
| 272 | 275 |
| 273 IPC::Message* msg = NULL; | 276 IPC::Message* msg = NULL; |
| 274 int value = 43; | 277 int value = 43; |
| 275 msg = new MsgClassIS(value, L"expect 43"); | 278 msg = new MsgClassIS(value, base::ASCIIToUTF16("expect 43")); |
| 276 sender()->Send(msg); | 279 sender()->Send(msg); |
| 277 EXPECT_TRUE(listener.ExpectMessage(value, MsgClassIS::ID)); | 280 EXPECT_TRUE(listener.ExpectMessage(value, MsgClassIS::ID)); |
| 278 | 281 |
| 279 msg = new MsgClassSI(L"expect 44", ++value); | 282 msg = new MsgClassSI(base::ASCIIToUTF16("expect 44"), ++value); |
| 280 sender()->Send(msg); | 283 sender()->Send(msg); |
| 281 EXPECT_TRUE(listener.ExpectMessage(value, MsgClassSI::ID)); | 284 EXPECT_TRUE(listener.ExpectMessage(value, MsgClassSI::ID)); |
| 282 | 285 |
| 283 EXPECT_TRUE(WaitForClientShutdown()); | 286 EXPECT_TRUE(WaitForClientShutdown()); |
| 284 DestroyChannel(); | 287 DestroyChannel(); |
| 285 } | 288 } |
| 286 | 289 |
| 287 // This test uses a payload that is smaller than expected. This generates an | 290 // This test uses a payload that is smaller than expected. This generates an |
| 288 // error while unpacking the IPC buffer which in debug trigger an assertion and | 291 // error while unpacking the IPC buffer which in debug trigger an assertion and |
| 289 // in release is ignored (!). Right after we generate another valid IPC to make | 292 // in release is ignored (!). Right after we generate another valid IPC to make |
| 290 // sure framing is working properly. | 293 // sure framing is working properly. |
| 291 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) | 294 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) |
| 292 TEST_F(IPCFuzzingTest, MsgBadPayloadShort) { | 295 TEST_F(IPCFuzzingTest, MsgBadPayloadShort) { |
| 293 Init("FuzzServerClient"); | 296 Init("FuzzServerClient"); |
| 294 | 297 |
| 295 FuzzerClientListener listener; | 298 FuzzerClientListener listener; |
| 296 CreateChannel(&listener); | 299 CreateChannel(&listener); |
| 297 listener.Init(channel()); | 300 listener.Init(channel()); |
| 298 ASSERT_TRUE(ConnectChannel()); | 301 ASSERT_TRUE(ConnectChannel()); |
| 299 ASSERT_TRUE(StartClient()); | 302 ASSERT_TRUE(StartClient()); |
| 300 | 303 |
| 301 IPC::Message* msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassIS::ID, | 304 IPC::Message* msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassIS::ID, |
| 302 IPC::Message::PRIORITY_NORMAL); | 305 IPC::Message::PRIORITY_NORMAL); |
| 303 msg->WriteInt(666); | 306 msg->WriteInt(666); |
| 304 sender()->Send(msg); | 307 sender()->Send(msg); |
| 305 EXPECT_TRUE(listener.ExpectMsgNotHandled(MsgClassIS::ID)); | 308 EXPECT_TRUE(listener.ExpectMsgNotHandled(MsgClassIS::ID)); |
| 306 | 309 |
| 307 msg = new MsgClassSI(L"expect one", 1); | 310 msg = new MsgClassSI(base::ASCIIToUTF16("expect one"), 1); |
| 308 sender()->Send(msg); | 311 sender()->Send(msg); |
| 309 EXPECT_TRUE(listener.ExpectMessage(1, MsgClassSI::ID)); | 312 EXPECT_TRUE(listener.ExpectMessage(1, MsgClassSI::ID)); |
| 310 | 313 |
| 311 EXPECT_TRUE(WaitForClientShutdown()); | 314 EXPECT_TRUE(WaitForClientShutdown()); |
| 312 DestroyChannel(); | 315 DestroyChannel(); |
| 313 } | 316 } |
| 314 #endif | 317 #endif |
| 315 | 318 |
| 316 // This test uses a payload that has too many arguments, but so the payload size | 319 // This test uses a payload that has too many arguments, but so the payload size |
| 317 // is big enough so the unpacking routine does not generate an error as in the | 320 // is big enough so the unpacking routine does not generate an error as in the |
| 318 // case of MsgBadPayloadShort test. This test does not pinpoint a flaw (per se) | 321 // case of MsgBadPayloadShort test. This test does not pinpoint a flaw (per se) |
| 319 // as by design we don't carry type information on the IPC message. | 322 // as by design we don't carry type information on the IPC message. |
| 320 TEST_F(IPCFuzzingTest, MsgBadPayloadArgs) { | 323 TEST_F(IPCFuzzingTest, MsgBadPayloadArgs) { |
| 321 Init("FuzzServerClient"); | 324 Init("FuzzServerClient"); |
| 322 | 325 |
| 323 FuzzerClientListener listener; | 326 FuzzerClientListener listener; |
| 324 CreateChannel(&listener); | 327 CreateChannel(&listener); |
| 325 listener.Init(channel()); | 328 listener.Init(channel()); |
| 326 ASSERT_TRUE(ConnectChannel()); | 329 ASSERT_TRUE(ConnectChannel()); |
| 327 ASSERT_TRUE(StartClient()); | 330 ASSERT_TRUE(StartClient()); |
| 328 | 331 |
| 329 IPC::Message* msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassSI::ID, | 332 IPC::Message* msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassSI::ID, |
| 330 IPC::Message::PRIORITY_NORMAL); | 333 IPC::Message::PRIORITY_NORMAL); |
| 331 msg->WriteWString(L"d"); | 334 msg->WriteString16(base::ASCIIToUTF16("d")); |
| 332 msg->WriteInt(0); | 335 msg->WriteInt(0); |
| 333 msg->WriteInt(0x65); // Extra argument. | 336 msg->WriteInt(0x65); // Extra argument. |
| 334 | 337 |
| 335 sender()->Send(msg); | 338 sender()->Send(msg); |
| 336 EXPECT_TRUE(listener.ExpectMessage(0, MsgClassSI::ID)); | 339 EXPECT_TRUE(listener.ExpectMessage(0, MsgClassSI::ID)); |
| 337 | 340 |
| 338 // Now send a well formed message to make sure the receiver wasn't | 341 // Now send a well formed message to make sure the receiver wasn't |
| 339 // thrown out of sync by the extra argument. | 342 // thrown out of sync by the extra argument. |
| 340 msg = new MsgClassIS(3, L"expect three"); | 343 msg = new MsgClassIS(3, base::ASCIIToUTF16("expect three")); |
| 341 sender()->Send(msg); | 344 sender()->Send(msg); |
| 342 EXPECT_TRUE(listener.ExpectMessage(3, MsgClassIS::ID)); | 345 EXPECT_TRUE(listener.ExpectMessage(3, MsgClassIS::ID)); |
| 343 | 346 |
| 344 EXPECT_TRUE(WaitForClientShutdown()); | 347 EXPECT_TRUE(WaitForClientShutdown()); |
| 345 DestroyChannel(); | 348 DestroyChannel(); |
| 346 } | 349 } |
| 347 | 350 |
| 348 } // namespace | 351 } // namespace |
| OLD | NEW |