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