Coverage Report

Created: 2026-02-14 06:22

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