• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 # Copyright 2020 Google Inc.
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 ################################################################################
17 */
18 
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #include "s2/s2shapeutil_range_iterator.h"
24 #include "s2/third_party/absl/strings/str_split.h"
25 #include "s2/third_party/absl/strings/string_view.h"
26 
27 #include "s2/mutable_s2shape_index.h"
28 #include "s2/s2text_format.h"
29 
30 // A string-splitter used to help validate the string
31 // passed to s2
SplitString(absl::string_view str,char separator)32 static std::vector<absl::string_view> SplitString(absl::string_view str,
33                                                   char separator) {
34   std::vector<absl::string_view> result =
35       absl::StrSplit(str, separator, absl::SkipWhitespace());
36   for (auto &e : result) {
37     e = absl::StripAsciiWhitespace(e);
38   }
39   return result;
40 }
41 
42 // Null-terminates the fuzzers input test case
null_terminated(const uint8_t * data,size_t size)43 char *null_terminated(const uint8_t *data, size_t size) {
44   char *new_str = (char *)malloc(size + 1);
45   if (new_str == NULL) {
46     return 0;
47   }
48   memcpy(new_str, data, size);
49   new_str[size] = '\0';
50   return new_str;
51 }
52 
53 // Do a bit of validation that is also done by s2
54 // We do them here since s2 would terminate if they
55 // would return false inside s2.
isValidFormat(char * nt_string,size_t size)56 bool isValidFormat(char *nt_string, size_t size) {
57   int hash_count = 0;
58   for (int i = 0; i < size; i++) {
59     if (nt_string[i] == 35) {
60       hash_count++;
61     }
62   }
63   if (hash_count != 2) {
64     return false;
65   }
66 
67   std::vector<absl::string_view> strs = SplitString(nt_string, '#');
68   size_t strs_size = strs.size();
69   if (strs.size() != 3) {
70     return false;
71   }
72 
73   auto index1 = absl::make_unique<MutableS2ShapeIndex>();
74   if (s2textformat::MakeIndex(nt_string, &index1) == false) {
75     return false;
76   }
77   return true;
78 }
79 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)80 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
81 
82   if (size < 5) {
83     return 0;
84   }
85 
86   char *nt_string = null_terminated(data, size);
87   if (nt_string == NULL) {
88     return 0;
89   }
90   if (isValidFormat(nt_string, size)) {
91     auto index = s2textformat::MakeIndex(nt_string);
92     s2shapeutil::RangeIterator it(*index);
93     if (!it.done()) {
94       it.Next();
95     }
96   }
97   free(nt_string);
98   return 0;
99 }
100