Home | History | Annotate | Download | only in iface_fuzzer
      1 /*
      2  * Copyright 2017 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 
     19 using std::cerr;
     20 using std::endl;
     21 
     22 namespace android {
     23 namespace vts {
     24 namespace fuzzer {
     25 
     26 // Creates an inital stub of mutation/random generation result.
     27 static VarInstance VarInstanceStubFromSpec(const VarSpec &var_spec) {
     28   VarInstance result{};
     29   if (var_spec.has_type()) {
     30     result.set_type(var_spec.type());
     31   } else {
     32     cerr << "VarInstance with no type field: " << var_spec.DebugString();
     33     exit(1);
     34   }
     35   if (var_spec.has_name()) {
     36     result.set_name(var_spec.name());
     37   }
     38   if (var_spec.has_predefined_type()) {
     39     result.set_predefined_type(var_spec.predefined_type());
     40   }
     41   return result;
     42 }
     43 
     44 VarInstance ProtoFuzzerMutator::ArrayRandomGen(const VarSpec &var_spec) {
     45   VarInstance result{VarInstanceStubFromSpec(var_spec)};
     46   size_t vector_size = var_spec.vector_size();
     47   result.set_vector_size(vector_size);
     48   for (size_t i = 0; i < vector_size; ++i) {
     49     *result.add_vector_value() = this->RandomGen(var_spec.vector_value(0));
     50   }
     51   return result;
     52 }
     53 
     54 VarInstance ProtoFuzzerMutator::ArrayMutate(const VarInstance &var_instance) {
     55   VarInstance result{var_instance};
     56   size_t vector_size = result.vector_size();
     57   size_t idx = rand_(vector_size);
     58   *result.mutable_vector_value(idx) = this->Mutate(result.vector_value(idx));
     59   return result;
     60 }
     61 
     62 VarInstance ProtoFuzzerMutator::EnumRandomGen(const VarSpec &var_spec) {
     63   VarInstance result{VarInstanceStubFromSpec(var_spec)};
     64   const EnumData &blueprint =
     65       FindPredefinedType(result.predefined_type()).enum_value();
     66 
     67   size_t size = blueprint.enumerator_size();
     68   size_t idx = rand_(size);
     69 
     70   ScalarData scalar_value = blueprint.scalar_value(idx);
     71   string scalar_type = blueprint.scalar_type();
     72 
     73   // Mutate this enum like a scalar with probability
     74   // odds_for/(odds_for + odds_against).
     75   uint64_t odds_for = (this->mutator_config_).enum_bias_.first;
     76   uint64_t odds_against = (this->mutator_config_).enum_bias_.second;
     77   uint64_t rand_num = rand_(odds_for + odds_against);
     78   if (rand_num < odds_for) {
     79     scalar_value = Mutate(scalar_value, scalar_type);
     80   }
     81 
     82   *(result.mutable_scalar_value()) = scalar_value;
     83   result.set_scalar_type(scalar_type);
     84   return result;
     85 }
     86 
     87 VarInstance ProtoFuzzerMutator::EnumMutate(const VarInstance &var_instance) {
     88   // For TYPE_ENUM, VarInstance contains superset info of VarSpec.
     89   return RandomGen(var_instance);
     90 }
     91 
     92 VarInstance ProtoFuzzerMutator::ScalarRandomGen(const VarSpec &var_spec) {
     93   VarInstance result{VarInstanceStubFromSpec(var_spec)};
     94   (*result.mutable_scalar_value()) =
     95       RandomGen(var_spec.scalar_value(), var_spec.scalar_type());
     96   return result;
     97 }
     98 
     99 VarInstance ProtoFuzzerMutator::ScalarMutate(const VarInstance &var_instance) {
    100   VarInstance result{var_instance};
    101   (*result.mutable_scalar_value()) =
    102       Mutate(result.scalar_value(), result.scalar_type());
    103   return result;
    104 }
    105 
    106 VarInstance ProtoFuzzerMutator::StructRandomGen(const VarSpec &var_spec) {
    107   VarInstance result{VarInstanceStubFromSpec(var_spec)};
    108   const TypeSpec &blueprint = FindPredefinedType(result.predefined_type());
    109   for (const VarSpec &struct_value : blueprint.struct_value()) {
    110     *result.add_struct_value() = this->RandomGen(struct_value);
    111   }
    112   return result;
    113 }
    114 
    115 VarInstance ProtoFuzzerMutator::StructMutate(const VarInstance &var_instance) {
    116   VarInstance result{var_instance};
    117   size_t size = result.struct_value_size();
    118   size_t idx = rand_(size);
    119   *result.mutable_struct_value(idx) = this->Mutate(result.struct_value(idx));
    120   return result;
    121 }
    122 
    123 VarInstance ProtoFuzzerMutator::UnionRandomGen(const VarSpec &var_spec) {
    124   VarInstance result{VarInstanceStubFromSpec(var_spec)};
    125   const TypeSpec &blueprint = FindPredefinedType(result.predefined_type());
    126   size_t size = blueprint.union_value_size();
    127   for (size_t i = 0; i < size; ++i) {
    128     result.add_union_value();
    129   }
    130   size_t idx = rand_(size);
    131   *result.mutable_union_value(idx) =
    132       this->RandomGen(blueprint.union_value(idx));
    133   return result;
    134 }
    135 
    136 VarInstance ProtoFuzzerMutator::UnionMutate(const VarInstance &var_instance) {
    137   VarInstance result{var_instance};
    138   size_t size = result.union_value_size();
    139   for (size_t i = 0; i < size; ++i) {
    140     if (result.union_value(i).has_name()) {
    141       *result.mutable_union_value(i) = this->Mutate(result.union_value(i));
    142     }
    143   }
    144   return result;
    145 }
    146 
    147 VarInstance ProtoFuzzerMutator::VectorRandomGen(const VarSpec &var_spec) {
    148   VarInstance result{VarInstanceStubFromSpec(var_spec)};
    149   size_t size = mutator_config_.default_vector_size_;
    150   for (size_t i = 0; i < size; ++i) {
    151     *result.add_vector_value() = this->RandomGen(var_spec.vector_value(0));
    152   }
    153   return result;
    154 }
    155 
    156 VarInstance ProtoFuzzerMutator::VectorMutate(const VarInstance &var_instance) {
    157   VarInstance result{var_instance};
    158   size_t size = result.vector_size();
    159   size_t idx = rand_(size);
    160   *result.mutable_vector_value(idx) = this->Mutate(result.vector_value(idx));
    161   return result;
    162 }
    163 
    164 ScalarData ProtoFuzzerMutator::RandomGen(const ScalarData &scalar_value,
    165                                          const string &scalar_type) {
    166   ScalarData result{};
    167 
    168   if (scalar_type == "bool_t") {
    169     result.set_bool_t(RandomGen(static_cast<bool>(scalar_value.bool_t())));
    170   } else if (scalar_type == "int8_t") {
    171     result.set_int8_t(RandomGen(scalar_value.int8_t()));
    172   } else if (scalar_type == "uint8_t") {
    173     result.set_uint8_t(RandomGen(scalar_value.uint8_t()));
    174   } else if (scalar_type == "int16_t") {
    175     result.set_int16_t(RandomGen(scalar_value.int16_t()));
    176   } else if (scalar_type == "uint16_t") {
    177     result.set_uint16_t(RandomGen(scalar_value.uint16_t()));
    178   } else if (scalar_type == "int32_t") {
    179     result.set_int32_t(RandomGen(scalar_value.int32_t()));
    180   } else if (scalar_type == "uint32_t") {
    181     result.set_uint32_t(RandomGen(scalar_value.uint32_t()));
    182   } else if (scalar_type == "int64_t") {
    183     result.set_int64_t(RandomGen(scalar_value.int64_t()));
    184   } else if (scalar_type == "uint64_t") {
    185     result.set_uint64_t(RandomGen(scalar_value.uint64_t()));
    186   } else if (scalar_type == "float_t") {
    187     result.set_float_t(RandomGen(scalar_value.float_t()));
    188   } else if (scalar_type == "double_t") {
    189     result.set_double_t(RandomGen(scalar_value.double_t()));
    190   } else {
    191     cout << scalar_type << " not supported.\n";
    192   }
    193 
    194   return result;
    195 }
    196 
    197 ScalarData ProtoFuzzerMutator::Mutate(const ScalarData &scalar_value,
    198                                       const string &scalar_type) {
    199   ScalarData result{};
    200 
    201   if (scalar_type == "bool_t") {
    202     result.set_bool_t(Mutate(static_cast<bool>(scalar_value.bool_t())));
    203   } else if (scalar_type == "int8_t") {
    204     result.set_int8_t(Mutate(scalar_value.int8_t()));
    205   } else if (scalar_type == "uint8_t") {
    206     result.set_uint8_t(Mutate(scalar_value.uint8_t()));
    207   } else if (scalar_type == "int16_t") {
    208     result.set_int16_t(Mutate(scalar_value.int16_t()));
    209   } else if (scalar_type == "uint16_t") {
    210     result.set_uint16_t(Mutate(scalar_value.uint16_t()));
    211   } else if (scalar_type == "int32_t") {
    212     result.set_int32_t(Mutate(scalar_value.int32_t()));
    213   } else if (scalar_type == "uint32_t") {
    214     result.set_uint32_t(Mutate(scalar_value.uint32_t()));
    215   } else if (scalar_type == "int64_t") {
    216     result.set_int64_t(Mutate(scalar_value.int64_t()));
    217   } else if (scalar_type == "uint64_t") {
    218     result.set_uint64_t(Mutate(scalar_value.uint64_t()));
    219   } else if (scalar_type == "float_t") {
    220     result.set_float_t(Mutate(scalar_value.float_t()));
    221   } else if (scalar_type == "double_t") {
    222     result.set_double_t(Mutate(scalar_value.double_t()));
    223   } else {
    224     cout << scalar_type << " not supported.\n";
    225   }
    226 
    227   return result;
    228 }
    229 
    230 template <typename T>
    231 T ProtoFuzzerMutator::RandomGen(T value) {
    232   // Generate a biased random scalar.
    233   uint64_t rand_int = mutator_config_.scalar_bias_(rand_);
    234 
    235   T result;
    236   memcpy(&result, &rand_int, sizeof(T));
    237   return result;
    238 }
    239 
    240 bool ProtoFuzzerMutator::RandomGen(bool value) {
    241   return static_cast<bool>(rand_(2));
    242 }
    243 
    244 template <typename T>
    245 T ProtoFuzzerMutator::Mutate(T value) {
    246   size_t num_bits = 8 * sizeof(T);
    247   T mask = static_cast<T>(1) << rand_(num_bits);
    248   return value ^ mask;
    249 }
    250 
    251 bool ProtoFuzzerMutator::Mutate(bool value) {
    252   return RandomGen(value);
    253 }
    254 
    255 float ProtoFuzzerMutator::Mutate(float value) {
    256   uint32_t copy;
    257   memcpy(&copy, &value, sizeof(float));
    258   uint32_t mask = static_cast<uint32_t>(1) << rand_(32);
    259   copy ^= mask;
    260   memcpy(&value, &copy, sizeof(float));
    261   return value;
    262 }
    263 
    264 double ProtoFuzzerMutator::Mutate(double value) {
    265   uint64_t copy;
    266   memcpy(&copy, &value, sizeof(double));
    267   uint64_t mask = static_cast<uint64_t>(1) << rand_(64);
    268   copy ^= mask;
    269   memcpy(&value, &copy, sizeof(double));
    270   return value;
    271 }
    272 
    273 }  // namespace fuzzer
    274 }  // namespace vts
    275 }  // namespace android
    276