summaryrefslogtreecommitdiff
path: root/chromium/net/dns/integrity_record_fuzzer.cc
blob: e3091b0763c00c8f9f392605094f60565d984438 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <limits>
#include <memory>
#include <string>
#include <vector>

#include "base/check_op.h"
#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "net/dns/record_rdata.h"

namespace net {

namespace {

base::StringPiece MakeStringPiece(const std::vector<uint8_t>& vec) {
  return base::StringPiece(reinterpret_cast<const char*>(vec.data()),
                           vec.size());
}

// For arbitrary data, check that parse(data).serialize() == data.
void ParseThenSerializeProperty(const std::vector<uint8_t>& data) {
  auto parsed = IntegrityRecordRdata::Create(MakeStringPiece(data));
  CHECK(parsed);
  base::Optional<std::vector<uint8_t>> maybe_serialized = parsed->Serialize();
  // Since |data| is chosen by a fuzzer, the record's digest is unlikely to
  // match its nonce. As a result, |parsed->IsIntact()| may be false, and thus
  // |parsed->Serialize()| may be |base::nullopt|.
  CHECK_EQ(parsed->IsIntact(), !!maybe_serialized);
  if (maybe_serialized) {
    CHECK(data == *maybe_serialized);
  }
}

// For arbitrary IntegrityRecordRdata r, check that parse(r.serialize()) == r.
void SerializeThenParseProperty(const std::vector<uint8_t>& data) {
  // Ensure that the nonce is not too long to be serialized.
  if (data.size() > std::numeric_limits<uint16_t>::max()) {
    // Property is vacuously true because the record is not serializable.
    return;
  }
  // Build an IntegrityRecordRdata by treating |data| as a nonce.
  IntegrityRecordRdata record(data);
  CHECK(record.IsIntact());
  base::Optional<std::vector<uint8_t>> maybe_serialized = record.Serialize();
  CHECK(maybe_serialized.has_value());

  // Parsing |serialized| always produces a record identical to the original.
  auto parsed =
      IntegrityRecordRdata::Create(MakeStringPiece(*maybe_serialized));
  CHECK(parsed);
  CHECK(parsed->IsIntact());
  CHECK(parsed->IsEqual(&record));
}

}  // namespace

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  const std::vector<uint8_t> data_vec(data, data + size);
  ParseThenSerializeProperty(data_vec);
  SerializeThenParseProperty(data_vec);
  // Construct a random IntegrityRecordRdata to exercise that code path. No need
  // to exercise parse/serialize since we already did that with |data|.
  IntegrityRecordRdata rand_record(IntegrityRecordRdata::Random());
  return 0;
}

}  // namespace net