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 
     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 
     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 
     60 void HalHidlFuzzerCodeGen::GenerateGlobalVars(Formatter &out) {
     61   out << "static string target_func;\n\n";
     62 }
     63 
     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 
     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 
    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 
    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 
    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 
    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 
    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