Coverage Report

Created: 2025-07-12 06:52

/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
38.0k
  UriHolder() {
28
38.0k
    memset((void *)&uri_, 0, sizeof(uri_));
29
38.0k
  }
30
31
76.0k
  ~UriHolder() {
32
76.0k
    URI_FUNC(FreeUriMembers)(&uri_);
33
76.0k
  }
UriHolder::~UriHolder()
Line
Count
Source
31
38.0k
  ~UriHolder() {
32
38.0k
    URI_FUNC(FreeUriMembers)(&uri_);
33
38.0k
  }
UriHolder::~UriHolder()
Line
Count
Source
31
38.0k
  ~UriHolder() {
32
38.0k
    URI_FUNC(FreeUriMembers)(&uri_);
33
38.0k
  }
34
35
75.9k
  URI_TYPE(Uri) * get() {
36
75.9k
    return &uri_;
37
75.9k
  }
38
39
private:
40
  URI_TYPE(Uri) uri_;
41
};
42
43
44
45
39.5k
void Escapes(const UriString & uri) {
46
39.5k
  const URI_CHAR * first = uri.c_str();
47
  // Up to 6 bytes per character with normalizeBreaks enabled (\n -> %0D%0A)
48
39.5k
  std::vector<URI_CHAR> buf1(uri.size() * 6 + 1);
49
  // and up to 3 bytes per character otherwise
50
39.5k
  std::vector<URI_CHAR> buf2(uri.size() * 3 + 1);
51
52
39.5k
  URI_CHAR * result;
53
39.5k
  result = URI_FUNC(Escape)(first, &buf1[0], URI_TRUE, URI_TRUE);
54
39.5k
  result = URI_FUNC(Escape)(first, &buf1[0], URI_FALSE, URI_TRUE);
55
39.5k
  if (buf1.data()) {
56
39.5k
    URI_FUNC(UnescapeInPlace)(&buf1[0]);
57
39.5k
  }
58
59
39.5k
  result = URI_FUNC(Escape)(first, &buf2[0], URI_TRUE, URI_FALSE);
60
39.5k
  result = URI_FUNC(Escape)(first, &buf2[0], URI_FALSE, URI_FALSE);
61
39.5k
  if (buf2.data()) {
62
39.5k
    URI_FUNC(UnescapeInPlace)(&buf2[0]);
63
39.5k
  }
64
39.5k
}
Escapes(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
45
18.8k
void Escapes(const UriString & uri) {
46
18.8k
  const URI_CHAR * first = uri.c_str();
47
  // Up to 6 bytes per character with normalizeBreaks enabled (\n -> %0D%0A)
48
18.8k
  std::vector<URI_CHAR> buf1(uri.size() * 6 + 1);
49
  // and up to 3 bytes per character otherwise
50
18.8k
  std::vector<URI_CHAR> buf2(uri.size() * 3 + 1);
51
52
18.8k
  URI_CHAR * result;
53
18.8k
  result = URI_FUNC(Escape)(first, &buf1[0], URI_TRUE, URI_TRUE);
54
18.8k
  result = URI_FUNC(Escape)(first, &buf1[0], URI_FALSE, URI_TRUE);
55
18.8k
  if (buf1.data()) {
56
18.8k
    URI_FUNC(UnescapeInPlace)(&buf1[0]);
57
18.8k
  }
58
59
18.8k
  result = URI_FUNC(Escape)(first, &buf2[0], URI_TRUE, URI_FALSE);
60
18.8k
  result = URI_FUNC(Escape)(first, &buf2[0], URI_FALSE, URI_FALSE);
61
18.8k
  if (buf2.data()) {
62
18.8k
    URI_FUNC(UnescapeInPlace)(&buf2[0]);
63
18.8k
  }
64
18.8k
}
Escapes(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&)
Line
Count
Source
45
20.6k
void Escapes(const UriString & uri) {
46
20.6k
  const URI_CHAR * first = uri.c_str();
47
  // Up to 6 bytes per character with normalizeBreaks enabled (\n -> %0D%0A)
48
20.6k
  std::vector<URI_CHAR> buf1(uri.size() * 6 + 1);
49
  // and up to 3 bytes per character otherwise
50
20.6k
  std::vector<URI_CHAR> buf2(uri.size() * 3 + 1);
51
52
20.6k
  URI_CHAR * result;
53
20.6k
  result = URI_FUNC(Escape)(first, &buf1[0], URI_TRUE, URI_TRUE);
54
20.6k
  result = URI_FUNC(Escape)(first, &buf1[0], URI_FALSE, URI_TRUE);
55
20.6k
  if (buf1.data()) {
56
20.6k
    URI_FUNC(UnescapeInPlace)(&buf1[0]);
57
20.6k
  }
58
59
20.6k
  result = URI_FUNC(Escape)(first, &buf2[0], URI_TRUE, URI_FALSE);
60
20.6k
  result = URI_FUNC(Escape)(first, &buf2[0], URI_FALSE, URI_FALSE);
61
20.6k
  if (buf2.data()) {
62
20.6k
    URI_FUNC(UnescapeInPlace)(&buf2[0]);
63
20.6k
  }
64
20.6k
}
65
66
67
68
39.5k
void FileNames(const UriString & uri) {
69
39.5k
  const size_t size = 8 + 3 * uri.size() + 1;
70
39.5k
  std::vector<URI_CHAR> buf(size);
71
72
39.5k
  URI_FUNC(UnixFilenameToUriString)(uri.c_str(), &buf[0]);
73
39.5k
  URI_FUNC(WindowsFilenameToUriString)(uri.c_str(), &buf[0]);
74
39.5k
  URI_FUNC(UriStringToUnixFilename)(uri.c_str(), &buf[0]);
75
39.5k
  URI_FUNC(UriStringToWindowsFilename)(uri.c_str(), &buf[0]);
76
39.5k
}
FileNames(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
68
18.8k
void FileNames(const UriString & uri) {
69
18.8k
  const size_t size = 8 + 3 * uri.size() + 1;
70
18.8k
  std::vector<URI_CHAR> buf(size);
71
72
18.8k
  URI_FUNC(UnixFilenameToUriString)(uri.c_str(), &buf[0]);
73
18.8k
  URI_FUNC(WindowsFilenameToUriString)(uri.c_str(), &buf[0]);
74
18.8k
  URI_FUNC(UriStringToUnixFilename)(uri.c_str(), &buf[0]);
75
18.8k
  URI_FUNC(UriStringToWindowsFilename)(uri.c_str(), &buf[0]);
76
18.8k
}
FileNames(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&)
Line
Count
Source
68
20.6k
void FileNames(const UriString & uri) {
69
20.6k
  const size_t size = 8 + 3 * uri.size() + 1;
70
20.6k
  std::vector<URI_CHAR> buf(size);
71
72
20.6k
  URI_FUNC(UnixFilenameToUriString)(uri.c_str(), &buf[0]);
73
20.6k
  URI_FUNC(WindowsFilenameToUriString)(uri.c_str(), &buf[0]);
74
20.6k
  URI_FUNC(UriStringToUnixFilename)(uri.c_str(), &buf[0]);
75
20.6k
  URI_FUNC(UriStringToWindowsFilename)(uri.c_str(), &buf[0]);
76
20.6k
}
77
78
79
80
39.5k
void Ipv4(const UriString & s) {
81
39.5k
  const URI_CHAR * cstr = s.c_str();
82
39.5k
  unsigned char result[4] = {};
83
39.5k
  URI_FUNC(ParseIpFourAddress)(result, cstr, &cstr[s.size()]);
84
39.5k
}
Ipv4(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
80
18.8k
void Ipv4(const UriString & s) {
81
18.8k
  const URI_CHAR * cstr = s.c_str();
82
18.8k
  unsigned char result[4] = {};
83
18.8k
  URI_FUNC(ParseIpFourAddress)(result, cstr, &cstr[s.size()]);
84
18.8k
}
Ipv4(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&)
Line
Count
Source
80
20.6k
void Ipv4(const UriString & s) {
81
20.6k
  const URI_CHAR * cstr = s.c_str();
82
20.6k
  unsigned char result[4] = {};
83
20.6k
  URI_FUNC(ParseIpFourAddress)(result, cstr, &cstr[s.size()]);
84
20.6k
}
85
86
87
88
39.5k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size) {
89
39.5k
  FuzzedDataProvider stream(data, size);
90
39.5k
  bool domainRelative = stream.ConsumeBool();
91
92
39.5k
  const UriString uri1 = consumeRandomLengthString(stream);
93
39.5k
  const UriString uri2 = consumeRemainingBytesAsString(stream);
94
95
39.5k
  Escapes(uri1);
96
39.5k
  Escapes(uri2);
97
98
39.5k
  FileNames(uri1);
99
39.5k
  FileNames(uri2);
100
101
39.5k
  Ipv4(uri1);
102
39.5k
  Ipv4(uri2);
103
104
39.5k
  UriHolder uriHolder1;
105
39.5k
  URI_TYPE(ParserState) state1;
106
39.5k
  state1.uri = uriHolder1.get();
107
39.5k
  if (URI_FUNC(ParseUri)(&state1, uri1.c_str()) != URI_SUCCESS) {
108
3.08k
    return 0;
109
3.08k
  }
110
111
36.4k
  URI_CHAR buf[1024 * 8] = {0};
112
36.4k
  int written = 0;
113
36.4k
  URI_FUNC(ToString)(buf, state1.uri, sizeof(buf) / sizeof(buf[0]), &written);
114
115
36.4k
  UriHolder uriHolder2;
116
36.4k
  if (URI_FUNC(ParseSingleUri)(uriHolder2.get(), uri2.c_str(), nullptr) != URI_SUCCESS) {
117
11.1k
    return 0;
118
11.1k
  }
119
120
25.3k
  URI_FUNC(EqualsUri)(state1.uri, uriHolder2.get());
121
122
25.3k
  unsigned int mask = 0;
123
25.3k
  URI_FUNC(NormalizeSyntaxMaskRequiredEx)(state1.uri, &mask);
124
25.3k
  URI_FUNC(NormalizeSyntax)(state1.uri);
125
126
25.3k
  URI_TYPE(Uri) absUri;
127
25.3k
  URI_FUNC(AddBaseUri)(&absUri, state1.uri, uriHolder2.get());
128
25.3k
  URI_FUNC(FreeUriMembers)(&absUri);
129
130
25.3k
  URI_TYPE(Uri) relUri;
131
25.3k
  URI_FUNC(RemoveBaseUri)(&relUri, state1.uri, uriHolder2.get(), domainRelative);
132
25.3k
  URI_FUNC(FreeUriMembers)(&relUri);
133
134
25.3k
  return 0;
135
36.4k
}
LLVMFuzzerTestOneInput
Line
Count
Source
88
19.7k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size) {
89
19.7k
  FuzzedDataProvider stream(data, size);
90
19.7k
  bool domainRelative = stream.ConsumeBool();
91
92
19.7k
  const UriString uri1 = consumeRandomLengthString(stream);
93
19.7k
  const UriString uri2 = consumeRemainingBytesAsString(stream);
94
95
19.7k
  Escapes(uri1);
96
19.7k
  Escapes(uri2);
97
98
19.7k
  FileNames(uri1);
99
19.7k
  FileNames(uri2);
100
101
19.7k
  Ipv4(uri1);
102
19.7k
  Ipv4(uri2);
103
104
19.7k
  UriHolder uriHolder1;
105
19.7k
  URI_TYPE(ParserState) state1;
106
19.7k
  state1.uri = uriHolder1.get();
107
19.7k
  if (URI_FUNC(ParseUri)(&state1, uri1.c_str()) != URI_SUCCESS) {
108
1.54k
    return 0;
109
1.54k
  }
110
111
18.2k
  URI_CHAR buf[1024 * 8] = {0};
112
18.2k
  int written = 0;
113
18.2k
  URI_FUNC(ToString)(buf, state1.uri, sizeof(buf) / sizeof(buf[0]), &written);
114
115
18.2k
  UriHolder uriHolder2;
116
18.2k
  if (URI_FUNC(ParseSingleUri)(uriHolder2.get(), uri2.c_str(), nullptr) != URI_SUCCESS) {
117
5.56k
    return 0;
118
5.56k
  }
119
120
12.6k
  URI_FUNC(EqualsUri)(state1.uri, uriHolder2.get());
121
122
12.6k
  unsigned int mask = 0;
123
12.6k
  URI_FUNC(NormalizeSyntaxMaskRequiredEx)(state1.uri, &mask);
124
12.6k
  URI_FUNC(NormalizeSyntax)(state1.uri);
125
126
12.6k
  URI_TYPE(Uri) absUri;
127
12.6k
  URI_FUNC(AddBaseUri)(&absUri, state1.uri, uriHolder2.get());
128
12.6k
  URI_FUNC(FreeUriMembers)(&absUri);
129
130
12.6k
  URI_TYPE(Uri) relUri;
131
12.6k
  URI_FUNC(RemoveBaseUri)(&relUri, state1.uri, uriHolder2.get(), domainRelative);
132
12.6k
  URI_FUNC(FreeUriMembers)(&relUri);
133
134
12.6k
  return 0;
135
18.2k
}
LLVMFuzzerTestOneInput
Line
Count
Source
88
19.7k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size) {
89
19.7k
  FuzzedDataProvider stream(data, size);
90
19.7k
  bool domainRelative = stream.ConsumeBool();
91
92
19.7k
  const UriString uri1 = consumeRandomLengthString(stream);
93
19.7k
  const UriString uri2 = consumeRemainingBytesAsString(stream);
94
95
19.7k
  Escapes(uri1);
96
19.7k
  Escapes(uri2);
97
98
19.7k
  FileNames(uri1);
99
19.7k
  FileNames(uri2);
100
101
19.7k
  Ipv4(uri1);
102
19.7k
  Ipv4(uri2);
103
104
19.7k
  UriHolder uriHolder1;
105
19.7k
  URI_TYPE(ParserState) state1;
106
19.7k
  state1.uri = uriHolder1.get();
107
19.7k
  if (URI_FUNC(ParseUri)(&state1, uri1.c_str()) != URI_SUCCESS) {
108
1.54k
    return 0;
109
1.54k
  }
110
111
18.2k
  URI_CHAR buf[1024 * 8] = {0};
112
18.2k
  int written = 0;
113
18.2k
  URI_FUNC(ToString)(buf, state1.uri, sizeof(buf) / sizeof(buf[0]), &written);
114
115
18.2k
  UriHolder uriHolder2;
116
18.2k
  if (URI_FUNC(ParseSingleUri)(uriHolder2.get(), uri2.c_str(), nullptr) != URI_SUCCESS) {
117
5.56k
    return 0;
118
5.56k
  }
119
120
12.6k
  URI_FUNC(EqualsUri)(state1.uri, uriHolder2.get());
121
122
12.6k
  unsigned int mask = 0;
123
12.6k
  URI_FUNC(NormalizeSyntaxMaskRequiredEx)(state1.uri, &mask);
124
12.6k
  URI_FUNC(NormalizeSyntax)(state1.uri);
125
126
12.6k
  URI_TYPE(Uri) absUri;
127
12.6k
  URI_FUNC(AddBaseUri)(&absUri, state1.uri, uriHolder2.get());
128
12.6k
  URI_FUNC(FreeUriMembers)(&absUri);
129
130
12.6k
  URI_TYPE(Uri) relUri;
131
12.6k
  URI_FUNC(RemoveBaseUri)(&relUri, state1.uri, uriHolder2.get(), domainRelative);
132
12.6k
  URI_FUNC(FreeUriMembers)(&relUri);
133
134
12.6k
  return 0;
135
18.2k
}