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