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

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

Powered by Google App Engine
This is Rietveld 408576698