1 // Copyright 2017 Google Inc. All rights reserved.
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 <cmath>
16 #include <iostream>
17
18 #include "examples/libfuzzer/libfuzzer_example.pb.h"
19 #include "port/protobuf.h"
20 #include "src/libfuzzer/libfuzzer_macro.h"
21
22 protobuf_mutator::protobuf::LogSilencer log_silincer;
23
24 template <class Proto>
25 using PostProcessor =
26 protobuf_mutator::libfuzzer::PostProcessorRegistration<Proto>;
27
28 static PostProcessor<libfuzzer_example::Msg> reg1 = {
__anon9333d74d0102() 29 [](libfuzzer_example::Msg* message, unsigned int seed) {
30 message->set_optional_uint64(
31 std::hash<std::string>{}(message->optional_string()));
32 }};
33
34 static PostProcessor<google::protobuf::Any> reg2 = {
__anon9333d74d0202() 35 [](google::protobuf::Any* any, unsigned int seed) {
36 // Guide mutator to usefull 'Any' types.
37 static const char* const expected_types[] = {
38 "type.googleapis.com/google.protobuf.DescriptorProto",
39 "type.googleapis.com/google.protobuf.FileDescriptorProto",
40 };
41
42 if (!std::count(std::begin(expected_types), std::end(expected_types),
43 any->type_url())) {
44 const size_t num =
45 (std::end(expected_types) - std::begin(expected_types));
46 any->set_type_url(expected_types[seed % num]);
47 }
48 }};
49
DEFINE_PROTO_FUZZER(const libfuzzer_example::Msg & message)50 DEFINE_PROTO_FUZZER(const libfuzzer_example::Msg& message) {
51 protobuf_mutator::protobuf::FileDescriptorProto file;
52
53 // Emulate a bug.
54 if (message.optional_uint64() ==
55 std::hash<std::string>{}(message.optional_string()) &&
56 message.optional_string() == "abcdefghijklmnopqrstuvwxyz" &&
57 !std::isnan(message.optional_float()) &&
58 std::fabs(message.optional_float()) > 1000 &&
59 message.any().UnpackTo(&file) && !file.name().empty()) {
60 std::cerr << message.DebugString() << "\n";
61 abort();
62 }
63 }
64