• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
__anonc9cd82dc0102() 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.
__anonc9cd82dc0202() 71     {1, 1000}};
72 
LLVMFuzzerInitialize(int * argc,char *** argv)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 
LLVMFuzzerCustomMutator(uint8_t * data,size_t size,size_t max_size,unsigned int seed)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.
LLVMFuzzerCustomCrossOver(const uint8_t * data1,size_t size1,const uint8_t * data2,size_t size2,uint8_t * out,size_t max_out_size,unsigned int seed)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 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)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