• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 "verifier_deps.h"
18 
19 #include <cstring>
20 #include <sstream>
21 
22 #include "art_field-inl.h"
23 #include "art_method-inl.h"
24 #include "base/indenter.h"
25 #include "base/leb128.h"
26 #include "base/mutex-inl.h"
27 #include "compiler_callbacks.h"
28 #include "dex/class_accessor-inl.h"
29 #include "dex/dex_file-inl.h"
30 #include "mirror/class-inl.h"
31 #include "mirror/class_loader.h"
32 #include "oat_file.h"
33 #include "obj_ptr-inl.h"
34 #include "runtime.h"
35 
36 namespace art {
37 namespace verifier {
38 
VerifierDeps(const std::vector<const DexFile * > & dex_files,bool output_only)39 VerifierDeps::VerifierDeps(const std::vector<const DexFile*>& dex_files, bool output_only)
40     : output_only_(output_only) {
41   for (const DexFile* dex_file : dex_files) {
42     DCHECK(GetDexFileDeps(*dex_file) == nullptr);
43     std::unique_ptr<DexFileDeps> deps(new DexFileDeps(dex_file->NumClassDefs()));
44     dex_deps_.emplace(dex_file, std::move(deps));
45   }
46 }
47 
VerifierDeps(const std::vector<const DexFile * > & dex_files)48 VerifierDeps::VerifierDeps(const std::vector<const DexFile*>& dex_files)
49     : VerifierDeps(dex_files, /*output_only=*/ true) {}
50 
51 // Perform logical OR on two bit vectors and assign back to LHS, i.e. `to_update |= other`.
52 // Size of the two vectors must be equal.
53 // Size of `other` must be equal to size of `to_update`.
BitVectorOr(std::vector<bool> & to_update,const std::vector<bool> & other)54 static inline void BitVectorOr(std::vector<bool>& to_update, const std::vector<bool>& other) {
55   DCHECK_EQ(to_update.size(), other.size());
56   std::transform(other.begin(),
57                  other.end(),
58                  to_update.begin(),
59                  to_update.begin(),
60                  std::logical_or<bool>());
61 }
62 
MergeWith(std::unique_ptr<VerifierDeps> other,const std::vector<const DexFile * > & dex_files)63 void VerifierDeps::MergeWith(std::unique_ptr<VerifierDeps> other,
64                              const std::vector<const DexFile*>& dex_files) {
65   DCHECK(other != nullptr);
66   DCHECK_EQ(dex_deps_.size(), other->dex_deps_.size());
67   for (const DexFile* dex_file : dex_files) {
68     DexFileDeps* my_deps = GetDexFileDeps(*dex_file);
69     DexFileDeps& other_deps = *other->GetDexFileDeps(*dex_file);
70     // We currently collect extra strings only on the main `VerifierDeps`,
71     // which should be the one passed as `this` in this method.
72     DCHECK(other_deps.strings_.empty());
73     my_deps->assignable_types_.merge(other_deps.assignable_types_);
74     my_deps->unassignable_types_.merge(other_deps.unassignable_types_);
75     my_deps->classes_.merge(other_deps.classes_);
76     my_deps->fields_.merge(other_deps.fields_);
77     my_deps->methods_.merge(other_deps.methods_);
78     BitVectorOr(my_deps->verified_classes_, other_deps.verified_classes_);
79     BitVectorOr(my_deps->redefined_classes_, other_deps.redefined_classes_);
80   }
81 }
82 
GetDexFileDeps(const DexFile & dex_file)83 VerifierDeps::DexFileDeps* VerifierDeps::GetDexFileDeps(const DexFile& dex_file) {
84   auto it = dex_deps_.find(&dex_file);
85   return (it == dex_deps_.end()) ? nullptr : it->second.get();
86 }
87 
GetDexFileDeps(const DexFile & dex_file) const88 const VerifierDeps::DexFileDeps* VerifierDeps::GetDexFileDeps(const DexFile& dex_file) const {
89   auto it = dex_deps_.find(&dex_file);
90   return (it == dex_deps_.end()) ? nullptr : it->second.get();
91 }
92 
93 // Access flags that impact vdex verification.
94 static constexpr uint32_t kAccVdexAccessFlags =
95     kAccPublic | kAccPrivate | kAccProtected | kAccStatic | kAccInterface;
96 
97 template <typename Ptr>
GetAccessFlags(Ptr element)98 uint16_t VerifierDeps::GetAccessFlags(Ptr element) {
99   static_assert(kAccJavaFlagsMask == 0xFFFF, "Unexpected value of a constant");
100   if (element == nullptr) {
101     return VerifierDeps::kUnresolvedMarker;
102   } else {
103     uint16_t access_flags = Low16Bits(element->GetAccessFlags()) & kAccVdexAccessFlags;
104     CHECK_NE(access_flags, VerifierDeps::kUnresolvedMarker);
105     return access_flags;
106   }
107 }
108 
GetClassDescriptorStringId(const DexFile & dex_file,ObjPtr<mirror::Class> klass)109 dex::StringIndex VerifierDeps::GetClassDescriptorStringId(const DexFile& dex_file,
110                                                           ObjPtr<mirror::Class> klass) {
111   DCHECK(klass != nullptr);
112   ObjPtr<mirror::DexCache> dex_cache = klass->GetDexCache();
113   // Array and proxy classes do not have a dex cache.
114   if (!klass->IsArrayClass() && !klass->IsProxyClass()) {
115     DCHECK(dex_cache != nullptr) << klass->PrettyClass();
116     if (dex_cache->GetDexFile() == &dex_file) {
117       // FindStringId is slow, try to go through the class def if we have one.
118       const dex::ClassDef* class_def = klass->GetClassDef();
119       DCHECK(class_def != nullptr) << klass->PrettyClass();
120       const dex::TypeId& type_id = dex_file.GetTypeId(class_def->class_idx_);
121       if (kIsDebugBuild) {
122         std::string temp;
123         CHECK_EQ(GetIdFromString(dex_file, klass->GetDescriptor(&temp)), type_id.descriptor_idx_);
124       }
125       return type_id.descriptor_idx_;
126     }
127   }
128   std::string temp;
129   return GetIdFromString(dex_file, klass->GetDescriptor(&temp));
130 }
131 
132 // Try to find the string descriptor of the class. type_idx is a best guess of a matching string id.
TryGetClassDescriptorStringId(const DexFile & dex_file,dex::TypeIndex type_idx,ObjPtr<mirror::Class> klass)133 static dex::StringIndex TryGetClassDescriptorStringId(const DexFile& dex_file,
134                                                       dex::TypeIndex type_idx,
135                                                       ObjPtr<mirror::Class> klass)
136     REQUIRES_SHARED(Locks::mutator_lock_) {
137   if (!klass->IsArrayClass()) {
138     const dex::TypeId& type_id = dex_file.GetTypeId(type_idx);
139     const DexFile& klass_dex = klass->GetDexFile();
140     const dex::TypeId& klass_type_id = klass_dex.GetTypeId(klass->GetClassDef()->class_idx_);
141     if (strcmp(dex_file.GetTypeDescriptor(type_id),
142                klass_dex.GetTypeDescriptor(klass_type_id)) == 0) {
143       return type_id.descriptor_idx_;
144     }
145   }
146   return dex::StringIndex::Invalid();
147 }
148 
GetMethodDeclaringClassStringId(const DexFile & dex_file,uint32_t dex_method_index,ArtMethod * method)149 dex::StringIndex VerifierDeps::GetMethodDeclaringClassStringId(const DexFile& dex_file,
150                                                                uint32_t dex_method_index,
151                                                                ArtMethod* method) {
152   static_assert(kAccJavaFlagsMask == 0xFFFF, "Unexpected value of a constant");
153   if (method == nullptr) {
154     return dex::StringIndex(VerifierDeps::kUnresolvedMarker);
155   }
156   const dex::StringIndex string_id = TryGetClassDescriptorStringId(
157       dex_file,
158       dex_file.GetMethodId(dex_method_index).class_idx_,
159       method->GetDeclaringClass());
160   if (string_id.IsValid()) {
161     // Got lucky using the original dex file, return based on the input dex file.
162     DCHECK_EQ(GetClassDescriptorStringId(dex_file, method->GetDeclaringClass()), string_id);
163     return string_id;
164   }
165   return GetClassDescriptorStringId(dex_file, method->GetDeclaringClass());
166 }
167 
GetFieldDeclaringClassStringId(const DexFile & dex_file,uint32_t dex_field_idx,ArtField * field)168 dex::StringIndex VerifierDeps::GetFieldDeclaringClassStringId(const DexFile& dex_file,
169                                                               uint32_t dex_field_idx,
170                                                               ArtField* field) {
171   static_assert(kAccJavaFlagsMask == 0xFFFF, "Unexpected value of a constant");
172   if (field == nullptr) {
173     return dex::StringIndex(VerifierDeps::kUnresolvedMarker);
174   }
175   const dex::StringIndex string_id = TryGetClassDescriptorStringId(
176       dex_file,
177       dex_file.GetFieldId(dex_field_idx).class_idx_,
178       field->GetDeclaringClass());
179   if (string_id.IsValid()) {
180     // Got lucky using the original dex file, return based on the input dex file.
181     DCHECK_EQ(GetClassDescriptorStringId(dex_file, field->GetDeclaringClass()), string_id);
182     return string_id;
183   }
184   return GetClassDescriptorStringId(dex_file, field->GetDeclaringClass());
185 }
186 
GetMainVerifierDeps()187 static inline VerifierDeps* GetMainVerifierDeps() {
188   // The main VerifierDeps is the one set in the compiler callbacks, which at the
189   // end of verification will have all the per-thread VerifierDeps merged into it.
190   CompilerCallbacks* callbacks = Runtime::Current()->GetCompilerCallbacks();
191   if (callbacks == nullptr) {
192     return nullptr;
193   }
194   return callbacks->GetVerifierDeps();
195 }
196 
GetThreadLocalVerifierDeps()197 static inline VerifierDeps* GetThreadLocalVerifierDeps() {
198   // During AOT, each thread has its own VerifierDeps, to avoid lock contention. At the end
199   // of full verification, these VerifierDeps will be merged into the main one.
200   if (!Runtime::Current()->IsAotCompiler()) {
201     return nullptr;
202   }
203   return Thread::Current()->GetVerifierDeps();
204 }
205 
FindExistingStringId(const std::vector<std::string> & strings,const std::string & str,uint32_t * found_id)206 static bool FindExistingStringId(const std::vector<std::string>& strings,
207                                  const std::string& str,
208                                  uint32_t* found_id) {
209   uint32_t num_extra_ids = strings.size();
210   for (size_t i = 0; i < num_extra_ids; ++i) {
211     if (strings[i] == str) {
212       *found_id = i;
213       return true;
214     }
215   }
216   return false;
217 }
218 
GetIdFromString(const DexFile & dex_file,const std::string & str)219 dex::StringIndex VerifierDeps::GetIdFromString(const DexFile& dex_file, const std::string& str) {
220   const dex::StringId* string_id = dex_file.FindStringId(str.c_str());
221   if (string_id != nullptr) {
222     // String is in the DEX file. Return its ID.
223     return dex_file.GetIndexForStringId(*string_id);
224   }
225 
226   // String is not in the DEX file. Assign a new ID to it which is higher than
227   // the number of strings in the DEX file.
228 
229   // We use the main `VerifierDeps` for adding new strings to simplify
230   // synchronization/merging of these entries between threads.
231   VerifierDeps* singleton = GetMainVerifierDeps();
232   DexFileDeps* deps = singleton->GetDexFileDeps(dex_file);
233   DCHECK(deps != nullptr);
234 
235   uint32_t num_ids_in_dex = dex_file.NumStringIds();
236   uint32_t found_id;
237 
238   {
239     ReaderMutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
240     if (FindExistingStringId(deps->strings_, str, &found_id)) {
241       return dex::StringIndex(num_ids_in_dex + found_id);
242     }
243   }
244   {
245     WriterMutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
246     if (FindExistingStringId(deps->strings_, str, &found_id)) {
247       return dex::StringIndex(num_ids_in_dex + found_id);
248     }
249     deps->strings_.push_back(str);
250     dex::StringIndex new_id(num_ids_in_dex + deps->strings_.size() - 1);
251     CHECK_GE(new_id.index_, num_ids_in_dex);  // check for overflows
252     DCHECK_EQ(str, singleton->GetStringFromId(dex_file, new_id));
253     return new_id;
254   }
255 }
256 
GetStringFromId(const DexFile & dex_file,dex::StringIndex string_id) const257 std::string VerifierDeps::GetStringFromId(const DexFile& dex_file, dex::StringIndex string_id)
258     const {
259   uint32_t num_ids_in_dex = dex_file.NumStringIds();
260   if (string_id.index_ < num_ids_in_dex) {
261     return std::string(dex_file.StringDataByIdx(string_id));
262   } else {
263     const DexFileDeps* deps = GetDexFileDeps(dex_file);
264     DCHECK(deps != nullptr);
265     string_id.index_ -= num_ids_in_dex;
266     CHECK_LT(string_id.index_, deps->strings_.size());
267     return deps->strings_[string_id.index_];
268   }
269 }
270 
IsInClassPath(ObjPtr<mirror::Class> klass) const271 bool VerifierDeps::IsInClassPath(ObjPtr<mirror::Class> klass) const {
272   DCHECK(klass != nullptr);
273 
274   // For array types, we return whether the non-array component type
275   // is in the classpath.
276   while (klass->IsArrayClass()) {
277     klass = klass->GetComponentType();
278   }
279 
280   if (klass->IsPrimitive()) {
281     return true;
282   }
283 
284   ObjPtr<mirror::DexCache> dex_cache = klass->GetDexCache();
285   DCHECK(dex_cache != nullptr);
286   const DexFile* dex_file = dex_cache->GetDexFile();
287   DCHECK(dex_file != nullptr);
288 
289   // Test if the `dex_deps_` contains an entry for `dex_file`. If not, the dex
290   // file was not registered as being compiled and we assume `klass` is in the
291   // classpath.
292   return (GetDexFileDeps(*dex_file) == nullptr);
293 }
294 
AddClassResolution(const DexFile & dex_file,dex::TypeIndex type_idx,ObjPtr<mirror::Class> klass)295 void VerifierDeps::AddClassResolution(const DexFile& dex_file,
296                                       dex::TypeIndex type_idx,
297                                       ObjPtr<mirror::Class> klass) {
298   DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
299   if (dex_deps == nullptr) {
300     // This invocation is from verification of a dex file which is not being compiled.
301     return;
302   }
303 
304   if (klass != nullptr && !IsInClassPath(klass)) {
305     // Class resolved into one of the DEX files which are being compiled.
306     // This is not a classpath dependency.
307     return;
308   }
309 
310   dex_deps->classes_.emplace(ClassResolution(type_idx, GetAccessFlags(klass)));
311 }
312 
AddFieldResolution(const DexFile & dex_file,uint32_t field_idx,ArtField * field)313 void VerifierDeps::AddFieldResolution(const DexFile& dex_file,
314                                       uint32_t field_idx,
315                                       ArtField* field) {
316   DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
317   if (dex_deps == nullptr) {
318     // This invocation is from verification of a dex file which is not being compiled.
319     return;
320   }
321 
322   if (field != nullptr && !IsInClassPath(field->GetDeclaringClass())) {
323     // Field resolved into one of the DEX files which are being compiled.
324     // This is not a classpath dependency.
325     return;
326   }
327 
328   dex_deps->fields_.emplace(FieldResolution(field_idx,
329                                             GetAccessFlags(field),
330                                             GetFieldDeclaringClassStringId(dex_file,
331                                                                            field_idx,
332                                                                            field)));
333 }
334 
AddMethodResolution(const DexFile & dex_file,uint32_t method_idx,ArtMethod * method)335 void VerifierDeps::AddMethodResolution(const DexFile& dex_file,
336                                        uint32_t method_idx,
337                                        ArtMethod* method) {
338   DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
339   if (dex_deps == nullptr) {
340     // This invocation is from verification of a dex file which is not being compiled.
341     return;
342   }
343 
344   if (method != nullptr && !IsInClassPath(method->GetDeclaringClass())) {
345     // Method resolved into one of the DEX files which are being compiled.
346     // This is not a classpath dependency.
347     return;
348   }
349 
350   MethodResolution method_tuple(method_idx,
351                                 GetAccessFlags(method),
352                                 GetMethodDeclaringClassStringId(dex_file, method_idx, method));
353   dex_deps->methods_.insert(method_tuple);
354 }
355 
FindOneClassPathBoundaryForInterface(ObjPtr<mirror::Class> destination,ObjPtr<mirror::Class> source) const356 ObjPtr<mirror::Class> VerifierDeps::FindOneClassPathBoundaryForInterface(
357     ObjPtr<mirror::Class> destination,
358     ObjPtr<mirror::Class> source) const {
359   DCHECK(destination->IsInterface());
360   DCHECK(IsInClassPath(destination));
361   Thread* thread = Thread::Current();
362   ObjPtr<mirror::Class> current = source;
363   // Record the classes that are at the boundary between the compiled DEX files and
364   // the classpath. We will check those classes later to find one class that inherits
365   // `destination`.
366   std::vector<ObjPtr<mirror::Class>> boundaries;
367   // If the destination is a direct interface of a class defined in the DEX files being
368   // compiled, no need to record it.
369   while (!IsInClassPath(current)) {
370     for (size_t i = 0; i < current->NumDirectInterfaces(); ++i) {
371       ObjPtr<mirror::Class> direct = mirror::Class::GetDirectInterface(thread, current, i);
372       if (direct == destination) {
373         return nullptr;
374       } else if (IsInClassPath(direct)) {
375         boundaries.push_back(direct);
376       }
377     }
378     current = current->GetSuperClass();
379   }
380   DCHECK(current != nullptr);
381   boundaries.push_back(current);
382 
383   // Check if we have an interface defined in the DEX files being compiled, direclty
384   // inheriting `destination`.
385   int32_t iftable_count = source->GetIfTableCount();
386   ObjPtr<mirror::IfTable> iftable = source->GetIfTable();
387   for (int32_t i = 0; i < iftable_count; ++i) {
388     ObjPtr<mirror::Class> itf = iftable->GetInterface(i);
389     if (!IsInClassPath(itf)) {
390       for (size_t j = 0; j < itf->NumDirectInterfaces(); ++j) {
391         ObjPtr<mirror::Class> direct = mirror::Class::GetDirectInterface(thread, itf, j);
392         if (direct == destination) {
393           return nullptr;
394         } else if (IsInClassPath(direct)) {
395           boundaries.push_back(direct);
396         }
397       }
398     }
399   }
400 
401   // Find a boundary making `source` inherit from `destination`. We must find one.
402   for (const ObjPtr<mirror::Class>& boundary : boundaries) {
403     if (destination->IsAssignableFrom(boundary)) {
404       return boundary;
405     }
406   }
407   LOG(FATAL) << "Should have found a classpath boundary";
408   UNREACHABLE();
409 }
410 
AddAssignability(const DexFile & dex_file,ObjPtr<mirror::Class> destination,ObjPtr<mirror::Class> source,bool is_strict,bool is_assignable)411 void VerifierDeps::AddAssignability(const DexFile& dex_file,
412                                     ObjPtr<mirror::Class> destination,
413                                     ObjPtr<mirror::Class> source,
414                                     bool is_strict,
415                                     bool is_assignable) {
416   // Test that the method is only called on reference types.
417   // Note that concurrent verification of `destination` and `source` may have
418   // set their status to erroneous. However, the tests performed below rely
419   // merely on no issues with linking (valid access flags, superclass and
420   // implemented interfaces). If the class at any point reached the IsResolved
421   // status, the requirement holds. This is guaranteed by RegTypeCache::ResolveClass.
422   DCHECK(destination != nullptr);
423   DCHECK(source != nullptr);
424 
425   if (destination->IsPrimitive() || source->IsPrimitive()) {
426     // Primitive types are trivially non-assignable to anything else.
427     // We do not need to record trivial assignability, as it will
428     // not change across releases.
429     return;
430   }
431 
432   if (source->IsObjectClass() && !is_assignable) {
433     // j.l.Object is trivially non-assignable to other types, don't
434     // record it.
435     return;
436   }
437 
438   if (destination == source ||
439       destination->IsObjectClass() ||
440       (!is_strict && destination->IsInterface())) {
441     // Cases when `destination` is trivially assignable from `source`.
442     DCHECK(is_assignable);
443     return;
444   }
445 
446   if (destination->IsArrayClass() && source->IsArrayClass()) {
447     // Both types are arrays. Break down to component types and add recursively.
448     // This helps filter out destinations from compiled DEX files (see below)
449     // and deduplicate entries with the same canonical component type.
450     ObjPtr<mirror::Class> destination_component = destination->GetComponentType();
451     ObjPtr<mirror::Class> source_component = source->GetComponentType();
452 
453     // Only perform the optimization if both types are resolved which guarantees
454     // that they linked successfully, as required at the top of this method.
455     if (destination_component->IsResolved() && source_component->IsResolved()) {
456       AddAssignability(dex_file,
457                        destination_component,
458                        source_component,
459                        /* is_strict= */ true,
460                        is_assignable);
461       return;
462     }
463   } else {
464     // We only do this check for non-array types, as arrays might have erroneous
465     // component types which makes the IsAssignableFrom check unreliable.
466     DCHECK_EQ(is_assignable, destination->IsAssignableFrom(source));
467   }
468 
469   DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
470   if (dex_deps == nullptr) {
471     // This invocation is from verification of a DEX file which is not being compiled.
472     return;
473   }
474 
475   if (!IsInClassPath(destination) && !IsInClassPath(source)) {
476     // Both `destination` and `source` are defined in the compiled DEX files.
477     // No need to record a dependency.
478     return;
479   }
480 
481   if (!IsInClassPath(source)) {
482     if (!destination->IsInterface() && !source->IsInterface()) {
483       // Find the super class at the classpath boundary. Only that class
484       // can change the assignability.
485       do {
486         source = source->GetSuperClass();
487       } while (!IsInClassPath(source));
488 
489       // If that class is the actual destination, no need to record it.
490       if (source == destination) {
491         return;
492       }
493     } else if (is_assignable) {
494       source = FindOneClassPathBoundaryForInterface(destination, source);
495       if (source == nullptr) {
496         // There was no classpath boundary, no need to record.
497         return;
498       }
499       DCHECK(IsInClassPath(source));
500     }
501   }
502 
503 
504   // Get string IDs for both descriptors and store in the appropriate set.
505   dex::StringIndex destination_id = GetClassDescriptorStringId(dex_file, destination);
506   dex::StringIndex source_id = GetClassDescriptorStringId(dex_file, source);
507 
508   if (is_assignable) {
509     dex_deps->assignable_types_.emplace(TypeAssignability(destination_id, source_id));
510   } else {
511     dex_deps->unassignable_types_.emplace(TypeAssignability(destination_id, source_id));
512   }
513 }
514 
MaybeRecordClassRedefinition(const DexFile & dex_file,const dex::ClassDef & class_def)515 void VerifierDeps::MaybeRecordClassRedefinition(const DexFile& dex_file,
516                                                 const dex::ClassDef& class_def) {
517   VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
518   if (thread_deps != nullptr) {
519     DexFileDeps* dex_deps = thread_deps->GetDexFileDeps(dex_file);
520     DCHECK_EQ(dex_deps->redefined_classes_.size(), dex_file.NumClassDefs());
521     dex_deps->redefined_classes_[dex_file.GetIndexForClassDef(class_def)] = true;
522   }
523 }
524 
MaybeRecordVerificationStatus(const DexFile & dex_file,const dex::ClassDef & class_def,FailureKind failure_kind)525 void VerifierDeps::MaybeRecordVerificationStatus(const DexFile& dex_file,
526                                                  const dex::ClassDef& class_def,
527                                                  FailureKind failure_kind) {
528   // The `verified_classes_` bit vector is initialized to `false`.
529   // Only continue if we are about to write `true`.
530   if (failure_kind == FailureKind::kNoFailure) {
531     VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
532     if (thread_deps != nullptr) {
533       thread_deps->RecordClassVerified(dex_file, class_def);
534     }
535   }
536 }
537 
RecordClassVerified(const DexFile & dex_file,const dex::ClassDef & class_def)538 void VerifierDeps::RecordClassVerified(const DexFile& dex_file, const dex::ClassDef& class_def) {
539   DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
540   DCHECK_EQ(dex_deps->verified_classes_.size(), dex_file.NumClassDefs());
541   dex_deps->verified_classes_[dex_file.GetIndexForClassDef(class_def)] = true;
542 }
543 
MaybeRecordClassResolution(const DexFile & dex_file,dex::TypeIndex type_idx,ObjPtr<mirror::Class> klass)544 void VerifierDeps::MaybeRecordClassResolution(const DexFile& dex_file,
545                                               dex::TypeIndex type_idx,
546                                               ObjPtr<mirror::Class> klass) {
547   VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
548   if (thread_deps != nullptr) {
549     thread_deps->AddClassResolution(dex_file, type_idx, klass);
550   }
551 }
552 
MaybeRecordFieldResolution(const DexFile & dex_file,uint32_t field_idx,ArtField * field)553 void VerifierDeps::MaybeRecordFieldResolution(const DexFile& dex_file,
554                                               uint32_t field_idx,
555                                               ArtField* field) {
556   VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
557   if (thread_deps != nullptr) {
558     thread_deps->AddFieldResolution(dex_file, field_idx, field);
559   }
560 }
561 
MaybeRecordMethodResolution(const DexFile & dex_file,uint32_t method_idx,ArtMethod * method)562 void VerifierDeps::MaybeRecordMethodResolution(const DexFile& dex_file,
563                                                uint32_t method_idx,
564                                                ArtMethod* method) {
565   VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
566   if (thread_deps != nullptr) {
567     thread_deps->AddMethodResolution(dex_file, method_idx, method);
568   }
569 }
570 
MaybeRecordAssignability(const DexFile & dex_file,ObjPtr<mirror::Class> destination,ObjPtr<mirror::Class> source,bool is_strict,bool is_assignable)571 void VerifierDeps::MaybeRecordAssignability(const DexFile& dex_file,
572                                             ObjPtr<mirror::Class> destination,
573                                             ObjPtr<mirror::Class> source,
574                                             bool is_strict,
575                                             bool is_assignable) {
576   VerifierDeps* thread_deps = GetThreadLocalVerifierDeps();
577   if (thread_deps != nullptr) {
578     thread_deps->AddAssignability(dex_file, destination, source, is_strict, is_assignable);
579   }
580 }
581 
582 namespace {
583 
DecodeUint32WithOverflowCheck(const uint8_t ** in,const uint8_t * end)584 static inline uint32_t DecodeUint32WithOverflowCheck(const uint8_t** in, const uint8_t* end) {
585   CHECK_LT(*in, end);
586   return DecodeUnsignedLeb128(in);
587 }
588 
589 template<typename T> inline uint32_t Encode(T in);
590 
Encode(uint16_t in)591 template<> inline uint32_t Encode<uint16_t>(uint16_t in) {
592   return in;
593 }
Encode(uint32_t in)594 template<> inline uint32_t Encode<uint32_t>(uint32_t in) {
595   return in;
596 }
Encode(dex::TypeIndex in)597 template<> inline uint32_t Encode<dex::TypeIndex>(dex::TypeIndex in) {
598   return in.index_;
599 }
Encode(dex::StringIndex in)600 template<> inline uint32_t Encode<dex::StringIndex>(dex::StringIndex in) {
601   return in.index_;
602 }
603 
604 template<typename T> inline T Decode(uint32_t in);
605 
Decode(uint32_t in)606 template<> inline uint16_t Decode<uint16_t>(uint32_t in) {
607   return dchecked_integral_cast<uint16_t>(in);
608 }
Decode(uint32_t in)609 template<> inline uint32_t Decode<uint32_t>(uint32_t in) {
610   return in;
611 }
Decode(uint32_t in)612 template<> inline dex::TypeIndex Decode<dex::TypeIndex>(uint32_t in) {
613   return dex::TypeIndex(in);
614 }
Decode(uint32_t in)615 template<> inline dex::StringIndex Decode<dex::StringIndex>(uint32_t in) {
616   return dex::StringIndex(in);
617 }
618 
619 template<typename T1, typename T2>
EncodeTuple(std::vector<uint8_t> * out,const std::tuple<T1,T2> & t)620 static inline void EncodeTuple(std::vector<uint8_t>* out, const std::tuple<T1, T2>& t) {
621   EncodeUnsignedLeb128(out, Encode(std::get<0>(t)));
622   EncodeUnsignedLeb128(out, Encode(std::get<1>(t)));
623 }
624 
625 template<typename T1, typename T2>
DecodeTuple(const uint8_t ** in,const uint8_t * end,std::tuple<T1,T2> * t)626 static inline void DecodeTuple(const uint8_t** in, const uint8_t* end, std::tuple<T1, T2>* t) {
627   T1 v1 = Decode<T1>(DecodeUint32WithOverflowCheck(in, end));
628   T2 v2 = Decode<T2>(DecodeUint32WithOverflowCheck(in, end));
629   *t = std::make_tuple(v1, v2);
630 }
631 
632 template<typename T1, typename T2, typename T3>
EncodeTuple(std::vector<uint8_t> * out,const std::tuple<T1,T2,T3> & t)633 static inline void EncodeTuple(std::vector<uint8_t>* out, const std::tuple<T1, T2, T3>& t) {
634   EncodeUnsignedLeb128(out, Encode(std::get<0>(t)));
635   EncodeUnsignedLeb128(out, Encode(std::get<1>(t)));
636   EncodeUnsignedLeb128(out, Encode(std::get<2>(t)));
637 }
638 
639 template<typename T1, typename T2, typename T3>
DecodeTuple(const uint8_t ** in,const uint8_t * end,std::tuple<T1,T2,T3> * t)640 static inline void DecodeTuple(const uint8_t** in, const uint8_t* end, std::tuple<T1, T2, T3>* t) {
641   T1 v1 = Decode<T1>(DecodeUint32WithOverflowCheck(in, end));
642   T2 v2 = Decode<T2>(DecodeUint32WithOverflowCheck(in, end));
643   T3 v3 = Decode<T3>(DecodeUint32WithOverflowCheck(in, end));
644   *t = std::make_tuple(v1, v2, v3);
645 }
646 
647 template<typename T>
EncodeSet(std::vector<uint8_t> * out,const std::set<T> & set)648 static inline void EncodeSet(std::vector<uint8_t>* out, const std::set<T>& set) {
649   EncodeUnsignedLeb128(out, set.size());
650   for (const T& entry : set) {
651     EncodeTuple(out, entry);
652   }
653 }
654 
655 template<typename T>
DecodeSet(const uint8_t ** in,const uint8_t * end,std::set<T> * set)656 static inline void DecodeSet(const uint8_t** in, const uint8_t* end, std::set<T>* set) {
657   DCHECK(set->empty());
658   size_t num_entries = DecodeUint32WithOverflowCheck(in, end);
659   for (size_t i = 0; i < num_entries; ++i) {
660     T tuple;
661     DecodeTuple(in, end, &tuple);
662     set->emplace(tuple);
663   }
664 }
665 
EncodeUint16SparseBitVector(std::vector<uint8_t> * out,const std::vector<bool> & vector,bool sparse_value)666 static inline void EncodeUint16SparseBitVector(std::vector<uint8_t>* out,
667                                                const std::vector<bool>& vector,
668                                                bool sparse_value) {
669   DCHECK(IsUint<16>(vector.size()));
670   EncodeUnsignedLeb128(out, std::count(vector.begin(), vector.end(), sparse_value));
671   for (uint16_t idx = 0; idx < vector.size(); ++idx) {
672     if (vector[idx] == sparse_value) {
673       EncodeUnsignedLeb128(out, Encode(idx));
674     }
675   }
676 }
677 
DecodeUint16SparseBitVector(const uint8_t ** in,const uint8_t * end,std::vector<bool> * vector,bool sparse_value)678 static inline void DecodeUint16SparseBitVector(const uint8_t** in,
679                                                const uint8_t* end,
680                                                std::vector<bool>* vector,
681                                                bool sparse_value) {
682   DCHECK(IsUint<16>(vector->size()));
683   std::fill(vector->begin(), vector->end(), !sparse_value);
684   size_t num_entries = DecodeUint32WithOverflowCheck(in, end);
685   for (size_t i = 0; i < num_entries; ++i) {
686     uint16_t idx = Decode<uint16_t>(DecodeUint32WithOverflowCheck(in, end));
687     DCHECK_LT(idx, vector->size());
688     (*vector)[idx] = sparse_value;
689   }
690 }
691 
EncodeStringVector(std::vector<uint8_t> * out,const std::vector<std::string> & strings)692 static inline void EncodeStringVector(std::vector<uint8_t>* out,
693                                       const std::vector<std::string>& strings) {
694   EncodeUnsignedLeb128(out, strings.size());
695   for (const std::string& str : strings) {
696     const uint8_t* data = reinterpret_cast<const uint8_t*>(str.c_str());
697     size_t length = str.length() + 1;
698     out->insert(out->end(), data, data + length);
699     DCHECK_EQ(0u, out->back());
700   }
701 }
702 
DecodeStringVector(const uint8_t ** in,const uint8_t * end,std::vector<std::string> * strings)703 static inline void DecodeStringVector(const uint8_t** in,
704                                       const uint8_t* end,
705                                       std::vector<std::string>* strings) {
706   DCHECK(strings->empty());
707   size_t num_strings = DecodeUint32WithOverflowCheck(in, end);
708   strings->reserve(num_strings);
709   for (size_t i = 0; i < num_strings; ++i) {
710     CHECK_LT(*in, end);
711     const char* string_start = reinterpret_cast<const char*>(*in);
712     strings->emplace_back(std::string(string_start));
713     *in += strings->back().length() + 1;
714   }
715 }
716 
ToHex(uint32_t value)717 static inline std::string ToHex(uint32_t value) {
718   std::stringstream ss;
719   ss << std::hex << value << std::dec;
720   return ss.str();
721 }
722 
723 }  // namespace
724 
Encode(const std::vector<const DexFile * > & dex_files,std::vector<uint8_t> * buffer) const725 void VerifierDeps::Encode(const std::vector<const DexFile*>& dex_files,
726                           std::vector<uint8_t>* buffer) const {
727   for (const DexFile* dex_file : dex_files) {
728     const DexFileDeps& deps = *GetDexFileDeps(*dex_file);
729     EncodeStringVector(buffer, deps.strings_);
730     EncodeSet(buffer, deps.assignable_types_);
731     EncodeSet(buffer, deps.unassignable_types_);
732     EncodeSet(buffer, deps.classes_);
733     EncodeSet(buffer, deps.fields_);
734     EncodeSet(buffer, deps.methods_);
735     EncodeUint16SparseBitVector(buffer, deps.verified_classes_, /* sparse_value= */ false);
736     EncodeUint16SparseBitVector(buffer, deps.redefined_classes_, /* sparse_value= */ true);
737   }
738 }
739 
DecodeDexFileDeps(DexFileDeps & deps,const uint8_t ** data_start,const uint8_t * data_end)740 void VerifierDeps::DecodeDexFileDeps(DexFileDeps& deps,
741                                      const uint8_t** data_start,
742                                      const uint8_t* data_end) {
743   DecodeStringVector(data_start, data_end, &deps.strings_);
744   DecodeSet(data_start, data_end, &deps.assignable_types_);
745   DecodeSet(data_start, data_end, &deps.unassignable_types_);
746   DecodeSet(data_start, data_end, &deps.classes_);
747   DecodeSet(data_start, data_end, &deps.fields_);
748   DecodeSet(data_start, data_end, &deps.methods_);
749   DecodeUint16SparseBitVector(data_start,
750                               data_end,
751                               &deps.verified_classes_,
752                               /* sparse_value= */ false);
753   DecodeUint16SparseBitVector(data_start,
754                               data_end,
755                               &deps.redefined_classes_,
756                               /* sparse_value= */ true);
757 }
758 
VerifierDeps(const std::vector<const DexFile * > & dex_files,ArrayRef<const uint8_t> data)759 VerifierDeps::VerifierDeps(const std::vector<const DexFile*>& dex_files,
760                            ArrayRef<const uint8_t> data)
761     : VerifierDeps(dex_files, /*output_only=*/ false) {
762   if (data.empty()) {
763     // Return eagerly, as the first thing we expect from VerifierDeps data is
764     // the number of created strings, even if there is no dependency.
765     // Currently, only the boot image does not have any VerifierDeps data.
766     return;
767   }
768   const uint8_t* data_start = data.data();
769   const uint8_t* data_end = data_start + data.size();
770   for (const DexFile* dex_file : dex_files) {
771     DexFileDeps* deps = GetDexFileDeps(*dex_file);
772     DecodeDexFileDeps(*deps, &data_start, data_end);
773   }
774   CHECK_LE(data_start, data_end);
775 }
776 
ParseVerifiedClasses(const std::vector<const DexFile * > & dex_files,ArrayRef<const uint8_t> data)777 std::vector<std::vector<bool>> VerifierDeps::ParseVerifiedClasses(
778     const std::vector<const DexFile*>& dex_files,
779     ArrayRef<const uint8_t> data) {
780   DCHECK(!data.empty());
781   DCHECK(!dex_files.empty());
782 
783   std::vector<std::vector<bool>> verified_classes_per_dex;
784   verified_classes_per_dex.reserve(dex_files.size());
785 
786   const uint8_t* data_start = data.data();
787   const uint8_t* data_end = data_start + data.size();
788   for (const DexFile* dex_file : dex_files) {
789     DexFileDeps deps(dex_file->NumClassDefs());
790     DecodeDexFileDeps(deps, &data_start, data_end);
791     verified_classes_per_dex.push_back(std::move(deps.verified_classes_));
792   }
793   return verified_classes_per_dex;
794 }
795 
Equals(const VerifierDeps & rhs) const796 bool VerifierDeps::Equals(const VerifierDeps& rhs) const {
797   if (dex_deps_.size() != rhs.dex_deps_.size()) {
798     return false;
799   }
800 
801   auto lhs_it = dex_deps_.begin();
802   auto rhs_it = rhs.dex_deps_.begin();
803 
804   for (; (lhs_it != dex_deps_.end()) && (rhs_it != rhs.dex_deps_.end()); lhs_it++, rhs_it++) {
805     const DexFile* lhs_dex_file = lhs_it->first;
806     const DexFile* rhs_dex_file = rhs_it->first;
807     if (lhs_dex_file != rhs_dex_file) {
808       return false;
809     }
810 
811     DexFileDeps* lhs_deps = lhs_it->second.get();
812     DexFileDeps* rhs_deps = rhs_it->second.get();
813     if (!lhs_deps->Equals(*rhs_deps)) {
814       return false;
815     }
816   }
817 
818   DCHECK((lhs_it == dex_deps_.end()) && (rhs_it == rhs.dex_deps_.end()));
819   return true;
820 }
821 
Equals(const VerifierDeps::DexFileDeps & rhs) const822 bool VerifierDeps::DexFileDeps::Equals(const VerifierDeps::DexFileDeps& rhs) const {
823   return (strings_ == rhs.strings_) &&
824          (assignable_types_ == rhs.assignable_types_) &&
825          (unassignable_types_ == rhs.unassignable_types_) &&
826          (classes_ == rhs.classes_) &&
827          (fields_ == rhs.fields_) &&
828          (methods_ == rhs.methods_) &&
829          (verified_classes_ == rhs.verified_classes_);
830 }
831 
Dump(VariableIndentationOutputStream * vios) const832 void VerifierDeps::Dump(VariableIndentationOutputStream* vios) const {
833   // Sort dex files by their location to ensure deterministic ordering.
834   using DepsEntry = std::pair<const DexFile*, const DexFileDeps*>;
835   std::vector<DepsEntry> dex_deps;
836   dex_deps.reserve(dex_deps_.size());
837   for (const auto& dep : dex_deps_) {
838     dex_deps.emplace_back(dep.first, dep.second.get());
839   }
840   std::sort(
841       dex_deps.begin(),
842       dex_deps.end(),
843       [](const DepsEntry& lhs, const DepsEntry& rhs) {
844         return lhs.first->GetLocation() < rhs.first->GetLocation();
845       });
846   for (const auto& dep : dex_deps) {
847     const DexFile& dex_file = *dep.first;
848     vios->Stream()
849         << "Dependencies of "
850         << dex_file.GetLocation()
851         << ":\n";
852 
853     ScopedIndentation indent(vios);
854 
855     for (const std::string& str : dep.second->strings_) {
856       vios->Stream() << "Extra string: " << str << "\n";
857     }
858 
859     for (const TypeAssignability& entry : dep.second->assignable_types_) {
860       vios->Stream()
861         << GetStringFromId(dex_file, entry.GetSource())
862         << " must be assignable to "
863         << GetStringFromId(dex_file, entry.GetDestination())
864         << "\n";
865     }
866 
867     for (const TypeAssignability& entry : dep.second->unassignable_types_) {
868       vios->Stream()
869         << GetStringFromId(dex_file, entry.GetSource())
870         << " must not be assignable to "
871         << GetStringFromId(dex_file, entry.GetDestination())
872         << "\n";
873     }
874 
875     for (const ClassResolution& entry : dep.second->classes_) {
876       vios->Stream()
877           << dex_file.StringByTypeIdx(entry.GetDexTypeIndex())
878           << (entry.IsResolved() ? " must be resolved " : "must not be resolved ")
879           << " with access flags " << std::hex << entry.GetAccessFlags() << std::dec
880           << "\n";
881     }
882 
883     for (const FieldResolution& entry : dep.second->fields_) {
884       const dex::FieldId& field_id = dex_file.GetFieldId(entry.GetDexFieldIndex());
885       vios->Stream()
886           << dex_file.GetFieldDeclaringClassDescriptor(field_id) << "->"
887           << dex_file.GetFieldName(field_id) << ":"
888           << dex_file.GetFieldTypeDescriptor(field_id)
889           << " is expected to be ";
890       if (!entry.IsResolved()) {
891         vios->Stream() << "unresolved\n";
892       } else {
893         vios->Stream()
894           << "in class "
895           << GetStringFromId(dex_file, entry.GetDeclaringClassIndex())
896           << ", and have the access flags " << std::hex << entry.GetAccessFlags() << std::dec
897           << "\n";
898       }
899     }
900 
901     for (const MethodResolution& method : dep.second->methods_) {
902       const dex::MethodId& method_id = dex_file.GetMethodId(method.GetDexMethodIndex());
903       vios->Stream()
904           << dex_file.GetMethodDeclaringClassDescriptor(method_id) << "->"
905           << dex_file.GetMethodName(method_id)
906           << dex_file.GetMethodSignature(method_id).ToString()
907           << " is expected to be ";
908       if (!method.IsResolved()) {
909         vios->Stream() << "unresolved\n";
910       } else {
911         vios->Stream()
912           << "in class "
913           << GetStringFromId(dex_file, method.GetDeclaringClassIndex())
914           << ", have the access flags " << std::hex << method.GetAccessFlags() << std::dec
915           << "\n";
916       }
917     }
918 
919     for (size_t idx = 0; idx < dep.second->verified_classes_.size(); idx++) {
920       if (!dep.second->verified_classes_[idx]) {
921         vios->Stream()
922             << dex_file.GetClassDescriptor(dex_file.GetClassDef(idx))
923             << " will be verified at runtime\n";
924       }
925     }
926   }
927 }
928 
ValidateDependencies(Thread * self,Handle<mirror::ClassLoader> class_loader,const std::vector<const DexFile * > & classpath,std::string * error_msg) const929 bool VerifierDeps::ValidateDependencies(Thread* self,
930                                         Handle<mirror::ClassLoader> class_loader,
931                                         const std::vector<const DexFile*>& classpath,
932                                         /* out */ std::string* error_msg) const {
933   for (const auto& entry : dex_deps_) {
934     if (!VerifyDexFile(class_loader, *entry.first, *entry.second, classpath, self, error_msg)) {
935       return false;
936     }
937   }
938   return true;
939 }
940 
941 // TODO: share that helper with other parts of the compiler that have
942 // the same lookup pattern.
FindClassAndClearException(ClassLinker * class_linker,Thread * self,const std::string & name,Handle<mirror::ClassLoader> class_loader)943 static ObjPtr<mirror::Class> FindClassAndClearException(ClassLinker* class_linker,
944                                                         Thread* self,
945                                                         const std::string& name,
946                                                         Handle<mirror::ClassLoader> class_loader)
947     REQUIRES_SHARED(Locks::mutator_lock_) {
948   ObjPtr<mirror::Class> result = class_linker->FindClass(self, name.c_str(), class_loader);
949   if (result == nullptr) {
950     DCHECK(self->IsExceptionPending());
951     self->ClearException();
952   }
953   return result;
954 }
955 
VerifyAssignability(Handle<mirror::ClassLoader> class_loader,const DexFile & dex_file,const std::set<TypeAssignability> & assignables,bool expected_assignability,Thread * self,std::string * error_msg) const956 bool VerifierDeps::VerifyAssignability(Handle<mirror::ClassLoader> class_loader,
957                                        const DexFile& dex_file,
958                                        const std::set<TypeAssignability>& assignables,
959                                        bool expected_assignability,
960                                        Thread* self,
961                                        /* out */ std::string* error_msg) const {
962   StackHandleScope<2> hs(self);
963   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
964   MutableHandle<mirror::Class> source(hs.NewHandle<mirror::Class>(nullptr));
965   MutableHandle<mirror::Class> destination(hs.NewHandle<mirror::Class>(nullptr));
966 
967   for (const auto& entry : assignables) {
968     const std::string& destination_desc = GetStringFromId(dex_file, entry.GetDestination());
969     destination.Assign(
970         FindClassAndClearException(class_linker, self, destination_desc.c_str(), class_loader));
971     const std::string& source_desc = GetStringFromId(dex_file, entry.GetSource());
972     source.Assign(
973         FindClassAndClearException(class_linker, self, source_desc.c_str(), class_loader));
974 
975     if (destination == nullptr) {
976       *error_msg = "Could not resolve class " + destination_desc;
977       return false;
978     }
979 
980     if (source == nullptr) {
981       *error_msg = "Could not resolve class " + source_desc;
982       return false;
983     }
984 
985     DCHECK(destination->IsResolved() && source->IsResolved());
986     if (destination->IsAssignableFrom(source.Get()) != expected_assignability) {
987       *error_msg = "Class " + destination_desc + (expected_assignability ? " not " : " ") +
988           "assignable from " + source_desc;
989       return false;
990     }
991   }
992   return true;
993 }
994 
VerifyClasses(Handle<mirror::ClassLoader> class_loader,const DexFile & dex_file,const std::set<ClassResolution> & classes,Thread * self,std::string * error_msg) const995 bool VerifierDeps::VerifyClasses(Handle<mirror::ClassLoader> class_loader,
996                                  const DexFile& dex_file,
997                                  const std::set<ClassResolution>& classes,
998                                  Thread* self,
999                                  /* out */ std::string* error_msg) const {
1000   StackHandleScope<1> hs(self);
1001   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1002   MutableHandle<mirror::Class> cls(hs.NewHandle<mirror::Class>(nullptr));
1003   for (const auto& entry : classes) {
1004     std::string descriptor = dex_file.StringByTypeIdx(entry.GetDexTypeIndex());
1005     cls.Assign(FindClassAndClearException(class_linker, self, descriptor, class_loader));
1006 
1007     if (entry.IsResolved()) {
1008       if (cls == nullptr) {
1009         *error_msg = "Could not resolve class " + descriptor;
1010         return false;
1011       } else if (entry.GetAccessFlags() != GetAccessFlags(cls.Get())) {
1012         *error_msg = "Unexpected access flags on class " + descriptor
1013             + " (expected=" + ToHex(entry.GetAccessFlags())
1014             + ", actual=" + ToHex(GetAccessFlags(cls.Get())) + ")";
1015         return false;
1016       }
1017     } else if (cls != nullptr) {
1018       *error_msg = "Unexpected successful resolution of class " + descriptor;
1019       return false;
1020     }
1021   }
1022   return true;
1023 }
1024 
GetFieldDescription(const DexFile & dex_file,uint32_t index)1025 static std::string GetFieldDescription(const DexFile& dex_file, uint32_t index) {
1026   const dex::FieldId& field_id = dex_file.GetFieldId(index);
1027   return std::string(dex_file.GetFieldDeclaringClassDescriptor(field_id))
1028       + "->"
1029       + dex_file.GetFieldName(field_id)
1030       + ":"
1031       + dex_file.GetFieldTypeDescriptor(field_id);
1032 }
1033 
VerifyFields(Handle<mirror::ClassLoader> class_loader,const DexFile & dex_file,const std::set<FieldResolution> & fields,Thread * self,std::string * error_msg) const1034 bool VerifierDeps::VerifyFields(Handle<mirror::ClassLoader> class_loader,
1035                                 const DexFile& dex_file,
1036                                 const std::set<FieldResolution>& fields,
1037                                 Thread* self,
1038                                 /* out */ std::string* error_msg) const {
1039   // Check recorded fields are resolved the same way, have the same recorded class,
1040   // and have the same recorded flags.
1041   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1042   for (const auto& entry : fields) {
1043     const dex::FieldId& field_id = dex_file.GetFieldId(entry.GetDexFieldIndex());
1044     std::string_view name(dex_file.StringDataByIdx(field_id.name_idx_));
1045     std::string_view type(
1046         dex_file.StringDataByIdx(dex_file.GetTypeId(field_id.type_idx_).descriptor_idx_));
1047     // Only use field_id.class_idx_ when the entry is unresolved, which is rare.
1048     // Otherwise, we might end up resolving an application class, which is expensive.
1049     std::string expected_decl_klass = entry.IsResolved()
1050         ? GetStringFromId(dex_file, entry.GetDeclaringClassIndex())
1051         : dex_file.StringByTypeIdx(field_id.class_idx_);
1052     ObjPtr<mirror::Class> cls = FindClassAndClearException(
1053         class_linker, self, expected_decl_klass.c_str(), class_loader);
1054     if (cls == nullptr) {
1055       *error_msg = "Could not resolve class " + expected_decl_klass;
1056       return false;
1057     }
1058     DCHECK(cls->IsResolved());
1059 
1060     ArtField* field = mirror::Class::FindField(self, cls, name, type);
1061     if (entry.IsResolved()) {
1062       std::string temp;
1063       if (field == nullptr) {
1064         *error_msg = "Could not resolve field " +
1065             GetFieldDescription(dex_file, entry.GetDexFieldIndex());
1066         return false;
1067       } else if (expected_decl_klass != field->GetDeclaringClass()->GetDescriptor(&temp)) {
1068         *error_msg = "Unexpected declaring class for field resolution "
1069             + GetFieldDescription(dex_file, entry.GetDexFieldIndex())
1070             + " (expected=" + expected_decl_klass
1071             + ", actual=" + field->GetDeclaringClass()->GetDescriptor(&temp) + ")";
1072         return false;
1073       } else if (entry.GetAccessFlags() != GetAccessFlags(field)) {
1074         *error_msg = "Unexpected access flags for resolved field "
1075             + GetFieldDescription(dex_file, entry.GetDexFieldIndex())
1076             + " (expected=" + ToHex(entry.GetAccessFlags())
1077             + ", actual=" + ToHex(GetAccessFlags(field)) + ")";
1078         return false;
1079       }
1080     } else if (field != nullptr) {
1081       *error_msg = "Unexpected successful resolution of field "
1082           + GetFieldDescription(dex_file, entry.GetDexFieldIndex());
1083       return false;
1084     }
1085   }
1086   return true;
1087 }
1088 
GetMethodDescription(const DexFile & dex_file,uint32_t index)1089 static std::string GetMethodDescription(const DexFile& dex_file, uint32_t index) {
1090   const dex::MethodId& method_id = dex_file.GetMethodId(index);
1091   return std::string(dex_file.GetMethodDeclaringClassDescriptor(method_id))
1092       + "->"
1093       + dex_file.GetMethodName(method_id)
1094       + dex_file.GetMethodSignature(method_id).ToString();
1095 }
1096 
VerifyMethods(Handle<mirror::ClassLoader> class_loader,const DexFile & dex_file,const std::set<MethodResolution> & methods,Thread * self,std::string * error_msg) const1097 bool VerifierDeps::VerifyMethods(Handle<mirror::ClassLoader> class_loader,
1098                                  const DexFile& dex_file,
1099                                  const std::set<MethodResolution>& methods,
1100                                  Thread* self,
1101                                  /* out */ std::string* error_msg) const {
1102   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1103   PointerSize pointer_size = class_linker->GetImagePointerSize();
1104 
1105   for (const auto& entry : methods) {
1106     const dex::MethodId& method_id = dex_file.GetMethodId(entry.GetDexMethodIndex());
1107 
1108     const char* name = dex_file.GetMethodName(method_id);
1109     const Signature signature = dex_file.GetMethodSignature(method_id);
1110     // Only use method_id.class_idx_ when the entry is unresolved, which is rare.
1111     // Otherwise, we might end up resolving an application class, which is expensive.
1112     std::string expected_decl_klass = entry.IsResolved()
1113         ? GetStringFromId(dex_file, entry.GetDeclaringClassIndex())
1114         : dex_file.StringByTypeIdx(method_id.class_idx_);
1115 
1116     ObjPtr<mirror::Class> cls = FindClassAndClearException(
1117         class_linker, self, expected_decl_klass.c_str(), class_loader);
1118     if (cls == nullptr) {
1119       *error_msg = "Could not resolve class " + expected_decl_klass;
1120       return false;
1121     }
1122     DCHECK(cls->IsResolved());
1123     ArtMethod* method = nullptr;
1124     if (cls->IsInterface()) {
1125       method = cls->FindInterfaceMethod(name, signature, pointer_size);
1126     } else {
1127       method = cls->FindClassMethod(name, signature, pointer_size);
1128     }
1129 
1130     if (entry.IsResolved()) {
1131       std::string temp;
1132       if (method == nullptr) {
1133         *error_msg = "Could not resolve method "
1134             + GetMethodDescription(dex_file, entry.GetDexMethodIndex());
1135         return false;
1136       } else if (expected_decl_klass != method->GetDeclaringClass()->GetDescriptor(&temp)) {
1137         *error_msg = "Unexpected declaring class for method resolution "
1138             + GetMethodDescription(dex_file, entry.GetDexMethodIndex())
1139             + " (expected=" + expected_decl_klass
1140             + ", actual=" + method->GetDeclaringClass()->GetDescriptor(&temp) + ")";
1141         return false;
1142       } else if (entry.GetAccessFlags() != GetAccessFlags(method)) {
1143         *error_msg = "Unexpected access flags for resolved method resolution "
1144             + GetMethodDescription(dex_file, entry.GetDexMethodIndex())
1145             + " (expected=" + ToHex(entry.GetAccessFlags())
1146             + ", actual=" + ToHex(GetAccessFlags(method)) + ")";
1147         return false;
1148       }
1149     } else if (method != nullptr) {
1150       *error_msg = "Unexpected successful resolution of method "
1151           + GetMethodDescription(dex_file, entry.GetDexMethodIndex());
1152       return false;
1153     }
1154   }
1155   return true;
1156 }
1157 
IsInDexFiles(const char * descriptor,size_t hash,const std::vector<const DexFile * > & dex_files,const DexFile ** out_dex_file) const1158 bool VerifierDeps::IsInDexFiles(const char* descriptor,
1159                                 size_t hash,
1160                                 const std::vector<const DexFile*>& dex_files,
1161                                 /* out */ const DexFile** out_dex_file) const {
1162   for (const DexFile* dex_file : dex_files) {
1163     if (OatDexFile::FindClassDef(*dex_file, descriptor, hash) != nullptr) {
1164       *out_dex_file = dex_file;
1165       return true;
1166     }
1167   }
1168   return false;
1169 }
1170 
VerifyInternalClasses(const DexFile & dex_file,const std::vector<const DexFile * > & classpath,const std::vector<bool> & verified_classes,const std::vector<bool> & redefined_classes,std::string * error_msg) const1171 bool VerifierDeps::VerifyInternalClasses(const DexFile& dex_file,
1172                                          const std::vector<const DexFile*>& classpath,
1173                                          const std::vector<bool>& verified_classes,
1174                                          const std::vector<bool>& redefined_classes,
1175                                          /* out */ std::string* error_msg) const {
1176   const std::vector<const DexFile*>& boot_classpath =
1177       Runtime::Current()->GetClassLinker()->GetBootClassPath();
1178 
1179   for (ClassAccessor accessor : dex_file.GetClasses()) {
1180     const char* descriptor = accessor.GetDescriptor();
1181 
1182     const uint16_t class_def_index = accessor.GetClassDefIndex();
1183     if (redefined_classes[class_def_index]) {
1184       if (verified_classes[class_def_index]) {
1185         *error_msg = std::string("Class ") + descriptor + " marked both verified and redefined";
1186         return false;
1187       }
1188 
1189       // Class was not verified under these dependencies. No need to check it further.
1190       continue;
1191     }
1192 
1193     // Check that the class resolved into the same dex file. Otherwise there is
1194     // a different class with the same descriptor somewhere in one of the parent
1195     // class loaders.
1196     const size_t hash = ComputeModifiedUtf8Hash(descriptor);
1197     const DexFile* cp_dex_file = nullptr;
1198     if (IsInDexFiles(descriptor, hash, boot_classpath, &cp_dex_file) ||
1199         IsInDexFiles(descriptor, hash, classpath, &cp_dex_file)) {
1200       *error_msg = std::string("Class ") + descriptor
1201           + " redefines a class in the classpath "
1202           + "(dexFile expected=" + dex_file.GetLocation()
1203           + ", actual=" + cp_dex_file->GetLocation() + ")";
1204       return false;
1205     }
1206   }
1207 
1208   return true;
1209 }
1210 
VerifyDexFile(Handle<mirror::ClassLoader> class_loader,const DexFile & dex_file,const DexFileDeps & deps,const std::vector<const DexFile * > & classpath,Thread * self,std::string * error_msg) const1211 bool VerifierDeps::VerifyDexFile(Handle<mirror::ClassLoader> class_loader,
1212                                  const DexFile& dex_file,
1213                                  const DexFileDeps& deps,
1214                                  const std::vector<const DexFile*>& classpath,
1215                                  Thread* self,
1216                                  /* out */ std::string* error_msg) const {
1217   return VerifyInternalClasses(dex_file,
1218                                classpath,
1219                                deps.verified_classes_,
1220                                deps.redefined_classes_,
1221                                error_msg) &&
1222          VerifyAssignability(class_loader,
1223                              dex_file,
1224                              deps.assignable_types_,
1225                              /* expected_assignability= */ true,
1226                              self,
1227                              error_msg) &&
1228          VerifyAssignability(class_loader,
1229                              dex_file,
1230                              deps.unassignable_types_,
1231                              /* expected_assignability= */ false,
1232                              self,
1233                              error_msg) &&
1234          VerifyClasses(class_loader, dex_file, deps.classes_, self, error_msg) &&
1235          VerifyFields(class_loader, dex_file, deps.fields_, self, error_msg) &&
1236          VerifyMethods(class_loader, dex_file, deps.methods_, self, error_msg);
1237 }
1238 
1239 }  // namespace verifier
1240 }  // namespace art
1241