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