blob: 3a209765b9516b2db20dc1b44c401780e9c4314b [file] [log] [blame]
Tri Vo77e0ca02016-12-05 10:08:59 -08001/*
2 * Copyright 2016 The Android Open Source Project
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#include "ProtoFuzzerMutator.h"
Tri Vo77e0ca02016-12-05 10:08:59 -080018#include <iostream>
19
20using std::endl;
21using std::cerr;
22using std::cout;
23using std::make_unique;
Tri Vo70c1ab62017-03-15 09:19:10 -070024using std::unordered_map;
25using namespace std::placeholders;
Tri Vo77e0ca02016-12-05 10:08:59 -080026
27namespace android {
28namespace vts {
Tri Vo70c1ab62017-03-15 09:19:10 -070029namespace fuzzer {
Tri Vo77e0ca02016-12-05 10:08:59 -080030
31ProtoFuzzerMutator::ProtoFuzzerMutator(
Tri Vo70c1ab62017-03-15 09:19:10 -070032 Random &rand, unordered_map<string, TypeSpec> predefined_types,
Tri Vof4037d42017-03-31 17:28:25 -070033 ProtoFuzzerMutatorConfig mutator_config)
Tri Vo70c1ab62017-03-15 09:19:10 -070034 : rand_(rand),
35 predefined_types_(predefined_types),
Tri Vof4037d42017-03-31 17:28:25 -070036 mutator_config_(mutator_config) {
Tri Vo70c1ab62017-03-15 09:19:10 -070037 // Default function used for mutation/random generation. Used for types for
38 // which the notion of mutation/random generation is not defined, e.g.
39 // TYPE_HANDLE, TYPE_HIDL_CALLBACK.
40 VarTransformFn default_transform =
41 [](const VariableSpecificationMessage &var_spec) {
42 return VariableSpecificationMessage{var_spec};
43 };
44
45 // Initialize random_gen_fns_ and mutate_fns_ tables.
46 random_gen_fns_[TYPE_ARRAY] =
47 std::bind(&ProtoFuzzerMutator::ArrayRandomGen, this, _1);
48 mutate_fns_[TYPE_ARRAY] =
49 std::bind(&ProtoFuzzerMutator::ArrayMutate, this, _1);
50
51 random_gen_fns_[TYPE_ENUM] =
52 std::bind(&ProtoFuzzerMutator::EnumRandomGen, this, _1);
53 mutate_fns_[TYPE_ENUM] = std::bind(&ProtoFuzzerMutator::EnumMutate, this, _1);
54
55 random_gen_fns_[TYPE_HANDLE] = default_transform;
56 mutate_fns_[TYPE_HANDLE] = default_transform;
57
58 random_gen_fns_[TYPE_HIDL_CALLBACK] = default_transform;
59 mutate_fns_[TYPE_HIDL_CALLBACK] = default_transform;
60
Tri Vo165b1ed2017-04-03 14:44:45 -070061 random_gen_fns_[TYPE_HIDL_INTERFACE] = default_transform;
62 mutate_fns_[TYPE_HIDL_INTERFACE] = default_transform;
63
Tri Vo69d71b32017-04-12 18:24:50 -070064 // Interpret masks as enums.
65 random_gen_fns_[TYPE_MASK] =
66 std::bind(&ProtoFuzzerMutator::EnumRandomGen, this, _1);
67 mutate_fns_[TYPE_MASK] = std::bind(&ProtoFuzzerMutator::EnumMutate, this, _1);
68
Tri Vo70c1ab62017-03-15 09:19:10 -070069 random_gen_fns_[TYPE_SCALAR] =
70 std::bind(&ProtoFuzzerMutator::ScalarRandomGen, this, _1);
71 mutate_fns_[TYPE_SCALAR] =
72 std::bind(&ProtoFuzzerMutator::ScalarMutate, this, _1);
73
Tri Vo5ecdf5b2017-04-14 08:30:48 -070074 random_gen_fns_[TYPE_STRING] =
75 std::bind(&ProtoFuzzerMutator::StringRandomGen, this, _1);
76 mutate_fns_[TYPE_STRING] =
77 std::bind(&ProtoFuzzerMutator::StringMutate, this, _1);
78
Tri Vo70c1ab62017-03-15 09:19:10 -070079 random_gen_fns_[TYPE_STRUCT] =
80 std::bind(&ProtoFuzzerMutator::StructRandomGen, this, _1);
81 mutate_fns_[TYPE_STRUCT] =
82 std::bind(&ProtoFuzzerMutator::StructMutate, this, _1);
83
84 random_gen_fns_[TYPE_UNION] =
85 std::bind(&ProtoFuzzerMutator::UnionRandomGen, this, _1);
86 mutate_fns_[TYPE_UNION] =
87 std::bind(&ProtoFuzzerMutator::UnionMutate, this, _1);
88
89 random_gen_fns_[TYPE_VECTOR] =
90 std::bind(&ProtoFuzzerMutator::VectorRandomGen, this, _1);
91 mutate_fns_[TYPE_VECTOR] =
92 std::bind(&ProtoFuzzerMutator::VectorMutate, this, _1);
Tri Vo77e0ca02016-12-05 10:08:59 -080093}
94
Tri Vo70c1ab62017-03-15 09:19:10 -070095ExecSpec ProtoFuzzerMutator::RandomGen(const IfaceSpec &iface_spec,
96 size_t num_calls) {
97 ExecSpec result{};
Tri Vo77e0ca02016-12-05 10:08:59 -080098
99 for (size_t i = 0; i < num_calls; ++i) {
100 size_t num_apis = iface_spec.api_size();
101 size_t rand_api_idx = rand_(num_apis);
Tri Vo70c1ab62017-03-15 09:19:10 -0700102 FuncSpec rand_api = RandomGen(iface_spec.api(rand_api_idx));
Tri Vo77e0ca02016-12-05 10:08:59 -0800103 result.add_api()->Swap(&rand_api);
104 }
105
106 return result;
107}
108
Tri Vo70c1ab62017-03-15 09:19:10 -0700109void ProtoFuzzerMutator::Mutate(const IfaceSpec &iface_spec,
110 ExecSpec *exec_spec) {
Tri Vof4037d42017-03-31 17:28:25 -0700111 // Mutate a randomly chosen function call with probability
112 // odds_for/(odds_for + odds_against).
113 uint64_t odds_for = mutator_config_.func_mutated_.first;
114 uint64_t odds_against = mutator_config_.func_mutated_.second;
115 uint64_t rand_num = rand_(odds_for + odds_against);
Tri Vo77e0ca02016-12-05 10:08:59 -0800116
Tri Vof4037d42017-03-31 17:28:25 -0700117 if (rand_num < odds_for) {
Tri Voafcb0242017-01-17 16:11:01 -0800118 // Mutate a random function in execution.
Tri Vo77e0ca02016-12-05 10:08:59 -0800119 size_t idx = rand_(exec_spec->api_size());
Tri Vo70c1ab62017-03-15 09:19:10 -0700120 const FuncSpec &rand_api = exec_spec->api(idx);
Tri Vo77e0ca02016-12-05 10:08:59 -0800121 (*exec_spec->mutable_api(idx)) = Mutate(rand_api);
122 } else {
Tri Voafcb0242017-01-17 16:11:01 -0800123 // Generate a random function call in place of randomly chosen function in
124 // execution.
125 size_t func_idx = rand_(exec_spec->api_size());
126 size_t blueprint_idx = rand_(iface_spec.api_size());
127 *(exec_spec->mutable_api(func_idx)) =
128 RandomGen(iface_spec.api(blueprint_idx));
Tri Vo77e0ca02016-12-05 10:08:59 -0800129 }
130}
131
Tri Vo70c1ab62017-03-15 09:19:10 -0700132FuncSpec ProtoFuzzerMutator::RandomGen(const FuncSpec &func_spec) {
133 FuncSpec result{func_spec};
Tri Vo77e0ca02016-12-05 10:08:59 -0800134 // We'll repopulate arg field.
135 result.clear_arg();
Tri Vof4037d42017-03-31 17:28:25 -0700136 result.clear_return_type_hidl();
Tri Vo77e0ca02016-12-05 10:08:59 -0800137 for (const auto &var_spec : func_spec.arg()) {
Tri Vo70c1ab62017-03-15 09:19:10 -0700138 VarInstance rand_var_spec = RandomGen(var_spec);
Tri Vo77e0ca02016-12-05 10:08:59 -0800139 auto *new_var = result.add_arg();
140 new_var->Swap(&rand_var_spec);
141 }
Tri Vo77e0ca02016-12-05 10:08:59 -0800142 return result;
143}
144
Tri Vo70c1ab62017-03-15 09:19:10 -0700145FuncSpec ProtoFuzzerMutator::Mutate(const FuncSpec &func_spec) {
146 FuncSpec result{func_spec};
Tri Vo77e0ca02016-12-05 10:08:59 -0800147 size_t num_args = result.arg_size();
148 if (num_args > 0) {
149 size_t rand_arg_idx = rand_(num_args);
Tri Vo70c1ab62017-03-15 09:19:10 -0700150 VarInstance rand_arg = Mutate(result.arg(rand_arg_idx));
Tri Vo77e0ca02016-12-05 10:08:59 -0800151 result.mutable_arg(rand_arg_idx)->Swap(&rand_arg);
152 }
153 return result;
154}
155
Tri Vo70c1ab62017-03-15 09:19:10 -0700156static VariableSpecificationMessage Transform(
157 const VariableSpecificationMessage &var_spec,
158 unordered_map<VariableType, VarTransformFn> &transform_fns) {
159 auto type = var_spec.type();
160 auto transform_fn = transform_fns.find(type);
161 if (transform_fn == transform_fns.end()) {
162 cerr << "Transformation function not found for type: " << type << endl;
Tri Voafcb0242017-01-17 16:11:01 -0800163 exit(1);
164 }
Tri Vo70c1ab62017-03-15 09:19:10 -0700165 return transform_fn->second(var_spec);
Tri Voafcb0242017-01-17 16:11:01 -0800166}
167
Tri Vo70c1ab62017-03-15 09:19:10 -0700168VarInstance ProtoFuzzerMutator::RandomGen(const VarSpec &var_spec) {
169 return Transform(var_spec, random_gen_fns_);
170}
171
172VarInstance ProtoFuzzerMutator::Mutate(const VarInstance &var_instance) {
173 return Transform(var_instance, mutate_fns_);
174}
175
176const TypeSpec &ProtoFuzzerMutator::FindPredefinedType(string name) {
177 auto type_spec = predefined_types_.find(name);
178 if (type_spec == predefined_types_.end()) {
179 cerr << "Predefined type not found: " << name << endl;
180 exit(1);
181 }
182 return type_spec->second;
183}
184
185} // namespace fuzzer
Tri Vo77e0ca02016-12-05 10:08:59 -0800186} // namespace vts
187} // namespace android