diff options
author | Ravi Jotwani <rjotwani@google.com> | 2020-07-20 16:50:20 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-20 16:50:20 -0700 |
commit | 36e6fa39fed738edff6bc2c6a1b03530c03576ed (patch) | |
tree | 46da7db72d3dc3b941656fd983f84c3af81bd740 /projects/uriparser | |
parent | 283447224d8a295027fd20fb5ac6962cc95dc55b (diff) |
[uriparser] Add new fuzzers (#4134)
* added new fuzzer
* added new fuzzer
* removed commented code
* add license header for uri_parse_fuzzer
* get values from FuzzedDataProvider, awaiting fuzz targets for FileNames and Ipv4 in parse_fuzzer
* build working
* fixed size mismatch, used better consumption function for remaining input
* reduced maxSize for uri_dissect_query_malloc_fuzzer
* added missing fuzz targets, removed unnecessary import
* removed unused include, changed instances of std::string to string, removed ToVector, added checks, and removed usage of FuzzedDataProvider in uri_dissect_query_malloc_fuzzer
* fixed vector issue in uri_parse_fuzzer
* added explicit value checks, removed Yoda comparisons
Diffstat (limited to 'projects/uriparser')
-rw-r--r-- | projects/uriparser/uri_dissect_query_malloc_fuzzer.cc | 58 | ||||
-rw-r--r-- | projects/uriparser/uri_parse_fuzzer.cc | 120 |
2 files changed, 178 insertions, 0 deletions
diff --git a/projects/uriparser/uri_dissect_query_malloc_fuzzer.cc b/projects/uriparser/uri_dissect_query_malloc_fuzzer.cc new file mode 100644 index 00000000..32e81555 --- /dev/null +++ b/projects/uriparser/uri_dissect_query_malloc_fuzzer.cc @@ -0,0 +1,58 @@ +// 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. + +// Fuzz UriQuery.c: +// uriDissectQueryMallocA +// uriComposeQueryA + +#include <cstddef> +#include <cstdint> +#include <string> +#include <utility> +#include <vector> + +using std::string; +#include "uriparser/include/uriparser/Uri.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + + const string query(reinterpret_cast<const char *>(data), size); + + UriQueryListA *query_list = nullptr; + int item_count = -1; + + const char *query_start = query.c_str(); + const char *query_end = query_start + size; + + // Break a query like "a=b&2=3" into key/value pairs. + int result = + uriDissectQueryMallocA(&query_list, &item_count, query_start, query_end); + + if (query_list == nullptr || result != URI_SUCCESS || item_count < 0) + return 0; + + int chars_required; + if (uriComposeQueryCharsRequiredA(query_list, &chars_required) != URI_SUCCESS) + return 0; + + std::vector<char> buf(chars_required, 0); + int written = -1; + char *dest = &buf[0]; + // Reverse the process of uriDissectQueryMallocA. + result = uriComposeQueryA(dest, query_list, chars_required, &written); + + uriFreeQueryListA(query_list); + + return 0; +} diff --git a/projects/uriparser/uri_parse_fuzzer.cc b/projects/uriparser/uri_parse_fuzzer.cc new file mode 100644 index 00000000..4eca6698 --- /dev/null +++ b/projects/uriparser/uri_parse_fuzzer.cc @@ -0,0 +1,120 @@ +// 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; +} |