• 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 "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.
__anona74cc55c0102() 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.
__anona74cc55c0202() 75     {1, 1000}};
76 
LLVMFuzzerInitialize(int * argc,char *** argv)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 
LLVMFuzzerCustomMutator(uint8_t * data,size_t size,size_t max_size,unsigned int seed)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.
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)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 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)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