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_HIDL_INTERFACE] = default_transform;
     62   mutate_fns_[TYPE_HIDL_INTERFACE] = default_transform;
     63 
     64   // 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 
     69   random_gen_fns_[TYPE_POINTER] = default_transform;
     70   mutate_fns_[TYPE_POINTER] = default_transform;
     71 
     72   random_gen_fns_[TYPE_SCALAR] =
     73       std::bind(&ProtoFuzzerMutator::ScalarRandomGen, this, _1);
     74   mutate_fns_[TYPE_SCALAR] =
     75       std::bind(&ProtoFuzzerMutator::ScalarMutate, this, _1);
     76 
     77   random_gen_fns_[TYPE_STRING] =
     78       std::bind(&ProtoFuzzerMutator::StringRandomGen, this, _1);
     79   mutate_fns_[TYPE_STRING] =
     80       std::bind(&ProtoFuzzerMutator::StringMutate, this, _1);
     81 
     82   random_gen_fns_[TYPE_STRUCT] =
     83       std::bind(&ProtoFuzzerMutator::StructRandomGen, this, _1);
     84   mutate_fns_[TYPE_STRUCT] =
     85       std::bind(&ProtoFuzzerMutator::StructMutate, this, _1);
     86 
     87   random_gen_fns_[TYPE_UNION] =
     88       std::bind(&ProtoFuzzerMutator::UnionRandomGen, this, _1);
     89   mutate_fns_[TYPE_UNION] =
     90       std::bind(&ProtoFuzzerMutator::UnionMutate, this, _1);
     91 
     92   random_gen_fns_[TYPE_VECTOR] =
     93       std::bind(&ProtoFuzzerMutator::VectorRandomGen, this, _1);
     94   mutate_fns_[TYPE_VECTOR] =
     95       std::bind(&ProtoFuzzerMutator::VectorMutate, this, _1);
     96 }
     97 
     98 // TODO(trong): add a mutator config option which controls how an interface is
     99 // selected.
    100 const CompSpec *ProtoFuzzerMutator::RandomSelectIface(const IfaceDescTbl &tbl) {
    101   size_t rand_idx = rand_(tbl.size());
    102   auto it = tbl.begin();
    103   std::advance(it, rand_idx);
    104   return it->second.comp_spec_;
    105 }
    106 
    107 ExecSpec ProtoFuzzerMutator::RandomGen(const IfaceDescTbl &tbl,
    108                                        size_t num_calls) {
    109   ExecSpec result{};
    110   for (size_t i = 0; i < num_calls; ++i) {
    111     const CompSpec *comp_spec = RandomSelectIface(tbl);
    112     string iface_name = comp_spec->component_name();
    113     const IfaceSpec &iface_spec = comp_spec->interface();
    114 
    115     // Generate a random interface function call.
    116     FuncCall rand_call{};
    117     rand_call.set_hidl_interface_name(iface_name);
    118     size_t num_apis = iface_spec.api_size();
    119     size_t rand_api_idx = rand_(num_apis);
    120     FuncSpec rand_api = RandomGen(iface_spec.api(rand_api_idx));
    121     *rand_call.mutable_api() = rand_api;
    122     *result.add_function_call() = rand_call;
    123   }
    124   return result;
    125 }
    126 
    127 void ProtoFuzzerMutator::Mutate(const IfaceDescTbl &tbl, ExecSpec *exec_spec) {
    128   // Mutate a randomly chosen function call with probability
    129   // odds_for/(odds_for + odds_against).
    130   uint64_t odds_for = mutator_config_.func_mutated_.first;
    131   uint64_t odds_against = mutator_config_.func_mutated_.second;
    132   uint64_t rand_num = rand_(odds_for + odds_against);
    133 
    134   if (rand_num < odds_for) {
    135     // Mutate a random function in execution.
    136     size_t idx = rand_(exec_spec->function_call_size());
    137     const FuncSpec &rand_api = exec_spec->function_call(idx).api();
    138     *exec_spec->mutable_function_call(idx)->mutable_api() = Mutate(rand_api);
    139   } else {
    140     // Generate a random function call in place of randomly chosen function in
    141     // execution.
    142     const CompSpec *comp_spec = RandomSelectIface(tbl);
    143     string iface_name = comp_spec->component_name();
    144     const IfaceSpec &iface_spec = comp_spec->interface();
    145 
    146     size_t func_idx = rand_(exec_spec->function_call_size());
    147     size_t blueprint_idx = rand_(iface_spec.api_size());
    148     FuncCall *func_call = exec_spec->mutable_function_call(func_idx);
    149     func_call->set_hidl_interface_name(iface_name);
    150     *func_call->mutable_api() = RandomGen(iface_spec.api(blueprint_idx));
    151   }
    152 }
    153 
    154 FuncSpec ProtoFuzzerMutator::RandomGen(const FuncSpec &func_spec) {
    155   FuncSpec result{func_spec};
    156   // We'll repopulate arg field.
    157   result.clear_arg();
    158   result.clear_return_type_hidl();
    159   for (const auto &var_spec : func_spec.arg()) {
    160     VarInstance rand_var_spec = RandomGen(var_spec);
    161     auto *new_var = result.add_arg();
    162     new_var->Swap(&rand_var_spec);
    163   }
    164   return result;
    165 }
    166 
    167 FuncSpec ProtoFuzzerMutator::Mutate(const FuncSpec &func_spec) {
    168   FuncSpec result{func_spec};
    169   size_t num_args = result.arg_size();
    170   if (num_args > 0) {
    171     size_t rand_arg_idx = rand_(num_args);
    172     VarInstance rand_arg = Mutate(result.arg(rand_arg_idx));
    173     result.mutable_arg(rand_arg_idx)->Swap(&rand_arg);
    174   }
    175   return result;
    176 }
    177 
    178 static VariableSpecificationMessage Transform(
    179     const VariableSpecificationMessage &var_spec,
    180     unordered_map<VariableType, VarTransformFn> &transform_fns) {
    181   auto type = var_spec.type();
    182   auto transform_fn = transform_fns.find(type);
    183   if (transform_fn == transform_fns.end()) {
    184     cerr << "Transformation function not found for type: " << type << endl;
    185     exit(1);
    186   }
    187   return transform_fn->second(var_spec);
    188 }
    189 
    190 VarInstance ProtoFuzzerMutator::RandomGen(const VarSpec &var_spec) {
    191   return Transform(var_spec, random_gen_fns_);
    192 }
    193 
    194 VarInstance ProtoFuzzerMutator::Mutate(const VarInstance &var_instance) {
    195   return Transform(var_instance, mutate_fns_);
    196 }
    197 
    198 const TypeSpec &ProtoFuzzerMutator::FindPredefinedType(string name) {
    199   auto type_spec = predefined_types_.find(name);
    200   if (type_spec == predefined_types_.end()) {
    201     cerr << "Predefined type not found: " << name << endl;
    202     exit(1);
    203   }
    204   return type_spec->second;
    205 }
    206 
    207 }  // namespace fuzzer
    208 }  // namespace vts
    209 }  // namespace android
    210