Home | History | Annotate | Download | only in iface_fuzzer
      1 /*
      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"
     18 #include <iostream>
     19 
     20 using std::endl;
     21 using std::cerr;
     22 using std::cout;
     23 using std::make_unique;
     24 using std::unordered_map;
     25 using namespace std::placeholders;
     26 
     27 namespace android {
     28 namespace vts {
     29 namespace fuzzer {
     30 
     31 ProtoFuzzerMutator::ProtoFuzzerMutator(
     32     Random &rand, unordered_map<string, TypeSpec> predefined_types,
     33     ProtoFuzzerMutatorConfig mutator_config)
     34     : rand_(rand),
     35       predefined_types_(predefined_types),
     36       mutator_config_(mutator_config) {
     37   // 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 
     61   random_gen_fns_[TYPE_SCALAR] =
     62       std::bind(&ProtoFuzzerMutator::ScalarRandomGen, this, _1);
     63   mutate_fns_[TYPE_SCALAR] =
     64       std::bind(&ProtoFuzzerMutator::ScalarMutate, this, _1);
     65 
     66   random_gen_fns_[TYPE_STRUCT] =
     67       std::bind(&ProtoFuzzerMutator::StructRandomGen, this, _1);
     68   mutate_fns_[TYPE_STRUCT] =
     69       std::bind(&ProtoFuzzerMutator::StructMutate, this, _1);
     70 
     71   random_gen_fns_[TYPE_UNION] =
     72       std::bind(&ProtoFuzzerMutator::UnionRandomGen, this, _1);
     73   mutate_fns_[TYPE_UNION] =
     74       std::bind(&ProtoFuzzerMutator::UnionMutate, this, _1);
     75 
     76   random_gen_fns_[TYPE_VECTOR] =
     77       std::bind(&ProtoFuzzerMutator::VectorRandomGen, this, _1);
     78   mutate_fns_[TYPE_VECTOR] =
     79       std::bind(&ProtoFuzzerMutator::VectorMutate, this, _1);
     80 }
     81 
     82 ExecSpec ProtoFuzzerMutator::RandomGen(const IfaceSpec &iface_spec,
     83                                        size_t num_calls) {
     84   ExecSpec result{};
     85 
     86   for (size_t i = 0; i < num_calls; ++i) {
     87     size_t num_apis = iface_spec.api_size();
     88     size_t rand_api_idx = rand_(num_apis);
     89     FuncSpec rand_api = RandomGen(iface_spec.api(rand_api_idx));
     90     result.add_api()->Swap(&rand_api);
     91   }
     92 
     93   return result;
     94 }
     95 
     96 void ProtoFuzzerMutator::Mutate(const IfaceSpec &iface_spec,
     97                                 ExecSpec *exec_spec) {
     98   // Mutate a randomly chosen function call with probability
     99   // odds_for/(odds_for + odds_against).
    100   uint64_t odds_for = mutator_config_.func_mutated_.first;
    101   uint64_t odds_against = mutator_config_.func_mutated_.second;
    102   uint64_t rand_num = rand_(odds_for + odds_against);
    103 
    104   if (rand_num < odds_for) {
    105     // Mutate a random function in execution.
    106     size_t idx = rand_(exec_spec->api_size());
    107     const FuncSpec &rand_api = exec_spec->api(idx);
    108     (*exec_spec->mutable_api(idx)) = Mutate(rand_api);
    109   } else {
    110     // Generate a random function call in place of randomly chosen function in
    111     // execution.
    112     size_t func_idx = rand_(exec_spec->api_size());
    113     size_t blueprint_idx = rand_(iface_spec.api_size());
    114     *(exec_spec->mutable_api(func_idx)) =
    115         RandomGen(iface_spec.api(blueprint_idx));
    116   }
    117 }
    118 
    119 FuncSpec ProtoFuzzerMutator::RandomGen(const FuncSpec &func_spec) {
    120   FuncSpec result{func_spec};
    121   // We'll repopulate arg field.
    122   result.clear_arg();
    123   result.clear_return_type_hidl();
    124   for (const auto &var_spec : func_spec.arg()) {
    125     VarInstance rand_var_spec = RandomGen(var_spec);
    126     auto *new_var = result.add_arg();
    127     new_var->Swap(&rand_var_spec);
    128   }
    129   return result;
    130 }
    131 
    132 FuncSpec ProtoFuzzerMutator::Mutate(const FuncSpec &func_spec) {
    133   FuncSpec result{func_spec};
    134   size_t num_args = result.arg_size();
    135   if (num_args > 0) {
    136     size_t rand_arg_idx = rand_(num_args);
    137     VarInstance rand_arg = Mutate(result.arg(rand_arg_idx));
    138     result.mutable_arg(rand_arg_idx)->Swap(&rand_arg);
    139   }
    140   return result;
    141 }
    142 
    143 static VariableSpecificationMessage Transform(
    144     const VariableSpecificationMessage &var_spec,
    145     unordered_map<VariableType, VarTransformFn> &transform_fns) {
    146   auto type = var_spec.type();
    147   auto transform_fn = transform_fns.find(type);
    148   if (transform_fn == transform_fns.end()) {
    149     cerr << "Transformation function not found for type: " << type << endl;
    150     exit(1);
    151   }
    152   return transform_fn->second(var_spec);
    153 }
    154 
    155 VarInstance ProtoFuzzerMutator::RandomGen(const VarSpec &var_spec) {
    156   return Transform(var_spec, random_gen_fns_);
    157 }
    158 
    159 VarInstance ProtoFuzzerMutator::Mutate(const VarInstance &var_instance) {
    160   return Transform(var_instance, mutate_fns_);
    161 }
    162 
    163 const TypeSpec &ProtoFuzzerMutator::FindPredefinedType(string name) {
    164   auto type_spec = predefined_types_.find(name);
    165   if (type_spec == predefined_types_.end()) {
    166     cerr << "Predefined type not found: " << name << endl;
    167     exit(1);
    168   }
    169   return type_spec->second;
    170 }
    171 
    172 }  // namespace fuzzer
    173 }  // namespace vts
    174 }  // namespace android
    175