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

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: Update other fuzzers (Lost them in a merge) Created 4 years, 8 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/22 22:07:10 Or alternately IPAddress::IPv4Localhost()
mmenke 2016/04/27 19:53:25 Handy. Done.
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_->ConsumeBits(1);
eroman 2016/04/22 22:07:11 How about adding a wrapper method: bool FuzzedDat
mmenke 2016/04/27 19:53:25 Hrm...We could make consume bits always round to t
49 sync = !!(random_val & 0x01); 58 result = data_provider_->ConsumeBits(7);
eroman 2016/04/22 22:07:11 Could combine this with the next line: result = s
mmenke 2016/04/27 19:53:25 You mean std::min(static_cast<uint32_t>(buf_len),
50 result = random_val >> 1;
51 if (result > buf_len) 59 if (result > buf_len)
52 result = buf_len; 60 result = buf_len;
53 // Can't read more data than is available in |data_|. 61
54 if (static_cast<size_t>(result) > data_.length()) 62 if (result > 0)
55 result = data_.length(); 63 result = data_provider_->ConsumeBytes(buf->data(), result);
56 64
57 if (result == 0) { 65 if (result == 0) {
58 net_error_ = ConsumeReadWriteErrorFromData(); 66 net_error_ = ConsumeReadWriteErrorFromData();
59 result = net_error_; 67 result = net_error_;
60 if (!sync) 68 if (!sync)
61 error_pending_ = true; 69 error_pending_ = true;
62 } else {
63 memcpy(buf->data(), data_.data(), result);
64 data_ = data_.substr(result);
65 } 70 }
66 } 71 }
67 72
68 // Graceful close of a socket returns OK, at least in theory. This doesn't 73 // Graceful close of a socket returns OK, at least in theory. This doesn't
69 // perfectly reflect real socket behavior, but close enough. 74 // perfectly reflect real socket behavior, but close enough.
70 if (result == ERR_CONNECTION_CLOSED) 75 if (result == ERR_CONNECTION_CLOSED)
71 result = 0; 76 result = 0;
72 77
73 if (sync) { 78 if (sync) {
74 if (result > 0) 79 if (result > 0)
75 total_bytes_read_ += result; 80 total_bytes_read_ += result;
76 return result; 81 return result;
77 } 82 }
78 83
79 read_pending_ = true; 84 read_pending_ = true;
80 base::ThreadTaskRunnerHandle::Get()->PostTask( 85 base::ThreadTaskRunnerHandle::Get()->PostTask(
81 FROM_HERE, base::Bind(&FuzzedSocket::OnReadComplete, 86 FROM_HERE, base::Bind(&FuzzedSocket::OnReadComplete,
82 weak_factory_.GetWeakPtr(), callback, result)); 87 weak_factory_.GetWeakPtr(), callback, result));
83 return ERR_IO_PENDING; 88 return ERR_IO_PENDING;
84 } 89 }
85 90
86 int FuzzedSocket::Write(IOBuffer* buf, 91 int FuzzedSocket::Write(IOBuffer* buf,
87 int buf_len, 92 int buf_len,
88 const CompletionCallback& callback) { 93 const CompletionCallback& callback) {
94 DCHECK(!connect_pending_);
89 DCHECK(!write_pending_); 95 DCHECK(!write_pending_);
90 96
91 bool sync; 97 bool sync;
92 int result; 98 int result;
93 99
94 if (net_error_ != OK) { 100 if (net_error_ != OK) {
95 // If an error has already been generated, use it to determine what to do. 101 // If an error has already been generated, use it to determine what to do.
96 result = net_error_; 102 result = net_error_;
97 sync = !error_pending_; 103 sync = !error_pending_;
98 } else { 104 } else {
99 // Otherwise, use |data_|. 105 // Otherwise, use |data_|.
100 uint8_t random_val = ConsumeUint8FromData(); 106 sync = !!data_provider_->ConsumeBits(1);
eroman 2016/04/22 22:07:11 Same suggestiong (ConsumeBool())
101 sync = !!(random_val & 0x01); 107 result = data_provider_->ConsumeBits(7);
102 result = random_val >> 1;
103 if (result > buf_len) 108 if (result > buf_len)
104 result = buf_len; 109 result = buf_len;
105 if (result == 0) { 110 if (result == 0) {
106 net_error_ = ConsumeReadWriteErrorFromData(); 111 net_error_ = ConsumeReadWriteErrorFromData();
107 result = net_error_; 112 result = net_error_;
108 if (!sync) 113 if (!sync)
109 error_pending_ = true; 114 error_pending_ = true;
110 } 115 }
111 } 116 }
112 117
(...skipping 14 matching lines...) Expand all
127 return OK; 132 return OK;
128 } 133 }
129 134
130 int FuzzedSocket::SetSendBufferSize(int32_t size) { 135 int FuzzedSocket::SetSendBufferSize(int32_t size) {
131 return OK; 136 return OK;
132 } 137 }
133 138
134 int FuzzedSocket::Connect(const CompletionCallback& callback) { 139 int FuzzedSocket::Connect(const CompletionCallback& callback) {
135 // Sockets can normally be reused, but don't support it here. 140 // Sockets can normally be reused, but don't support it here.
136 DCHECK_NE(net_error_, OK); 141 DCHECK_NE(net_error_, OK);
142 DCHECK(!connect_pending_);
137 DCHECK(!read_pending_); 143 DCHECK(!read_pending_);
138 DCHECK(!write_pending_); 144 DCHECK(!write_pending_);
139 DCHECK(!error_pending_); 145 DCHECK(!error_pending_);
140 DCHECK(!total_bytes_read_); 146 DCHECK(!total_bytes_read_);
141 DCHECK(!total_bytes_written_); 147 DCHECK(!total_bytes_written_);
142 148
143 net_error_ = OK; 149 int sync = true;
eroman 2016/04/22 22:07:10 Why not a bool?
144 return OK; 150 Error result = OK;
151 if (fuzz_connect_result_) {
152 // Decide if sync or async. Use async, if no data is left.
153 sync = !!data_provider_->ConsumeBits(1);
154 // Decide if the connect succeeds or not. Fail, if no data is left.
155 bool is_error = !data_provider_->ConsumeBits(1);
156
157 // Remove 6 bits, so a full byte as been consumed. If the connect is going
eroman 2016/04/22 22:07:11 as been --> has been. Also note I don't think it
158 // to fail, use them to decide the error code. Otherwise, throw them away.
159 uint32_t error_bits = data_provider_->ConsumeBits(6);
eroman 2016/04/22 22:07:11 Why not just Consume these 6 bits when |is_error|
mmenke 2016/04/25 15:09:19 See my other comments on how the fuzzer traverses
160 if (is_error)
161 result = kConnectErrors[error_bits % arraysize(kConnectErrors)];
eroman 2016/04/22 22:07:11 Note: would have been sufficient to consume 3 bits
162 }
163
164 if (sync) {
165 net_error_ = result;
166 return result;
167 }
168
169 connect_pending_ = true;
170 if (result != OK)
171 error_pending_ = true;
172 base::ThreadTaskRunnerHandle::Get()->PostTask(
173 FROM_HERE, base::Bind(&FuzzedSocket::OnConnectComplete,
174 weak_factory_.GetWeakPtr(), callback, result));
175 return ERR_IO_PENDING;
145 } 176 }
146 177
147 void FuzzedSocket::Disconnect() { 178 void FuzzedSocket::Disconnect() {
148 net_error_ = ERR_CONNECTION_CLOSED; 179 net_error_ = ERR_CONNECTION_CLOSED;
149 weak_factory_.InvalidateWeakPtrs(); 180 weak_factory_.InvalidateWeakPtrs();
181 connect_pending_ = false;
150 read_pending_ = false; 182 read_pending_ = false;
151 write_pending_ = false; 183 write_pending_ = false;
152 error_pending_ = false; 184 error_pending_ = false;
153 } 185 }
154 186
155 bool FuzzedSocket::IsConnected() const { 187 bool FuzzedSocket::IsConnected() const {
156 return net_error_ == OK && !error_pending_; 188 return net_error_ == OK && !error_pending_;
157 } 189 }
158 190
159 bool FuzzedSocket::IsConnectedAndIdle() const { 191 bool FuzzedSocket::IsConnectedAndIdle() const {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 } 237 }
206 238
207 void FuzzedSocket::ClearConnectionAttempts() {} 239 void FuzzedSocket::ClearConnectionAttempts() {}
208 240
209 void FuzzedSocket::AddConnectionAttempts(const ConnectionAttempts& attempts) {} 241 void FuzzedSocket::AddConnectionAttempts(const ConnectionAttempts& attempts) {}
210 242
211 int64_t FuzzedSocket::GetTotalReceivedBytes() const { 243 int64_t FuzzedSocket::GetTotalReceivedBytes() const {
212 return total_bytes_read_; 244 return total_bytes_read_;
213 } 245 }
214 246
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() { 247 Error FuzzedSocket::ConsumeReadWriteErrorFromData() {
225 return kReadWriteErrors[ConsumeUint8FromData() % arraysize(kReadWriteErrors)]; 248 return kReadWriteErrors[data_provider_->ConsumeBits(8) %
eroman 2016/04/22 22:07:11 Ditto here -- 8 bits is more than we need. Not a p
249 arraysize(kReadWriteErrors)];
226 } 250 }
227 251
228 void FuzzedSocket::OnReadComplete(const CompletionCallback& callback, 252 void FuzzedSocket::OnReadComplete(const CompletionCallback& callback,
229 int result) { 253 int result) {
230 CHECK(read_pending_); 254 CHECK(read_pending_);
231 read_pending_ = false; 255 read_pending_ = false;
232 if (result <= 0) { 256 if (result <= 0) {
233 error_pending_ = false; 257 error_pending_ = false;
234 } else { 258 } else {
235 total_bytes_read_ += result; 259 total_bytes_read_ += result;
236 } 260 }
237 callback.Run(result); 261 callback.Run(result);
238 } 262 }
239 263
240 void FuzzedSocket::OnWriteComplete(const CompletionCallback& callback, 264 void FuzzedSocket::OnWriteComplete(const CompletionCallback& callback,
241 int result) { 265 int result) {
242 CHECK(write_pending_); 266 CHECK(write_pending_);
243 write_pending_ = false; 267 write_pending_ = false;
244 if (result <= 0) { 268 if (result <= 0) {
245 error_pending_ = false; 269 error_pending_ = false;
246 } else { 270 } else {
247 total_bytes_written_ += result; 271 total_bytes_written_ += result;
248 } 272 }
249 callback.Run(result); 273 callback.Run(result);
250 } 274 }
251 275
276 void FuzzedSocket::OnConnectComplete(const CompletionCallback& callback,
277 int result) {
278 CHECK(connect_pending_);
279 connect_pending_ = false;
280 if (result < 0)
281 error_pending_ = false;
282 callback.Run(result);
283 }
284
252 } // namespace net 285 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698