Coverage Report

Created: 2026-04-12 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ada-url/fuzz/can_parse.cc
Line
Count
Source
1
#include <fuzzer/FuzzedDataProvider.h>
2
3
#include <cstdio>
4
#include <memory>
5
#include <string>
6
7
#include "ada.cpp"
8
#include "ada.h"
9
10
7.06k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
11
7.06k
  FuzzedDataProvider fdp(data, size);
12
7.06k
  std::string source = fdp.ConsumeRandomLengthString(256);
13
7.06k
  std::string base_source = fdp.ConsumeRandomLengthString(256);
14
15
  /**
16
   * ada::can_parse consistency checks.
17
   *
18
   * can_parse() must agree with parse().has_value() in all cases.
19
   * This invariant must hold regardless of input encoding.
20
   */
21
22
  // Test 1: can_parse(source) must equal
23
  // parse<url_aggregator>(source).has_value()
24
7.06k
  bool can_parse_result = ada::can_parse(source);
25
7.06k
  auto parsed_agg = ada::parse<ada::url_aggregator>(source);
26
7.06k
  if (can_parse_result != parsed_agg.has_value()) {
27
0
    printf("can_parse vs parse<url_aggregator> inconsistency for: %s\n",
28
0
           source.c_str());
29
0
    abort();
30
0
  }
31
32
  // Test 2: can_parse(source) must also equal parse<url>(source).has_value()
33
7.06k
  auto parsed_url = ada::parse<ada::url>(source);
34
7.06k
  if (can_parse_result != parsed_url.has_value()) {
35
0
    printf("can_parse vs parse<url> inconsistency for: %s\n", source.c_str());
36
0
    abort();
37
0
  }
38
39
  // Test 3: can_parse with base
40
7.06k
  auto base_source_view =
41
7.06k
      std::string_view(base_source.data(), base_source.length());
42
7.06k
  bool can_parse_with_base = ada::can_parse(source, &base_source_view);
43
44
  // Test 4: can_parse(source, base) must equal parse<url_aggregator>(source,
45
  // base).has_value()
46
7.06k
  auto base_agg = ada::parse<ada::url_aggregator>(base_source);
47
7.06k
  if (base_agg) {
48
2.46k
    auto parsed_with_base = ada::parse<ada::url_aggregator>(source, &*base_agg);
49
2.46k
    if (can_parse_with_base != parsed_with_base.has_value()) {
50
0
      printf(
51
0
          "can_parse_with_base vs parse<url_aggregator> inconsistency for "
52
0
          "source=%s base=%s\n",
53
0
          source.c_str(), base_source.c_str());
54
0
      abort();
55
0
    }
56
2.46k
  }
57
58
  // Test 5: Empty string edge cases
59
7.06k
  {
60
7.06k
    std::string_view empty_view;
61
7.06k
    bool empty_can_parse = ada::can_parse("");
62
7.06k
    auto empty_parsed = ada::parse<ada::url_aggregator>("");
63
7.06k
    if (empty_can_parse != empty_parsed.has_value()) {
64
0
      printf("Empty string can_parse inconsistency\n");
65
0
      abort();
66
0
    }
67
7.06k
  }
68
69
  // Test 6: href round-trip.
70
  //
71
  // If parse(source) succeeds, can_parse(href) must return true and
72
  // re-parsing the href must produce the same href (idempotency).
73
  // This verifies that the serialised form of every parsed URL is itself
74
  // a valid absolute URL that round-trips perfectly.
75
7.06k
  if (parsed_agg) {
76
3.26k
    std::string href = std::string(parsed_agg->get_href());
77
78
    // can_parse must accept the normalised href.
79
3.26k
    if (!ada::can_parse(href)) {
80
0
      printf("can_parse rejected normalised href: '%s'\n", href.c_str());
81
0
      abort();
82
0
    }
83
84
    // Re-parsing the href must succeed.
85
3.26k
    auto reparsed = ada::parse<ada::url_aggregator>(href);
86
3.26k
    if (!reparsed) {
87
0
      printf("Re-parse of href failed: '%s'\n", href.c_str());
88
0
      abort();
89
0
    }
90
91
    // The href of the re-parsed URL must equal the original href.
92
3.26k
    std::string href2 = std::string(reparsed->get_href());
93
3.26k
    if (href2 != href) {
94
0
      printf(
95
0
          "href idempotency failure!\n"
96
0
          "  href1: %s\n  href2: %s\n",
97
0
          href.c_str(), href2.c_str());
98
0
      abort();
99
0
    }
100
101
    // url and url_aggregator must agree on whether the href is parseable.
102
3.26k
    bool url_can_parse = ada::parse<ada::url>(href).has_value();
103
3.26k
    if (url_can_parse != ada::can_parse(href)) {
104
0
      printf("parse<url> vs can_parse disagreement on normalised href: '%s'\n",
105
0
             href.c_str());
106
0
      abort();
107
0
    }
108
3.26k
  }
109
110
7.06k
  (void)can_parse_result;
111
7.06k
  (void)can_parse_with_base;
112
113
7.06k
  return 0;
114
7.06k
}