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