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

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

Issue 1854813004: Add SOCKS4 and SOCKS5 fuzzers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Return OK on read close, remove log spam 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "net/socket/fuzzed_socket.h"
6
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "net/base/io_buffer.h"
12
13 namespace net {
14
15 namespace {
16
17 // Subset of the socket errors that can be returned by normal socket reads /
18 // writes. The first one is returned when no more seed data remains, so it's one
19 // of the most common ones.
20 const Error kReadWriteErrors[] = {ERR_CONNECTION_CLOSED, ERR_FAILED,
21 ERR_TIMED_OUT, ERR_CONNECTION_RESET};
22
23 } // namespace
24
25 FuzzedSocket::FuzzedSocket(const uint8_t* data,
26 size_t data_size,
27 const BoundNetLog& bound_net_log)
28 : seed_(reinterpret_cast<const char*>(data), data_size),
29 bound_net_log_(bound_net_log),
30 weak_factory_(this) {}
31
32 FuzzedSocket::~FuzzedSocket() {}
33
34 int FuzzedSocket::Read(IOBuffer* buf,
35 int buf_len,
36 const CompletionCallback& callback) {
37 DCHECK(!read_pending_);
eroman 2016/04/14 17:56:27 Do we run DCHECKs in fuzzers? Seems like we defin
mmenke 2016/04/14 19:01:51 Good question...I *think* we do, but I've switched
eroman 2016/04/14 19:32:39 (At least when I build fuzzers locally following t
38
39 bool sync;
40 int result;
41
42 if (net_error_ != OK) {
43 // If an error has already been generated, use it to determine what to do.
44 result = net_error_;
45 sync = !error_pending_;
46 } else {
47 // Otherwise, use a random seed.
48 uint8_t random_val = GetUint8FromSeed();
49 sync = !!(random_val & 0x01);
50 result = random_val >> 1;
51 if (result > buf_len)
52 result = buf_len;
53 if (static_cast<size_t>(result) > seed_.length())
54 result = seed_.length();
55 if (result == 0) {
56 net_error_ = GetReadWriteErrorFromSeed();
57 result = net_error_;
58 if (!sync)
59 error_pending_ = true;
60 } else {
61 memcpy(buf->data(), seed_.data(), result);
62 seed_ = seed_.substr(result);
63 }
64 }
65
66 // Graceful close of a socket returns OK, at least in theory. This doesn't
67 // perfectly reflect real socket behavior, but close enough.
68 if (result == ERR_CONNECTION_CLOSED)
69 result = OK;
eroman 2016/04/14 17:56:27 This is implementing the socket interface. So thro
mmenke 2016/04/14 19:01:51 Done.
70
71 if (sync) {
72 if (result > 0)
73 total_bytes_read_ += result;
74 return result;
75 }
76
77 read_pending_ = true;
78 base::ThreadTaskRunnerHandle::Get()->PostTask(
79 FROM_HERE, base::Bind(&FuzzedSocket::OnReadComplete,
80 weak_factory_.GetWeakPtr(), callback, result));
81 return ERR_IO_PENDING;
82 }
83
84 int FuzzedSocket::Write(IOBuffer* buf,
85 int buf_len,
86 const CompletionCallback& callback) {
87 DCHECK(!write_pending_);
eroman 2016/04/14 17:56:27 Same dcheck question.
mmenke 2016/04/14 19:01:51 Done.
88
89 bool sync;
90 int result;
91
92 if (net_error_ != OK) {
93 // If an error has already been generated, use it to determine what to do.
94 result = net_error_;
95 sync = !error_pending_;
96 } else {
97 // Otherwise, use a random seed.
98 uint8_t random_val = GetUint8FromSeed();
99 sync = !!(random_val & 0x01);
100 result = random_val >> 1;
101 if (result > buf_len)
102 result = buf_len;
103 if (static_cast<size_t>(result) > seed_.length())
104 result = seed_.length();
105 if (static_cast<size_t>(result) > seed_.length())
eroman 2016/04/14 17:56:27 duplicated line?
mmenke 2016/04/14 19:01:51 Done. Actually, removed *both* copies, as they're
106 result = seed_.length();
107 if (result == 0) {
108 net_error_ = GetReadWriteErrorFromSeed();
109 result = net_error_;
110 if (!sync)
111 error_pending_ = true;
112 }
113 }
114
115 if (sync) {
116 if (result > 0)
117 total_bytes_written_ += result;
118 return result;
119 }
120
121 write_pending_ = true;
122 base::ThreadTaskRunnerHandle::Get()->PostTask(
123 FROM_HERE, base::Bind(&FuzzedSocket::OnWriteComplete,
124 weak_factory_.GetWeakPtr(), callback, result));
125 return ERR_IO_PENDING;
126 }
127
128 int FuzzedSocket::SetReceiveBufferSize(int32_t size) {
129 return OK;
130 }
131
132 int FuzzedSocket::SetSendBufferSize(int32_t size) {
133 return OK;
134 }
135
136 int FuzzedSocket::Connect(const CompletionCallback& callback) {
137 // Sockets can normally be reused, but don't support it here.
138 DCHECK_NE(net_error_, OK);
139 DCHECK(!read_pending_);
140 DCHECK(!write_pending_);
141 DCHECK(!error_pending_);
142 DCHECK(!total_bytes_read_);
143 DCHECK(!total_bytes_written_);
144
145 net_error_ = OK;
146 return OK;
eroman 2016/04/14 17:56:27 Might consider fuzzing this too (use first byte to
mmenke 2016/04/14 19:01:51 It's not relevant for these fuzzers. I'm thinking
147 }
148
149 void FuzzedSocket::Disconnect() {
150 net_error_ = ERR_CONNECTION_CLOSED;
151 weak_factory_.InvalidateWeakPtrs();
152 read_pending_ = false;
153 write_pending_ = false;
154 error_pending_ = false;
155 }
156
157 bool FuzzedSocket::IsConnected() const {
158 return net_error_ != OK && !error_pending_;
159 }
160
161 bool FuzzedSocket::IsConnectedAndIdle() const {
162 return IsConnected();
163 }
164
165 int FuzzedSocket::GetPeerAddress(IPEndPoint* address) const {
166 if (!IsConnected())
167 return ERR_SOCKET_NOT_CONNECTED;
168 *address = IPEndPoint(IPAddress(127, 0, 0, 1), 80);
169 return OK;
170 }
171
172 int FuzzedSocket::GetLocalAddress(IPEndPoint* address) const {
173 if (!IsConnected())
174 return ERR_SOCKET_NOT_CONNECTED;
175 *address = IPEndPoint(IPAddress(127, 0, 0, 1), 43434);
176 return OK;
177 }
178
179 const BoundNetLog& FuzzedSocket::NetLog() const {
180 return bound_net_log_;
181 }
182
183 void FuzzedSocket::SetSubresourceSpeculation() {}
184
185 void FuzzedSocket::SetOmniboxSpeculation() {}
186
187 bool FuzzedSocket::WasEverUsed() const {
188 return total_bytes_written_ != 0 || total_bytes_read_ != 0;
eroman 2016/04/14 17:56:27 technically in the case where we returned 0 from r
mmenke 2016/04/14 19:01:51 This is actually duplicating tcp_client_socket's b
189 }
190
191 void FuzzedSocket::EnableTCPFastOpenIfSupported() {}
192
193 bool FuzzedSocket::WasNpnNegotiated() const {
194 return false;
195 }
196
197 NextProto FuzzedSocket::GetNegotiatedProtocol() const {
198 return kProtoUnknown;
199 }
200
201 bool FuzzedSocket::GetSSLInfo(SSLInfo* ssl_info) {
202 return false;
203 }
204
205 void FuzzedSocket::GetConnectionAttempts(ConnectionAttempts* out) const {
206 out->clear();
207 }
208
209 void FuzzedSocket::ClearConnectionAttempts() {}
210
211 void FuzzedSocket::AddConnectionAttempts(const ConnectionAttempts& attempts) {}
212
213 int64_t FuzzedSocket::GetTotalReceivedBytes() const {
214 return total_bytes_read_;
215 }
216
217 uint8_t FuzzedSocket::GetUint8FromSeed() {
eroman 2016/04/14 17:56:27 optional: Instead of "Get*" I would suggest someth
mmenke 2016/04/14 19:01:51 Done. Went with Consume*FromData.
218 size_t length = seed_.length();
219 if (!length)
220 return 0;
221 uint8_t out = seed_[length - 1];
222 seed_ = seed_.substr(0, length - 1);
223 return out;
224 }
225
226 Error FuzzedSocket::GetReadWriteErrorFromSeed() {
227 return kReadWriteErrors[GetUint8FromSeed() % arraysize(kReadWriteErrors)];
228 }
229
230 void FuzzedSocket::OnReadComplete(const CompletionCallback& callback,
231 int result) {
232 DCHECK(read_pending_);
233 read_pending_ = false;
234 if (result <= 0) {
235 error_pending_ = false;
236 } else {
237 total_bytes_read_ += result;
238 }
239 callback.Run(result);
240 }
241
242 void FuzzedSocket::OnWriteComplete(const CompletionCallback& callback,
243 int result) {
244 DCHECK(write_pending_);
245 write_pending_ = false;
246 if (result <= 0) {
247 error_pending_ = false;
248 } else {
249 total_bytes_written_ += result;
250 }
251 callback.Run(result);
252 }
253
254 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698