integrity_record_fuzzer.cc 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. // Copyright 2020 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. #include <limits>
  5. #include <memory>
  6. #include <string>
  7. #include <vector>
  8. #include "base/check_op.h"
  9. #include "base/strings/string_piece.h"
  10. #include "net/dns/record_rdata.h"
  11. #include "third_party/abseil-cpp/absl/types/optional.h"
  12. namespace net {
  13. namespace {
  14. base::StringPiece MakeStringPiece(const std::vector<uint8_t>& vec) {
  15. return base::StringPiece(reinterpret_cast<const char*>(vec.data()),
  16. vec.size());
  17. }
  18. // For arbitrary data, check that parse(data).serialize() == data.
  19. void ParseThenSerializeProperty(const std::vector<uint8_t>& data) {
  20. auto parsed = IntegrityRecordRdata::Create(MakeStringPiece(data));
  21. CHECK(parsed);
  22. absl::optional<std::vector<uint8_t>> maybe_serialized = parsed->Serialize();
  23. // Since |data| is chosen by a fuzzer, the record's digest is unlikely to
  24. // match its nonce. As a result, |parsed->IsIntact()| may be false, and thus
  25. // |parsed->Serialize()| may be |absl::nullopt|.
  26. CHECK_EQ(parsed->IsIntact(), !!maybe_serialized);
  27. if (maybe_serialized) {
  28. CHECK(data == *maybe_serialized);
  29. }
  30. }
  31. // For arbitrary IntegrityRecordRdata r, check that parse(r.serialize()) == r.
  32. void SerializeThenParseProperty(const std::vector<uint8_t>& data) {
  33. // Ensure that the nonce is not too long to be serialized.
  34. if (data.size() > std::numeric_limits<uint16_t>::max()) {
  35. // Property is vacuously true because the record is not serializable.
  36. return;
  37. }
  38. // Build an IntegrityRecordRdata by treating |data| as a nonce.
  39. IntegrityRecordRdata record(data);
  40. CHECK(record.IsIntact());
  41. absl::optional<std::vector<uint8_t>> maybe_serialized = record.Serialize();
  42. CHECK(maybe_serialized.has_value());
  43. // Parsing |serialized| always produces a record identical to the original.
  44. auto parsed =
  45. IntegrityRecordRdata::Create(MakeStringPiece(*maybe_serialized));
  46. CHECK(parsed);
  47. CHECK(parsed->IsIntact());
  48. CHECK(parsed->IsEqual(&record));
  49. }
  50. } // namespace
  51. extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  52. const std::vector<uint8_t> data_vec(data, data + size);
  53. ParseThenSerializeProperty(data_vec);
  54. SerializeThenParseProperty(data_vec);
  55. // Construct a random IntegrityRecordRdata to exercise that code path. No need
  56. // to exercise parse/serialize since we already did that with |data|.
  57. IntegrityRecordRdata rand_record(IntegrityRecordRdata::Random());
  58. return 0;
  59. }
  60. } // namespace net