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