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