[veridex] New veridex improvements.
1) Take the type of the receiver on a getClass call.
2) Dedupe reflection uses in precise hidden API finder.
3) Don't do a cheap check that a method is resolved, in case the app
itself is defining a blacklisted API.
bug: 77513322
Test: m
(cherry picked from commit 57b2a550a2215261569a33838a14978c7a9ccde2)
Change-Id: Ia441a637386b2232cf9d7f71f6a612d476b37041
diff --git a/tools/veridex/flow_analysis.cc b/tools/veridex/flow_analysis.cc
index a4553f9..736abb7 100644
--- a/tools/veridex/flow_analysis.cc
+++ b/tools/veridex/flow_analysis.cc
@@ -262,8 +262,17 @@
last_result_ = GetReturnType(instruction.VRegB_35c());
} else if (method == VeriClass::getClass_) {
RegisterValue obj = GetRegister(args[0]);
- last_result_ = RegisterValue(
- obj.GetSource(), obj.GetDexFileReference(), VeriClass::class_);
+ const VeriClass* cls = obj.GetType();
+ if (cls != nullptr && cls->GetClassDef() != nullptr) {
+ const DexFile::ClassDef* def = cls->GetClassDef();
+ last_result_ = RegisterValue(
+ RegisterSource::kClass,
+ DexFileReference(&resolver_->GetDexFileOf(*cls), def->class_idx_.index_),
+ VeriClass::class_);
+ } else {
+ last_result_ = RegisterValue(
+ obj.GetSource(), obj.GetDexFileReference(), VeriClass::class_);
+ }
} else if (method == VeriClass::loadClass_) {
RegisterValue value = GetRegister(args[1]);
last_result_ = RegisterValue(
diff --git a/tools/veridex/hidden_api_finder.cc b/tools/veridex/hidden_api_finder.cc
index b1ae7dd..8c6139f 100644
--- a/tools/veridex/hidden_api_finder.cc
+++ b/tools/veridex/hidden_api_finder.cc
@@ -31,11 +31,8 @@
void HiddenApiFinder::CheckMethod(uint32_t method_id,
VeridexResolver* resolver,
MethodReference ref) {
- // Cheap check that the method is resolved. If it is, we know it's not in
- // a restricted list.
- if (resolver->GetMethod(method_id) != nullptr) {
- return;
- }
+ // Note: we always query whether a method is in a list, as the app
+ // might define blacklisted APIs (which won't be used at runtime).
std::string name = HiddenApi::GetApiMethodName(resolver->GetDexFile(), method_id);
if (hidden_api_.IsInRestrictionList(name)) {
method_locations_[name].push_back(ref);
@@ -45,11 +42,8 @@
void HiddenApiFinder::CheckField(uint32_t field_id,
VeridexResolver* resolver,
MethodReference ref) {
- // Cheap check that the field is resolved. If it is, we know it's not in
- // a restricted list.
- if (resolver->GetField(field_id) != nullptr) {
- return;
- }
+ // Note: we always query whether a field is in a list, as the app
+ // might define blacklisted APIs (which won't be used at runtime).
std::string name = HiddenApi::GetApiFieldName(resolver->GetDexFile(), field_id);
if (hidden_api_.IsInRestrictionList(name)) {
field_locations_[name].push_back(ref);
diff --git a/tools/veridex/precise_hidden_api_finder.cc b/tools/veridex/precise_hidden_api_finder.cc
index 2092af3..4ae5769 100644
--- a/tools/veridex/precise_hidden_api_finder.cc
+++ b/tools/veridex/precise_hidden_api_finder.cc
@@ -63,6 +63,7 @@
void PreciseHiddenApiFinder::Dump(std::ostream& os, HiddenApiStats* stats) {
static const char* kPrefix = " ";
+ std::map<std::string, std::vector<MethodReference>> uses;
for (auto kinds : { field_uses_, method_uses_ }) {
for (auto it : kinds) {
MethodReference ref = it.first;
@@ -74,19 +75,26 @@
std::string name(info.second.ToString());
std::string full_name = cls + "->" + name;
HiddenApiAccessFlags::ApiList api_list = hidden_api_.GetApiList(full_name);
- stats->api_counts[api_list]++;
if (api_list != HiddenApiAccessFlags::kWhitelist) {
- ++stats->reflection_count;
- os << "#" << ++stats->count << ": Reflection " << api_list << " " << full_name
- << " use:";
- os << std::endl;
- os << kPrefix << HiddenApi::GetApiMethodName(ref) << std::endl;
- os << std::endl;
+ uses[full_name].push_back(ref);
}
}
}
}
}
+
+ for (auto it : uses) {
+ ++stats->reflection_count;
+ const std::string& full_name = it.first;
+ HiddenApiAccessFlags::ApiList api_list = hidden_api_.GetApiList(full_name);
+ stats->api_counts[api_list]++;
+ os << "#" << ++stats->count << ": Reflection " << api_list << " " << full_name << " use(s):";
+ os << std::endl;
+ for (const MethodReference& ref : it.second) {
+ os << kPrefix << HiddenApi::GetApiMethodName(ref) << std::endl;
+ }
+ os << std::endl;
+ }
}
} // namespace art
diff --git a/tools/veridex/resolver.h b/tools/veridex/resolver.h
index 52b15fe..65b2961 100644
--- a/tools/veridex/resolver.h
+++ b/tools/veridex/resolver.h
@@ -79,6 +79,10 @@
return dex_file_;
}
+ const DexFile& GetDexFileOf(const VeriClass& kls) {
+ return GetResolverOf(kls)->dex_file_;
+ }
+
private:
// Return the resolver where `kls` is from.
VeridexResolver* GetResolverOf(const VeriClass& kls) const;