Home | History | Annotate | Download | only in fuzzer
      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 
     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 
     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 
     54 void HalHidlFuzzerCodeGen::GenerateGlobalVars(Formatter &out) {
     55   out << "static string target_func;\n\n";
     56 }
     57 
     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 
     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 
     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 
    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 
    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 
    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 
    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