xref: /aosp_15_r20/external/cronet/net/dns/https_record_rdata_fuzzer.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 The Chromium Authors
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/dns/https_record_rdata.h"
6 
7 #include <fuzzer/FuzzedDataProvider.h>
8 
9 #include <stdint.h>
10 
11 #include <memory>
12 #include <set>
13 #include <string>
14 #include <vector>
15 
16 #include "base/check.h"
17 #include "base/containers/contains.h"
18 #include "base/strings/string_piece.h"
19 #include "net/base/ip_address.h"
20 #include "net/dns/public/dns_protocol.h"
21 
22 namespace net {
23 namespace {
24 
ParseAndExercise(FuzzedDataProvider & data_provider)25 void ParseAndExercise(FuzzedDataProvider& data_provider) {
26   std::string data1 = data_provider.ConsumeRandomLengthString();
27   std::unique_ptr<HttpsRecordRdata> parsed = HttpsRecordRdata::Parse(data1);
28   std::unique_ptr<HttpsRecordRdata> parsed2 = HttpsRecordRdata::Parse(data1);
29   std::unique_ptr<HttpsRecordRdata> parsed3 =
30       HttpsRecordRdata::Parse(data_provider.ConsumeRemainingBytesAsString());
31 
32   CHECK_EQ(!!parsed, !!parsed2);
33 
34   if (!parsed)
35     return;
36 
37   // `parsed` and `parsed2` parsed from the same data, so they should always be
38   // equal.
39   CHECK(parsed->IsEqual(parsed.get()));
40   CHECK(parsed->IsEqual(parsed2.get()));
41   CHECK(parsed2->IsEqual(parsed.get()));
42 
43   // Attempt comparison with an rdata parsed from separate data. IsEqual() will
44   // probably return false most of the time, but easily could be true if the
45   // input data is similar enough.
46   if (parsed3)
47     CHECK_EQ(parsed->IsEqual(parsed3.get()), parsed3->IsEqual(parsed.get()));
48 
49   CHECK_EQ(parsed->Type(), dns_protocol::kTypeHttps);
50   if (parsed->IsAlias()) {
51     AliasFormHttpsRecordRdata* alias = parsed->AsAliasForm();
52     alias->alias_name();
53   } else {
54     ServiceFormHttpsRecordRdata* service = parsed->AsServiceForm();
55     CHECK_GT(service->priority(), 0);
56     service->service_name();
57     service->alpn_ids();
58     service->default_alpn();
59     service->port();
60     service->ech_config();
61     service->unparsed_params();
62     service->IsCompatible();
63 
64     std::set<uint16_t> mandatory_keys = service->mandatory_keys();
65     CHECK(!base::Contains(mandatory_keys,
66                           dns_protocol::kHttpsServiceParamKeyMandatory));
67 
68     std::vector<IPAddress> ipv4_hint = service->ipv4_hint();
69     for (const IPAddress& address : ipv4_hint) {
70       CHECK(address.IsIPv4());
71     }
72 
73     std::vector<IPAddress> ipv6_hint = service->ipv6_hint();
74     for (const IPAddress& address : ipv6_hint) {
75       CHECK(address.IsIPv6());
76     }
77   }
78 }
79 
80 }  // namespace
81 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)82 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
83   FuzzedDataProvider data_provider(data, size);
84   ParseAndExercise(data_provider);
85   return 0;
86 }
87 
88 }  // namespace net
89