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 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/url_formatter/url_fixer.h"
#include <stdint.h>
#include <string>
#include <string_view>
#include <tuple>
#include "base/check.h"
#include "base/files/file_path.h"
#include "base/i18n/icu_util.h"
#include "base/logging.h"
#include "base/strings/escape.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/url_formatter/url_formatter.h"
#include "third_party/fuzztest/src/fuzztest/fuzztest.h"
#include "url/third_party/mozilla/url_parse.h"
namespace url_formatter {
namespace {
base::FilePath GenerateFuzzedFilePath(std::string_view valid_utf8_string) {
#if BUILDFLAG(IS_WIN)
return base::FilePath(base::UTF8ToWide(valid_utf8_string));
#else
return base::FilePath(valid_utf8_string);
#endif
}
// Theoretically, FuzzTest should be able to apply `.WithMaxSize()`
// onto the UTF-8 strings domain, but not right this moment.
static constexpr size_t kMaxFuzzerInputBytes = 100 * 1024;
// Initializes ICU tables for functions that require them.
class URLFixerFuzzer {
public:
URLFixerFuzzer() {
base::i18n::AllowMultipleInitializeCallsForTesting();
CHECK(base::i18n::InitializeICU());
}
~URLFixerFuzzer() = default;
void FuzzSegmentURL(std::string_view valid_utf8_string) {
if (valid_utf8_string.length() > kMaxFuzzerInputBytes) {
return;
}
url::Parsed parts;
std::ignore = url_formatter::SegmentURL(valid_utf8_string, &parts);
}
void FuzzUTF16SegmentURL(std::string_view valid_utf8_string) {
if (valid_utf8_string.length() > kMaxFuzzerInputBytes) {
return;
}
url::Parsed parts;
std::ignore =
url_formatter::SegmentURL(base::UTF8ToUTF16(valid_utf8_string), &parts);
}
void FuzzFormatURL(std::string_view first_valid_utf8_string,
url_formatter::FormatUrlType format_url_type,
base::UnescapeRule::Type unescape_rule_type) {
url::Parsed parsed;
GURL unparsed(first_valid_utf8_string);
url_formatter::FormatUrl(unparsed, format_url_type, unescape_rule_type,
&parsed, nullptr, nullptr);
}
void FuzzFixupURL(const std::string& first_valid_utf8_string,
const std::string& string_not_beginning_with_dot) {
if (first_valid_utf8_string.length() > kMaxFuzzerInputBytes ||
string_not_beginning_with_dot.length() > kMaxFuzzerInputBytes) {
return;
}
std::ignore = url_formatter::FixupURL(first_valid_utf8_string,
string_not_beginning_with_dot);
}
void FuzzFixupRelativeFile(std::string_view first_valid_utf8_string,
std::string_view second_valid_utf8_string) {
if (first_valid_utf8_string.length() > kMaxFuzzerInputBytes ||
second_valid_utf8_string.length() > kMaxFuzzerInputBytes) {
return;
}
std::ignore = url_formatter::FixupRelativeFile(
GenerateFuzzedFilePath(first_valid_utf8_string),
GenerateFuzzedFilePath(second_valid_utf8_string));
}
};
// Given the highest bit of an enum-ish bitflag, calculates the "max"
// value of the bitflag.
// Toy example: given `0b100`, the "maximal bitflag" would be `0b111`.
// Assumes without enforcing that `max_enum_bit` is a power of 2.
constexpr uint32_t MaxBitflagOf(uint32_t max_enum_bit) {
return (max_enum_bit << 1) - 1;
}
} // namespace
FUZZ_TEST_F(URLFixerFuzzer, FuzzSegmentURL).WithDomains(fuzztest::Utf8String());
FUZZ_TEST_F(URLFixerFuzzer, FuzzUTF16SegmentURL)
.WithDomains(fuzztest::Utf8String());
FUZZ_TEST_F(URLFixerFuzzer, FuzzFormatURL)
.WithDomains(
fuzztest::Utf8String(),
fuzztest::InRange(
0u,
MaxBitflagOf(url_formatter::kFormatUrlOmitMobilePrefix)),
fuzztest::InRange(
0u,
MaxBitflagOf(base::UnescapeRule::REPLACE_PLUS_WITH_SPACE)));
// `AddDesiredTLD()` will `DCHECK` that the TLD does _not_ begin
// with `.`.
FUZZ_TEST_F(URLFixerFuzzer, FuzzFixupURL)
.WithDomains(fuzztest::Utf8String(), fuzztest::InRegexp("^[^.].+"));
FUZZ_TEST_F(URLFixerFuzzer, FuzzFixupRelativeFile)
.WithDomains(fuzztest::Utf8String(), fuzztest::Utf8String());
} // namespace url_formatter
|