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