Merge "Add pre-upload style checker for cpp and java code"
diff --git a/iface_fuzzer/Android.bp b/iface_fuzzer/Android.bp
index 23bdce7..c273479 100644
--- a/iface_fuzzer/Android.bp
+++ b/iface_fuzzer/Android.bp
@@ -27,6 +27,7 @@
],
shared_libs: [
"libprotobuf-cpp-full",
+ "libvintf",
"libvts_common",
"libvts_multidevice_proto",
"libvts_proto_fuzzer_proto",
diff --git a/iface_fuzzer/ProtoFuzzerMain.cpp b/iface_fuzzer/ProtoFuzzerMain.cpp
index 2975bf5..42803fe 100644
--- a/iface_fuzzer/ProtoFuzzerMain.cpp
+++ b/iface_fuzzer/ProtoFuzzerMain.cpp
@@ -80,8 +80,7 @@
FindTargetCompSpec(params.comp_specs_, params.target_iface_);
mutator = make_unique<ProtoFuzzerMutator>(
random, ExtractPredefinedTypes(params.comp_specs_), mutator_config);
- hal.reset(
- InitHalDriver(target_comp_spec, params.service_name_, params.get_stub_));
+ hal.reset(InitHalDriver(target_comp_spec, params.binder_mode_));
return 0;
}
diff --git a/iface_fuzzer/ProtoFuzzerMutateFns.cpp b/iface_fuzzer/ProtoFuzzerMutateFns.cpp
index 416320f..9960dae 100644
--- a/iface_fuzzer/ProtoFuzzerMutateFns.cpp
+++ b/iface_fuzzer/ProtoFuzzerMutateFns.cpp
@@ -91,8 +91,9 @@
VarInstance ProtoFuzzerMutator::ScalarRandomGen(const VarSpec &var_spec) {
VarInstance result{VarInstanceStubFromSpec(var_spec)};
+ result.set_scalar_type(var_spec.scalar_type());
(*result.mutable_scalar_value()) =
- RandomGen(var_spec.scalar_value(), var_spec.scalar_type());
+ RandomGen(result.scalar_value(), result.scalar_type());
return result;
}
@@ -103,6 +104,58 @@
return result;
}
+VarInstance ProtoFuzzerMutator::StringRandomGen(const VarSpec &var_spec) {
+ VarInstance result{VarInstanceStubFromSpec(var_spec)};
+
+ size_t str_size = mutator_config_.default_string_size_;
+ string str(str_size, 0);
+ auto rand_char = std::bind(&ProtoFuzzerMutator::RandomAsciiChar, this);
+ std::generate_n(str.begin(), str_size, rand_char);
+
+ StringDataValueMessage string_data;
+ string_data.set_message(str.c_str());
+ string_data.set_length(str_size);
+
+ *result.mutable_string_value() = string_data;
+ return result;
+}
+
+VarInstance ProtoFuzzerMutator::StringMutate(const VarInstance &var_instance) {
+ VarInstance result{var_instance};
+ string str = result.string_value().message();
+ size_t str_size = result.string_value().length();
+
+ // Three things can happen when mutating a string:
+ // 1. A random char is inserted into a random position.
+ // 2. A randomly selected char is removed from the string.
+ // 3. A randomly selected char in the string is replaced by a random char.
+ size_t dice_roll = str.empty() ? 0 : rand_(3);
+ size_t idx = rand_(str_size);
+ switch (dice_roll) {
+ case 0:
+ // Insert a random char.
+ str.insert(str.begin() + idx, RandomAsciiChar());
+ ++str_size;
+ break;
+ case 1:
+ // Remove a randomly selected char.
+ str.erase(str.begin() + idx);
+ --str_size;
+ break;
+ case 2:
+ // Replace a randomly selected char.
+ str[idx] = RandomAsciiChar();
+ break;
+ default:
+ // Do nothing.
+ break;
+ }
+
+ result.mutable_string_value()->set_message(str);
+ result.mutable_string_value()->set_length(str_size);
+ return result;
+}
+
VarInstance ProtoFuzzerMutator::StructRandomGen(const VarSpec &var_spec) {
VarInstance result{VarInstanceStubFromSpec(var_spec)};
const TypeSpec &blueprint = FindPredefinedType(result.predefined_type());
@@ -270,6 +323,16 @@
return value;
}
+char ProtoFuzzerMutator::RandomAsciiChar() {
+ const char char_set[] =
+ "0123456789"
+ "`~!@#$%^&*()-_=+[{]};:',<.>/? "
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz";
+ size_t num_chars = sizeof(char_set) - 1;
+ return char_set[rand_(num_chars)];
+}
+
} // namespace fuzzer
} // namespace vts
} // namespace android
diff --git a/iface_fuzzer/ProtoFuzzerMutator.cpp b/iface_fuzzer/ProtoFuzzerMutator.cpp
index a52b0c9..3a20976 100644
--- a/iface_fuzzer/ProtoFuzzerMutator.cpp
+++ b/iface_fuzzer/ProtoFuzzerMutator.cpp
@@ -61,11 +61,21 @@
random_gen_fns_[TYPE_HIDL_INTERFACE] = default_transform;
mutate_fns_[TYPE_HIDL_INTERFACE] = default_transform;
+ // Interpret masks as enums.
+ random_gen_fns_[TYPE_MASK] =
+ std::bind(&ProtoFuzzerMutator::EnumRandomGen, this, _1);
+ mutate_fns_[TYPE_MASK] = std::bind(&ProtoFuzzerMutator::EnumMutate, this, _1);
+
random_gen_fns_[TYPE_SCALAR] =
std::bind(&ProtoFuzzerMutator::ScalarRandomGen, this, _1);
mutate_fns_[TYPE_SCALAR] =
std::bind(&ProtoFuzzerMutator::ScalarMutate, this, _1);
+ random_gen_fns_[TYPE_STRING] =
+ std::bind(&ProtoFuzzerMutator::StringRandomGen, this, _1);
+ mutate_fns_[TYPE_STRING] =
+ std::bind(&ProtoFuzzerMutator::StringMutate, this, _1);
+
random_gen_fns_[TYPE_STRUCT] =
std::bind(&ProtoFuzzerMutator::StructRandomGen, this, _1);
mutate_fns_[TYPE_STRUCT] =
diff --git a/iface_fuzzer/ProtoFuzzerUtils.cpp b/iface_fuzzer/ProtoFuzzerUtils.cpp
index 870f1a7..0a14a25 100644
--- a/iface_fuzzer/ProtoFuzzerUtils.cpp
+++ b/iface_fuzzer/ProtoFuzzerUtils.cpp
@@ -23,8 +23,12 @@
#include <sstream>
#include "specification_parser/InterfaceSpecificationParser.h"
+#include "vintf/HalManifest.h"
+#include "vintf/VintfObject.h"
#include "utils/InterfaceSpecUtil.h"
+using android::vintf::HalManifest;
+
using std::cout;
using std::cerr;
using std::string;
@@ -40,15 +44,20 @@
stdout,
"Usage:\n"
"\n"
- "./<fuzzer> <vts flags> -- <libfuzzer flags>\n"
+ "./vts_proto_fuzzer <vts flags> -- <libfuzzer flags>\n"
"\n"
"VTS flags (strictly in form --flag=value):\n"
"\n"
- " vts_spec_files \tColumn-separated list of paths to vts spec files.\n"
- " vts_exec_size \t\tNumber of function calls per fuzzer execution.\n"
+ "\tvts_binder_mode: if set, fuzzer will open the HAL in binder mode.\n"
+ "\tvts_exec_size: number of function calls per 1 run of "
+ "LLVMFuzzerTestOneInput.\n"
+ "\tvts_spec_dir: \":\"-separated list of directories on the target "
+ "containing .vts spec files.\n"
+ "\tvts_target_iface: name of interface targeted for fuzz, e.g. "
+ "\"INfc\".\n"
"\n"
"libfuzzer flags (strictly in form -flag=value):\n"
- " Use -help=1 to see libfuzzer flags\n"
+ "\tUse -help=1 to see libfuzzer flags\n"
"\n");
}
@@ -57,7 +66,6 @@
{"vts_binder_mode", no_argument, 0, 'b'},
{"vts_spec_dir", required_argument, 0, 'd'},
{"vts_exec_size", required_argument, 0, 'e'},
- {"vts_service_name", required_argument, 0, 's'},
{"vts_target_iface", required_argument, 0, 't'}};
static string GetDriverName(const CompSpec &comp_spec) {
@@ -70,9 +78,25 @@
}
static string GetServiceName(const CompSpec &comp_spec) {
- // Infer HAL service name from its package name.
- string prefix = "android.hardware.";
- string service_name = comp_spec.package().substr(prefix.size());
+ static const HalManifest *vendor_manifest =
+ ::android::vintf::VintfObject::GetDeviceHalManifest();
+ string hal_name = comp_spec.package();
+ string iface_name = comp_spec.component_name();
+
+ auto instance_names = vendor_manifest->getInstances(hal_name, iface_name);
+ if (instance_names.empty()) {
+ cerr << "HAL service name not available in VINTF." << endl;
+ exit(1);
+ }
+
+ // For fuzzing we don't care which instance of the HAL is targeted.
+ string service_name = *instance_names.begin();
+ cout << "Available HAL instances: " << endl;
+ for (const string &instance_name : instance_names) {
+ cout << instance_name << endl;
+ }
+ cout << "Using HAL instance: " << service_name << endl;
+
return service_name;
}
@@ -90,23 +114,28 @@
}
}
-static vector<CompSpec> ExtractCompSpecs(string dir_path) {
+static vector<CompSpec> ExtractCompSpecs(string arg) {
vector<CompSpec> result{};
- DIR *dir;
- struct dirent *ent;
- if (!(dir = opendir(dir_path.c_str()))) {
- cerr << "Could not open directory: " << dir_path << endl;
- exit(1);
- }
- while ((ent = readdir(dir))) {
- string vts_spec_name{ent->d_name};
- if (vts_spec_name.find(".vts") != string::npos) {
- cout << "Loading: " << vts_spec_name << endl;
- string vts_spec_path = dir_path + "/" + vts_spec_name;
- CompSpec comp_spec{};
- InterfaceSpecificationParser::parse(vts_spec_path.c_str(), &comp_spec);
- TrimCompSpec(&comp_spec);
- result.emplace_back(std::move(comp_spec));
+ string dir_path;
+ std::istringstream iss(arg);
+
+ while (std::getline(iss, dir_path, ':')) {
+ DIR *dir;
+ struct dirent *ent;
+ if (!(dir = opendir(dir_path.c_str()))) {
+ cerr << "Could not open directory: " << dir_path << endl;
+ exit(1);
+ }
+ while ((ent = readdir(dir))) {
+ string vts_spec_name{ent->d_name};
+ if (vts_spec_name.find(".vts") != string::npos) {
+ cout << "Loading: " << vts_spec_name << endl;
+ string vts_spec_path = dir_path + "/" + vts_spec_name;
+ CompSpec comp_spec{};
+ InterfaceSpecificationParser::parse(vts_spec_path.c_str(), &comp_spec);
+ TrimCompSpec(&comp_spec);
+ result.emplace_back(std::move(comp_spec));
+ }
}
}
return result;
@@ -131,7 +160,7 @@
usage();
exit(0);
case 'b':
- params.get_stub_ = false;
+ params.binder_mode_ = true;
break;
case 'd':
params.comp_specs_ = ExtractCompSpecs(optarg);
@@ -139,9 +168,6 @@
case 'e':
params.exec_size_ = atoi(optarg);
break;
- case 's':
- params.service_name_ = optarg;
- break;
case 't':
params.target_iface_ = optarg;
break;
@@ -171,8 +197,7 @@
}
// TODO(trong): this should be done using FuzzerWrapper.
-FuzzerBase *InitHalDriver(const CompSpec &comp_spec, string service_name,
- bool get_stub) {
+FuzzerBase *InitHalDriver(const CompSpec &comp_spec, bool binder_mode) {
const char *error;
string driver_name = GetDriverName(comp_spec);
void *handle = dlopen(driver_name.c_str(), RTLD_LAZY);
@@ -194,16 +219,29 @@
}
FuzzerBase *hal = hal_loader();
+ string service_name = GetServiceName(comp_spec);
+ cerr << "HAL name: " << comp_spec.package() << endl
+ << "Interface name: " << comp_spec.component_name() << endl
+ << "Service name: " << service_name << endl;
+
// For fuzzing, only passthrough mode provides coverage.
- if (get_stub) {
- cout << "HAL used in passthrough mode." << endl;
- } else {
- cout << "HAL used in binderized mode." << endl;
+ // If binder mode is not requested, attempt to open HAL in passthrough mode.
+ // If the attempt fails, fall back to binder mode.
+ if (!binder_mode) {
+ if (!hal->GetService(true, service_name.c_str())) {
+ cerr << __func__ << ": Failed to open HAL in passthrough mode. "
+ << "Falling back to binder mode." << endl;
+ } else {
+ cerr << "HAL opened in passthrough mode." << endl;
+ return hal;
+ }
}
- if (!hal->GetService(get_stub, service_name.c_str())) {
- cerr << __func__ << ": GetService(true, " << service_name << ") failed."
- << endl;
+
+ if (!hal->GetService(false, service_name.c_str())) {
+ cerr << __func__ << ": Failed to open HAL in binder mode." << endl;
exit(1);
+ } else {
+ cerr << "HAL opened in binder mode." << endl;
}
return hal;
}
@@ -215,6 +253,9 @@
for (const auto &var_spec : comp_spec.attribute()) {
ExtractPredefinedTypesFromVar(var_spec, predefined_types);
}
+ for (const auto &var_spec : comp_spec.interface().attribute()) {
+ ExtractPredefinedTypesFromVar(var_spec, predefined_types);
+ }
}
return predefined_types;
}
diff --git a/iface_fuzzer/include/ProtoFuzzerMutator.h b/iface_fuzzer/include/ProtoFuzzerMutator.h
index 90a0562..0609684 100644
--- a/iface_fuzzer/include/ProtoFuzzerMutator.h
+++ b/iface_fuzzer/include/ProtoFuzzerMutator.h
@@ -47,6 +47,8 @@
Odds func_mutated_ = {100, 1};
// Default size used to randomly generate a vector.
size_t default_vector_size_ = 64;
+ // Default size used to randomly generate a string.
+ size_t default_string_size_ = 16;
};
// Provides methods for mutation or random generation.
@@ -75,6 +77,8 @@
VarInstance EnumMutate(const VarInstance &);
VarInstance ScalarRandomGen(const VarSpec &);
VarInstance ScalarMutate(const VarInstance &);
+ VarInstance StringRandomGen(const VarSpec &);
+ VarInstance StringMutate(const VarInstance &);
VarInstance StructRandomGen(const VarSpec &);
VarInstance StructMutate(const VarInstance &);
VarInstance UnionRandomGen(const VarSpec &);
@@ -95,6 +99,8 @@
bool Mutate(bool);
float Mutate(float);
double Mutate(double);
+ // Generates a random ASCII character.
+ char RandomAsciiChar();
// Looks up predefined type by name.
const TypeSpec &FindPredefinedType(std::string);
diff --git a/iface_fuzzer/include/ProtoFuzzerUtils.h b/iface_fuzzer/include/ProtoFuzzerUtils.h
index b5516c3..afa978d 100644
--- a/iface_fuzzer/include/ProtoFuzzerUtils.h
+++ b/iface_fuzzer/include/ProtoFuzzerUtils.h
@@ -69,13 +69,11 @@
size_t exec_size_;
// VTS specs supplied to the fuzzer.
std::vector<CompSpec> comp_specs_;
- // Service name of target interface, e.g. "INfc".
- std::string service_name_ = "default";
- // Name of target interface, e.g. "default".
+ // Name of target interface, e.g. "INfc".
std::string target_iface_;
// Controls whether HAL is opened in passthrough or binder mode.
- // Passthrough mode is default. Used for testsing.
- bool get_stub_ = true;
+ // Passthrough mode is default. Used for testing.
+ bool binder_mode_ = false;
};
// Parses command-line flags to create a ProtoFuzzerParams instance.
@@ -85,7 +83,7 @@
CompSpec FindTargetCompSpec(const std::vector<CompSpec> &, const std::string &);
// Loads VTS HAL driver library.
-FuzzerBase *InitHalDriver(const CompSpec &, std::string, bool);
+FuzzerBase *InitHalDriver(const CompSpec &, bool);
// Creates a key, value look-up table with keys being names of predefined types,
// and values being their definitions.
diff --git a/template/iface_fuzzer_test/iface_fuzzer_test.py b/template/iface_fuzzer_test/iface_fuzzer_test.py
index 7733a8d..079c4c7 100644
--- a/template/iface_fuzzer_test/iface_fuzzer_test.py
+++ b/template/iface_fuzzer_test/iface_fuzzer_test.py
@@ -45,9 +45,11 @@
hal_version: string, version of the hal, e.g '7.4'
"""
# Push .vts spec files.
- hal_name_dir = hal_name.replace('.', '/')
+ hal_name_dir = vts_spec_utils.HalNameDir(hal_name)
src_dir = os.path.join(self.data_file_path, 'spec', 'hardware',
'interfaces', hal_name_dir, hal_version, 'vts')
+ dst_dir = os.path.join(self._VTS_SPEC_DIR_TARGET, hal_name_dir,
+ hal_version)
# Push corresponding VTS drivers.
driver_name = 'android.hardware.%s@%s-vts.driver.so' % (hal_name,
@@ -56,37 +58,63 @@
driver32 = os.path.join(asan_path, 'lib', driver_name)
driver64 = os.path.join(asan_path, 'lib64', driver_name)
try:
- self._dut.adb.push(src_dir, self._VTS_SPEC_DIR_TARGET)
+ self._dut.adb.push(src_dir, dst_dir)
self._dut.adb.push(driver32, 'data/local/tmp/32')
self._dut.adb.push(driver64, 'data/local/tmp/64')
except adb.AdbError as e:
logging.exception(e)
+ def _VtsSpecDirsTarget(self, hal_name, hal_version):
+ """Returns a list of directories on target with .vts specs.
+
+ Args:
+ hal_name: string, name of the hal, e.g. 'vibrator'.
+ hal_version: string, version of the hal, e.g '7.4'
+
+ Returns:
+ string list, directories on target
+ """
+ hal_name_dir = vts_spec_utils.HalNameDir(hal_name)
+ spec_dirs = [os.path.join(self._VTS_SPEC_DIR_TARGET, hal_name_dir,
+ hal_version)]
+
+ imported_hals = self._vts_spec_parser.ImportedHals(hal_name,
+ hal_version)
+ for name, version in imported_hals:
+ spec_dirs.append(
+ os.path.join(self._VTS_SPEC_DIR_TARGET,
+ vts_spec_utils.HalNameDir(name), version))
+ return spec_dirs
+
# Override
def CreateTestCases(self):
"""See base class."""
hal_package = self.hal_hidl_package_name
hal_name, hal_version = vts_spec_utils.HalPackageToNameAndVersion(
hal_package)
+
+ imported_hals = self._vts_spec_parser.ImportedHals(hal_name,
+ hal_version)
self._PushVtsResources(hal_name, hal_version)
- vts_spec_names = self._vts_spec_parser.VtsSpecNames(hal_name,
- hal_version)
- registered_interfaces = self._RegisteredInterfaces(
- self.hal_hidl_package_name)
+ for name, version in imported_hals:
+ self._PushVtsResources(name, version)
+
+ registered_interfaces = self._RegisteredInterfaces(hal_package)
+ spec_dirs = ':'.join(self._VtsSpecDirsTarget(hal_name, hal_version))
test_cases = []
for iface in registered_interfaces:
additional_params = {
- 'vts_spec_dir': self._VTS_SPEC_DIR_TARGET,
- 'vts_exec_size': 128,
+ 'vts_spec_dir': spec_dirs,
+ 'vts_exec_size': 16,
'vts_target_iface': iface,
}
libfuzzer_params = {
'max_len': 65536,
- 'max_total_time': 1,
+ 'max_total_time': 10,
}
bin_host_path = os.path.join(self.data_file_path, 'DATA', 'bin',
- 'vts_proto_fuzzer')
+ 'vts_proto_fuzzer')
test_case = libfuzzer_test_case.LibFuzzerTestCase(
bin_host_path, libfuzzer_params, additional_params)
test_case.test_name = iface
diff --git a/template/libfuzzer_test/libfuzzer_test_config.py b/template/libfuzzer_test/libfuzzer_test_config.py
index d191404..c330f48 100644
--- a/template/libfuzzer_test/libfuzzer_test_config.py
+++ b/template/libfuzzer_test/libfuzzer_test_config.py
@@ -37,5 +37,6 @@
FUZZER_DEFAULT_PARAMS = {
"max_len": 100,
"max_total_time": 60,
- "exact_artifact_path": FUZZER_TEST_CRASH_REPORT
+ "exact_artifact_path": FUZZER_TEST_CRASH_REPORT,
+ "timeout": 120,
}