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/oat_file.h"
33 #include "obj_ptr-inl.h"
34 #include "reg_type.h"
35 #include "reg_type_cache-inl.h"
36 #include "runtime.h"
37
38 namespace art HIDDEN {
39 namespace verifier {
40
VerifierDeps(const std::vector<const DexFile * > & dex_files,bool output_only)41 VerifierDeps::VerifierDeps(const std::vector<const DexFile*>& dex_files, bool output_only)
42 : output_only_(output_only) {
43 for (const DexFile* dex_file : dex_files) {
44 DCHECK(GetDexFileDeps(*dex_file) == nullptr);
45 std::unique_ptr<DexFileDeps> deps(new DexFileDeps(dex_file->NumClassDefs()));
46 dex_deps_.emplace(dex_file, std::move(deps));
47 }
48 }
49
50 // Perform logical OR on two bit vectors and assign back to LHS, i.e. `to_update |= other`.
51 // Size of the two vectors must be equal.
52 // Size of `other` must be equal to size of `to_update`.
BitVectorOr(std::vector<bool> & to_update,const std::vector<bool> & other)53 static inline void BitVectorOr(std::vector<bool>& to_update, const std::vector<bool>& other) {
54 DCHECK_EQ(to_update.size(), other.size());
55 std::transform(
56 other.begin(), other.end(), to_update.begin(), to_update.begin(), std::logical_or<bool>());
57 }
58
MergeWith(std::unique_ptr<VerifierDeps> other,const std::vector<const DexFile * > & dex_files)59 void VerifierDeps::MergeWith(std::unique_ptr<VerifierDeps> other,
60 const std::vector<const DexFile*>& dex_files) {
61 DCHECK(other != nullptr);
62 DCHECK_EQ(dex_deps_.size(), other->dex_deps_.size());
63 for (const DexFile* dex_file : dex_files) {
64 DexFileDeps* my_deps = GetDexFileDeps(*dex_file);
65 DexFileDeps& other_deps = *other->GetDexFileDeps(*dex_file);
66 // We currently collect extra strings only on the main `VerifierDeps`,
67 // which should be the one passed as `this` in this method.
68 DCHECK(other_deps.strings_.empty());
69 // Size is the number of class definitions in the dex file, and must be the
70 // same between the two `VerifierDeps`.
71 DCHECK_EQ(my_deps->assignable_types_.size(), other_deps.assignable_types_.size());
72 for (uint32_t i = 0; i < my_deps->assignable_types_.size(); ++i) {
73 my_deps->assignable_types_[i].merge(other_deps.assignable_types_[i]);
74 }
75 BitVectorOr(my_deps->verified_classes_, other_deps.verified_classes_);
76 }
77 }
78
GetDexFileDeps(const DexFile & dex_file)79 VerifierDeps::DexFileDeps* VerifierDeps::GetDexFileDeps(const DexFile& dex_file) {
80 auto it = dex_deps_.find(&dex_file);
81 return (it == dex_deps_.end()) ? nullptr : it->second.get();
82 }
83
GetDexFileDeps(const DexFile & dex_file) const84 const VerifierDeps::DexFileDeps* VerifierDeps::GetDexFileDeps(const DexFile& dex_file) const {
85 auto it = dex_deps_.find(&dex_file);
86 return (it == dex_deps_.end()) ? nullptr : it->second.get();
87 }
88
GetClassDescriptorStringId(const DexFile & dex_file,ObjPtr<mirror::Class> klass)89 dex::StringIndex VerifierDeps::GetClassDescriptorStringId(const DexFile& dex_file,
90 ObjPtr<mirror::Class> klass) {
91 DCHECK(klass != nullptr);
92 ObjPtr<mirror::DexCache> dex_cache = klass->GetDexCache();
93 // Array and proxy classes do not have a dex cache.
94 if (!klass->IsArrayClass() && !klass->IsProxyClass()) {
95 DCHECK(dex_cache != nullptr) << klass->PrettyClass();
96 if (dex_cache->GetDexFile() == &dex_file) {
97 // FindStringId is slow, try to go through the class def if we have one.
98 const dex::ClassDef* class_def = klass->GetClassDef();
99 DCHECK(class_def != nullptr) << klass->PrettyClass();
100 const dex::TypeId& type_id = dex_file.GetTypeId(class_def->class_idx_);
101 if (kIsDebugBuild) {
102 std::string temp;
103 CHECK_EQ(GetIdFromString(dex_file, klass->GetDescriptor(&temp)), type_id.descriptor_idx_);
104 }
105 return type_id.descriptor_idx_;
106 }
107 }
108 std::string temp;
109 return GetIdFromString(dex_file, klass->GetDescriptor(&temp));
110 }
111
GetMainVerifierDeps(VerifierDeps * local_deps)112 static inline VerifierDeps* GetMainVerifierDeps(VerifierDeps* local_deps) {
113 // The main VerifierDeps is the one set in the compiler callbacks, which at the
114 // end of verification will have all the per-thread VerifierDeps merged into it.
115 CompilerCallbacks* callbacks = Runtime::Current()->GetCompilerCallbacks();
116 if (callbacks == nullptr) {
117 DCHECK(!Runtime::Current()->IsAotCompiler());
118 return local_deps;
119 }
120 DCHECK(Runtime::Current()->IsAotCompiler());
121 return callbacks->GetVerifierDeps();
122 }
123
FindExistingStringId(const std::vector<std::string> & strings,const std::string & str,uint32_t * found_id)124 static bool FindExistingStringId(const std::vector<std::string>& strings,
125 const std::string& str,
126 uint32_t* found_id) {
127 uint32_t num_extra_ids = strings.size();
128 for (size_t i = 0; i < num_extra_ids; ++i) {
129 if (strings[i] == str) {
130 *found_id = i;
131 return true;
132 }
133 }
134 return false;
135 }
136
GetIdFromString(const DexFile & dex_file,const std::string & str)137 dex::StringIndex VerifierDeps::GetIdFromString(const DexFile& dex_file, const std::string& str) {
138 const dex::StringId* string_id = dex_file.FindStringId(str.c_str());
139 if (string_id != nullptr) {
140 // String is in the DEX file. Return its ID.
141 return dex_file.GetIndexForStringId(*string_id);
142 }
143
144 // String is not in the DEX file. Assign a new ID to it which is higher than
145 // the number of strings in the DEX file.
146
147 // We use the main `VerifierDeps` for adding new strings to simplify
148 // synchronization/merging of these entries between threads.
149 VerifierDeps* singleton = GetMainVerifierDeps(this);
150 DexFileDeps* deps = singleton->GetDexFileDeps(dex_file);
151 DCHECK(deps != nullptr);
152
153 uint32_t num_ids_in_dex = dex_file.NumStringIds();
154 uint32_t found_id;
155
156 {
157 ReaderMutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
158 if (FindExistingStringId(deps->strings_, str, &found_id)) {
159 return dex::StringIndex(num_ids_in_dex + found_id);
160 }
161 }
162 {
163 WriterMutexLock mu(Thread::Current(), *Locks::verifier_deps_lock_);
164 if (FindExistingStringId(deps->strings_, str, &found_id)) {
165 return dex::StringIndex(num_ids_in_dex + found_id);
166 }
167 deps->strings_.push_back(str);
168 dex::StringIndex new_id(num_ids_in_dex + deps->strings_.size() - 1);
169 CHECK_GE(new_id.index_, num_ids_in_dex); // check for overflows
170 DCHECK_EQ(str, singleton->GetStringFromId(dex_file, new_id));
171 return new_id;
172 }
173 }
174
GetStringFromId(const DexFile & dex_file,dex::StringIndex string_id) const175 std::string VerifierDeps::GetStringFromId(const DexFile& dex_file,
176 dex::StringIndex string_id) const {
177 uint32_t num_ids_in_dex = dex_file.NumStringIds();
178 if (string_id.index_ < num_ids_in_dex) {
179 return std::string(dex_file.GetStringView(string_id));
180 } else {
181 const DexFileDeps* deps = GetDexFileDeps(dex_file);
182 DCHECK(deps != nullptr);
183 string_id.index_ -= num_ids_in_dex;
184 CHECK_LT(string_id.index_, deps->strings_.size());
185 return deps->strings_[string_id.index_];
186 }
187 }
188
AddAssignability(const DexFile & dex_file,const dex::ClassDef & class_def,ObjPtr<mirror::Class> destination,ObjPtr<mirror::Class> source)189 void VerifierDeps::AddAssignability(const DexFile& dex_file,
190 const dex::ClassDef& class_def,
191 ObjPtr<mirror::Class> destination,
192 ObjPtr<mirror::Class> source) {
193 // Test that the method is only called on reference types.
194 // Note that concurrent verification of `destination` and `source` may have
195 // set their status to erroneous. However, the tests performed below rely
196 // merely on no issues with linking (valid access flags, superclass and
197 // implemented interfaces). If the class at any point reached the IsResolved
198 // status, the requirement holds. This is guaranteed by RegTypeCache::ResolveClass.
199 DCHECK(destination != nullptr);
200 DCHECK(source != nullptr);
201
202 if (destination->IsPrimitive() || source->IsPrimitive()) {
203 // Primitive types are trivially non-assignable to anything else.
204 // We do not need to record trivial assignability, as it will
205 // not change across releases.
206 return;
207 }
208
209 if (destination == source || destination->IsObjectClass()) {
210 // Cases when `destination` is trivially assignable from `source`.
211 return;
212 }
213
214 if (destination->IsArrayClass() && source->IsArrayClass()) {
215 // Both types are arrays. Break down to component types and add recursively.
216 // This helps filter out destinations from compiled DEX files (see below)
217 // and deduplicate entries with the same canonical component type.
218 ObjPtr<mirror::Class> destination_component = destination->GetComponentType();
219 ObjPtr<mirror::Class> source_component = source->GetComponentType();
220
221 // Only perform the optimization if both types are resolved which guarantees
222 // that they linked successfully, as required at the top of this method.
223 if (destination_component->IsResolved() && source_component->IsResolved()) {
224 AddAssignability(dex_file, class_def, destination_component, source_component);
225 return;
226 }
227 }
228
229 DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
230 if (dex_deps == nullptr) {
231 // This invocation is from verification of a DEX file which is not being compiled.
232 return;
233 }
234
235 // Get string IDs for both descriptors and store in the appropriate set.
236 dex::StringIndex destination_id = GetClassDescriptorStringId(dex_file, destination);
237 dex::StringIndex source_id = GetClassDescriptorStringId(dex_file, source);
238
239 uint16_t index = dex_file.GetIndexForClassDef(class_def);
240 dex_deps->assignable_types_[index].emplace(TypeAssignability(destination_id, source_id));
241 }
242
AddAssignability(const DexFile & dex_file,const dex::ClassDef & class_def,const RegType & destination,const RegType & source)243 void VerifierDeps::AddAssignability(const DexFile& dex_file,
244 const dex::ClassDef& class_def,
245 const RegType& destination,
246 const RegType& source) {
247 DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
248 if (dex_deps == nullptr) {
249 // This invocation is from verification of a DEX file which is not being compiled.
250 return;
251 }
252
253 CHECK(destination.IsUnresolvedReference() || destination.HasClass());
254 CHECK(!destination.IsUnresolvedMergedReference());
255
256 if (source.IsUnresolvedReference() || source.HasClass()) {
257 // Get string IDs for both descriptors and store in the appropriate set.
258 dex::StringIndex destination_id =
259 GetIdFromString(dex_file, std::string(destination.GetDescriptor()));
260 dex::StringIndex source_id = GetIdFromString(dex_file, std::string(source.GetDescriptor()));
261 uint16_t index = dex_file.GetIndexForClassDef(class_def);
262 dex_deps->assignable_types_[index].emplace(TypeAssignability(destination_id, source_id));
263 } else if (source.IsZeroOrNull()) {
264 // Nothing to record, null is always assignable.
265 } else {
266 CHECK(source.IsUnresolvedMergedReference()) << source.Dump();
267 const UnresolvedMergedType& merge = *down_cast<const UnresolvedMergedType*>(&source);
268 AddAssignability(dex_file, class_def, destination, merge.GetResolvedPart());
269 for (uint32_t idx : merge.GetUnresolvedTypes().Indexes()) {
270 AddAssignability(dex_file, class_def, destination, merge.GetRegTypeCache()->GetFromId(idx));
271 }
272 }
273 }
274
MaybeRecordVerificationStatus(VerifierDeps * verifier_deps,const DexFile & dex_file,const dex::ClassDef & class_def,FailureKind failure_kind)275 void VerifierDeps::MaybeRecordVerificationStatus(VerifierDeps* verifier_deps,
276 const DexFile& dex_file,
277 const dex::ClassDef& class_def,
278 FailureKind failure_kind) {
279 if (verifier_deps != nullptr) {
280 switch (failure_kind) {
281 case verifier::FailureKind::kHardFailure:
282 case verifier::FailureKind::kSoftFailure: {
283 // Class will be verified at runtime.
284 DexFileDeps* dex_deps = verifier_deps->GetDexFileDeps(dex_file);
285 uint16_t index = dex_file.GetIndexForClassDef(class_def);
286 dex_deps->assignable_types_[index].clear();
287 break;
288 }
289 case verifier::FailureKind::kAccessChecksFailure:
290 case verifier::FailureKind::kTypeChecksFailure:
291 case verifier::FailureKind::kNoFailure: {
292 verifier_deps->RecordClassVerified(dex_file, class_def);
293 break;
294 }
295 }
296 }
297 }
298
RecordClassVerified(const DexFile & dex_file,const dex::ClassDef & class_def)299 void VerifierDeps::RecordClassVerified(const DexFile& dex_file, const dex::ClassDef& class_def) {
300 DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
301 DCHECK_EQ(dex_deps->verified_classes_.size(), dex_file.NumClassDefs());
302 dex_deps->verified_classes_[dex_file.GetIndexForClassDef(class_def)] = true;
303 }
304
HasRecordedVerifiedStatus(const DexFile & dex_file,const dex::ClassDef & class_def)305 bool VerifierDeps::HasRecordedVerifiedStatus(const DexFile& dex_file,
306 const dex::ClassDef& class_def) {
307 DexFileDeps* dex_deps = GetDexFileDeps(dex_file);
308 DCHECK_EQ(dex_deps->verified_classes_.size(), dex_file.NumClassDefs());
309 return dex_deps->verified_classes_[dex_file.GetIndexForClassDef(class_def)];
310 }
311
MaybeRecordAssignability(VerifierDeps * verifier_deps,const DexFile & dex_file,const dex::ClassDef & class_def,ObjPtr<mirror::Class> destination,ObjPtr<mirror::Class> source)312 void VerifierDeps::MaybeRecordAssignability(VerifierDeps* verifier_deps,
313 const DexFile& dex_file,
314 const dex::ClassDef& class_def,
315 ObjPtr<mirror::Class> destination,
316 ObjPtr<mirror::Class> source) {
317 if (verifier_deps != nullptr) {
318 verifier_deps->AddAssignability(dex_file, class_def, destination, source);
319 }
320 }
321
MaybeRecordAssignability(VerifierDeps * verifier_deps,const DexFile & dex_file,const dex::ClassDef & class_def,const RegType & destination,const RegType & source)322 void VerifierDeps::MaybeRecordAssignability(VerifierDeps* verifier_deps,
323 const DexFile& dex_file,
324 const dex::ClassDef& class_def,
325 const RegType& destination,
326 const RegType& source) {
327 if (verifier_deps != nullptr) {
328 verifier_deps->AddAssignability(dex_file, class_def, destination, source);
329 }
330 }
331
332 namespace {
333
334 template <typename T>
335 inline uint32_t Encode(T in);
336
337 template <>
Encode(dex::StringIndex in)338 inline uint32_t Encode<dex::StringIndex>(dex::StringIndex in) {
339 return in.index_;
340 }
341
342 template <typename T>
343 inline T Decode(uint32_t in);
344
345 template <>
Decode(uint32_t in)346 inline dex::StringIndex Decode<dex::StringIndex>(uint32_t in) {
347 return dex::StringIndex(in);
348 }
349
350 template <typename T1, typename T2>
EncodeTuple(std::vector<uint8_t> * out,const std::tuple<T1,T2> & t)351 static inline void EncodeTuple(std::vector<uint8_t>* out, const std::tuple<T1, T2>& t) {
352 EncodeUnsignedLeb128(out, Encode(std::get<0>(t)));
353 EncodeUnsignedLeb128(out, Encode(std::get<1>(t)));
354 }
355
356 template <typename T1, typename T2>
DecodeTuple(const uint8_t ** in,const uint8_t * end,std::tuple<T1,T2> * t)357 static inline bool DecodeTuple(const uint8_t** in, const uint8_t* end, std::tuple<T1, T2>* t) {
358 uint32_t v1, v2;
359 if (UNLIKELY(!DecodeUnsignedLeb128Checked(in, end, &v1)) ||
360 UNLIKELY(!DecodeUnsignedLeb128Checked(in, end, &v2))) {
361 return false;
362 }
363 *t = std::make_tuple(Decode<T1>(v1), Decode<T2>(v2));
364 return true;
365 }
366
367 template <typename T1, typename T2, typename T3>
EncodeTuple(std::vector<uint8_t> * out,const std::tuple<T1,T2,T3> & t)368 static inline void EncodeTuple(std::vector<uint8_t>* out, const std::tuple<T1, T2, T3>& t) {
369 EncodeUnsignedLeb128(out, Encode(std::get<0>(t)));
370 EncodeUnsignedLeb128(out, Encode(std::get<1>(t)));
371 EncodeUnsignedLeb128(out, Encode(std::get<2>(t)));
372 }
373
374 template <typename T1, typename T2, typename T3>
DecodeTuple(const uint8_t ** in,const uint8_t * end,std::tuple<T1,T2,T3> * t)375 static inline bool DecodeTuple(const uint8_t** in, const uint8_t* end, std::tuple<T1, T2, T3>* t) {
376 uint32_t v1, v2, v3;
377 if (UNLIKELY(!DecodeUnsignedLeb128Checked(in, end, &v1)) ||
378 UNLIKELY(!DecodeUnsignedLeb128Checked(in, end, &v2)) ||
379 UNLIKELY(!DecodeUnsignedLeb128Checked(in, end, &v3))) {
380 return false;
381 }
382 *t = std::make_tuple(Decode<T1>(v1), Decode<T2>(v2), Decode<T3>(v3));
383 return true;
384 }
385
SetUint32InUint8Array(std::vector<uint8_t> * out,uint32_t uint8_offset,uint32_t uint32_offset,uint32_t value)386 static void SetUint32InUint8Array(std::vector<uint8_t>* out,
387 uint32_t uint8_offset,
388 uint32_t uint32_offset,
389 uint32_t value) {
390 DCHECK(IsAligned<sizeof(uint32_t)>(out->data() + uint8_offset));
391 (reinterpret_cast<uint32_t*>(out->data() + uint8_offset))[uint32_offset] = value;
392 }
393
394 template <typename T>
EncodeSetVector(std::vector<uint8_t> * out,const std::vector<std::set<T>> & vector,const std::vector<bool> & verified_classes)395 static void EncodeSetVector(std::vector<uint8_t>* out,
396 const std::vector<std::set<T>>& vector,
397 const std::vector<bool>& verified_classes) {
398 uint32_t offsets_index = out->size();
399 // Make room for offsets for each class, +1 for marking the end of the
400 // assignability types data.
401 out->resize(out->size() + (vector.size() + 1) * sizeof(uint32_t));
402 uint32_t class_def_index = 0;
403 for (const std::set<T>& set : vector) {
404 if (verified_classes[class_def_index]) {
405 // Store the offset of the set for this class.
406 SetUint32InUint8Array(out, offsets_index, class_def_index, out->size());
407 for (const T& entry : set) {
408 EncodeTuple(out, entry);
409 }
410 } else {
411 SetUint32InUint8Array(out, offsets_index, class_def_index, VerifierDeps::kNotVerifiedMarker);
412 }
413 class_def_index++;
414 }
415 SetUint32InUint8Array(out, offsets_index, class_def_index, out->size());
416 }
417
418 template <bool kFillSet, typename T>
DecodeSetVector(const uint8_t ** cursor,const uint8_t * start,const uint8_t * end,std::vector<std::set<T>> * vector,std::vector<bool> * verified_classes,size_t num_class_defs)419 static bool DecodeSetVector(const uint8_t** cursor,
420 const uint8_t* start,
421 const uint8_t* end,
422 std::vector<std::set<T>>* vector,
423 std::vector<bool>* verified_classes,
424 size_t num_class_defs) {
425 const uint32_t* offsets = reinterpret_cast<const uint32_t*>(*cursor);
426 uint32_t next_valid_offset_index = 1;
427 // Put the cursor after the offsets of each class, +1 for the offset of the
428 // end of the assignable types data.
429 *cursor += (num_class_defs + 1) * sizeof(uint32_t);
430 for (uint32_t i = 0; i < num_class_defs; ++i) {
431 uint32_t offset = offsets[i];
432 if (offset == VerifierDeps::kNotVerifiedMarker) {
433 (*verified_classes)[i] = false;
434 continue;
435 }
436 (*verified_classes)[i] = true;
437 *cursor = start + offset;
438 // Fetch the assignability checks.
439 std::set<T>& set = (*vector)[i];
440 // Find the offset of the next entry. This will tell us where to stop when
441 // reading the checks. Note that the last entry in the `offsets` array points
442 // to the end of the assignability types data, so the loop will terminate correctly.
443 while (next_valid_offset_index <= i ||
444 offsets[next_valid_offset_index] == VerifierDeps::kNotVerifiedMarker) {
445 next_valid_offset_index++;
446 }
447 const uint8_t* set_end = start + offsets[next_valid_offset_index];
448 // Decode each check.
449 while (*cursor < set_end) {
450 T tuple;
451 if (UNLIKELY(!DecodeTuple(cursor, end, &tuple))) {
452 return false;
453 }
454 if (kFillSet) {
455 set.emplace(tuple);
456 }
457 }
458 }
459 // Align the cursor to start decoding the strings.
460 *cursor = AlignUp(*cursor, sizeof(uint32_t));
461 return true;
462 }
463
EncodeStringVector(std::vector<uint8_t> * out,const std::vector<std::string> & strings)464 static inline void EncodeStringVector(std::vector<uint8_t>* out,
465 const std::vector<std::string>& strings) {
466 uint32_t offsets_index = out->size();
467 // Make room for offsets for each string, +1 for putting the number of
468 // strings.
469 out->resize(out->size() + (strings.size() + 1) * sizeof(uint32_t));
470 (reinterpret_cast<uint32_t*>(out->data() + offsets_index))[0] = strings.size();
471 uint32_t string_index = 1;
472 for (const std::string& str : strings) {
473 // Store the offset of the string.
474 (reinterpret_cast<uint32_t*>(out->data() + offsets_index))[string_index++] = out->size();
475
476 // Store the string data.
477 const uint8_t* data = reinterpret_cast<const uint8_t*>(str.c_str());
478 size_t length = str.length() + 1;
479 out->insert(out->end(), data, data + length);
480 DCHECK_EQ(0u, out->back());
481 }
482 }
483
484 template <bool kFillVector>
DecodeStringVector(const uint8_t ** cursor,const uint8_t * start,const uint8_t * end,std::vector<std::string> * strings)485 static inline bool DecodeStringVector(const uint8_t** cursor,
486 const uint8_t* start,
487 const uint8_t* end,
488 std::vector<std::string>* strings) {
489 DCHECK(strings->empty());
490 uint32_t num_strings = reinterpret_cast<const uint32_t*>(*cursor)[0];
491 if (kFillVector) {
492 strings->reserve(num_strings);
493 }
494 const uint8_t* offsets = *cursor;
495 *cursor += sizeof(uint32_t) + num_strings * sizeof(uint32_t);
496 for (uint32_t i = 0; i < num_strings; ++i) {
497 uint32_t string_offset = reinterpret_cast<const uint32_t*>(offsets)[i + 1];
498 const char* string_start = reinterpret_cast<const char*>(start + string_offset);
499 const char* string_end =
500 reinterpret_cast<const char*>(memchr(string_start, 0, end - start - string_offset));
501 if (UNLIKELY(string_end == nullptr)) {
502 return false;
503 }
504 size_t string_length = string_end - string_start;
505 if (kFillVector) {
506 strings->emplace_back(string_start, string_length);
507 }
508 *cursor = reinterpret_cast<const uint8_t*>(string_end + 1);
509 }
510 return true;
511 }
512
513 } // namespace
514
Encode(const std::vector<const DexFile * > & dex_files,std::vector<uint8_t> * buffer) const515 void VerifierDeps::Encode(const std::vector<const DexFile*>& dex_files,
516 std::vector<uint8_t>* buffer) const {
517 DCHECK(buffer->empty());
518 buffer->resize(dex_files.size() * sizeof(uint32_t));
519 uint32_t dex_file_index = 0;
520 for (const DexFile* dex_file : dex_files) {
521 // Four byte alignment before encoding the data.
522 buffer->resize(RoundUp(buffer->size(), sizeof(uint32_t)));
523 (reinterpret_cast<uint32_t*>(buffer->data()))[dex_file_index++] = buffer->size();
524 const DexFileDeps& deps = *GetDexFileDeps(*dex_file);
525 EncodeSetVector(buffer, deps.assignable_types_, deps.verified_classes_);
526 // Four byte alignment before encoding strings.
527 buffer->resize(RoundUp(buffer->size(), sizeof(uint32_t)));
528 EncodeStringVector(buffer, deps.strings_);
529 }
530 }
531
532 template <bool kOnlyVerifiedClasses>
DecodeDexFileDeps(DexFileDeps & deps,const uint8_t ** cursor,const uint8_t * data_start,const uint8_t * data_end,size_t num_class_defs)533 bool VerifierDeps::DecodeDexFileDeps(DexFileDeps& deps,
534 const uint8_t** cursor,
535 const uint8_t* data_start,
536 const uint8_t* data_end,
537 size_t num_class_defs) {
538 return DecodeSetVector</*kFillSet=*/!kOnlyVerifiedClasses>(cursor,
539 data_start,
540 data_end,
541 &deps.assignable_types_,
542 &deps.verified_classes_,
543 num_class_defs) &&
544 DecodeStringVector</*kFillVector=*/!kOnlyVerifiedClasses>(
545 cursor, data_start, data_end, &deps.strings_);
546 }
547
ParseStoredData(const std::vector<const DexFile * > & dex_files,ArrayRef<const uint8_t> data)548 bool VerifierDeps::ParseStoredData(const std::vector<const DexFile*>& dex_files,
549 ArrayRef<const uint8_t> data) {
550 if (data.empty()) {
551 // Return eagerly, as the first thing we expect from VerifierDeps data is
552 // the number of created strings, even if there is no dependency.
553 // Currently, only the boot image does not have any VerifierDeps data.
554 return true;
555 }
556 const uint8_t* data_start = data.data();
557 const uint8_t* data_end = data_start + data.size();
558 const uint8_t* cursor = data_start;
559 uint32_t dex_file_index = 0;
560 for (const DexFile* dex_file : dex_files) {
561 DexFileDeps* deps = GetDexFileDeps(*dex_file);
562 // Fetch the offset of this dex file's verifier data.
563 cursor = data_start + reinterpret_cast<const uint32_t*>(data_start)[dex_file_index++];
564 size_t num_class_defs = dex_file->NumClassDefs();
565 if (UNLIKELY(!DecodeDexFileDeps</*kOnlyVerifiedClasses=*/false>(
566 *deps, &cursor, data_start, data_end, num_class_defs))) {
567 LOG(ERROR) << "Failed to parse dex file dependencies for " << dex_file->GetLocation();
568 return false;
569 }
570 }
571 // TODO: We should check that `data_start == data_end`. Why are we passing excessive data?
572 return true;
573 }
574
ParseVerifiedClasses(const std::vector<const DexFile * > & dex_files,ArrayRef<const uint8_t> data,std::vector<std::vector<bool>> * verified_classes_per_dex)575 bool VerifierDeps::ParseVerifiedClasses(
576 const std::vector<const DexFile*>& dex_files,
577 ArrayRef<const uint8_t> data,
578 /*out*/ std::vector<std::vector<bool>>* verified_classes_per_dex) {
579 DCHECK(!data.empty());
580 DCHECK(!dex_files.empty());
581 DCHECK(verified_classes_per_dex->empty());
582
583 verified_classes_per_dex->reserve(dex_files.size());
584
585 const uint8_t* data_start = data.data();
586 const uint8_t* data_end = data_start + data.size();
587 const uint8_t* cursor = data_start;
588 uint32_t dex_file_index = 0;
589 for (const DexFile* dex_file : dex_files) {
590 DexFileDeps deps(/*num_class_defs=*/0u); // Do not initialize vectors.
591 // Fetch the offset of this dex file's verifier data.
592 cursor = data_start + reinterpret_cast<const uint32_t*>(data_start)[dex_file_index++];
593 size_t num_class_defs = dex_file->NumClassDefs();
594 deps.verified_classes_.resize(num_class_defs);
595 if (UNLIKELY(!DecodeDexFileDeps</*kOnlyVerifiedClasses=*/true>(
596 deps, &cursor, data_start, data_end, num_class_defs))) {
597 LOG(ERROR) << "Failed to parse dex file dependencies for " << dex_file->GetLocation();
598 return false;
599 }
600 verified_classes_per_dex->push_back(std::move(deps.verified_classes_));
601 }
602 // TODO: We should check that `data_start == data_end`. Why are we passing excessive data?
603 return true;
604 }
605
Equals(const VerifierDeps & rhs) const606 bool VerifierDeps::Equals(const VerifierDeps& rhs) const {
607 if (dex_deps_.size() != rhs.dex_deps_.size()) {
608 return false;
609 }
610
611 auto lhs_it = dex_deps_.begin();
612 auto rhs_it = rhs.dex_deps_.begin();
613
614 for (; (lhs_it != dex_deps_.end()) && (rhs_it != rhs.dex_deps_.end()); lhs_it++, rhs_it++) {
615 const DexFile* lhs_dex_file = lhs_it->first;
616 const DexFile* rhs_dex_file = rhs_it->first;
617 if (lhs_dex_file != rhs_dex_file) {
618 return false;
619 }
620
621 DexFileDeps* lhs_deps = lhs_it->second.get();
622 DexFileDeps* rhs_deps = rhs_it->second.get();
623 if (!lhs_deps->Equals(*rhs_deps)) {
624 return false;
625 }
626 }
627
628 DCHECK((lhs_it == dex_deps_.end()) && (rhs_it == rhs.dex_deps_.end()));
629 return true;
630 }
631
Equals(const VerifierDeps::DexFileDeps & rhs) const632 bool VerifierDeps::DexFileDeps::Equals(const VerifierDeps::DexFileDeps& rhs) const {
633 return (strings_ == rhs.strings_) && (assignable_types_ == rhs.assignable_types_) &&
634 (verified_classes_ == rhs.verified_classes_);
635 }
636
Dump(VariableIndentationOutputStream * vios) const637 void VerifierDeps::Dump(VariableIndentationOutputStream* vios) const {
638 // Sort dex files by their location to ensure deterministic ordering.
639 using DepsEntry = std::pair<const DexFile*, const DexFileDeps*>;
640 std::vector<DepsEntry> dex_deps;
641 dex_deps.reserve(dex_deps_.size());
642 for (const auto& dep : dex_deps_) {
643 dex_deps.emplace_back(dep.first, dep.second.get());
644 }
645 std::sort(dex_deps.begin(), dex_deps.end(), [](const DepsEntry& lhs, const DepsEntry& rhs) {
646 return lhs.first->GetLocation() < rhs.first->GetLocation();
647 });
648 for (const auto& dep : dex_deps) {
649 const DexFile& dex_file = *dep.first;
650 vios->Stream() << "Dependencies of " << dex_file.GetLocation() << ":\n";
651
652 ScopedIndentation indent(vios);
653
654 for (const std::string& str : dep.second->strings_) {
655 vios->Stream() << "Extra string: " << str << "\n";
656 }
657
658 for (size_t idx = 0; idx < dep.second->assignable_types_.size(); idx++) {
659 vios->Stream() << "Dependencies of " << dex_file.GetClassDescriptor(dex_file.GetClassDef(idx))
660 << ":\n";
661 for (const TypeAssignability& entry : dep.second->assignable_types_[idx]) {
662 vios->Stream() << GetStringFromId(dex_file, entry.GetSource()) << " must be assignable to "
663 << GetStringFromId(dex_file, entry.GetDestination()) << "\n";
664 }
665 }
666
667 for (size_t idx = 0; idx < dep.second->verified_classes_.size(); idx++) {
668 if (!dep.second->verified_classes_[idx]) {
669 vios->Stream() << dex_file.GetClassDescriptor(dex_file.GetClassDef(idx))
670 << " will be verified at runtime\n";
671 }
672 }
673 }
674 }
675
ValidateDependenciesAndUpdateStatus(Thread * self,Handle<mirror::ClassLoader> class_loader,const std::vector<const DexFile * > & dex_files)676 bool VerifierDeps::ValidateDependenciesAndUpdateStatus(
677 Thread* self,
678 Handle<mirror::ClassLoader> class_loader,
679 const std::vector<const DexFile*>& dex_files) {
680 bool all_validated = true;
681 for (const auto* dex_file : dex_files) {
682 DexFileDeps* my_deps = GetDexFileDeps(*dex_file);
683 if (!VerifyDexFileAndUpdateStatus(class_loader, *dex_file, *my_deps, self)) {
684 all_validated = false;
685 }
686 }
687 return all_validated;
688 }
689
690 // TODO: share that helper with other parts of the compiler that have
691 // the same lookup pattern.
FindClassAndClearException(ClassLinker * class_linker,Thread * self,const std::string & name,Handle<mirror::ClassLoader> class_loader)692 static ObjPtr<mirror::Class> FindClassAndClearException(ClassLinker* class_linker,
693 Thread* self,
694 const std::string& name,
695 Handle<mirror::ClassLoader> class_loader)
696 REQUIRES_SHARED(Locks::mutator_lock_) {
697 ObjPtr<mirror::Class> result = class_linker->FindClass(self, name.c_str(), class_loader);
698 if (result == nullptr) {
699 DCHECK(self->IsExceptionPending());
700 self->ClearException();
701 }
702 return result;
703 }
704
VerifyDexFileAndUpdateStatus(Handle<mirror::ClassLoader> class_loader,const DexFile & dex_file,DexFileDeps & deps,Thread * self)705 bool VerifierDeps::VerifyDexFileAndUpdateStatus(
706 Handle<mirror::ClassLoader> class_loader,
707 const DexFile& dex_file,
708 DexFileDeps& deps,
709 Thread* self) {
710 StackHandleScope<2> hs(self);
711 const std::vector<std::set<TypeAssignability>>& assignables = deps.assignable_types_;
712 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
713 MutableHandle<mirror::Class> source(hs.NewHandle<mirror::Class>(nullptr));
714 MutableHandle<mirror::Class> destination(hs.NewHandle<mirror::Class>(nullptr));
715
716 uint32_t class_def_index = 0u;
717 bool all_validated = true;
718 uint32_t number_of_warnings = 0;
719 static constexpr uint32_t kMaxWarnings = 5;
720 for (const auto& vec : assignables) {
721 for (const auto& entry : vec) {
722 const std::string& destination_desc = GetStringFromId(dex_file, entry.GetDestination());
723 destination.Assign(
724 FindClassAndClearException(class_linker, self, destination_desc, class_loader));
725 const std::string& source_desc = GetStringFromId(dex_file, entry.GetSource());
726 source.Assign(FindClassAndClearException(class_linker, self, source_desc, class_loader));
727
728 if (destination == nullptr || source == nullptr) {
729 // We currently don't use assignability information for unresolved
730 // types, as the status of the class using unresolved types will be soft
731 // fail in the vdex.
732 continue;
733 }
734
735 DCHECK(destination->IsResolved() && source->IsResolved());
736 if (!destination->IsAssignableFrom(source.Get())) {
737 deps.verified_classes_[class_def_index] = false;
738 all_validated = false;
739 if (number_of_warnings++ < kMaxWarnings) {
740 LOG(WARNING) << "Class "
741 << dex_file.PrettyType(dex_file.GetClassDef(class_def_index).class_idx_)
742 << " could not be fast verified because one of its methods wrongly expected "
743 << destination_desc << " to be assignable from " << source_desc;
744 }
745 break;
746 }
747 }
748 class_def_index++;
749 }
750 return all_validated;
751 }
752
753 } // namespace verifier
754 } // namespace art
755