Chromium Code Reviews| Index: net/socket/fuzzed_socket.cc |
| diff --git a/net/socket/fuzzed_socket.cc b/net/socket/fuzzed_socket.cc |
| index c00faafd3f655729cbdbdcd10fabceed1cdd8317..3a722a739dd5f9f4533c815b0ecf06d8ad13a52e 100644 |
| --- a/net/socket/fuzzed_socket.cc |
| +++ b/net/socket/fuzzed_socket.cc |
| @@ -8,13 +8,21 @@ |
| #include "base/location.h" |
| #include "base/logging.h" |
| #include "base/thread_task_runner_handle.h" |
| +#include "net/base/fuzzed_data_provider.h" |
| #include "net/base/io_buffer.h" |
| namespace net { |
| namespace { |
| -// Subset of the socket errors that can be returned by normal socket reads / |
| +// Some of the socket errors that can be returned by normal socket connection |
| +// attempts. |
| +const Error kConnectErrors[] = { |
| + ERR_CONNECTION_RESET, ERR_CONNECTION_CLOSED, ERR_FAILED, |
| + ERR_CONNECTION_TIMED_OUT, ERR_ACCESS_DENIED, ERR_CONNECTION_REFUSED, |
| + ERR_ADDRESS_UNREACHABLE}; |
| + |
| +// Some of the socket errors that can be returned by normal socket reads / |
| // writes. The first one is returned when no more input data remains, so it's |
| // one of the most common ones. |
| const Error kReadWriteErrors[] = {ERR_CONNECTION_CLOSED, ERR_FAILED, |
| @@ -22,11 +30,11 @@ const Error kReadWriteErrors[] = {ERR_CONNECTION_CLOSED, ERR_FAILED, |
| } // namespace |
| -FuzzedSocket::FuzzedSocket(const uint8_t* data, |
| - size_t data_size, |
| - const BoundNetLog& bound_net_log) |
| - : data_(reinterpret_cast<const char*>(data), data_size), |
| - bound_net_log_(bound_net_log), |
| +FuzzedSocket::FuzzedSocket(FuzzedDataProvider* data_provider, |
| + net::NetLog* net_log) |
| + : data_provider_(data_provider), |
| + bound_net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)), |
| + remote_address_(IPEndPoint(IPAddress(127, 0, 0, 1), 80)), |
|
eroman
2016/04/28 01:32:36
I thought you were changing this to IPAddress::IPv
mmenke
2016/04/28 16:01:38
Done. I did it earlier, but I reverted a bunch of
|
| weak_factory_(this) {} |
| FuzzedSocket::~FuzzedSocket() {} |
| @@ -34,6 +42,7 @@ FuzzedSocket::~FuzzedSocket() {} |
| int FuzzedSocket::Read(IOBuffer* buf, |
| int buf_len, |
| const CompletionCallback& callback) { |
| + DCHECK(!connect_pending_); |
| DCHECK(!read_pending_); |
| bool sync; |
| @@ -44,24 +53,22 @@ int FuzzedSocket::Read(IOBuffer* buf, |
| result = net_error_; |
| sync = !error_pending_; |
| } else { |
| - // Otherwise, use |data_|. |
| - uint8_t random_val = ConsumeUint8FromData(); |
| - sync = !!(random_val & 0x01); |
| - result = random_val >> 1; |
| + // Otherwise, use |data_provider_|. |
| + sync = data_provider_->ConsumeBool(); |
| + // This allows for more consistent behavior across mutations of the fuzzed |
| + // data than ConsumeValueInRange(0,255). |
| + result = data_provider_->ConsumeBits(8); |
| if (result > buf_len) |
| result = buf_len; |
| - // Can't read more data than is available in |data_|. |
| - if (static_cast<size_t>(result) > data_.length()) |
| - result = data_.length(); |
| + |
| + if (result > 0) |
| + result = data_provider_->ConsumeBytes(buf->data(), result); |
| if (result == 0) { |
| net_error_ = ConsumeReadWriteErrorFromData(); |
| result = net_error_; |
| if (!sync) |
| error_pending_ = true; |
| - } else { |
| - memcpy(buf->data(), data_.data(), result); |
| - data_ = data_.substr(result); |
| } |
| } |
| @@ -86,6 +93,7 @@ int FuzzedSocket::Read(IOBuffer* buf, |
| int FuzzedSocket::Write(IOBuffer* buf, |
| int buf_len, |
| const CompletionCallback& callback) { |
| + DCHECK(!connect_pending_); |
| DCHECK(!write_pending_); |
| bool sync; |
| @@ -97,9 +105,10 @@ int FuzzedSocket::Write(IOBuffer* buf, |
| sync = !error_pending_; |
| } else { |
| // Otherwise, use |data_|. |
| - uint8_t random_val = ConsumeUint8FromData(); |
| - sync = !!(random_val & 0x01); |
| - result = random_val >> 1; |
| + sync = data_provider_->ConsumeBool(); |
| + // This allows for more consistent behavior across mutations of the fuzzed |
| + // data than ConsumeValueInRange(0,255). |
| + result = data_provider_->ConsumeBits(8); |
| if (result > buf_len) |
| result = buf_len; |
| if (result == 0) { |
| @@ -134,19 +143,43 @@ int FuzzedSocket::SetSendBufferSize(int32_t size) { |
| int FuzzedSocket::Connect(const CompletionCallback& callback) { |
| // Sockets can normally be reused, but don't support it here. |
| DCHECK_NE(net_error_, OK); |
| + DCHECK(!connect_pending_); |
| DCHECK(!read_pending_); |
| DCHECK(!write_pending_); |
| DCHECK(!error_pending_); |
| DCHECK(!total_bytes_read_); |
| DCHECK(!total_bytes_written_); |
| - net_error_ = OK; |
| - return OK; |
| + bool sync = true; |
| + Error result = OK; |
| + if (fuzz_connect_result_) { |
| + // Decide if sync or async. Use async, if no data is left. |
| + sync = data_provider_->ConsumeBool(); |
| + // Decide if the connect succeeds or not, and if so, pick an error code. |
| + if (data_provider_->ConsumeBool()) { |
| + result = kConnectErrors[data_provider_->ConsumeValueInRange( |
| + 0, arraysize(kConnectErrors) - 1)]; |
| + } |
| + } |
| + |
| + if (sync) { |
| + net_error_ = result; |
| + return result; |
| + } |
| + |
| + connect_pending_ = true; |
| + if (result != OK) |
| + error_pending_ = true; |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, base::Bind(&FuzzedSocket::OnConnectComplete, |
| + weak_factory_.GetWeakPtr(), callback, result)); |
| + return ERR_IO_PENDING; |
| } |
| void FuzzedSocket::Disconnect() { |
| net_error_ = ERR_CONNECTION_CLOSED; |
| weak_factory_.InvalidateWeakPtrs(); |
| + connect_pending_ = false; |
| read_pending_ = false; |
| write_pending_ = false; |
| error_pending_ = false; |
| @@ -212,17 +245,9 @@ int64_t FuzzedSocket::GetTotalReceivedBytes() const { |
| return total_bytes_read_; |
| } |
| -uint8_t FuzzedSocket::ConsumeUint8FromData() { |
| - size_t length = data_.length(); |
| - if (!length) |
| - return 0; |
| - uint8_t out = data_[length - 1]; |
| - data_ = data_.substr(0, length - 1); |
| - return out; |
| -} |
| - |
| Error FuzzedSocket::ConsumeReadWriteErrorFromData() { |
| - return kReadWriteErrors[ConsumeUint8FromData() % arraysize(kReadWriteErrors)]; |
| + return kReadWriteErrors[data_provider_->ConsumeValueInRange( |
| + 0, arraysize(kReadWriteErrors) - 1)]; |
| } |
| void FuzzedSocket::OnReadComplete(const CompletionCallback& callback, |
| @@ -249,4 +274,13 @@ void FuzzedSocket::OnWriteComplete(const CompletionCallback& callback, |
| callback.Run(result); |
| } |
| +void FuzzedSocket::OnConnectComplete(const CompletionCallback& callback, |
| + int result) { |
| + CHECK(connect_pending_); |
| + connect_pending_ = false; |
| + if (result < 0) |
| + error_pending_ = false; |
| + callback.Run(result); |
| +} |
| + |
| } // namespace net |