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 
     19 #include "test/vts/proto/ComponentSpecificationMessage.pb.h"
     20 
     21 #include <unistd.h>
     22 
     23 #include <iostream>
     24 #include <memory>
     25 #include <string>
     26 #include <vector>
     27 
     28 using std::cout;
     29 using std::endl;
     30 using std::make_unique;
     31 using std::string;
     32 using std::unique_ptr;
     33 using std::vector;
     34 
     35 namespace android {
     36 namespace vts {
     37 namespace fuzzer {
     38 
     39 // 64-bit random number generator.
     40 static Random random{static_cast<uint64_t>(time(0))};
     41 // Parameters that were passed in to fuzzer.
     42 static ProtoFuzzerParams params;
     43 // Used to mutate inputs to hal driver.
     44 static unique_ptr<ProtoFuzzerMutator> mutator;
     45 // Used to exercise HIDL HAL's API.
     46 static unique_ptr<ProtoFuzzerRunner> runner;
     47 
     48 static ProtoFuzzerMutatorConfig mutator_config{
     49     // Heuristic: values close to 0 are likely to be meaningful scalar input
     50     // values.
     51     [](Random &rand) {
     52       size_t dice_roll = rand(10);
     53       if (dice_roll < 3) {
     54         // With probability of 30% return an integer in range [0, 10).
     55         return rand(10);
     56       } else if (dice_roll >= 3 && dice_roll < 6) {
     57         // With probability of 30% return an integer in range [0, 100).
     58         return rand(100);
     59       } else if (dice_roll >= 6 && dice_roll < 9) {
     60         // With probability of 30% return an integer in range [0, 100).
     61         return rand(1000);
     62       }
     63       if (rand(10) == 0) {
     64         // With probability of 1% return 0xffffffffffffffff.
     65         return 0xffffffffffffffff;
     66       }
     67       // With probability 9% result is uniformly random.
     68       return rand.Rand();
     69     },
     70     // Odds of an enum being treated like a scalar are 1:1000.
     71     {1, 1000}};
     72 
     73 extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
     74   params = ExtractProtoFuzzerParams(*argc, *argv);
     75   mutator = make_unique<ProtoFuzzerMutator>(
     76       random, ExtractPredefinedTypes(params.comp_specs_), mutator_config);
     77   runner = make_unique<ProtoFuzzerRunner>(params.comp_specs_);
     78 
     79   runner->Init(params.target_iface_, params.binder_mode_);
     80   return 0;
     81 }
     82 
     83 extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *data, size_t size,
     84                                           size_t max_size, unsigned int seed) {
     85   ExecSpec exec_spec{};
     86   if (!FromArray(data, size, &exec_spec)) {
     87     exec_spec =
     88         mutator->RandomGen(runner->GetOpenedIfaces(), params.exec_size_);
     89   } else {
     90     mutator->Mutate(runner->GetOpenedIfaces(), &exec_spec);
     91   }
     92   return ToArray(data, size, &exec_spec);
     93 }
     94 
     95 // TODO(trong): implement a meaningful cross-over mechanism.
     96 size_t LLVMFuzzerCustomCrossOver(const uint8_t *data1, size_t size1,
     97                                  const uint8_t *data2, size_t size2,
     98                                  uint8_t *out, size_t max_out_size,
     99                                  unsigned int seed) {
    100   memcpy(out, data1, size1);
    101   return size1;
    102 }
    103 
    104 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    105   ExecSpec exec_spec{};
    106   if (!FromArray(data, size, &exec_spec)) {
    107     cerr << "Failed to deserialize an ExecSpec." << endl;
    108     return 0;
    109   }
    110   runner->Execute(exec_spec);
    111   return 0;
    112 }
    113 
    114 }  // namespace fuzzer
    115 }  // namespace vts
    116 }  // namespace android
    117