diff options
author | rockot <rockot@chromium.org> | 2016-03-06 13:48:54 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-06 21:49:54 +0000 |
commit | d3c78c0a5c043d2d7f714f767ca482f6eb3d18b5 (patch) | |
tree | 6c32ab78d0f4e20edcd6a97b50c2ed43bd2317c4 /extensions/browser/api | |
parent | 295ae19dead08c00aed4c7dd634b101551c14d10 (diff) | |
download | chromium_src-d3c78c0a5c043d2d7f714f767ca482f6eb3d18b5.zip chromium_src-d3c78c0a5c043d2d7f714f767ca482f6eb3d18b5.tar.gz chromium_src-d3c78c0a5c043d2d7f714f767ca482f6eb3d18b5.tar.bz2 |
[extensions] Fix several broken assumptions in TCP sockets API
This CL addresses three independent issues:
1. Undefined behavior when double-connecting a socket
(hitting an unexpected DCHECK)
2. Undefined behavior when reading from a disconnected socket.
(hitting an unexpected DCHECK)
3. Crash when reading from a socket with connection in progress.
BUG=582650
TEST=extensive fuzzing with extension attached to linked bug, no more crashes
Review URL: https://codereview.chromium.org/1767993002
Cr-Commit-Position: refs/heads/master@{#379498}
Diffstat (limited to 'extensions/browser/api')
-rw-r--r-- | extensions/browser/api/socket/tcp_socket.cc | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/extensions/browser/api/socket/tcp_socket.cc b/extensions/browser/api/socket/tcp_socket.cc index 2a8e718..a69ed02 100644 --- a/extensions/browser/api/socket/tcp_socket.cc +++ b/extensions/browser/api/socket/tcp_socket.cc @@ -86,6 +86,12 @@ void TCPSocket::Connect(const net::AddressList& address, callback.Run(net::ERR_CONNECTION_FAILED); return; } + + if (is_connected_) { + callback.Run(net::ERR_SOCKET_IS_CONNECTED); + return; + } + DCHECK(!server_socket_.get()); socket_mode_ = CLIENT; connect_callback_ = callback; @@ -130,7 +136,9 @@ void TCPSocket::Read(int count, const ReadCompletionCallback& callback) { return; } - if (!read_callback_.is_null()) { + if (!read_callback_.is_null() || !connect_callback_.is_null()) { + // It's illegal to read a net::TCPSocket while a pending Connect or Read is + // already in progress. callback.Run(net::ERR_IO_PENDING, NULL); return; } @@ -140,7 +148,7 @@ void TCPSocket::Read(int count, const ReadCompletionCallback& callback) { return; } - if (!socket_.get()) { + if (!socket_.get() || !is_connected_) { callback.Run(net::ERR_SOCKET_NOT_CONNECTED, NULL); return; } @@ -277,8 +285,12 @@ void TCPSocket::OnConnectComplete(int result) { DCHECK(!connect_callback_.is_null()); DCHECK(!is_connected_); is_connected_ = result == net::OK; - connect_callback_.Run(result); + + // The completion callback may re-enter TCPSocket, e.g. to Read(); therefore + // we reset |connect_callback_| before calling it. + CompletionCallback connect_callback = connect_callback_; connect_callback_.Reset(); + connect_callback.Run(result); } void TCPSocket::OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer, |