Coverage Report

Created: 2025-12-10 07:00

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