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