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