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