Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: google_apis/gcm/engine/connection_handler_impl_unittest.cc

Issue 643133003: [GCM] Fix crash when size packet splits two socket reads (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address comments Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « google_apis/gcm/engine/connection_handler_impl.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "google_apis/gcm/engine/connection_handler_impl.h" 5 #include "google_apis/gcm/engine/connection_handler_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/run_loop.h" 9 #include "base/run_loop.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
(...skipping 23 matching lines...) Expand all
34 const char kDataMsgFrom2[] = "data_from2"; 34 const char kDataMsgFrom2[] = "data_from2";
35 const char kDataMsgCategory2[] = "data_category2"; 35 const char kDataMsgCategory2[] = "data_category2";
36 const char kDataMsgFromLong[] = 36 const char kDataMsgFromLong[] =
37 "this is a long from that will result in a message > 128 bytes"; 37 "this is a long from that will result in a message > 128 bytes";
38 const char kDataMsgCategoryLong[] = 38 const char kDataMsgCategoryLong[] =
39 "this is a long category that will result in a message > 128 bytes"; 39 "this is a long category that will result in a message > 128 bytes";
40 const char kDataMsgFromLong2[] = 40 const char kDataMsgFromLong2[] =
41 "this is a second long from that will result in a message > 128 bytes"; 41 "this is a second long from that will result in a message > 128 bytes";
42 const char kDataMsgCategoryLong2[] = 42 const char kDataMsgCategoryLong2[] =
43 "this is a second long category that will result in a message > 128 bytes"; 43 "this is a second long category that will result in a message > 128 bytes";
44 const uint8 kInvalidTag = 100; // An invalid tag.
44 45
45 // ---- Helpers for building messages. ---- 46 // ---- Helpers for building messages. ----
46 47
47 // Encode a protobuf packet with protobuf type |tag| and serialized protobuf 48 // Encode a protobuf packet with protobuf type |tag| and serialized protobuf
48 // bytes |proto| into the MCS message form (tag + varint size + bytes). 49 // bytes |proto| into the MCS message form (tag + varint size + bytes).
49 std::string EncodePacket(uint8 tag, const std::string& proto) { 50 std::string EncodePacket(uint8 tag, const std::string& proto) {
50 std::string result; 51 std::string result;
51 google::protobuf::io::StringOutputStream string_output_stream(&result); 52 google::protobuf::io::StringOutputStream string_output_stream(&result);
52 { 53 {
53 google::protobuf::io::CodedOutputStream coded_output_stream( 54 google::protobuf::io::CodedOutputStream coded_output_stream(
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 130
130 private: 131 private:
131 void ReadContinuation(ScopedMessage* dst_proto, ScopedMessage new_proto); 132 void ReadContinuation(ScopedMessage* dst_proto, ScopedMessage new_proto);
132 void WriteContinuation(); 133 void WriteContinuation();
133 void ConnectionContinuation(int error); 134 void ConnectionContinuation(int error);
134 135
135 // SocketStreams and their data provider. 136 // SocketStreams and their data provider.
136 ReadList mock_reads_; 137 ReadList mock_reads_;
137 WriteList mock_writes_; 138 WriteList mock_writes_;
138 scoped_ptr<net::DelayedSocketData> data_provider_; 139 scoped_ptr<net::DelayedSocketData> data_provider_;
139 scoped_ptr<SocketInputStream> socket_input_stream_;
140 scoped_ptr<SocketOutputStream> socket_output_stream_;
141 140
142 // The connection handler being tested. 141 // The connection handler being tested.
143 scoped_ptr<ConnectionHandlerImpl> connection_handler_; 142 scoped_ptr<ConnectionHandlerImpl> connection_handler_;
144 143
145 // The last connection error received. 144 // The last connection error received.
146 int last_error_; 145 int last_error_;
147 146
148 // net:: components. 147 // net:: components.
149 scoped_ptr<net::StreamSocket> socket_; 148 scoped_ptr<net::StreamSocket> socket_;
150 net::MockClientSocketFactory socket_factory_; 149 net::MockClientSocketFactory socket_factory_;
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 data_message.set_from(kDataMsgFrom); 666 data_message.set_from(kDataMsgFrom);
668 data_message.set_category(kDataMsgCategory); 667 data_message.set_category(kDataMsgCategory);
669 connection_handler()->SendMessage(data_message); 668 connection_handler()->SendMessage(data_message);
670 EXPECT_FALSE(connection_handler()->CanSendMessage()); 669 EXPECT_FALSE(connection_handler()->CanSendMessage());
671 WaitForMessage(); // The message send. Should result in an error 670 WaitForMessage(); // The message send. Should result in an error
672 EXPECT_FALSE(connection_handler()->CanSendMessage()); 671 EXPECT_FALSE(connection_handler()->CanSendMessage());
673 EXPECT_EQ(net::ERR_CONNECTION_CLOSED, last_error()); 672 EXPECT_EQ(net::ERR_CONNECTION_CLOSED, last_error());
674 } 673 }
675 674
676 // Receive a message whose size field was corrupted and is larger than the 675 // Receive a message whose size field was corrupted and is larger than the
677 // socket's buffer. Should fail gracefully. 676 // socket's buffer. Should fail gracefully with a size error.
678 TEST_F(GCMConnectionHandlerImplTest, CorruptedSize) { 677 TEST_F(GCMConnectionHandlerImplTest, OutOfBuffer) {
679 std::string handshake_request = EncodeHandshakeRequest(); 678 std::string handshake_request = EncodeHandshakeRequest();
680 WriteList write_list(1, net::MockWrite(net::ASYNC, 679 WriteList write_list(1, net::MockWrite(net::ASYNC,
681 handshake_request.c_str(), 680 handshake_request.c_str(),
682 handshake_request.size())); 681 handshake_request.size()));
683 std::string handshake_response = EncodeHandshakeResponse(); 682 std::string handshake_response = EncodeHandshakeResponse();
684 683
685 // Fill a string with 9000 character zero. 684 // Fill a string with 9000 character zero.
686 std::string data_message_proto(9000, '0'); 685 std::string data_message_proto(9000, '0');
687 std::string data_message_pkt = 686 std::string data_message_pkt =
688 EncodePacket(kDataMessageStanzaTag, data_message_proto); 687 EncodePacket(kDataMessageStanzaTag, data_message_proto);
689 ReadList read_list; 688 ReadList read_list;
690 read_list.push_back(net::MockRead(net::ASYNC, 689 read_list.push_back(net::MockRead(net::ASYNC,
691 handshake_response.c_str(), 690 handshake_response.c_str(),
692 handshake_response.size())); 691 handshake_response.size()));
693 read_list.push_back(net::MockRead(net::ASYNC, 692 read_list.push_back(net::MockRead(net::ASYNC,
694 data_message_pkt.c_str(), 693 data_message_pkt.c_str(),
695 data_message_pkt.size())); 694 data_message_pkt.size()));
696 BuildSocket(read_list, write_list); 695 BuildSocket(read_list, write_list);
697 696
698 ScopedMessage received_message; 697 ScopedMessage received_message;
699 Connect(&received_message); 698 Connect(&received_message);
700 WaitForMessage(); // The login send. 699 WaitForMessage(); // The login send.
701 WaitForMessage(); // The login response. 700 WaitForMessage(); // The login response.
702 received_message.reset(); 701 received_message.reset();
703 WaitForMessage(); // The data message. 702 WaitForMessage(); // The data message.
704 EXPECT_FALSE(received_message.get()); 703 EXPECT_FALSE(received_message.get());
705 EXPECT_EQ(net::ERR_FILE_TOO_BIG, last_error()); 704 EXPECT_EQ(net::ERR_FILE_TOO_BIG, last_error());
706 } 705 }
707 706
707 // Receive a message whose size field was corrupted and takes more than two
708 // bytes to encode. Should fail gracefully with a size error.
709 TEST_F(GCMConnectionHandlerImplTest, InvalidSizePacket) {
710 std::string handshake_request = EncodeHandshakeRequest();
711 WriteList write_list(1, net::MockWrite(net::ASYNC,
712 handshake_request.c_str(),
713 handshake_request.size()));
714 std::string handshake_response = EncodeHandshakeResponse();
715
716 // Fill a string with 20000 character zero (which uses more than 2 bytes to
717 // encode the size packet).
718 std::string data_message_proto(20000, '0');
719 std::string data_message_pkt =
720 EncodePacket(kDataMessageStanzaTag, data_message_proto);
721 ReadList read_list;
722 read_list.push_back(net::MockRead(net::ASYNC,
723 handshake_response.c_str(),
724 handshake_response.size()));
725 read_list.push_back(net::MockRead(net::ASYNC,
726 data_message_pkt.c_str(),
727 data_message_pkt.size()));
728 BuildSocket(read_list, write_list);
729
730 ScopedMessage received_message;
731 Connect(&received_message);
732 WaitForMessage(); // The login send.
733 WaitForMessage(); // The login response.
734 received_message.reset();
735 WaitForMessage(); // The data message.
736 EXPECT_FALSE(received_message.get());
737 EXPECT_EQ(net::ERR_FILE_TOO_BIG, last_error());
738 }
739
740 // Make sure a message with an invalid tag is handled gracefully and resets
741 // the connection with an invalid argument error.
742 TEST_F(GCMConnectionHandlerImplTest, InvalidTag) {
743 std::string handshake_request = EncodeHandshakeRequest();
744 WriteList write_list(1, net::MockWrite(net::ASYNC,
745 handshake_request.c_str(),
746 handshake_request.size()));
747 std::string handshake_response = EncodeHandshakeResponse();
748
749 std::string invalid_message = "0";
750 std::string invalid_message_pkt =
751 EncodePacket(kInvalidTag, invalid_message);
752 ReadList read_list;
753 read_list.push_back(net::MockRead(net::ASYNC,
754 handshake_response.c_str(),
755 handshake_response.size()));
756 read_list.push_back(net::MockRead(net::ASYNC,
757 invalid_message_pkt.c_str(),
758 invalid_message_pkt.size()));
759 BuildSocket(read_list, write_list);
760
761 ScopedMessage received_message;
762 Connect(&received_message);
763 WaitForMessage(); // The login send.
764 WaitForMessage(); // The login response.
765 received_message.reset();
766 WaitForMessage(); // The invalid message.
767 EXPECT_FALSE(received_message.get());
768 EXPECT_EQ(net::ERR_INVALID_ARGUMENT, last_error());
769 }
770
771 // Receive a message where the size field spans two socket reads.
772 TEST_F(GCMConnectionHandlerImplTest, RecvMsgSplitSize) {
773 std::string handshake_request = EncodeHandshakeRequest();
774 WriteList write_list(1, net::MockWrite(net::ASYNC,
775 handshake_request.c_str(),
776 handshake_request.size()));
777 std::string handshake_response = EncodeHandshakeResponse();
778
779 std::string data_message_proto =
780 BuildDataMessage(kDataMsgFromLong, kDataMsgCategoryLong);
781 std::string data_message_pkt =
782 EncodePacket(kDataMessageStanzaTag, data_message_proto);
783 DCHECK_GT(data_message_pkt.size(), 128U);
784 ReadList read_list;
785 read_list.push_back(net::MockRead(net::ASYNC,
786 handshake_response.c_str(),
787 handshake_response.size()));
788 // The first two bytes are the tag byte and the first byte of the size packet.
789 read_list.push_back(net::MockRead(net::ASYNC,
790 data_message_pkt.c_str(),
791 2));
792 // Start from the second byte of the size packet.
793 read_list.push_back(net::MockRead(net::ASYNC,
794 data_message_pkt.c_str() + 2,
795 data_message_pkt.size() - 2));
796 BuildSocket(read_list, write_list);
797
798 ScopedMessage received_message;
799 Connect(&received_message);
800 WaitForMessage(); // The login send.
801 WaitForMessage(); // The login response.
802 WaitForMessage(); // The data message.
803 ASSERT_TRUE(received_message.get());
804 EXPECT_EQ(data_message_proto, received_message->SerializeAsString());
805 EXPECT_EQ(net::OK, last_error());
806 }
807
708 } // namespace 808 } // namespace
709 } // namespace gcm 809 } // namespace gcm
OLDNEW
« no previous file with comments | « google_apis/gcm/engine/connection_handler_impl.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698