• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 #ifndef ART_RUNTIME_VERIFIER_METHOD_VERIFIER_H_
18 #define ART_RUNTIME_VERIFIER_METHOD_VERIFIER_H_
19 
20 #include <memory>
21 #include <sstream>
22 #include <vector>
23 
24 #include <android-base/logging.h>
25 
26 #include "base/arena_allocator.h"
27 #include "base/arena_containers.h"
28 #include "base/macros.h"
29 #include "base/value_object.h"
30 #include "dex/code_item_accessors.h"
31 #include "dex/dex_file_types.h"
32 #include "dex/method_reference.h"
33 #include "handle.h"
34 #include "instruction_flags.h"
35 #include "register_line.h"
36 #include "verifier_enums.h"
37 
38 namespace art HIDDEN {
39 
40 class ClassLinker;
41 class DexFile;
42 class Instruction;
43 struct ReferenceMap2Visitor;
44 class Thread;
45 class VariableIndentationOutputStream;
46 
47 namespace dex {
48 struct ClassDef;
49 struct CodeItem;
50 }  // namespace dex
51 
52 namespace mirror {
53 class ClassLoader;
54 class DexCache;
55 }  // namespace mirror
56 
57 namespace verifier {
58 
59 class MethodVerifier;
60 class RegType;
61 class RegTypeCache;
62 struct ScopedNewLine;
63 class VerifierDeps;
64 
65 // A mapping from a dex pc to the register line statuses as they are immediately prior to the
66 // execution of that instruction.
67 class PcToRegisterLineTable {
68  public:
69   explicit PcToRegisterLineTable(ArenaAllocator& allocator);
70   ~PcToRegisterLineTable();
71 
72   // Initialize the RegisterTable. Every instruction address can have a different set of information
73   // about what's in which register, but for verification purposes we only need to store it at
74   // branch target addresses (because we merge into that).
75   void Init(InstructionFlags* flags,
76             uint32_t insns_size,
77             uint16_t registers_size,
78             ArenaAllocator& allocator,
79             uint32_t interesting_dex_pc);
80 
IsInitialized()81   bool IsInitialized() const {
82     return !register_lines_.empty();
83   }
84 
GetLine(size_t idx)85   RegisterLine* GetLine(size_t idx) const {
86     return register_lines_[idx].get();
87   }
88 
89  private:
90   ArenaVector<RegisterLineArenaUniquePtr> register_lines_;
91 
92   DISALLOW_COPY_AND_ASSIGN(PcToRegisterLineTable);
93 };
94 
95 // The verifier
96 class MethodVerifier {
97  public:
98   EXPORT static void VerifyMethodAndDump(Thread* self,
99                                          VariableIndentationOutputStream* vios,
100                                          uint32_t method_idx,
101                                          const DexFile* dex_file,
102                                          Handle<mirror::DexCache> dex_cache,
103                                          Handle<mirror::ClassLoader> class_loader,
104                                          const dex::ClassDef& class_def,
105                                          const dex::CodeItem* code_item,
106                                          uint32_t method_access_flags,
107                                          uint32_t api_level)
108       REQUIRES_SHARED(Locks::mutator_lock_);
109 
110   // Calculates the type information at the given `dex_pc`.
111   // No classes will be loaded.
112   EXPORT static MethodVerifier* CalculateVerificationInfo(Thread* self,
113                                                           RegTypeCache* reg_types,
114                                                           ArtMethod* method,
115                                                           Handle<mirror::DexCache> dex_cache,
116                                                           uint32_t dex_pc)
117       REQUIRES_SHARED(Locks::mutator_lock_);
118 
GetDexFile()119   const DexFile& GetDexFile() const {
120     DCHECK(dex_file_ != nullptr);
121     return *dex_file_;
122   }
123 
GetClassDef()124   const dex::ClassDef& GetClassDef() const {
125     return class_def_;
126   }
127 
GetRegTypeCache()128   RegTypeCache* GetRegTypeCache() {
129     return &reg_types_;
130   }
131 
132   // Log a verification failure.
133   std::ostream& Fail(VerifyError error, bool pending_exc = true);
134 
135   // Log for verification information.
136   ScopedNewLine LogVerifyInfo();
137 
138   // Information structure for a lock held at a certain point in time.
139   struct DexLockInfo {
140     // The registers aliasing the lock.
141     std::set<uint32_t> dex_registers;
142     // The dex PC of the monitor-enter instruction.
143     uint32_t dex_pc;
144 
DexLockInfoDexLockInfo145     explicit DexLockInfo(uint32_t dex_pc_in) {
146       dex_pc = dex_pc_in;
147     }
148   };
149   // Fills 'monitor_enter_dex_pcs' with the dex pcs of the monitor-enter instructions corresponding
150   // to the locks held at 'dex_pc' in method 'm'.
151   // Note: this is the only situation where the verifier will visit quickened instructions.
152   static void FindLocksAtDexPc(ArtMethod* m,
153                                uint32_t dex_pc,
154                                std::vector<DexLockInfo>* monitor_enter_dex_pcs,
155                                uint32_t api_level)
156       REQUIRES_SHARED(Locks::mutator_lock_);
157 
~MethodVerifier()158   virtual ~MethodVerifier() {}
159 
CodeItem()160   const CodeItemDataAccessor& CodeItem() const {
161     return code_item_accessor_;
162   }
163   RegisterLine* GetRegLine(uint32_t dex_pc);
164   ALWAYS_INLINE const InstructionFlags& GetInstructionFlags(size_t index) const;
165 
166   MethodReference GetMethodReference() const;
167   bool HasFailures() const;
HasInstructionThatWillThrow()168   bool HasInstructionThatWillThrow() const {
169     return (encountered_failure_types_ & VERIFY_ERROR_RUNTIME_THROW) != 0;
170   }
171 
GetEncounteredFailureTypes()172   uint32_t GetEncounteredFailureTypes() const {
173     return encountered_failure_types_;
174   }
175 
176   ClassLinker* GetClassLinker() const;
177 
IsAotMode()178   bool IsAotMode() const {
179     return const_flags_.aot_mode_;
180   }
181 
CanLoadClasses()182   bool CanLoadClasses() const {
183     return const_flags_.can_load_classes_;
184   }
185 
GetVerifierDeps()186   VerifierDeps* GetVerifierDeps() const {
187     return verifier_deps_;
188   }
189 
190  protected:
191   MethodVerifier(Thread* self,
192                  ArenaPool* arena_pool,
193                  RegTypeCache* reg_types,
194                  VerifierDeps* verifier_deps,
195                  const dex::ClassDef& class_def,
196                  const dex::CodeItem* code_item,
197                  uint32_t dex_method_idx,
198                  bool aot_mode)
199       REQUIRES_SHARED(Locks::mutator_lock_);
200 
201   // Verification result for method(s). Includes a (maximum) failure kind, and (the union of)
202   // all failure types.
203   struct FailureData : ValueObject {
204     FailureKind kind = FailureKind::kNoFailure;
205     uint32_t types = 0U;
206 
207     // Merge src into this. Uses the most severe failure kind, and the union of types.
208     void Merge(const FailureData& src);
209   };
210 
211   /*
212    * Perform verification on a single method.
213    *
214    * We do this in three passes:
215    *  (1) Walk through all code units, determining instruction locations,
216    *      widths, and other characteristics.
217    *  (2) Walk through all code units, performing static checks on
218    *      operands.
219    *  (3) Iterate through the method, checking type safety and looking
220    *      for code flow problems.
221    */
222   static FailureData VerifyMethod(Thread* self,
223                                   ArenaPool* arena_pool,
224                                   RegTypeCache* reg_types,
225                                   VerifierDeps* verifier_deps,
226                                   uint32_t method_idx,
227                                   Handle<mirror::DexCache> dex_cache,
228                                   const dex::ClassDef& class_def_idx,
229                                   const dex::CodeItem* code_item,
230                                   uint32_t method_access_flags,
231                                   HardFailLogMode log_level,
232                                   uint32_t api_level,
233                                   bool aot_mode,
234                                   std::string* hard_failure_msg)
235       REQUIRES_SHARED(Locks::mutator_lock_);
236 
237   template <bool kVerifierDebug>
238   static FailureData VerifyMethod(Thread* self,
239                                   ArenaPool* arena_pool,
240                                   RegTypeCache* reg_types,
241                                   VerifierDeps* verifier_deps,
242                                   uint32_t method_idx,
243                                   Handle<mirror::DexCache> dex_cache,
244                                   const dex::ClassDef& class_def_idx,
245                                   const dex::CodeItem* code_item,
246                                   uint32_t method_access_flags,
247                                   HardFailLogMode log_level,
248                                   uint32_t api_level,
249                                   bool aot_mode,
250                                   std::string* hard_failure_msg)
251       REQUIRES_SHARED(Locks::mutator_lock_);
252 
253   /*
254    * Get the "this" pointer from a non-static method invocation. This returns the RegType so the
255    * caller can decide whether it needs the reference to be initialized or not.
256    *
257    * The argument count is in vA, and the first argument is in vC, for both "simple" and "range"
258    * versions. We just need to make sure vA is >= 1 and then return vC.
259    */
260   const RegType& GetInvocationThis(const Instruction* inst)
261       REQUIRES_SHARED(Locks::mutator_lock_);
262 
263   // Can a variable with type `lhs` be assigned a value with type `rhs`?
264   // Note: Object and interface types may always be assigned to one another, see
265   // comment on `ClassJoin()`.
266   bool IsAssignableFrom(const RegType& lhs, const RegType& rhs) const
267       REQUIRES_SHARED(Locks::mutator_lock_);
268 
269   // Can a variable with type `lhs` be assigned a value with type `rhs`?
270   // Variant of IsAssignableFrom that doesn't allow assignment to an interface from an Object.
271   bool IsStrictlyAssignableFrom(const RegType& lhs, const RegType& rhs) const
272       REQUIRES_SHARED(Locks::mutator_lock_);
273 
274   // Implementation helper for `IsAssignableFrom()` and `IsStrictlyAssignableFrom()`.
275   bool AssignableFrom(const RegType& lhs, const RegType& rhs, bool strict) const
276       REQUIRES_SHARED(Locks::mutator_lock_);
277 
278   // For VerifierDepsTest. TODO: Refactor.
279 
280   // Run verification on the method. Returns true if verification completes and false if the input
281   // has an irrecoverable corruption.
282   virtual bool Verify() REQUIRES_SHARED(Locks::mutator_lock_) = 0;
283   static MethodVerifier* CreateVerifier(Thread* self,
284                                         RegTypeCache* reg_types,
285                                         VerifierDeps* verifier_deps,
286                                         Handle<mirror::DexCache> dex_cache,
287                                         const dex::ClassDef& class_def,
288                                         const dex::CodeItem* code_item,
289                                         uint32_t method_idx,
290                                         uint32_t access_flags,
291                                         bool verify_to_dump,
292                                         uint32_t api_level)
293       REQUIRES_SHARED(Locks::mutator_lock_);
294 
295   virtual void PotentiallyMarkRuntimeThrow() = 0;
296 
InfoMessages()297   std::ostringstream& InfoMessages() {
298     if (!info_messages_.has_value()) {
299       info_messages_.emplace();
300     }
301     return info_messages_.value();
302   }
303 
304   // The thread we're verifying on.
305   Thread* const self_;
306 
307   // Arena allocator.
308   ArenaAllocator allocator_;
309 
310   RegTypeCache& reg_types_;  // TODO: Change to a pointer in a separate CL.
311 
312   PcToRegisterLineTable reg_table_;
313 
314   // Storage for the register status we're currently working on.
315   RegisterLineArenaUniquePtr work_line_;
316 
317   // The address of the instruction we're currently working on, note that this is in 2 byte
318   // quantities
319   uint32_t work_insn_idx_;
320 
321   // Storage for the register status we're saving for later.
322   RegisterLineArenaUniquePtr saved_line_;
323 
324   const uint32_t dex_method_idx_;   // The method we're working on.
325   const DexFile* const dex_file_;   // The dex file containing the method.
326   const dex::ClassDef& class_def_;  // The class being verified.
327   const CodeItemDataAccessor code_item_accessor_;
328 
329   // Instruction widths and flags, one entry per code unit.
330   // Owned, but not unique_ptr since insn_flags_ are allocated in arenas.
331   ArenaUniquePtr<InstructionFlags[]> insn_flags_;
332 
333   // The types of any error that occurs and associated error messages.
334   using MessageOStream =
335       std::basic_ostringstream<char, std::char_traits<char>, ArenaAllocatorAdapter<char>>;
336   struct VerifyErrorAndMessage {
VerifyErrorAndMessageVerifyErrorAndMessage337     VerifyErrorAndMessage(VerifyError e, const std::string& location, ArenaAllocatorAdapter<char> a)
338         : error(e), message(location, std::ios_base::ate, a) {}
339     VerifyError error;
340     MessageOStream message;
341   };
342   ArenaList<VerifyErrorAndMessage> failures_;
343 
344   struct {
345     // Is there a pending hard failure?
346     bool have_pending_hard_failure_ : 1;
347 
348     // Is there a pending runtime throw failure? A runtime throw failure is when an instruction
349     // would fail at runtime throwing an exception. Such an instruction causes the following code
350     // to be unreachable. This is set by Fail and used to ensure we don't process unreachable
351     // instructions that would hard fail the verification.
352     // Note: this flag is reset after processing each instruction.
353     bool have_pending_runtime_throw_failure_ : 1;
354   } flags_;
355 
356   struct {
357     // Verify in AoT mode?
358     bool aot_mode_ : 1;
359 
360     // Whether the `MethodVerifer` can load classes.
361     bool can_load_classes_ : 1;
362   } const const_flags_;
363 
364   // Bitset of the encountered failure types. Bits are according to the values in VerifyError.
365   uint32_t encountered_failure_types_;
366 
367   // Info message log use primarily for verifier diagnostics.
368   std::optional<std::ostringstream> info_messages_;
369 
370   // The verifier deps object we are going to report type assigability
371   // constraints to. Can be null for runtime verification.
372   VerifierDeps* verifier_deps_;
373 
374   // Link, for the method verifier root linked list.
375   MethodVerifier* link_;
376 
377   friend class art::Thread;
378   friend class ClassVerifier;
379   friend class RegisterLineTest;
380   friend class VerifierDepsTest;
381 
382   DISALLOW_COPY_AND_ASSIGN(MethodVerifier);
383 };
384 
385 }  // namespace verifier
386 }  // namespace art
387 
388 #endif  // ART_RUNTIME_VERIFIER_METHOD_VERIFIER_H_
389