Coverage Report

Created: 2025-11-11 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ada-url/fuzz/url_pattern.cc
Line
Count
Source
1
#include <fuzzer/FuzzedDataProvider.h>
2
3
#include <memory>
4
#include <string>
5
6
#include "ada.cpp"
7
#include "ada.h"
8
9
using regex_provider = ada::url_pattern_regex::std_regex_provider;
10
11
3.87k
void exercise_result(auto result) {
12
3.87k
  (void)result.get_protocol();
13
3.87k
  (void)result.get_username();
14
3.87k
  (void)result.get_password();
15
3.87k
  (void)result.get_hostname();
16
3.87k
  (void)result.get_port();
17
3.87k
  (void)result.get_pathname();
18
3.87k
  (void)result.get_search();
19
3.87k
  (void)result.get_hash();
20
3.87k
  (void)result.ignore_case();
21
3.87k
  (void)result.has_regexp_groups();
22
3.87k
}
23
24
1.29k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
25
7.75k
  auto to_ascii = [](const std::string& source) -> std::string {
26
7.75k
    std::string result;
27
7.75k
    result.reserve(source.size());
28
28.6k
    for (char c : source) {
29
28.6k
      result.push_back(static_cast<unsigned char>(c) % 128);
30
28.6k
    }
31
7.75k
    return result;
32
7.75k
  };
33
1.29k
  FuzzedDataProvider fdp(data, size);
34
  // We do not want to trigger arbitrary regex matching.
35
1.29k
  std::string source_1 = "/" + to_ascii(fdp.ConsumeRandomLengthString(50)) +
36
1.29k
                         "/" + to_ascii(fdp.ConsumeRandomLengthString(50));
37
1.29k
  std::string base_source_1 = "/" +
38
1.29k
                              to_ascii(fdp.ConsumeRandomLengthString(50)) +
39
1.29k
                              "/" + to_ascii(fdp.ConsumeRandomLengthString(50));
40
41
1.29k
  std::string source_2 = "https://ada-url.com/*";
42
1.29k
  std::string base_source_2 = "https://ada-url.com";
43
44
1.29k
  std::array<std::pair<std::string, std::string>, 2> sources = {{
45
1.29k
      {source_1, base_source_1},
46
1.29k
      {source_2, base_source_2},
47
1.29k
  }};
48
49
2.58k
  for (const auto& [source, base_source] : sources) {
50
    // Without base or options
51
2.58k
    auto result =
52
2.58k
        ada::parse_url_pattern<regex_provider>(source, nullptr, nullptr);
53
2.58k
    if (result) exercise_result(*result);
54
55
    // Testing with base_url
56
2.58k
    std::string_view base_source_view(base_source.data(), base_source.length());
57
2.58k
    auto result_with_base = ada::parse_url_pattern<regex_provider>(
58
2.58k
        source, &base_source_view, nullptr);
59
2.58k
    if (result_with_base) exercise_result(*result_with_base);
60
61
    // Testing with base_url and options
62
2.58k
    ada::url_pattern_options options{.ignore_case = fdp.ConsumeBool()};
63
2.58k
    auto result_with_base_and_options = ada::parse_url_pattern<regex_provider>(
64
2.58k
        source, &base_source_view, &options);
65
2.58k
    if (result_with_base_and_options)
66
1.29k
      exercise_result(*result_with_base_and_options);
67
68
    // Testing with url_pattern_init and base url.
69
2.58k
    int field_index = fdp.ConsumeIntegralInRange(0, 7);
70
2.58k
    std::string random_value = to_ascii(fdp.ConsumeRandomLengthString(50));
71
2.58k
    ada::url_pattern_init init{};
72
2.58k
    switch (field_index) {
73
2.41k
      case 0:
74
2.41k
        init.protocol = random_value;
75
2.41k
        break;
76
19
      case 1:
77
19
        init.username = random_value;
78
19
        break;
79
28
      case 2:
80
28
        init.password = random_value;
81
28
        break;
82
23
      case 3:
83
23
        init.hostname = random_value;
84
23
        break;
85
37
      case 4:
86
37
        init.port = random_value;
87
37
        break;
88
20
      case 5:
89
20
        init.pathname = random_value;
90
20
        break;
91
17
      case 6:
92
17
        init.search = random_value;
93
17
        break;
94
26
      case 7:
95
26
        init.hash = random_value;
96
26
        break;
97
2.58k
    }
98
2.58k
    auto result_with_init = ada::parse_url_pattern<regex_provider>(
99
2.58k
        init, &base_source_view, nullptr);
100
2.58k
    if (result_with_init) exercise_result(*result_with_init);
101
2.58k
  }
102
103
1.29k
  return 0;
104
1.29k
}