Coverage Report

Created: 2025-08-29 06:30

/src/uriparser/fuzz/ParseFuzzer.cpp
Line
Count
Source
1
// Copyright 2020 Google LLC
2
// Copyright 2025 Mikhail Khachaiants <mkhachaiants@gmail.com>
3
//
4
// Licensed under the Apache License, Version 2.0 (the "License");
5
// you may not use this file except in compliance with the License.
6
// You may obtain a copy of the License at
7
//
8
//      http://www.apache.org/licenses/LICENSE-2.0
9
//
10
// Unless required by applicable law or agreed to in writing, software
11
// distributed under the License is distributed on an "AS IS" BASIS,
12
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
// See the License for the specific language governing permissions and
14
// limitations under the License.
15
16
#include "uriparser/Uri.h"
17
#include "uriparser/UriIp4.h"
18
#include "FuzzingUtils.h"
19
#include <cstddef>
20
#include <cstring>
21
#include <vector>
22
23
24
25
class UriHolder {
26
public:
27
41.3k
  UriHolder() {
28
41.3k
    memset((void *)&uri_, 0, sizeof(uri_));
29
41.3k
  }
30
31
82.6k
  ~UriHolder() {
32
82.6k
    URI_FUNC(FreeUriMembers)(&uri_);
33
82.6k
  }
UriHolder::~UriHolder()
Line
Count
Source
31
41.3k
  ~UriHolder() {
32
41.3k
    URI_FUNC(FreeUriMembers)(&uri_);
33
41.3k
  }
UriHolder::~UriHolder()
Line
Count
Source
31
41.3k
  ~UriHolder() {
32
41.3k
    URI_FUNC(FreeUriMembers)(&uri_);
33
41.3k
  }
34
35
83.1k
  URI_TYPE(Uri) * get() {
36
83.1k
    return &uri_;
37
83.1k
  }
38
39
private:
40
  URI_TYPE(Uri) uri_;
41
};
42
43
44
45
42.9k
void Escapes(const UriString & uri) {
46
42.9k
  const URI_CHAR * first = uri.c_str();
47
  // Up to 6 bytes per character with normalizeBreaks enabled (\n -> %0D%0A)
48
42.9k
  std::vector<URI_CHAR> buf1(uri.size() * 6 + 1);
49
  // and up to 3 bytes per character otherwise
50
42.9k
  std::vector<URI_CHAR> buf2(uri.size() * 3 + 1);
51
52
42.9k
  URI_CHAR * result;
53
42.9k
  result = URI_FUNC(Escape)(first, &buf1[0], URI_TRUE, URI_TRUE);
54
42.9k
  result = URI_FUNC(Escape)(first, &buf1[0], URI_FALSE, URI_TRUE);
55
42.9k
  if (buf1.data()) {
56
42.9k
    URI_FUNC(UnescapeInPlace)(&buf1[0]);
57
42.9k
  }
58
59
42.9k
  result = URI_FUNC(Escape)(first, &buf2[0], URI_TRUE, URI_FALSE);
60
42.9k
  result = URI_FUNC(Escape)(first, &buf2[0], URI_FALSE, URI_FALSE);
61
42.9k
  if (buf2.data()) {
62
42.9k
    URI_FUNC(UnescapeInPlace)(&buf2[0]);
63
42.9k
  }
64
42.9k
}
Escapes(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
45
20.7k
void Escapes(const UriString & uri) {
46
20.7k
  const URI_CHAR * first = uri.c_str();
47
  // Up to 6 bytes per character with normalizeBreaks enabled (\n -> %0D%0A)
48
20.7k
  std::vector<URI_CHAR> buf1(uri.size() * 6 + 1);
49
  // and up to 3 bytes per character otherwise
50
20.7k
  std::vector<URI_CHAR> buf2(uri.size() * 3 + 1);
51
52
20.7k
  URI_CHAR * result;
53
20.7k
  result = URI_FUNC(Escape)(first, &buf1[0], URI_TRUE, URI_TRUE);
54
20.7k
  result = URI_FUNC(Escape)(first, &buf1[0], URI_FALSE, URI_TRUE);
55
20.7k
  if (buf1.data()) {
56
20.7k
    URI_FUNC(UnescapeInPlace)(&buf1[0]);
57
20.7k
  }
58
59
20.7k
  result = URI_FUNC(Escape)(first, &buf2[0], URI_TRUE, URI_FALSE);
60
20.7k
  result = URI_FUNC(Escape)(first, &buf2[0], URI_FALSE, URI_FALSE);
61
20.7k
  if (buf2.data()) {
62
20.7k
    URI_FUNC(UnescapeInPlace)(&buf2[0]);
63
20.7k
  }
64
20.7k
}
Escapes(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&)
Line
Count
Source
45
22.2k
void Escapes(const UriString & uri) {
46
22.2k
  const URI_CHAR * first = uri.c_str();
47
  // Up to 6 bytes per character with normalizeBreaks enabled (\n -> %0D%0A)
48
22.2k
  std::vector<URI_CHAR> buf1(uri.size() * 6 + 1);
49
  // and up to 3 bytes per character otherwise
50
22.2k
  std::vector<URI_CHAR> buf2(uri.size() * 3 + 1);
51
52
22.2k
  URI_CHAR * result;
53
22.2k
  result = URI_FUNC(Escape)(first, &buf1[0], URI_TRUE, URI_TRUE);
54
22.2k
  result = URI_FUNC(Escape)(first, &buf1[0], URI_FALSE, URI_TRUE);
55
22.2k
  if (buf1.data()) {
56
22.2k
    URI_FUNC(UnescapeInPlace)(&buf1[0]);
57
22.2k
  }
58
59
22.2k
  result = URI_FUNC(Escape)(first, &buf2[0], URI_TRUE, URI_FALSE);
60
22.2k
  result = URI_FUNC(Escape)(first, &buf2[0], URI_FALSE, URI_FALSE);
61
22.2k
  if (buf2.data()) {
62
22.2k
    URI_FUNC(UnescapeInPlace)(&buf2[0]);
63
22.2k
  }
64
22.2k
}
65
66
67
68
42.9k
void FileNames(const UriString & uri) {
69
42.9k
  const size_t size = 8 + 3 * uri.size() + 1;
70
42.9k
  std::vector<URI_CHAR> buf(size);
71
72
42.9k
  URI_FUNC(UnixFilenameToUriString)(uri.c_str(), &buf[0]);
73
42.9k
  URI_FUNC(WindowsFilenameToUriString)(uri.c_str(), &buf[0]);
74
42.9k
  URI_FUNC(UriStringToUnixFilename)(uri.c_str(), &buf[0]);
75
42.9k
  URI_FUNC(UriStringToWindowsFilename)(uri.c_str(), &buf[0]);
76
42.9k
}
FileNames(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
68
20.7k
void FileNames(const UriString & uri) {
69
20.7k
  const size_t size = 8 + 3 * uri.size() + 1;
70
20.7k
  std::vector<URI_CHAR> buf(size);
71
72
20.7k
  URI_FUNC(UnixFilenameToUriString)(uri.c_str(), &buf[0]);
73
20.7k
  URI_FUNC(WindowsFilenameToUriString)(uri.c_str(), &buf[0]);
74
20.7k
  URI_FUNC(UriStringToUnixFilename)(uri.c_str(), &buf[0]);
75
20.7k
  URI_FUNC(UriStringToWindowsFilename)(uri.c_str(), &buf[0]);
76
20.7k
}
FileNames(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&)
Line
Count
Source
68
22.2k
void FileNames(const UriString & uri) {
69
22.2k
  const size_t size = 8 + 3 * uri.size() + 1;
70
22.2k
  std::vector<URI_CHAR> buf(size);
71
72
22.2k
  URI_FUNC(UnixFilenameToUriString)(uri.c_str(), &buf[0]);
73
22.2k
  URI_FUNC(WindowsFilenameToUriString)(uri.c_str(), &buf[0]);
74
22.2k
  URI_FUNC(UriStringToUnixFilename)(uri.c_str(), &buf[0]);
75
22.2k
  URI_FUNC(UriStringToWindowsFilename)(uri.c_str(), &buf[0]);
76
22.2k
}
77
78
79
80
42.9k
void Ipv4(const UriString & s) {
81
42.9k
  const URI_CHAR * cstr = s.c_str();
82
42.9k
  unsigned char result[4] = {};
83
42.9k
  URI_FUNC(ParseIpFourAddress)(result, cstr, &cstr[s.size()]);
84
42.9k
}
Ipv4(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
80
20.7k
void Ipv4(const UriString & s) {
81
20.7k
  const URI_CHAR * cstr = s.c_str();
82
20.7k
  unsigned char result[4] = {};
83
20.7k
  URI_FUNC(ParseIpFourAddress)(result, cstr, &cstr[s.size()]);
84
20.7k
}
Ipv4(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&)
Line
Count
Source
80
22.2k
void Ipv4(const UriString & s) {
81
22.2k
  const URI_CHAR * cstr = s.c_str();
82
22.2k
  unsigned char result[4] = {};
83
22.2k
  URI_FUNC(ParseIpFourAddress)(result, cstr, &cstr[s.size()]);
84
22.2k
}
85
86
87
88
42.9k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size) {
89
42.9k
  FuzzedDataProvider stream(data, size);
90
42.9k
  bool domainRelative = stream.ConsumeBool();
91
92
42.9k
  const UriString uri1 = consumeRandomLengthString(stream);
93
42.9k
  const UriString uri2 = consumeRemainingBytesAsString(stream);
94
95
42.9k
  Escapes(uri1);
96
42.9k
  Escapes(uri2);
97
98
42.9k
  FileNames(uri1);
99
42.9k
  FileNames(uri2);
100
101
42.9k
  Ipv4(uri1);
102
42.9k
  Ipv4(uri2);
103
104
42.9k
  UriHolder uriHolder1;
105
42.9k
  URI_TYPE(ParserState) state1;
106
42.9k
  state1.uri = uriHolder1.get();
107
42.9k
  if (URI_FUNC(ParseUri)(&state1, uri1.c_str()) != URI_SUCCESS) {
108
3.20k
    return 0;
109
3.20k
  }
110
111
39.7k
  URI_CHAR buf[1024 * 8] = {0};
112
39.7k
  int written = 0;
113
39.7k
  URI_FUNC(ToString)(buf, state1.uri, sizeof(buf) / sizeof(buf[0]), &written);
114
115
39.7k
  UriHolder uriHolder2;
116
39.7k
  if (URI_FUNC(ParseSingleUri)(uriHolder2.get(), uri2.c_str(), nullptr) != URI_SUCCESS) {
117
11.8k
    return 0;
118
11.8k
  }
119
120
27.8k
  URI_FUNC(EqualsUri)(state1.uri, uriHolder2.get());
121
122
27.8k
  unsigned int mask = 0;
123
27.8k
  URI_FUNC(NormalizeSyntaxMaskRequiredEx)(state1.uri, &mask);
124
27.8k
  URI_FUNC(NormalizeSyntax)(state1.uri);
125
126
27.8k
  URI_TYPE(Uri) absUri;
127
27.8k
  URI_FUNC(AddBaseUri)(&absUri, state1.uri, uriHolder2.get());
128
27.8k
  URI_FUNC(FreeUriMembers)(&absUri);
129
130
27.8k
  URI_TYPE(Uri) relUri;
131
27.8k
  URI_FUNC(RemoveBaseUri)(&relUri, state1.uri, uriHolder2.get(), domainRelative);
132
27.8k
  URI_FUNC(FreeUriMembers)(&relUri);
133
134
27.8k
  return 0;
135
39.7k
}
LLVMFuzzerTestOneInput
Line
Count
Source
88
21.4k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size) {
89
21.4k
  FuzzedDataProvider stream(data, size);
90
21.4k
  bool domainRelative = stream.ConsumeBool();
91
92
21.4k
  const UriString uri1 = consumeRandomLengthString(stream);
93
21.4k
  const UriString uri2 = consumeRemainingBytesAsString(stream);
94
95
21.4k
  Escapes(uri1);
96
21.4k
  Escapes(uri2);
97
98
21.4k
  FileNames(uri1);
99
21.4k
  FileNames(uri2);
100
101
21.4k
  Ipv4(uri1);
102
21.4k
  Ipv4(uri2);
103
104
21.4k
  UriHolder uriHolder1;
105
21.4k
  URI_TYPE(ParserState) state1;
106
21.4k
  state1.uri = uriHolder1.get();
107
21.4k
  if (URI_FUNC(ParseUri)(&state1, uri1.c_str()) != URI_SUCCESS) {
108
1.60k
    return 0;
109
1.60k
  }
110
111
19.8k
  URI_CHAR buf[1024 * 8] = {0};
112
19.8k
  int written = 0;
113
19.8k
  URI_FUNC(ToString)(buf, state1.uri, sizeof(buf) / sizeof(buf[0]), &written);
114
115
19.8k
  UriHolder uriHolder2;
116
19.8k
  if (URI_FUNC(ParseSingleUri)(uriHolder2.get(), uri2.c_str(), nullptr) != URI_SUCCESS) {
117
5.94k
    return 0;
118
5.94k
  }
119
120
13.9k
  URI_FUNC(EqualsUri)(state1.uri, uriHolder2.get());
121
122
13.9k
  unsigned int mask = 0;
123
13.9k
  URI_FUNC(NormalizeSyntaxMaskRequiredEx)(state1.uri, &mask);
124
13.9k
  URI_FUNC(NormalizeSyntax)(state1.uri);
125
126
13.9k
  URI_TYPE(Uri) absUri;
127
13.9k
  URI_FUNC(AddBaseUri)(&absUri, state1.uri, uriHolder2.get());
128
13.9k
  URI_FUNC(FreeUriMembers)(&absUri);
129
130
13.9k
  URI_TYPE(Uri) relUri;
131
13.9k
  URI_FUNC(RemoveBaseUri)(&relUri, state1.uri, uriHolder2.get(), domainRelative);
132
13.9k
  URI_FUNC(FreeUriMembers)(&relUri);
133
134
13.9k
  return 0;
135
19.8k
}
LLVMFuzzerTestOneInput
Line
Count
Source
88
21.4k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size) {
89
21.4k
  FuzzedDataProvider stream(data, size);
90
21.4k
  bool domainRelative = stream.ConsumeBool();
91
92
21.4k
  const UriString uri1 = consumeRandomLengthString(stream);
93
21.4k
  const UriString uri2 = consumeRemainingBytesAsString(stream);
94
95
21.4k
  Escapes(uri1);
96
21.4k
  Escapes(uri2);
97
98
21.4k
  FileNames(uri1);
99
21.4k
  FileNames(uri2);
100
101
21.4k
  Ipv4(uri1);
102
21.4k
  Ipv4(uri2);
103
104
21.4k
  UriHolder uriHolder1;
105
21.4k
  URI_TYPE(ParserState) state1;
106
21.4k
  state1.uri = uriHolder1.get();
107
21.4k
  if (URI_FUNC(ParseUri)(&state1, uri1.c_str()) != URI_SUCCESS) {
108
1.60k
    return 0;
109
1.60k
  }
110
111
19.8k
  URI_CHAR buf[1024 * 8] = {0};
112
19.8k
  int written = 0;
113
19.8k
  URI_FUNC(ToString)(buf, state1.uri, sizeof(buf) / sizeof(buf[0]), &written);
114
115
19.8k
  UriHolder uriHolder2;
116
19.8k
  if (URI_FUNC(ParseSingleUri)(uriHolder2.get(), uri2.c_str(), nullptr) != URI_SUCCESS) {
117
5.94k
    return 0;
118
5.94k
  }
119
120
13.9k
  URI_FUNC(EqualsUri)(state1.uri, uriHolder2.get());
121
122
13.9k
  unsigned int mask = 0;
123
13.9k
  URI_FUNC(NormalizeSyntaxMaskRequiredEx)(state1.uri, &mask);
124
13.9k
  URI_FUNC(NormalizeSyntax)(state1.uri);
125
126
13.9k
  URI_TYPE(Uri) absUri;
127
13.9k
  URI_FUNC(AddBaseUri)(&absUri, state1.uri, uriHolder2.get());
128
13.9k
  URI_FUNC(FreeUriMembers)(&absUri);
129
130
13.9k
  URI_TYPE(Uri) relUri;
131
13.9k
  URI_FUNC(RemoveBaseUri)(&relUri, state1.uri, uriHolder2.get(), domainRelative);
132
13.9k
  URI_FUNC(FreeUriMembers)(&relUri);
133
134
13.9k
  return 0;
135
19.8k
}