xref: /aosp_15_r20/external/cronet/net/dns/dns_response_fuzzer.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2018 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "net/dns/dns_response.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <fuzzer/FuzzedDataProvider.h>
8*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
9*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include <optional>
12*6777b538SAndroid Build Coastguard Worker 
13*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_piece.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/base/io_buffer.h"
17*6777b538SAndroid Build Coastguard Worker #include "net/dns/dns_names_util.h"
18*6777b538SAndroid Build Coastguard Worker #include "net/dns/dns_query.h"
19*6777b538SAndroid Build Coastguard Worker #include "net/dns/dns_util.h"
20*6777b538SAndroid Build Coastguard Worker #include "net/dns/public/dns_protocol.h"
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker namespace {
23*6777b538SAndroid Build Coastguard Worker 
ValidateParsedResponse(net::DnsResponse & response,const net::IOBufferWithSize & packet,std::optional<net::DnsQuery> query=std::nullopt)24*6777b538SAndroid Build Coastguard Worker void ValidateParsedResponse(net::DnsResponse& response,
25*6777b538SAndroid Build Coastguard Worker                             const net::IOBufferWithSize& packet,
26*6777b538SAndroid Build Coastguard Worker                             std::optional<net::DnsQuery> query = std::nullopt) {
27*6777b538SAndroid Build Coastguard Worker   CHECK_EQ(response.io_buffer(), &packet);
28*6777b538SAndroid Build Coastguard Worker   CHECK_EQ(static_cast<int>(response.io_buffer_size()), packet.size());
29*6777b538SAndroid Build Coastguard Worker 
30*6777b538SAndroid Build Coastguard Worker   response.id();
31*6777b538SAndroid Build Coastguard Worker   if (response.IsValid()) {
32*6777b538SAndroid Build Coastguard Worker     CHECK(response.id().has_value());
33*6777b538SAndroid Build Coastguard Worker     response.flags();
34*6777b538SAndroid Build Coastguard Worker     response.rcode();
35*6777b538SAndroid Build Coastguard Worker 
36*6777b538SAndroid Build Coastguard Worker     CHECK_EQ(response.dotted_qnames().size(), response.question_count());
37*6777b538SAndroid Build Coastguard Worker     CHECK_EQ(response.qtypes().size(), response.question_count());
38*6777b538SAndroid Build Coastguard Worker     if (response.question_count() == 1) {
39*6777b538SAndroid Build Coastguard Worker       response.GetSingleDottedName();
40*6777b538SAndroid Build Coastguard Worker       response.GetSingleQType();
41*6777b538SAndroid Build Coastguard Worker     }
42*6777b538SAndroid Build Coastguard Worker 
43*6777b538SAndroid Build Coastguard Worker     response.answer_count();
44*6777b538SAndroid Build Coastguard Worker     response.authority_count();
45*6777b538SAndroid Build Coastguard Worker     response.additional_answer_count();
46*6777b538SAndroid Build Coastguard Worker 
47*6777b538SAndroid Build Coastguard Worker     bool success = false;
48*6777b538SAndroid Build Coastguard Worker     size_t last_offset = 0;
49*6777b538SAndroid Build Coastguard Worker     net::DnsRecordParser parser = response.Parser();
50*6777b538SAndroid Build Coastguard Worker     do {
51*6777b538SAndroid Build Coastguard Worker       net::DnsResourceRecord record;
52*6777b538SAndroid Build Coastguard Worker       success = parser.ReadRecord(&record);
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker       CHECK(!success || parser.GetOffset() > last_offset);
55*6777b538SAndroid Build Coastguard Worker       last_offset = parser.GetOffset();
56*6777b538SAndroid Build Coastguard Worker     } while (success);
57*6777b538SAndroid Build Coastguard Worker 
58*6777b538SAndroid Build Coastguard Worker     // Attempt to parse a couple more.
59*6777b538SAndroid Build Coastguard Worker     for (int i = 0; i < 10; ++i) {
60*6777b538SAndroid Build Coastguard Worker       net::DnsResourceRecord record;
61*6777b538SAndroid Build Coastguard Worker       CHECK(!parser.ReadRecord(&record));
62*6777b538SAndroid Build Coastguard Worker     }
63*6777b538SAndroid Build Coastguard Worker 
64*6777b538SAndroid Build Coastguard Worker     if (query) {
65*6777b538SAndroid Build Coastguard Worker       CHECK_EQ(response.question_count(), 1u);
66*6777b538SAndroid Build Coastguard Worker       CHECK_EQ(response.id().value(), query->id());
67*6777b538SAndroid Build Coastguard Worker       std::optional<std::string> dotted_qname =
68*6777b538SAndroid Build Coastguard Worker           net::dns_names_util::NetworkToDottedName(query->qname(),
69*6777b538SAndroid Build Coastguard Worker                                                    /*require_complete=*/true);
70*6777b538SAndroid Build Coastguard Worker       CHECK(dotted_qname.has_value());
71*6777b538SAndroid Build Coastguard Worker       CHECK_EQ(response.GetSingleDottedName(), dotted_qname.value());
72*6777b538SAndroid Build Coastguard Worker       CHECK_EQ(response.GetSingleQType(), query->qtype());
73*6777b538SAndroid Build Coastguard Worker     }
74*6777b538SAndroid Build Coastguard Worker   }
75*6777b538SAndroid Build Coastguard Worker }
76*6777b538SAndroid Build Coastguard Worker 
77*6777b538SAndroid Build Coastguard Worker }  // namespace
78*6777b538SAndroid Build Coastguard Worker 
79*6777b538SAndroid Build Coastguard Worker // Entry point for LibFuzzer.
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)80*6777b538SAndroid Build Coastguard Worker extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
81*6777b538SAndroid Build Coastguard Worker   FuzzedDataProvider data_provider(data, size);
82*6777b538SAndroid Build Coastguard Worker   std::string response_string = data_provider.ConsumeRandomLengthString();
83*6777b538SAndroid Build Coastguard Worker 
84*6777b538SAndroid Build Coastguard Worker   auto response_packet =
85*6777b538SAndroid Build Coastguard Worker       base::MakeRefCounted<net::IOBufferWithSize>(response_string.size());
86*6777b538SAndroid Build Coastguard Worker   memcpy(response_packet->data(), response_string.data(),
87*6777b538SAndroid Build Coastguard Worker          response_string.size());
88*6777b538SAndroid Build Coastguard Worker 
89*6777b538SAndroid Build Coastguard Worker   net::DnsResponse received_response(response_packet, response_string.size());
90*6777b538SAndroid Build Coastguard Worker   received_response.InitParseWithoutQuery(response_string.size());
91*6777b538SAndroid Build Coastguard Worker   ValidateParsedResponse(received_response, *response_packet.get());
92*6777b538SAndroid Build Coastguard Worker 
93*6777b538SAndroid Build Coastguard Worker   size_t query_size = data_provider.remaining_bytes();
94*6777b538SAndroid Build Coastguard Worker   auto query_packet = base::MakeRefCounted<net::IOBufferWithSize>(query_size);
95*6777b538SAndroid Build Coastguard Worker   data_provider.ConsumeData(query_packet->data(), query_size);
96*6777b538SAndroid Build Coastguard Worker   net::DnsQuery query(query_packet);
97*6777b538SAndroid Build Coastguard Worker 
98*6777b538SAndroid Build Coastguard Worker   if (!query.Parse(query_size))
99*6777b538SAndroid Build Coastguard Worker     return 0;
100*6777b538SAndroid Build Coastguard Worker 
101*6777b538SAndroid Build Coastguard Worker   net::DnsResponse received_response_with_query(response_packet,
102*6777b538SAndroid Build Coastguard Worker                                                 response_string.size());
103*6777b538SAndroid Build Coastguard Worker   received_response_with_query.InitParse(response_string.size(), query);
104*6777b538SAndroid Build Coastguard Worker   ValidateParsedResponse(received_response_with_query, *response_packet.get(),
105*6777b538SAndroid Build Coastguard Worker                          query);
106*6777b538SAndroid Build Coastguard Worker 
107*6777b538SAndroid Build Coastguard Worker   net::DnsResponse response(query.id(), true /* is_authoritative */,
108*6777b538SAndroid Build Coastguard Worker                             {} /* answers */, {} /* authority_records */,
109*6777b538SAndroid Build Coastguard Worker                             {} /* additional records */, query);
110*6777b538SAndroid Build Coastguard Worker   std::string out =
111*6777b538SAndroid Build Coastguard Worker       base::HexEncode(response.io_buffer()->data(), response.io_buffer_size());
112*6777b538SAndroid Build Coastguard Worker 
113*6777b538SAndroid Build Coastguard Worker   return 0;
114*6777b538SAndroid Build Coastguard Worker }
115