1 /*
2  * Copyright (C) 2018 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 "flow_analysis.h"
18 
19 #include "dex/bytecode_utils.h"
20 #include "dex/code_item_accessors-inl.h"
21 #include "dex/dex_instruction-inl.h"
22 #include "dex/dex_file-inl.h"
23 #include "dex/dex_file_exception_helpers.h"
24 #include "resolver.h"
25 #include "veridex.h"
26 
27 namespace art {
28 
29 
SetAsBranchTarget(uint32_t dex_pc)30 void VeriFlowAnalysis::SetAsBranchTarget(uint32_t dex_pc) {
31   if (dex_registers_[dex_pc] == nullptr) {
32     dex_registers_[dex_pc].reset(
33         new std::vector<RegisterValue>(code_item_accessor_.RegistersSize()));
34   }
35 }
36 
IsBranchTarget(uint32_t dex_pc)37 bool VeriFlowAnalysis::IsBranchTarget(uint32_t dex_pc) {
38   return dex_registers_[dex_pc] != nullptr;
39 }
40 
MergeRegisterValues(uint32_t dex_pc)41 bool VeriFlowAnalysis::MergeRegisterValues(uint32_t dex_pc) {
42   // TODO: Do the merging. Right now, just return that we should continue
43   // the iteration if the instruction has not been visited.
44   if (!instruction_infos_[dex_pc].has_been_visited) {
45     dex_registers_[dex_pc]->assign(current_registers_.begin(), current_registers_.end());
46     return true;
47   }
48   return false;
49 }
50 
SetVisited(uint32_t dex_pc)51 void VeriFlowAnalysis::SetVisited(uint32_t dex_pc) {
52   instruction_infos_[dex_pc].has_been_visited = true;
53 }
54 
FindBranches()55 void VeriFlowAnalysis::FindBranches() {
56   SetAsBranchTarget(0);
57 
58   if (code_item_accessor_.TriesSize() != 0) {
59     // TODO: We need to mark the range of dex pcs as flowing in the handlers.
60     /*
61     for (const DexFile::TryItem& try_item : code_item_accessor_.TryItems()) {
62       uint32_t dex_pc_start = try_item.start_addr_;
63       uint32_t dex_pc_end = dex_pc_start + try_item.insn_count_;
64     }
65     */
66 
67     // Create branch targets for exception handlers.
68     const uint8_t* handlers_ptr = code_item_accessor_.GetCatchHandlerData();
69     uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
70     for (uint32_t idx = 0; idx < handlers_size; ++idx) {
71       CatchHandlerIterator iterator(handlers_ptr);
72       for (; iterator.HasNext(); iterator.Next()) {
73         SetAsBranchTarget(iterator.GetHandlerAddress());
74       }
75       handlers_ptr = iterator.EndDataPointer();
76     }
77   }
78 
79   // Iterate over all instructions and find branching instructions.
80   for (const DexInstructionPcPair& pair : code_item_accessor_) {
81     const uint32_t dex_pc = pair.DexPc();
82     const Instruction& instruction = pair.Inst();
83 
84     if (instruction.IsBranch()) {
85       SetAsBranchTarget(dex_pc + instruction.GetTargetOffset());
86     } else if (instruction.IsSwitch()) {
87       DexSwitchTable table(instruction, dex_pc);
88       for (DexSwitchTableIterator s_it(table); !s_it.Done(); s_it.Advance()) {
89         SetAsBranchTarget(dex_pc + s_it.CurrentTargetOffset());
90         if (table.ShouldBuildDecisionTree() && !s_it.IsLast()) {
91           SetAsBranchTarget(s_it.GetDexPcForCurrentIndex());
92         }
93       }
94     }
95   }
96 }
97 
UpdateRegister(uint32_t dex_register,RegisterSource kind,VeriClass * cls,uint32_t source_id)98 void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register,
99                                       RegisterSource kind,
100                                       VeriClass* cls,
101                                       uint32_t source_id) {
102   current_registers_[dex_register] = RegisterValue(
103       kind, DexFileReference(&resolver_->GetDexFile(), source_id), cls);
104 }
105 
UpdateRegister(uint32_t dex_register,const RegisterValue & value)106 void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, const RegisterValue& value) {
107   current_registers_[dex_register] = value;
108 }
109 
UpdateRegister(uint32_t dex_register,const VeriClass * cls)110 void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, const VeriClass* cls) {
111   current_registers_[dex_register] =
112       RegisterValue(RegisterSource::kNone, DexFileReference(nullptr, 0), cls);
113 }
114 
UpdateRegister(uint32_t dex_register,int32_t value,const VeriClass * cls)115 void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, int32_t value, const VeriClass* cls) {
116   current_registers_[dex_register] =
117       RegisterValue(RegisterSource::kConstant, value, DexFileReference(nullptr, 0), cls);
118 }
119 
GetRegister(uint32_t dex_register) const120 const RegisterValue& VeriFlowAnalysis::GetRegister(uint32_t dex_register) const {
121   return current_registers_[dex_register];
122 }
123 
GetReturnType(uint32_t method_index)124 RegisterValue VeriFlowAnalysis::GetReturnType(uint32_t method_index) {
125   const DexFile& dex_file = resolver_->GetDexFile();
126   const DexFile::MethodId& method_id = dex_file.GetMethodId(method_index);
127   const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id);
128   VeriClass* cls = resolver_->GetVeriClass(proto_id.return_type_idx_);
129   return RegisterValue(RegisterSource::kMethod, DexFileReference(&dex_file, method_index), cls);
130 }
131 
GetFieldType(uint32_t field_index)132 RegisterValue VeriFlowAnalysis::GetFieldType(uint32_t field_index) {
133   const DexFile& dex_file = resolver_->GetDexFile();
134   const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
135   VeriClass* cls = resolver_->GetVeriClass(field_id.type_idx_);
136   return RegisterValue(RegisterSource::kField, DexFileReference(&dex_file, field_index), cls);
137 }
138 
GetBranchFlags(const Instruction & instruction) const139 int VeriFlowAnalysis::GetBranchFlags(const Instruction& instruction) const {
140   switch (instruction.Opcode()) {
141     #define IF_XX(cond, op) \
142     case Instruction::IF_##cond: { \
143       RegisterValue lhs = GetRegister(instruction.VRegA()); \
144       RegisterValue rhs = GetRegister(instruction.VRegB()); \
145       if (lhs.IsConstant() && rhs.IsConstant()) { \
146         if (lhs.GetConstant() op rhs.GetConstant()) { \
147           return Instruction::kBranch; \
148         } else { \
149           return Instruction::kContinue; \
150         } \
151       } \
152       break; \
153     } \
154     case Instruction::IF_##cond##Z: { \
155       RegisterValue val = GetRegister(instruction.VRegA()); \
156       if (val.IsConstant()) { \
157         if (val.GetConstant() op 0) { \
158           return Instruction::kBranch; \
159         } else { \
160           return Instruction::kContinue; \
161         } \
162       } \
163       break; \
164     }
165 
166     IF_XX(EQ, ==);
167     IF_XX(NE, !=);
168     IF_XX(LT, <);
169     IF_XX(LE, <=);
170     IF_XX(GT, >);
171     IF_XX(GE, >=);
172 
173     #undef IF_XX
174 
175     default:
176       break;
177   }
178 
179   return Instruction::FlagsOf(instruction.Opcode());
180 }
181 
AnalyzeCode()182 void VeriFlowAnalysis::AnalyzeCode() {
183   std::vector<uint32_t> work_list;
184   work_list.push_back(0);
185   // Iterate over the code.
186   // When visiting unconditional branches (goto), move to that instruction.
187   // When visiting conditional branches, move to one destination, and put the other
188   // in the worklist.
189   while (!work_list.empty()) {
190     uint32_t dex_pc = work_list.back();
191     work_list.pop_back();
192     CHECK(IsBranchTarget(dex_pc));
193     current_registers_ = *dex_registers_[dex_pc].get();
194     while (true) {
195       const uint16_t* insns = code_item_accessor_.Insns() + dex_pc;
196       const Instruction& inst = *Instruction::At(insns);
197       ProcessDexInstruction(inst);
198       SetVisited(dex_pc);
199 
200       int branch_flags = GetBranchFlags(inst);
201 
202       if ((branch_flags & Instruction::kContinue) != 0) {
203         if ((branch_flags & Instruction::kBranch) != 0) {
204           uint32_t branch_dex_pc = dex_pc + inst.GetTargetOffset();
205           if (MergeRegisterValues(branch_dex_pc)) {
206             work_list.push_back(branch_dex_pc);
207           }
208         }
209         dex_pc += inst.SizeInCodeUnits();
210       } else if ((branch_flags & Instruction::kBranch) != 0) {
211         dex_pc += inst.GetTargetOffset();
212         DCHECK(IsBranchTarget(dex_pc));
213       } else {
214         break;
215       }
216 
217       if (IsBranchTarget(dex_pc)) {
218         if (MergeRegisterValues(dex_pc)) {
219           current_registers_ = *dex_registers_[dex_pc].get();
220         } else {
221           break;
222         }
223       }
224     }
225   }
226 }
227 
ProcessDexInstruction(const Instruction & instruction)228 void VeriFlowAnalysis::ProcessDexInstruction(const Instruction& instruction) {
229   switch (instruction.Opcode()) {
230     case Instruction::CONST_4: {
231       int32_t register_index = instruction.VRegA();
232       int32_t value = instruction.VRegB_11n();
233       UpdateRegister(register_index, value, VeriClass::integer_);
234       break;
235     }
236     case Instruction::CONST_16: {
237       int32_t register_index = instruction.VRegA();
238       int32_t value = instruction.VRegB_21s();
239       UpdateRegister(register_index, value, VeriClass::integer_);
240       break;
241     }
242 
243     case Instruction::CONST: {
244       int32_t register_index = instruction.VRegA();
245       int32_t value = instruction.VRegB_31i();
246       UpdateRegister(register_index, value, VeriClass::integer_);
247       break;
248     }
249 
250     case Instruction::CONST_HIGH16: {
251       int32_t register_index = instruction.VRegA();
252       int32_t value = instruction.VRegB_21h();
253       UpdateRegister(register_index, value, VeriClass::integer_);
254       break;
255     }
256 
257     case Instruction::CONST_WIDE_16:
258     case Instruction::CONST_WIDE_32:
259     case Instruction::CONST_WIDE:
260     case Instruction::CONST_WIDE_HIGH16: {
261       int32_t register_index = instruction.VRegA();
262       UpdateRegister(register_index, VeriClass::long_);
263       break;
264     }
265 
266     case Instruction::MOVE:
267     case Instruction::MOVE_FROM16:
268     case Instruction::MOVE_16: {
269       UpdateRegister(instruction.VRegA(), GetRegister(instruction.VRegB()));
270       break;
271     }
272 
273     case Instruction::MOVE_WIDE:
274     case Instruction::MOVE_WIDE_FROM16:
275     case Instruction::MOVE_WIDE_16: {
276       UpdateRegister(instruction.VRegA(), GetRegister(instruction.VRegB()));
277       break;
278     }
279 
280     case Instruction::MOVE_OBJECT:
281     case Instruction::MOVE_OBJECT_16:
282     case Instruction::MOVE_OBJECT_FROM16: {
283       UpdateRegister(instruction.VRegA(), GetRegister(instruction.VRegB()));
284       break;
285     }
286     case Instruction::CONST_CLASS: {
287       UpdateRegister(instruction.VRegA_21c(),
288                      RegisterSource::kClass,
289                      VeriClass::class_,
290                      instruction.VRegB_21c());
291       break;
292     }
293     case Instruction::CONST_STRING: {
294       UpdateRegister(instruction.VRegA_21c(),
295                      RegisterSource::kString,
296                      VeriClass::string_,
297                      instruction.VRegB_21c());
298       break;
299     }
300 
301     case Instruction::CONST_STRING_JUMBO: {
302       UpdateRegister(instruction.VRegA_31c(),
303                      RegisterSource::kString,
304                      VeriClass::string_,
305                      instruction.VRegB_31c());
306       break;
307     }
308     case Instruction::INVOKE_DIRECT:
309     case Instruction::INVOKE_INTERFACE:
310     case Instruction::INVOKE_STATIC:
311     case Instruction::INVOKE_SUPER:
312     case Instruction::INVOKE_VIRTUAL: {
313       last_result_ = AnalyzeInvoke(instruction, /* is_range */ false);
314       break;
315     }
316 
317     case Instruction::INVOKE_DIRECT_RANGE:
318     case Instruction::INVOKE_INTERFACE_RANGE:
319     case Instruction::INVOKE_STATIC_RANGE:
320     case Instruction::INVOKE_SUPER_RANGE:
321     case Instruction::INVOKE_VIRTUAL_RANGE: {
322       last_result_ = AnalyzeInvoke(instruction, /* is_range */ true);
323       break;
324     }
325 
326     case Instruction::MOVE_RESULT:
327     case Instruction::MOVE_RESULT_WIDE:
328     case Instruction::MOVE_RESULT_OBJECT: {
329       UpdateRegister(instruction.VRegA(), last_result_);
330       break;
331     }
332     case Instruction::RETURN_VOID:
333     case Instruction::RETURN_OBJECT:
334     case Instruction::RETURN_WIDE:
335     case Instruction::RETURN: {
336       break;
337     }
338 
339     // If operations will be handled when looking at the control flow.
340     #define IF_XX(cond) \
341     case Instruction::IF_##cond: break; \
342     case Instruction::IF_##cond##Z: break
343 
344     IF_XX(EQ);
345     IF_XX(NE);
346     IF_XX(LT);
347     IF_XX(LE);
348     IF_XX(GT);
349     IF_XX(GE);
350 
351     #undef IF_XX
352 
353     case Instruction::GOTO:
354     case Instruction::GOTO_16:
355     case Instruction::GOTO_32: {
356       break;
357     }
358     case Instruction::INVOKE_POLYMORPHIC: {
359       // TODO
360       break;
361     }
362 
363     case Instruction::INVOKE_POLYMORPHIC_RANGE: {
364       // TODO
365       break;
366     }
367 
368     case Instruction::NEG_INT:
369     case Instruction::NEG_LONG:
370     case Instruction::NEG_FLOAT:
371     case Instruction::NEG_DOUBLE:
372     case Instruction::NOT_INT:
373     case Instruction::NOT_LONG: {
374       UpdateRegister(instruction.VRegA(), VeriClass::integer_);
375       break;
376     }
377 
378     case Instruction::INT_TO_LONG:
379     case Instruction::INT_TO_FLOAT:
380     case Instruction::INT_TO_DOUBLE:
381     case Instruction::LONG_TO_INT:
382     case Instruction::LONG_TO_FLOAT:
383     case Instruction::LONG_TO_DOUBLE:
384     case Instruction::FLOAT_TO_INT:
385     case Instruction::FLOAT_TO_LONG:
386     case Instruction::FLOAT_TO_DOUBLE:
387     case Instruction::DOUBLE_TO_INT:
388     case Instruction::DOUBLE_TO_LONG:
389     case Instruction::DOUBLE_TO_FLOAT:
390     case Instruction::INT_TO_BYTE:
391     case Instruction::INT_TO_SHORT:
392     case Instruction::INT_TO_CHAR: {
393       UpdateRegister(instruction.VRegA(), VeriClass::integer_);
394       break;
395     }
396 
397     case Instruction::ADD_INT:
398     case Instruction::ADD_LONG:
399     case Instruction::ADD_DOUBLE:
400     case Instruction::ADD_FLOAT:
401     case Instruction::SUB_INT:
402     case Instruction::SUB_LONG:
403     case Instruction::SUB_FLOAT:
404     case Instruction::SUB_DOUBLE:
405     case Instruction::MUL_INT:
406     case Instruction::MUL_LONG:
407     case Instruction::MUL_FLOAT:
408     case Instruction::MUL_DOUBLE:
409     case Instruction::DIV_INT:
410     case Instruction::DIV_LONG:
411     case Instruction::DIV_FLOAT:
412     case Instruction::DIV_DOUBLE:
413     case Instruction::REM_INT:
414     case Instruction::REM_LONG:
415     case Instruction::REM_FLOAT:
416     case Instruction::REM_DOUBLE:
417     case Instruction::AND_INT:
418     case Instruction::AND_LONG:
419     case Instruction::SHL_INT:
420     case Instruction::SHL_LONG:
421     case Instruction::SHR_INT:
422     case Instruction::SHR_LONG:
423     case Instruction::USHR_INT:
424     case Instruction::USHR_LONG:
425     case Instruction::OR_INT:
426     case Instruction::OR_LONG:
427     case Instruction::XOR_INT:
428     case Instruction::XOR_LONG: {
429       UpdateRegister(instruction.VRegA(), VeriClass::integer_);
430       break;
431     }
432 
433     case Instruction::ADD_INT_2ADDR:
434     case Instruction::ADD_LONG_2ADDR:
435     case Instruction::ADD_DOUBLE_2ADDR:
436     case Instruction::ADD_FLOAT_2ADDR:
437     case Instruction::SUB_INT_2ADDR:
438     case Instruction::SUB_LONG_2ADDR:
439     case Instruction::SUB_FLOAT_2ADDR:
440     case Instruction::SUB_DOUBLE_2ADDR:
441     case Instruction::MUL_INT_2ADDR:
442     case Instruction::MUL_LONG_2ADDR:
443     case Instruction::MUL_FLOAT_2ADDR:
444     case Instruction::MUL_DOUBLE_2ADDR:
445     case Instruction::DIV_INT_2ADDR:
446     case Instruction::DIV_LONG_2ADDR:
447     case Instruction::REM_INT_2ADDR:
448     case Instruction::REM_LONG_2ADDR:
449     case Instruction::REM_FLOAT_2ADDR:
450     case Instruction::REM_DOUBLE_2ADDR:
451     case Instruction::SHL_INT_2ADDR:
452     case Instruction::SHL_LONG_2ADDR:
453     case Instruction::SHR_INT_2ADDR:
454     case Instruction::SHR_LONG_2ADDR:
455     case Instruction::USHR_INT_2ADDR:
456     case Instruction::USHR_LONG_2ADDR:
457     case Instruction::DIV_FLOAT_2ADDR:
458     case Instruction::DIV_DOUBLE_2ADDR:
459     case Instruction::AND_INT_2ADDR:
460     case Instruction::AND_LONG_2ADDR:
461     case Instruction::OR_INT_2ADDR:
462     case Instruction::OR_LONG_2ADDR:
463     case Instruction::XOR_INT_2ADDR:
464     case Instruction::XOR_LONG_2ADDR: {
465       UpdateRegister(instruction.VRegA(), VeriClass::integer_);
466       break;
467     }
468 
469     case Instruction::ADD_INT_LIT16:
470     case Instruction::AND_INT_LIT16:
471     case Instruction::OR_INT_LIT16:
472     case Instruction::XOR_INT_LIT16:
473     case Instruction::RSUB_INT:
474     case Instruction::MUL_INT_LIT16:
475     case Instruction::DIV_INT_LIT16:
476     case Instruction::REM_INT_LIT16: {
477       UpdateRegister(instruction.VRegA(), VeriClass::integer_);
478       break;
479     }
480 
481     case Instruction::ADD_INT_LIT8:
482     case Instruction::AND_INT_LIT8:
483     case Instruction::OR_INT_LIT8:
484     case Instruction::XOR_INT_LIT8:
485     case Instruction::RSUB_INT_LIT8:
486     case Instruction::MUL_INT_LIT8:
487     case Instruction::DIV_INT_LIT8:
488     case Instruction::REM_INT_LIT8:
489     case Instruction::SHL_INT_LIT8:
490     case Instruction::SHR_INT_LIT8: {
491     case Instruction::USHR_INT_LIT8: {
492       UpdateRegister(instruction.VRegA(), VeriClass::integer_);
493       break;
494     }
495 
496     case Instruction::NEW_INSTANCE: {
497       VeriClass* cls = resolver_->GetVeriClass(dex::TypeIndex(instruction.VRegB_21c()));
498       UpdateRegister(instruction.VRegA(), cls);
499       break;
500     }
501 
502     case Instruction::NEW_ARRAY: {
503       dex::TypeIndex type_index(instruction.VRegC_22c());
504       VeriClass* cls = resolver_->GetVeriClass(type_index);
505       UpdateRegister(instruction.VRegA_22c(), cls);
506       break;
507     }
508 
509     case Instruction::FILLED_NEW_ARRAY: {
510       dex::TypeIndex type_index(instruction.VRegB_35c());
511       VeriClass* cls = resolver_->GetVeriClass(type_index);
512       UpdateRegister(instruction.VRegA_22c(), cls);
513       break;
514     }
515 
516     case Instruction::FILLED_NEW_ARRAY_RANGE: {
517       dex::TypeIndex type_index(instruction.VRegB_3rc());
518       uint32_t register_index = instruction.VRegC_3rc();
519       VeriClass* cls = resolver_->GetVeriClass(type_index);
520       UpdateRegister(register_index, cls);
521       break;
522     }
523 
524     case Instruction::FILL_ARRAY_DATA: {
525       break;
526     }
527 
528     case Instruction::CMP_LONG:
529     case Instruction::CMPG_FLOAT:
530     case Instruction::CMPG_DOUBLE:
531     case Instruction::CMPL_FLOAT:
532     case Instruction::CMPL_DOUBLE:
533       UpdateRegister(instruction.VRegA(), VeriClass::integer_);
534       break;
535     }
536 
537     case Instruction::NOP:
538       break;
539 
540     case Instruction::IGET:
541     case Instruction::IGET_WIDE:
542     case Instruction::IGET_OBJECT:
543     case Instruction::IGET_BOOLEAN:
544     case Instruction::IGET_BYTE:
545     case Instruction::IGET_CHAR:
546     case Instruction::IGET_SHORT: {
547       UpdateRegister(instruction.VRegA_22c(), GetFieldType(instruction.VRegC_22c()));
548       break;
549     }
550 
551     case Instruction::IPUT:
552     case Instruction::IPUT_WIDE:
553     case Instruction::IPUT_OBJECT:
554     case Instruction::IPUT_BOOLEAN:
555     case Instruction::IPUT_BYTE:
556     case Instruction::IPUT_CHAR:
557     case Instruction::IPUT_SHORT: {
558       AnalyzeFieldSet(instruction);
559       break;
560     }
561 
562     case Instruction::SGET:
563     case Instruction::SGET_WIDE:
564     case Instruction::SGET_OBJECT:
565     case Instruction::SGET_BOOLEAN:
566     case Instruction::SGET_BYTE:
567     case Instruction::SGET_CHAR:
568     case Instruction::SGET_SHORT: {
569       uint32_t dest_reg = instruction.VRegA_21c();
570       uint16_t field_index = instruction.VRegB_21c();
571       if (VeriClass::sdkInt_ != nullptr && resolver_->GetField(field_index) == VeriClass::sdkInt_) {
572         UpdateRegister(dest_reg, gTargetSdkVersion, VeriClass::integer_);
573       } else {
574         UpdateRegister(dest_reg, GetFieldType(instruction.VRegC_22c()));
575       }
576       break;
577     }
578 
579     case Instruction::SPUT:
580     case Instruction::SPUT_WIDE:
581     case Instruction::SPUT_OBJECT:
582     case Instruction::SPUT_BOOLEAN:
583     case Instruction::SPUT_BYTE:
584     case Instruction::SPUT_CHAR:
585     case Instruction::SPUT_SHORT: {
586       AnalyzeFieldSet(instruction);
587       break;
588     }
589 
590 #define ARRAY_XX(kind, anticipated_type)                                          \
591     case Instruction::AGET##kind: {                                               \
592       UpdateRegister(instruction.VRegA_23x(), anticipated_type);                  \
593       break;                                                                      \
594     }                                                                             \
595     case Instruction::APUT##kind: {                                               \
596       break;                                                                      \
597     }
598 
599     ARRAY_XX(, VeriClass::integer_);
600     ARRAY_XX(_WIDE, VeriClass::long_);
601     ARRAY_XX(_BOOLEAN, VeriClass::boolean_);
602     ARRAY_XX(_BYTE, VeriClass::byte_);
603     ARRAY_XX(_CHAR, VeriClass::char_);
604     ARRAY_XX(_SHORT, VeriClass::short_);
605 
606     case Instruction::AGET_OBJECT: {
607       // TODO: take the component type.
608       UpdateRegister(instruction.VRegA_23x(), VeriClass::object_);
609       break;
610     }
611 
612     case Instruction::APUT_OBJECT: {
613       break;
614     }
615 
616     case Instruction::ARRAY_LENGTH: {
617       UpdateRegister(instruction.VRegA_12x(), VeriClass::integer_);
618       break;
619     }
620 
621     case Instruction::MOVE_EXCEPTION: {
622       UpdateRegister(instruction.VRegA_11x(), VeriClass::throwable_);
623       break;
624     }
625 
626     case Instruction::THROW: {
627       break;
628     }
629 
630     case Instruction::INSTANCE_OF: {
631       uint8_t destination = instruction.VRegA_22c();
632       UpdateRegister(destination, VeriClass::boolean_);
633       break;
634     }
635 
636     case Instruction::CHECK_CAST: {
637       uint8_t reference = instruction.VRegA_21c();
638       dex::TypeIndex type_index(instruction.VRegB_21c());
639       UpdateRegister(reference, resolver_->GetVeriClass(type_index));
640       break;
641     }
642 
643     case Instruction::MONITOR_ENTER:
644     case Instruction::MONITOR_EXIT: {
645       break;
646     }
647 
648     case Instruction::SPARSE_SWITCH:
649     case Instruction::PACKED_SWITCH:
650       break;
651 
652     default:
653       break;
654   }
655 }
656 
Run()657 void VeriFlowAnalysis::Run() {
658   FindBranches();
659   uint32_t number_of_registers = code_item_accessor_.RegistersSize();
660   uint32_t number_of_parameters = code_item_accessor_.InsSize();
661   std::vector<RegisterValue>& initial_values = *dex_registers_[0].get();
662   for (uint32_t i = 0; i < number_of_parameters; ++i) {
663     initial_values[number_of_registers - number_of_parameters + i] = RegisterValue(
664       RegisterSource::kParameter,
665       i,
666       DexFileReference(&resolver_->GetDexFile(), method_id_),
667       nullptr);
668   }
669   AnalyzeCode();
670 }
671 
GetParameterAt(const Instruction & instruction,bool is_range,uint32_t * args,uint32_t index)672 static uint32_t GetParameterAt(const Instruction& instruction,
673                                bool is_range,
674                                uint32_t* args,
675                                uint32_t index) {
676   return is_range ? instruction.VRegC() + index : args[index];
677 }
678 
AnalyzeInvoke(const Instruction & instruction,bool is_range)679 RegisterValue FlowAnalysisCollector::AnalyzeInvoke(const Instruction& instruction, bool is_range) {
680   uint32_t id = is_range ? instruction.VRegB_3rc() : instruction.VRegB_35c();
681   VeriMethod method = resolver_->GetMethod(id);
682   uint32_t args[5];
683   if (!is_range) {
684     instruction.GetVarArgs(args);
685   }
686 
687   if (method == VeriClass::forName_) {
688     // Class.forName. Fetch the first parameter.
689     RegisterValue value = GetRegister(GetParameterAt(instruction, is_range, args, 0));
690     return RegisterValue(
691         value.GetSource(), value.GetDexFileReference(), VeriClass::class_);
692   } else if (IsGetField(method)) {
693     // Class.getField or Class.getDeclaredField. Fetch the first parameter for the class, and the
694     // second parameter for the field name.
695     RegisterValue cls = GetRegister(GetParameterAt(instruction, is_range, args, 0));
696     RegisterValue name = GetRegister(GetParameterAt(instruction, is_range, args, 1));
697     uses_.push_back(ReflectAccessInfo(cls, name, /* is_method */ false));
698     return GetReturnType(id);
699   } else if (IsGetMethod(method)) {
700     // Class.getMethod or Class.getDeclaredMethod. Fetch the first parameter for the class, and the
701     // second parameter for the field name.
702     RegisterValue cls = GetRegister(GetParameterAt(instruction, is_range, args, 0));
703     RegisterValue name = GetRegister(GetParameterAt(instruction, is_range, args, 1));
704     uses_.push_back(ReflectAccessInfo(cls, name, /* is_method */ true));
705     return GetReturnType(id);
706   } else if (method == VeriClass::getClass_) {
707     // Get the type of the first parameter.
708     RegisterValue obj = GetRegister(GetParameterAt(instruction, is_range, args, 0));
709     const VeriClass* cls = obj.GetType();
710     if (cls != nullptr && cls->GetClassDef() != nullptr) {
711       const DexFile::ClassDef* def = cls->GetClassDef();
712       return RegisterValue(
713           RegisterSource::kClass,
714           DexFileReference(&resolver_->GetDexFileOf(*cls), def->class_idx_.index_),
715           VeriClass::class_);
716     } else {
717       return RegisterValue(
718           obj.GetSource(), obj.GetDexFileReference(), VeriClass::class_);
719     }
720   } else if (method == VeriClass::loadClass_) {
721     // ClassLoader.loadClass. Fetch the first parameter.
722     RegisterValue value = GetRegister(GetParameterAt(instruction, is_range, args, 1));
723     return RegisterValue(
724         value.GetSource(), value.GetDexFileReference(), VeriClass::class_);
725   } else {
726     // Return a RegisterValue referencing the method whose type is the return type
727     // of the method.
728     return GetReturnType(id);
729   }
730 }
731 
AnalyzeFieldSet(const Instruction & instruction ATTRIBUTE_UNUSED)732 void FlowAnalysisCollector::AnalyzeFieldSet(const Instruction& instruction ATTRIBUTE_UNUSED) {
733   // There are no fields that escape reflection uses.
734 }
735 
AnalyzeInvoke(const Instruction & instruction,bool is_range)736 RegisterValue FlowAnalysisSubstitutor::AnalyzeInvoke(const Instruction& instruction,
737                                                      bool is_range) {
738   uint32_t id = is_range ? instruction.VRegB_3rc() : instruction.VRegB_35c();
739   MethodReference method(&resolver_->GetDexFile(), id);
740   // TODO: doesn't work for multidex
741   // TODO: doesn't work for overriding (but maybe should be done at a higher level);
742   if (accesses_.find(method) == accesses_.end()) {
743     return GetReturnType(id);
744   }
745   uint32_t args[5];
746   if (!is_range) {
747     instruction.GetVarArgs(args);
748   }
749   for (const ReflectAccessInfo& info : accesses_.at(method)) {
750     if (info.cls.IsParameter() || info.name.IsParameter()) {
751       RegisterValue cls = info.cls.IsParameter()
752           ? GetRegister(GetParameterAt(instruction, is_range, args, info.cls.GetParameterIndex()))
753           : info.cls;
754       RegisterValue name = info.name.IsParameter()
755           ? GetRegister(GetParameterAt(instruction, is_range, args, info.name.GetParameterIndex()))
756           : info.name;
757       uses_.push_back(ReflectAccessInfo(cls, name, info.is_method));
758     }
759   }
760   return GetReturnType(id);
761 }
762 
AnalyzeFieldSet(const Instruction & instruction ATTRIBUTE_UNUSED)763 void FlowAnalysisSubstitutor::AnalyzeFieldSet(const Instruction& instruction ATTRIBUTE_UNUSED) {
764   // TODO: analyze field sets.
765 }
766 
767 }  // namespace art
768