diff --git a/content/DEPS b/content/DEPS index d09ff525c6331..a3b7b7d10b56f 100644 --- a/content/DEPS +++ b/content/DEPS @@ -146,6 +146,11 @@ specific_include_rules = { # content -> tools dependency is disallowed, except buildflags for switches. "+tools/v8_context_snapshot/buildflags.h", ], + ".*_unittest\.(cc|h|m)": [ + # unittests can now embed fuzzing tests, and this dependency is needed to + # access FUZZ_TEST macro and various domain generators. + "+third_party/fuzztest", + ], } new_usages_require_review = True diff --git a/content/browser/first_party_sets/first_party_set_parser_unittest.cc b/content/browser/first_party_sets/first_party_set_parser_unittest.cc index 77598c491f315..d3aef532ad7e9 100644 --- a/content/browser/first_party_sets/first_party_set_parser_unittest.cc +++ b/content/browser/first_party_sets/first_party_set_parser_unittest.cc @@ -8,6 +8,9 @@ #include <sstream> #include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/rand_util.h" +#include "base/test/fuzztest_support.h" #include "base/test/metrics/histogram_tester.h" #include "base/version.h" #include "content/public/browser/first_party_sets_handler.h" @@ -19,6 +22,7 @@ #include "net/first_party_sets/sets_mutation.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/fuzztest/src/fuzztest/fuzztest.h" #include "url/gurl.h" using ::testing::ElementsAre; @@ -1766,4 +1770,42 @@ TEST(FirstPartySetParser, /*aliases=*/{{associated2_cctld, associated2}})); } +void ParsesSetsCorrectly(std::string input) { + std::istringstream stream(input); + FirstPartySetParser::ParseSetsFromStream(stream, base::Version("1.0"), false, + false); +} + +auto JsonDomain() { + return fuzztest::ReversibleMap( + // The mapping function maps a base::Value to its JSON string + // representation. + [](base::Value value) { + std::string res; + base::JSONWriter::Write(std::move(value), &res); + return res; + }, + // The inverse mapping function maps the JSON string representation to + // a tuple of base::Value. The return value is additionally wrapped in + // std::optional. + [](const std::string& value) -> std::optional<std::tuple<base::Value>> { + auto res = base::JSONReader::Read(value); + if (!res) { + return std::nullopt; + } + // We use a tuple because the FuzzTest API requires it, since the + // inverse mapping can map one input value to multiple output values. + return std::tuple{std::move(*res)}; + }, + fuzztest::Arbitrary<base::Value>()); +} + +FUZZ_TEST(FirstPartySetFuzzer, ParsesSetsCorrectly) + .WithDomains(fuzztest::OneOf(JsonDomain(), + fuzztest::Arbitrary<std::string>().WithSeeds( + []() -> std::vector<std::string> { + auto domain = JsonDomain(); + return {domain.GetRandomValue( + base::RandomBitGenerator())}; + }))); } // namespace content diff --git a/content/browser/first_party_sets/test/first_party_set_parser_fuzzer.cc b/content/browser/first_party_sets/test/first_party_set_parser_fuzzer.cc deleted file mode 100644 index 53500c0099249..0000000000000 --- a/content/browser/first_party_sets/test/first_party_set_parser_fuzzer.cc +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/first_party_sets/first_party_set_parser.h" - -#include <cstdint> -#include <memory> -#include <sstream> - -#include "base/version.h" - -namespace content { - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - std::string string_input(reinterpret_cast<const char*>(data), size); - std::istringstream stream(string_input); - FirstPartySetParser::ParseSetsFromStream(stream, base::Version("1.0"), false, - false); - - return 0; -} - -} // namespace content diff --git a/content/browser/first_party_sets/test/first_party_set_parser_fuzzer.dict b/content/browser/first_party_sets/test/first_party_set_parser_fuzzer.dict deleted file mode 100644 index e9488082991f4..0000000000000 --- a/content/browser/first_party_sets/test/first_party_set_parser_fuzzer.dict +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2020 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"{" -"}" -"[" -"]" -"\"" -"'" -"\\" -"//" -":" -"," -" " -"\\n" -"\\r" -"/*" -"*/" -"true" -"false" -"null" -"\\u" -"\\b" -"\\f" -"\\t" -"." -"e" -"e+" -"e-" -"E" -"E+" -"E-" -"owner" -"members" diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 31c72f85c42e3..5ab3088a8d2f1 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn @@ -2962,6 +2962,7 @@ test("content_unittests") { fuzztests = [ "BiddingAndAuctionSerializerTargetSizeEstimator.DoesNotCrashForAnyInput", "ActionsParserFuzzTest.ParsesJSONCorrectly", + "FirstPartySetFuzzer.ParsesSetsCorrectly", ] if (is_mac) { diff --git a/content/test/fuzzer/BUILD.gn b/content/test/fuzzer/BUILD.gn index 167796972d1c3..287e0dbd7037d 100644 --- a/content/test/fuzzer/BUILD.gn +++ b/content/test/fuzzer/BUILD.gn @@ -332,15 +332,6 @@ if (use_fuzzing_engine) { } } -fuzzer_test("first_party_set_parser_fuzzer") { - sources = - [ "../../browser/first_party_sets/test/first_party_set_parser_fuzzer.cc" ] - deps = [ ":first_party_set_parser_fuzzer_support" ] - dict = - "../../browser/first_party_sets/test/first_party_set_parser_fuzzer.dict" - seed_corpus = "//third_party/grpc/source/test/core/json/corpus/" -} - fuzzer_test("first_party_set_parser_json_fuzzer") { sources = [ "../../browser/first_party_sets/test/first_party_set_parser_json_fuzzer.cc",