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 "HalHidlFuzzerCodeGen.h"
18 #include "VtsCompilerUtils.h"
19 #include "code_gen/common/HalHidlCodeGenUtils.h"
20 #include "utils/InterfaceSpecUtil.h"
21 #include "utils/StringUtil.h"
22
23 using std::cerr;
24 using std::cout;
25 using std::endl;
26 using std::vector;
27
28 namespace android {
29 namespace vts {
30
GenerateSourceIncludeFiles(Formatter & out)31 void HalHidlFuzzerCodeGen::GenerateSourceIncludeFiles(Formatter &out) {
32 out << "#include <iostream>\n\n";
33 out << "#include \"FuncFuzzerUtils.h\"\n";
34 out << "#include <" << GetPackagePath(comp_spec_) << "/"
35 << GetVersion(comp_spec_) << "/" << GetComponentName(comp_spec_)
36 << ".h>\n";
37 out << "\n";
38 }
39
GenerateUsingDeclaration(Formatter & out)40 void HalHidlFuzzerCodeGen::GenerateUsingDeclaration(Formatter &out) {
41 out << "using std::cerr;\n";
42 out << "using std::endl;\n";
43 out << "using std::string;\n\n";
44
45 string package_path = comp_spec_.package();
46 ReplaceSubString(package_path, ".", "::");
47 string comp_version = GetVersion(comp_spec_, true);
48
49 out << "using namespace ::" << package_path << "::" << comp_version << ";\n";
50 out << "using namespace ::android::hardware;\n";
51 out << "\n";
52 }
53
GenerateGlobalVars(Formatter & out)54 void HalHidlFuzzerCodeGen::GenerateGlobalVars(Formatter &out) {
55 out << "static string target_func;\n\n";
56 }
57
GenerateLLVMFuzzerInitialize(Formatter & out)58 void HalHidlFuzzerCodeGen::GenerateLLVMFuzzerInitialize(Formatter &out) {
59 out << "extern \"C\" int LLVMFuzzerInitialize(int *argc, char ***argv) "
60 "{\n";
61 out.indent();
62 out << "FuncFuzzerParams params{ExtractFuncFuzzerParams(*argc, *argv)};\n";
63 out << "target_func = params.target_func_;\n";
64 out << "return 0;\n";
65 out.unindent();
66 out << "}\n\n";
67 }
68
GenerateLLVMFuzzerTestOneInput(Formatter & out)69 void HalHidlFuzzerCodeGen::GenerateLLVMFuzzerTestOneInput(Formatter &out) {
70 out << "extern \"C\" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t "
71 "size) {\n";
72 out.indent();
73 out << "static ::android::sp<" << comp_spec_.component_name() << "> "
74 << GetHalPointerName() << " = " << comp_spec_.component_name()
75 << "::getService(true);\n";
76 out << "if (" << GetHalPointerName() << " == nullptr) {\n";
77 out.indent();
78 out << "cerr << \"" << comp_spec_.component_name()
79 << "::getService() failed\" << endl;\n";
80 out << "exit(1);\n";
81 out.unindent();
82 out << "}\n\n";
83 for (const auto &func_spec : comp_spec_.interface().api()) {
84 GenerateHalFunctionCall(out, func_spec);
85 }
86 out << "{\n";
87 out.indent();
88 out << "cerr << \"No such function: \" << target_func << endl;\n";
89 out << "exit(1);\n";
90 out.unindent();
91 out << "}\n";
92
93 out.unindent();
94 out << "}\n\n";
95 }
96
GetHalPointerName()97 string HalHidlFuzzerCodeGen::GetHalPointerName() {
98 string prefix = "android.hardware.";
99 string hal_pointer_name = comp_spec_.package().substr(prefix.size());
100 ReplaceSubString(hal_pointer_name, ".", "_");
101 return hal_pointer_name;
102 }
103
GenerateReturnCallback(Formatter & out,const FunctionSpecificationMessage & func_spec)104 void HalHidlFuzzerCodeGen::GenerateReturnCallback(
105 Formatter &out, const FunctionSpecificationMessage &func_spec) {
106 if (CanElideCallback(func_spec)) {
107 return;
108 }
109 out << "// No-op. Only need this to make HAL function call.\n";
110 out << "auto " << return_cb_name << " = [](";
111 size_t num_cb_arg = func_spec.return_type_hidl_size();
112 for (size_t i = 0; i < num_cb_arg; ++i) {
113 const auto &return_val = func_spec.return_type_hidl(i);
114 out << GetCppVariableType(return_val, IsConstType(return_val.type()));
115 out << " arg" << i << ((i != num_cb_arg - 1) ? ", " : "");
116 }
117 out << "){};\n\n";
118 }
119
GenerateHalFunctionCall(Formatter & out,const FunctionSpecificationMessage & func_spec)120 void HalHidlFuzzerCodeGen::GenerateHalFunctionCall(
121 Formatter &out, const FunctionSpecificationMessage &func_spec) {
122 string func_name = func_spec.name();
123 out << "if (target_func == \"" << func_name << "\") {\n";
124 out.indent();
125
126 GenerateReturnCallback(out, func_spec);
127 vector<string> types{GetFuncArgTypes(func_spec)};
128 for (size_t i = 0; i < types.size(); ++i) {
129 out << "size_t type_size" << i << " = sizeof(" << types[i] << ");\n";
130 out << "if (size < type_size" << i << ") { return 0; }\n";
131 out << "size -= type_size" << i << ";\n";
132 out << types[i] << " arg" << i << ";\n";
133 out << "memcpy(&arg" << i << ", data, type_size" << i << ");\n";
134 out << "data += type_size" << i << ";\n\n";
135 }
136
137 out << GetHalPointerName() << "->" << func_spec.name() << "(";
138 for (size_t i = 0; i < types.size(); ++i) {
139 out << "arg" << i << ((i != types.size() - 1) ? ", " : "");
140 }
141 if (!CanElideCallback(func_spec)) {
142 if (func_spec.arg_size() > 0) {
143 out << ", ";
144 }
145 out << return_cb_name;
146 }
147 out << ");\n";
148 out << "return 0;\n";
149
150 out.unindent();
151 out << "} else ";
152 }
153
CanElideCallback(const FunctionSpecificationMessage & func_spec)154 bool HalHidlFuzzerCodeGen::CanElideCallback(
155 const FunctionSpecificationMessage &func_spec) {
156 if (func_spec.return_type_hidl_size() == 0) {
157 return true;
158 }
159 // Can't elide callback for void or tuple-returning methods
160 if (func_spec.return_type_hidl_size() != 1) {
161 return false;
162 }
163 const VariableType &type = func_spec.return_type_hidl(0).type();
164 if (type == TYPE_ARRAY || type == TYPE_VECTOR || type == TYPE_REF) {
165 return false;
166 }
167 return IsElidableType(type);
168 }
169
GetFuncArgTypes(const FunctionSpecificationMessage & func_spec)170 vector<string> HalHidlFuzzerCodeGen::GetFuncArgTypes(
171 const FunctionSpecificationMessage &func_spec) {
172 vector<string> types{};
173 for (const auto &var_spec : func_spec.arg()) {
174 string type = GetCppVariableType(var_spec);
175 types.emplace_back(GetCppVariableType(var_spec));
176 }
177 return types;
178 }
179
180 } // namespace vts
181 } // namespace android
182