121 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
| // Copyright 2020 Google LLC
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //      http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| #include <cstddef>
 | |
| #include <cstring>
 | |
| #include <string>
 | |
| #include <vector>
 | |
| #include <fuzzer/FuzzedDataProvider.h>
 | |
| 
 | |
| using std::string;
 | |
| #include "uriparser/include/uriparser/Uri.h"
 | |
| #include "uriparser/include/uriparser/UriIp4.h"
 | |
| 
 | |
| class UriParserA {
 | |
|  public:
 | |
|   UriParserA() { memset((void *)&uri_, 0, sizeof(uri_)); }
 | |
|   ~UriParserA() { uriFreeUriMembersA(&uri_); }
 | |
| 
 | |
|   UriUriA *get_mutable_uri() { return &uri_; }
 | |
|   UriUriA *get_uri() const { return const_cast<UriUriA *>(&uri_); }
 | |
| 
 | |
|  private:
 | |
|   UriUriA uri_;
 | |
| };
 | |
| 
 | |
| void Escapes(const string &uri) {
 | |
|   const char *first = uri.c_str();
 | |
|   // A new line char takes 6 char to encode.
 | |
|   // Use a vector to make a C string.
 | |
|   std::vector<char> buf1(uri.size() * 6 + 1);
 | |
|   std::vector<char> buf2(uri.size() * 3 + 1);
 | |
| 
 | |
|   char *result;
 | |
|   result = uriEscapeA(first, &buf1[0], URI_TRUE, URI_TRUE);
 | |
|   result = uriEscapeA(first, &buf1[0], URI_FALSE, URI_TRUE);
 | |
|   if (buf1.data()) uriUnescapeInPlaceA(&buf1[0]);
 | |
| 
 | |
|   result = uriEscapeA(first, &buf2[0], URI_TRUE, URI_FALSE);
 | |
|   result = uriEscapeA(first, &buf2[0], URI_FALSE, URI_FALSE);
 | |
|   if (buf2.data()) uriUnescapeInPlaceA(&buf2[0]);
 | |
| }
 | |
| 
 | |
| void FileNames(const string &uri) {
 | |
|   const size_t size = 8 + 3 * uri.size() + 1;
 | |
|   std::vector<char> buf(size);
 | |
| 
 | |
|   uriUnixFilenameToUriStringA(uri.c_str(), &buf[0]);
 | |
|   uriWindowsFilenameToUriStringA(uri.c_str(), &buf[0]);
 | |
|   uriUriStringToUnixFilenameA(uri.c_str(), &buf[0]);
 | |
|   uriUriStringToWindowsFilenameA(uri.c_str(), &buf[0]);
 | |
| }
 | |
| 
 | |
| int uriParseIpFourAddressA(unsigned char *octetOutput, const char *first,
 | |
|                            const char *afterLast);
 | |
| 
 | |
| void Ipv4(const string &s) {
 | |
|   const char *cstr = s.c_str();
 | |
|   unsigned char result[4] = {};
 | |
|   uriParseIpFourAddressA(result, cstr, &cstr[s.size()]);
 | |
| }
 | |
| 
 | |
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
 | |
| 
 | |
|   FuzzedDataProvider stream(data, size);
 | |
|   bool domainRelative = stream.ConsumeBool();
 | |
|   size_t uriSize = stream.remaining_bytes() / 2;
 | |
| 
 | |
|   const string uri1 = stream.ConsumeBytesAsString(uriSize);
 | |
|   const string uri2 = stream.ConsumeRemainingBytesAsString();
 | |
| 
 | |
|   Escapes(uri1);
 | |
|   Escapes(uri2);
 | |
| 
 | |
|   FileNames(uri1);
 | |
|   FileNames(uri2);
 | |
| 
 | |
|   Ipv4(uri1);
 | |
|   Ipv4(uri2);
 | |
| 
 | |
|   UriParserA parser1;
 | |
|   UriParserStateA state1;
 | |
|   state1.uri = parser1.get_mutable_uri();
 | |
|   if (uriParseUriA(&state1, uri1.c_str()) != URI_SUCCESS)
 | |
|     return 0;
 | |
| 
 | |
|   char buf[1024 * 8] = {0};
 | |
|   int written = 0;
 | |
|   uriToStringA(buf, state1.uri, sizeof(buf), &written);
 | |
| 
 | |
|   UriParserA parser2;
 | |
|   UriParserStateA state2;
 | |
|   state2.uri = parser2.get_mutable_uri();
 | |
|   if (uriParseUriA(&state2, uri2.c_str()) != URI_SUCCESS)
 | |
|     return 0;
 | |
| 
 | |
|   uriEqualsUriA(state1.uri, state2.uri);
 | |
| 
 | |
|   uriNormalizeSyntaxA(state1.uri);
 | |
| 
 | |
|   UriUriA absUri;
 | |
|   uriAddBaseUriA(&absUri, state1.uri, state2.uri);
 | |
|   uriFreeUriMembersA(&absUri);
 | |
| 
 | |
|   UriUriA relUri;
 | |
|   uriRemoveBaseUriA(&relUri, state1.uri, state2.uri, domainRelative);
 | |
|   uriFreeUriMembersA(&relUri);
 | |
| 
 | |
|   return 0;
 | |
| }
 |