• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <cstddef>
16 #include <cstring>
17 #include <string>
18 #include <vector>
19 #include <fuzzer/FuzzedDataProvider.h>
20 
21 using std::string;
22 #include "uriparser/include/uriparser/Uri.h"
23 #include "uriparser/include/uriparser/UriIp4.h"
24 
25 class UriParserA {
26  public:
UriParserA()27   UriParserA() { memset((void *)&uri_, 0, sizeof(uri_)); }
~UriParserA()28   ~UriParserA() { uriFreeUriMembersA(&uri_); }
29 
get_mutable_uri()30   UriUriA *get_mutable_uri() { return &uri_; }
get_uri() const31   UriUriA *get_uri() const { return const_cast<UriUriA *>(&uri_); }
32 
33  private:
34   UriUriA uri_;
35 };
36 
Escapes(const string & uri)37 void Escapes(const string &uri) {
38   const char *first = uri.c_str();
39   // A new line char takes 6 char to encode.
40   // Use a vector to make a C string.
41   std::vector<char> buf1(uri.size() * 6 + 1);
42   std::vector<char> buf2(uri.size() * 3 + 1);
43 
44   char *result;
45   result = uriEscapeA(first, &buf1[0], URI_TRUE, URI_TRUE);
46   result = uriEscapeA(first, &buf1[0], URI_FALSE, URI_TRUE);
47   if (buf1.data()) uriUnescapeInPlaceA(&buf1[0]);
48 
49   result = uriEscapeA(first, &buf2[0], URI_TRUE, URI_FALSE);
50   result = uriEscapeA(first, &buf2[0], URI_FALSE, URI_FALSE);
51   if (buf2.data()) uriUnescapeInPlaceA(&buf2[0]);
52 }
53 
FileNames(const string & uri)54 void FileNames(const string &uri) {
55   const size_t size = 8 + 3 * uri.size() + 1;
56   std::vector<char> buf(size);
57 
58   uriUnixFilenameToUriStringA(uri.c_str(), &buf[0]);
59   uriWindowsFilenameToUriStringA(uri.c_str(), &buf[0]);
60   uriUriStringToUnixFilenameA(uri.c_str(), &buf[0]);
61   uriUriStringToWindowsFilenameA(uri.c_str(), &buf[0]);
62 }
63 
64 int uriParseIpFourAddressA(unsigned char *octetOutput, const char *first,
65                            const char *afterLast);
66 
Ipv4(const string & s)67 void Ipv4(const string &s) {
68   const char *cstr = s.c_str();
69   unsigned char result[4] = {};
70   uriParseIpFourAddressA(result, cstr, &cstr[s.size()]);
71 }
72 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)73 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
74 
75   FuzzedDataProvider stream(data, size);
76   bool domainRelative = stream.ConsumeBool();
77   size_t uriSize = stream.remaining_bytes() / 2;
78 
79   const string uri1 = stream.ConsumeBytesAsString(uriSize);
80   const string uri2 = stream.ConsumeRemainingBytesAsString();
81 
82   Escapes(uri1);
83   Escapes(uri2);
84 
85   FileNames(uri1);
86   FileNames(uri2);
87 
88   Ipv4(uri1);
89   Ipv4(uri2);
90 
91   UriParserA parser1;
92   UriParserStateA state1;
93   state1.uri = parser1.get_mutable_uri();
94   if (uriParseUriA(&state1, uri1.c_str()) != URI_SUCCESS)
95     return 0;
96 
97   char buf[1024 * 8] = {0};
98   int written = 0;
99   uriToStringA(buf, state1.uri, sizeof(buf), &written);
100 
101   UriParserA parser2;
102   UriParserStateA state2;
103   state2.uri = parser2.get_mutable_uri();
104   if (uriParseUriA(&state2, uri2.c_str()) != URI_SUCCESS)
105     return 0;
106 
107   uriEqualsUriA(state1.uri, state2.uri);
108 
109   uriNormalizeSyntaxA(state1.uri);
110 
111   UriUriA absUri;
112   uriAddBaseUriA(&absUri, state1.uri, state2.uri);
113   uriFreeUriMembersA(&absUri);
114 
115   UriUriA relUri;
116   uriRemoveBaseUriA(&relUri, state1.uri, state2.uri, domainRelative);
117   uriFreeUriMembersA(&relUri);
118 
119   return 0;
120 }
121