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

Unified Diff: google_apis/gcm/engine/connection_handler_impl.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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | google_apis/gcm/engine/connection_handler_impl_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: google_apis/gcm/engine/connection_handler_impl.cc
diff --git a/google_apis/gcm/engine/connection_handler_impl.cc b/google_apis/gcm/engine/connection_handler_impl.cc
index 751b1cd1daa52fabcbcc583cdcc6d61b04e37861..ccb6362936bdd71ff14b72b1e475d9b3831df9dc 100644
--- a/google_apis/gcm/engine/connection_handler_impl.cc
+++ b/google_apis/gcm/engine/connection_handler_impl.cc
@@ -22,7 +22,13 @@ namespace {
const int kVersionPacketLen = 1;
// # of bytes a tag packet consumes.
const int kTagPacketLen = 1;
-// Max # of bytes a length packet consumes.
+// Max # of bytes a length packet consumes. A Varint32 can consume up to 5 bytes
+// (the MSB in each byte is reserved for denoting whether more bytes follow).
+// But, the protocol only allows for 4KiB payloads, and the socket stream buffer
+// is only of size 8KiB. As such we should never need more than 2 bytes (max
+// value of 16KiB). Anything higher than that will result in an error, either
+// because the socket stream buffer overflowed or too many bytes were required
+// in the size packet.
const int kSizePacketLenMin = 1;
const int kSizePacketLenMax = 2;
@@ -321,7 +327,7 @@ void ConnectionHandlerImpl::OnGotMessageSize() {
}
bool need_another_byte = false;
- int prev_byte_count = input_stream_->ByteCount();
+ int prev_byte_count = input_stream_->UnreadByteCount();
{
CodedInputStream coded_input_stream(input_stream_.get());
if (!coded_input_stream.ReadVarint32(&message_size_))
@@ -332,12 +338,12 @@ void ConnectionHandlerImpl::OnGotMessageSize() {
DVLOG(1) << "Expecting another message size byte.";
if (prev_byte_count >= kSizePacketLenMax) {
// Already had enough bytes, something else went wrong.
- LOG(ERROR) << "Failed to process message size.";
- read_callback_.Run(scoped_ptr<google::protobuf::MessageLite>());
+ LOG(ERROR) << "Failed to process message size, too many bytes needed.";
+ connection_callback_.Run(net::ERR_FILE_TOO_BIG);
return;
}
// Back up by the amount read (should always be 1 byte).
- int bytes_read = prev_byte_count - input_stream_->ByteCount();
+ int bytes_read = prev_byte_count - input_stream_->UnreadByteCount();
DCHECK_EQ(bytes_read, 1);
input_stream_->BackUp(bytes_read);
WaitForData(MCS_FULL_SIZE);
@@ -367,8 +373,7 @@ void ConnectionHandlerImpl::OnGotMessageBytes() {
return;
}
- if (!protobuf.get() ||
- input_stream_->GetState() != SocketInputStream::READY) {
+ if (input_stream_->GetState() != SocketInputStream::READY) {
LOG(ERROR) << "Failed to extract protobuf bytes of type "
<< static_cast<unsigned int>(message_tag_);
// Reset the connection.
@@ -376,6 +381,13 @@ void ConnectionHandlerImpl::OnGotMessageBytes() {
return;
}
+ if (!protobuf.get()) {
+ LOG(ERROR) << "Received message of invalid type "
+ << static_cast<unsigned int>(message_tag_);
+ connection_callback_.Run(net::ERR_INVALID_ARGUMENT);
+ return;
+ }
+
{
CodedInputStream coded_input_stream(input_stream_.get());
if (!protobuf->ParsePartialFromCodedStream(&coded_input_stream)) {
« no previous file with comments | « no previous file | google_apis/gcm/engine/connection_handler_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698