File: url_fixer_fuzzer.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (130 lines) | stat: -rw-r--r-- 4,372 bytes parent folder | download | duplicates (3)
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