1 /*
2  * Copyright 2019 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 "ProtoFuzzerUtils.h"
18 
19 #include <android-base/file.h>
20 #include <android-base/macros.h>
21 #include <android-base/strings.h>
22 #include <vintf/VintfObject.h>
23 
24 #define STRINGIFY(x) STRINGIFY_INTERNAL(x)
25 #define STRINGIFY_INTERNAL(x) #x
26 
27 using android::FQName;
28 using android::base::GetExecutableDirectory;
29 using android::base::Join;
30 using android::base::Split;
31 using android::vintf::Version;
32 using android::vintf::VintfObject;
33 using std::cerr;
34 using std::cout;
35 using std::string;
36 
37 namespace android {
38 namespace vts {
39 namespace fuzzer {
40 
41 // TODO(b/145220086): fuzzer should attempt to fuzz all interfaces and instances
42 // it can find.
FindAnyIfaceFQName(const FQName & package_and_version,const vector<CompSpec> & comp_specs)43 static FQName FindAnyIfaceFQName(const FQName &package_and_version,
44                                  const vector<CompSpec> &comp_specs) {
45   for (const auto &spec : comp_specs) {
46     auto package = package_and_version.package();
47     auto major_version = package_and_version.getPackageMajorVersion();
48     auto minor_version = package_and_version.getPackageMinorVersion();
49 
50     if (package == spec.package() &&
51         major_version == spec.component_type_version_major() &&
52         minor_version == spec.component_type_version_minor()) {
53       auto iface_name = spec.component_name();
54       auto instance_names =
55           VintfObject::GetDeviceHalManifest()->getHidlInstances(
56               package,
57               Version(spec.component_type_version_major(),
58                       spec.component_type_version_minor()),
59               iface_name);
60 
61       if (!instance_names.empty()) {
62         auto version =
63             std::to_string(major_version) + "." + std::to_string(minor_version);
64         return FQName{package, version, iface_name};
65       }
66     }
67   }
68   return FQName{};
69 }
70 
71 // Returns path to base directory where fuzzer specs are installed.
GetSpecBaseDir()72 static inline const string &GetSpecBaseDir() {
73   static const string spec_base_dir = GetExecutableDirectory() + "/data/";
74   return spec_base_dir;
75 }
76 
77 // Parses a column-separated list of packages into a list of corresponding
78 // directories.
ParseDirs(const string & packages)79 static vector<string> ParseDirs(const string &packages) {
80   vector<string> result{};
81 
82   for (const auto &package : Split(packages, ":")) {
83     FQName fq_name;
84     if (!FQName::parse(package, &fq_name)) {
85       cerr << "package list is malformed" << endl;
86       std::abort();
87     }
88 
89     vector<string> components = fq_name.getPackageAndVersionComponents(false);
90     string spec_dir = GetSpecBaseDir() + Join(components, '/');
91     result.emplace_back(std::move(spec_dir));
92   }
93   return result;
94 }
95 
ExtractProtoFuzzerStaticParams(int argc,char ** argv)96 ProtoFuzzerParams ExtractProtoFuzzerStaticParams(int argc, char **argv) {
97   FQName package_and_version;
98   if (!FQName::parse(STRINGIFY(STATIC_TARGET_FQ_NAME), &package_and_version)) {
99     cerr << "STATIC_TARGET_FQ_NAME is malformed" << endl;
100     std::abort();
101   }
102 
103   string spec_data_list = STRINGIFY(STATIC_SPEC_DATA);
104   if (spec_data_list.empty()) {
105     cerr << "STATIC_SPEC_DATA is malformed" << endl;
106     std::abort();
107   }
108 
109   ProtoFuzzerParams params;
110   params.comp_specs_ = ExtractCompSpecs(ParseDirs(spec_data_list));
111 
112   // Find first interface in the given package that fits the bill.
113   params.target_fq_name_ =
114       FindAnyIfaceFQName(package_and_version, params.comp_specs_);
115   if (!params.target_fq_name_.isFullyQualified()) {
116     cerr << "HAL service name not available in VINTF." << endl;
117     std::exit(0);
118   }
119 
120   // Hard-coded values
121   params.exec_size_ = 16;
122   return params;
123 }
124 
125 }  // namespace fuzzer
126 }  // namespace vts
127 }  // namespace android
128