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

Side by Side Diff: net/socket/fuzzed_socket.cc

Issue 1917503002: URLRequest fuzzer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@fuzz
Patch Set: merge Created 4 years, 7 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
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "net/socket/fuzzed_socket.h" 5 #include "net/socket/fuzzed_socket.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/location.h" 8 #include "base/location.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/thread_task_runner_handle.h" 10 #include "base/thread_task_runner_handle.h"
11 #include "net/base/fuzzed_data_provider.h"
11 #include "net/base/io_buffer.h" 12 #include "net/base/io_buffer.h"
12 13
13 namespace net { 14 namespace net {
14 15
15 namespace { 16 namespace {
16 17
17 // Subset of the socket errors that can be returned by normal socket reads / 18 // Some of the socket errors that can be returned by normal socket connection
19 // attempts.
20 const Error kConnectErrors[] = {
21 ERR_CONNECTION_RESET, ERR_CONNECTION_CLOSED, ERR_FAILED,
22 ERR_CONNECTION_TIMED_OUT, ERR_ACCESS_DENIED, ERR_CONNECTION_REFUSED,
23 ERR_ADDRESS_UNREACHABLE};
24
25 // Some of the socket errors that can be returned by normal socket reads /
18 // writes. The first one is returned when no more input data remains, so it's 26 // writes. The first one is returned when no more input data remains, so it's
19 // one of the most common ones. 27 // one of the most common ones.
20 const Error kReadWriteErrors[] = {ERR_CONNECTION_CLOSED, ERR_FAILED, 28 const Error kReadWriteErrors[] = {ERR_CONNECTION_CLOSED, ERR_FAILED,
21 ERR_TIMED_OUT, ERR_CONNECTION_RESET}; 29 ERR_TIMED_OUT, ERR_CONNECTION_RESET};
22 30
23 } // namespace 31 } // namespace
24 32
25 FuzzedSocket::FuzzedSocket(const uint8_t* data, 33 FuzzedSocket::FuzzedSocket(FuzzedDataProvider* data_provider,
26 size_t data_size, 34 net::NetLog* net_log)
27 const BoundNetLog& bound_net_log) 35 : data_provider_(data_provider),
28 : data_(reinterpret_cast<const char*>(data), data_size), 36 bound_net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)),
29 bound_net_log_(bound_net_log), 37 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
30 weak_factory_(this) {} 38 weak_factory_(this) {}
31 39
32 FuzzedSocket::~FuzzedSocket() {} 40 FuzzedSocket::~FuzzedSocket() {}
33 41
34 int FuzzedSocket::Read(IOBuffer* buf, 42 int FuzzedSocket::Read(IOBuffer* buf,
35 int buf_len, 43 int buf_len,
36 const CompletionCallback& callback) { 44 const CompletionCallback& callback) {
45 DCHECK(!connect_pending_);
37 DCHECK(!read_pending_); 46 DCHECK(!read_pending_);
38 47
39 bool sync; 48 bool sync;
40 int result; 49 int result;
41 50
42 if (net_error_ != OK) { 51 if (net_error_ != OK) {
43 // If an error has already been generated, use it to determine what to do. 52 // If an error has already been generated, use it to determine what to do.
44 result = net_error_; 53 result = net_error_;
45 sync = !error_pending_; 54 sync = !error_pending_;
46 } else { 55 } else {
47 // Otherwise, use |data_|. 56 // Otherwise, use |data_provider_|.
48 uint8_t random_val = ConsumeUint8FromData(); 57 sync = data_provider_->ConsumeBool();
49 sync = !!(random_val & 0x01); 58 // This allows for more consistent behavior across mutations of the fuzzed
50 result = random_val >> 1; 59 // data than ConsumeValueInRange(0,255).
60 result = data_provider_->ConsumeBits(8);
51 if (result > buf_len) 61 if (result > buf_len)
52 result = buf_len; 62 result = buf_len;
53 // Can't read more data than is available in |data_|. 63
54 if (static_cast<size_t>(result) > data_.length()) 64 if (result > 0)
55 result = data_.length(); 65 result = data_provider_->ConsumeBytes(buf->data(), result);
56 66
57 if (result == 0) { 67 if (result == 0) {
58 net_error_ = ConsumeReadWriteErrorFromData(); 68 net_error_ = ConsumeReadWriteErrorFromData();
59 result = net_error_; 69 result = net_error_;
60 if (!sync) 70 if (!sync)
61 error_pending_ = true; 71 error_pending_ = true;
62 } else {
63 memcpy(buf->data(), data_.data(), result);
64 data_ = data_.substr(result);
65 } 72 }
66 } 73 }
67 74
68 // Graceful close of a socket returns OK, at least in theory. This doesn't 75 // Graceful close of a socket returns OK, at least in theory. This doesn't
69 // perfectly reflect real socket behavior, but close enough. 76 // perfectly reflect real socket behavior, but close enough.
70 if (result == ERR_CONNECTION_CLOSED) 77 if (result == ERR_CONNECTION_CLOSED)
71 result = 0; 78 result = 0;
72 79
73 if (sync) { 80 if (sync) {
74 if (result > 0) 81 if (result > 0)
75 total_bytes_read_ += result; 82 total_bytes_read_ += result;
76 return result; 83 return result;
77 } 84 }
78 85
79 read_pending_ = true; 86 read_pending_ = true;
80 base::ThreadTaskRunnerHandle::Get()->PostTask( 87 base::ThreadTaskRunnerHandle::Get()->PostTask(
81 FROM_HERE, base::Bind(&FuzzedSocket::OnReadComplete, 88 FROM_HERE, base::Bind(&FuzzedSocket::OnReadComplete,
82 weak_factory_.GetWeakPtr(), callback, result)); 89 weak_factory_.GetWeakPtr(), callback, result));
83 return ERR_IO_PENDING; 90 return ERR_IO_PENDING;
84 } 91 }
85 92
86 int FuzzedSocket::Write(IOBuffer* buf, 93 int FuzzedSocket::Write(IOBuffer* buf,
87 int buf_len, 94 int buf_len,
88 const CompletionCallback& callback) { 95 const CompletionCallback& callback) {
96 DCHECK(!connect_pending_);
89 DCHECK(!write_pending_); 97 DCHECK(!write_pending_);
90 98
91 bool sync; 99 bool sync;
92 int result; 100 int result;
93 101
94 if (net_error_ != OK) { 102 if (net_error_ != OK) {
95 // If an error has already been generated, use it to determine what to do. 103 // If an error has already been generated, use it to determine what to do.
96 result = net_error_; 104 result = net_error_;
97 sync = !error_pending_; 105 sync = !error_pending_;
98 } else { 106 } else {
99 // Otherwise, use |data_|. 107 // Otherwise, use |data_|.
100 uint8_t random_val = ConsumeUint8FromData(); 108 sync = data_provider_->ConsumeBool();
101 sync = !!(random_val & 0x01); 109 // This allows for more consistent behavior across mutations of the fuzzed
102 result = random_val >> 1; 110 // data than ConsumeValueInRange(0,255).
111 result = data_provider_->ConsumeBits(8);
103 if (result > buf_len) 112 if (result > buf_len)
104 result = buf_len; 113 result = buf_len;
105 if (result == 0) { 114 if (result == 0) {
106 net_error_ = ConsumeReadWriteErrorFromData(); 115 net_error_ = ConsumeReadWriteErrorFromData();
107 result = net_error_; 116 result = net_error_;
108 if (!sync) 117 if (!sync)
109 error_pending_ = true; 118 error_pending_ = true;
110 } 119 }
111 } 120 }
112 121
(...skipping 14 matching lines...) Expand all
127 return OK; 136 return OK;
128 } 137 }
129 138
130 int FuzzedSocket::SetSendBufferSize(int32_t size) { 139 int FuzzedSocket::SetSendBufferSize(int32_t size) {
131 return OK; 140 return OK;
132 } 141 }
133 142
134 int FuzzedSocket::Connect(const CompletionCallback& callback) { 143 int FuzzedSocket::Connect(const CompletionCallback& callback) {
135 // Sockets can normally be reused, but don't support it here. 144 // Sockets can normally be reused, but don't support it here.
136 DCHECK_NE(net_error_, OK); 145 DCHECK_NE(net_error_, OK);
146 DCHECK(!connect_pending_);
137 DCHECK(!read_pending_); 147 DCHECK(!read_pending_);
138 DCHECK(!write_pending_); 148 DCHECK(!write_pending_);
139 DCHECK(!error_pending_); 149 DCHECK(!error_pending_);
140 DCHECK(!total_bytes_read_); 150 DCHECK(!total_bytes_read_);
141 DCHECK(!total_bytes_written_); 151 DCHECK(!total_bytes_written_);
142 152
143 net_error_ = OK; 153 bool sync = true;
144 return OK; 154 Error result = OK;
155 if (fuzz_connect_result_) {
156 // Decide if sync or async. Use async, if no data is left.
157 sync = data_provider_->ConsumeBool();
158 // Decide if the connect succeeds or not, and if so, pick an error code.
159 if (data_provider_->ConsumeBool()) {
160 result = kConnectErrors[data_provider_->ConsumeValueInRange(
161 0, arraysize(kConnectErrors) - 1)];
162 }
163 }
164
165 if (sync) {
166 net_error_ = result;
167 return result;
168 }
169
170 connect_pending_ = true;
171 if (result != OK)
172 error_pending_ = true;
173 base::ThreadTaskRunnerHandle::Get()->PostTask(
174 FROM_HERE, base::Bind(&FuzzedSocket::OnConnectComplete,
175 weak_factory_.GetWeakPtr(), callback, result));
176 return ERR_IO_PENDING;
145 } 177 }
146 178
147 void FuzzedSocket::Disconnect() { 179 void FuzzedSocket::Disconnect() {
148 net_error_ = ERR_CONNECTION_CLOSED; 180 net_error_ = ERR_CONNECTION_CLOSED;
149 weak_factory_.InvalidateWeakPtrs(); 181 weak_factory_.InvalidateWeakPtrs();
182 connect_pending_ = false;
150 read_pending_ = false; 183 read_pending_ = false;
151 write_pending_ = false; 184 write_pending_ = false;
152 error_pending_ = false; 185 error_pending_ = false;
153 } 186 }
154 187
155 bool FuzzedSocket::IsConnected() const { 188 bool FuzzedSocket::IsConnected() const {
156 return net_error_ == OK && !error_pending_; 189 return net_error_ == OK && !error_pending_;
157 } 190 }
158 191
159 bool FuzzedSocket::IsConnectedAndIdle() const { 192 bool FuzzedSocket::IsConnectedAndIdle() const {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 } 238 }
206 239
207 void FuzzedSocket::ClearConnectionAttempts() {} 240 void FuzzedSocket::ClearConnectionAttempts() {}
208 241
209 void FuzzedSocket::AddConnectionAttempts(const ConnectionAttempts& attempts) {} 242 void FuzzedSocket::AddConnectionAttempts(const ConnectionAttempts& attempts) {}
210 243
211 int64_t FuzzedSocket::GetTotalReceivedBytes() const { 244 int64_t FuzzedSocket::GetTotalReceivedBytes() const {
212 return total_bytes_read_; 245 return total_bytes_read_;
213 } 246 }
214 247
215 uint8_t FuzzedSocket::ConsumeUint8FromData() {
216 size_t length = data_.length();
217 if (!length)
218 return 0;
219 uint8_t out = data_[length - 1];
220 data_ = data_.substr(0, length - 1);
221 return out;
222 }
223
224 Error FuzzedSocket::ConsumeReadWriteErrorFromData() { 248 Error FuzzedSocket::ConsumeReadWriteErrorFromData() {
225 return kReadWriteErrors[ConsumeUint8FromData() % arraysize(kReadWriteErrors)]; 249 return kReadWriteErrors[data_provider_->ConsumeValueInRange(
250 0, arraysize(kReadWriteErrors) - 1)];
226 } 251 }
227 252
228 void FuzzedSocket::OnReadComplete(const CompletionCallback& callback, 253 void FuzzedSocket::OnReadComplete(const CompletionCallback& callback,
229 int result) { 254 int result) {
230 CHECK(read_pending_); 255 CHECK(read_pending_);
231 read_pending_ = false; 256 read_pending_ = false;
232 if (result <= 0) { 257 if (result <= 0) {
233 error_pending_ = false; 258 error_pending_ = false;
234 } else { 259 } else {
235 total_bytes_read_ += result; 260 total_bytes_read_ += result;
236 } 261 }
237 callback.Run(result); 262 callback.Run(result);
238 } 263 }
239 264
240 void FuzzedSocket::OnWriteComplete(const CompletionCallback& callback, 265 void FuzzedSocket::OnWriteComplete(const CompletionCallback& callback,
241 int result) { 266 int result) {
242 CHECK(write_pending_); 267 CHECK(write_pending_);
243 write_pending_ = false; 268 write_pending_ = false;
244 if (result <= 0) { 269 if (result <= 0) {
245 error_pending_ = false; 270 error_pending_ = false;
246 } else { 271 } else {
247 total_bytes_written_ += result; 272 total_bytes_written_ += result;
248 } 273 }
249 callback.Run(result); 274 callback.Run(result);
250 } 275 }
251 276
277 void FuzzedSocket::OnConnectComplete(const CompletionCallback& callback,
278 int result) {
279 CHECK(connect_pending_);
280 connect_pending_ = false;
281 if (result < 0)
282 error_pending_ = false;
283 callback.Run(result);
284 }
285
252 } // namespace net 286 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698