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

Side by Side Diff: net/dns/host_resolver_impl_fuzzer.cc

Issue 1946793002: net: Add fuzzer for HostResolverImpl. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove port 0 check Created 4 years, 6 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
« no previous file with comments | « net/dns/host_resolver_impl.cc ('k') | net/socket/fuzzed_socket.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <stddef.h>
6 #include <stdint.h>
7
8 #include <memory>
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/logging.h"
13 #include "base/run_loop.h"
14 #include "net/base/address_family.h"
15 #include "net/base/address_list.h"
16 #include "net/base/fuzzed_data_provider.h"
17 #include "net/base/net_errors.h"
18 #include "net/base/request_priority.h"
19 #include "net/dns/fuzzed_host_resolver.h"
20 #include "net/dns/host_resolver.h"
21 #include "net/log/test_net_log.h"
22
23 namespace {
24
25 const char* kHostNames[] = {"foo", "foo.com", "a.foo.com",
26 "bar", "localhost", "localhost6"};
27
28 net::AddressFamily kAddressFamilies[] = {
29 net::ADDRESS_FAMILY_UNSPECIFIED, net::ADDRESS_FAMILY_IPV4,
30 net::ADDRESS_FAMILY_IPV6,
31 };
32
33 class DnsRequest {
34 public:
35 DnsRequest(net::HostResolver* host_resolver,
36 net::FuzzedDataProvider* data_provider,
37 std::vector<std::unique_ptr<DnsRequest>>* dns_requests)
38 : host_resolver_(host_resolver),
39 data_provider_(data_provider),
40 dns_requests_(dns_requests),
41 handle_(nullptr),
42 is_running_(false) {}
43
44 ~DnsRequest() {
45 if (is_running_)
46 Cancel();
47 }
48
49 // Creates and starts a DNS request using fuzzed parameters. If the request
50 // doesn't complete synchronously, adds it to |dns_requests|.
51 static void CreateRequest(
52 net::HostResolver* host_resolver,
53 net::FuzzedDataProvider* data_provider,
54 std::vector<std::unique_ptr<DnsRequest>>* dns_requests) {
55 std::unique_ptr<DnsRequest> dns_request(
56 new DnsRequest(host_resolver, data_provider, dns_requests));
57
58 if (dns_request->Start() == net::ERR_IO_PENDING)
59 dns_requests->push_back(std::move(dns_request));
60 }
61
62 // If |dns_requests| is non-empty, waits for a randomly chosen one of the
63 // requests to complete and removes it from |dns_requests|.
64 static void WaitForRequestComplete(
65 net::FuzzedDataProvider* data_provider,
66 std::vector<std::unique_ptr<DnsRequest>>* dns_requests) {
67 if (dns_requests->empty())
68 return;
69 uint32_t index =
70 data_provider->ConsumeUint32InRange(0, dns_requests->size() - 1);
71
72 // Remove the request from the list before waiting on it - this prevents one
73 // of the other callbacks from deleting the callback being waited on.
74 std::unique_ptr<DnsRequest> request = std::move((*dns_requests)[index]);
75 dns_requests->erase(dns_requests->begin() + index);
76 request->WaitUntilDone();
77 }
78
79 // If |dns_requests| is non-empty, attempts to cancel a randomly chosen one of
80 // them and removes it from |dns_requests|. If the one it picks is already
81 // complete, just removes it from the list.
82 static void CancelRequest(
83 net::HostResolver* host_resolver,
84 net::FuzzedDataProvider* data_provider,
85 std::vector<std::unique_ptr<DnsRequest>>* dns_requests) {
86 if (dns_requests->empty())
87 return;
88 uint32_t index =
89 data_provider->ConsumeUint32InRange(0, dns_requests->size() - 1);
90 auto request = dns_requests->begin() + index;
91 (*request)->Cancel();
92 dns_requests->erase(request);
93 }
94
95 private:
96 void OnCallback(int result) {
97 CHECK_NE(net::ERR_IO_PENDING, result);
98
99 is_running_ = false;
100
101 // Remove |this| from |dns_requests| and take ownership of it, if it wasn't
102 // already removed from the vector. It may have been removed if this is in a
103 // WaitForRequest call, in which case, do nothing.
104 std::unique_ptr<DnsRequest> self;
105 for (auto request = dns_requests_->begin(); request != dns_requests_->end();
106 ++request) {
107 if (request->get() != this)
108 continue;
109 self = std::move(*request);
110 dns_requests_->erase(request);
111 break;
112 }
113
114 while (true) {
115 bool done = false;
116 switch (data_provider_->ConsumeInt32InRange(0, 2)) {
117 case 0:
118 // Quit on 0, or when no data is left.
119 done = true;
120 break;
121 case 1:
122 CreateRequest(host_resolver_, data_provider_, dns_requests_);
123 break;
124 case 2:
125 CancelRequest(host_resolver_, data_provider_, dns_requests_);
126 break;
127 }
128
129 if (done)
130 break;
131 }
132
133 if (run_loop_)
134 run_loop_->Quit();
135 }
136
137 // Starts the DNS request, using a fuzzed set of parameters.
138 int Start() {
139 const char* hostname = data_provider_->PickValueInArray(kHostNames);
140 net::HostResolver::RequestInfo info(net::HostPortPair(hostname, 80));
141 info.set_address_family(data_provider_->PickValueInArray(kAddressFamilies));
142 if (data_provider_->ConsumeBool())
143 info.set_host_resolver_flags(net::HOST_RESOLVER_CANONNAME);
144
145 net::RequestPriority priority =
146 static_cast<net::RequestPriority>(data_provider_->ConsumeInt32InRange(
147 net::MINIMUM_PRIORITY, net::MAXIMUM_PRIORITY));
148
149 // Decide if should be a cache-only resolution.
150 if (data_provider_->ConsumeBool()) {
151 return host_resolver_->ResolveFromCache(info, &address_list_,
152 net::BoundNetLog());
153 }
154
155 info.set_allow_cached_response(data_provider_->ConsumeBool());
156 return host_resolver_->Resolve(
157 info, priority, &address_list_,
158 base::Bind(&DnsRequest::OnCallback, base::Unretained(this)), &handle_,
159 net::BoundNetLog());
160 }
161
162 // Waits until the request is done, if it isn't done already.
163 void WaitUntilDone() {
164 CHECK(!run_loop_);
165 if (is_running_) {
166 run_loop_.reset(new base::RunLoop());
167 run_loop_->Run();
168 run_loop_.reset();
169 CHECK(!is_running_);
170 }
171 }
172
173 // Cancel the request, if not already completed. Otherwise, does nothing.
174 void Cancel() {
175 if (is_running_)
176 host_resolver_->CancelRequest(handle_);
177 is_running_ = false;
178 }
179
180 net::HostResolver* host_resolver_;
181 net::FuzzedDataProvider* data_provider_;
182 std::vector<std::unique_ptr<DnsRequest>>* dns_requests_;
183
184 net::HostResolver::RequestHandle handle_;
185 net::AddressList address_list_;
186
187 bool is_running_;
188
189 std::unique_ptr<base::RunLoop> run_loop_;
190
191 DISALLOW_COPY_AND_ASSIGN(DnsRequest);
192 };
193
194 } // namespace
195
196 // Fuzzer for HostResolverImpl. Fuzzes using both the system resolver and
197 // built-in DNS client paths.
198 //
199 // TODO(mmenke): Add coverage for things this does not cover:
200 // * Out of order completion, particularly for the platform resolver path.
201 // * Simulate network changes, including both enabling and disabling the
202 // async resolver while lookups are active as a result of the change.
203 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
204 {
205 net::FuzzedDataProvider data_provider(data, size);
206 net::TestNetLog net_log;
207
208 net::HostResolver::Options options;
209 options.max_concurrent_resolves = data_provider.ConsumeUint32InRange(1, 8);
210 options.enable_caching = data_provider.ConsumeBool();
211 net::FuzzedHostResolver host_resolver(options, &net_log, &data_provider);
212 host_resolver.SetDnsClientEnabled(data_provider.ConsumeBool());
213
214 std::vector<std::unique_ptr<DnsRequest>> dns_requests;
215 while (true) {
216 switch (data_provider.ConsumeInt32InRange(0, 3)) {
217 case 0:
218 // Quit on 0, or when no data is left.
219 return 0;
220 case 1:
221 DnsRequest::CreateRequest(&host_resolver, &data_provider,
222 &dns_requests);
223 break;
224 case 2:
225 DnsRequest::WaitForRequestComplete(&data_provider, &dns_requests);
226 break;
227 case 3:
228 DnsRequest::CancelRequest(&host_resolver, &data_provider,
229 &dns_requests);
230 break;
231 }
232 }
233 }
234
235 // Clean up any pending tasks, after deleting everything.
236 base::RunLoop().RunUntilIdle();
237
238 return 0;
239 }
OLDNEW
« no previous file with comments | « net/dns/host_resolver_impl.cc ('k') | net/socket/fuzzed_socket.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698