Added extra safety in veridex

We need extra safeguard prevents segfaulting
on run away instructions.

Test: veridex apk, GtsUnofficialApisUsageTestCases
Bug: 177480896
Change-Id: I3779b5f4a675b7d3bf75461019ad2f8740d22a53
Merged-In: I3779b5f4a675b7d3bf75461019ad2f8740d22a53
(cherry picked from commit 7eb5a95d96175ab6bfca3e9b19673443651ac997)
diff --git a/tools/veridex/flow_analysis.cc b/tools/veridex/flow_analysis.cc
index 65f2363..2a8b8a0 100644
--- a/tools/veridex/flow_analysis.cc
+++ b/tools/veridex/flow_analysis.cc
@@ -47,6 +47,9 @@
 }
 
 bool VeriFlowAnalysis::MergeRegisterValues(uint32_t dex_pc) {
+  if (dex_pc >= code_item_accessor_.InsnsSizeInCodeUnits()) {
+    return false;
+  }
   // TODO: Do the merging. Right now, just return that we should continue
   // the iteration if the instruction has not been visited.
   if (!instruction_infos_[dex_pc].has_been_visited) {
@@ -85,9 +88,14 @@
   }
 
   // Iterate over all instructions and find branching instructions.
+  const uint32_t max_pc = code_item_accessor_.InsnsSizeInCodeUnits();
   for (const DexInstructionPcPair& pair : code_item_accessor_) {
     const uint32_t dex_pc = pair.DexPc();
     const Instruction& instruction = pair.Inst();
+    if (dex_pc >= max_pc) {
+      // We need to prevent abnormal access for outside of code
+      break;
+    }
 
     if (instruction.IsBranch()) {
       SetAsBranchTarget(dex_pc + instruction.GetTargetOffset());
@@ -107,22 +115,32 @@
                                       RegisterSource kind,
                                       VeriClass* cls,
                                       uint32_t source_id) {
-  current_registers_[dex_register] = RegisterValue(
-      kind, DexFileReference(&resolver_->GetDexFile(), source_id), cls);
+  // veridex doesn't do any code verification, so it can be that there are bogus dex
+  // instructions that update a non-existent register.
+  if (dex_register < current_registers_.size()) {
+    current_registers_[dex_register] = RegisterValue(
+        kind, DexFileReference(&resolver_->GetDexFile(), source_id), cls);
+  }
 }
 
 void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, const RegisterValue& value) {
-  current_registers_[dex_register] = value;
+  if (dex_register < current_registers_.size()) {
+    current_registers_[dex_register] = value;
+  }
 }
 
 void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, const VeriClass* cls) {
-  current_registers_[dex_register] =
-      RegisterValue(RegisterSource::kNone, DexFileReference(nullptr, 0), cls);
+  if (dex_register < current_registers_.size()) {
+    current_registers_[dex_register] =
+        RegisterValue(RegisterSource::kNone, DexFileReference(nullptr, 0), cls);
+  }
 }
 
 void VeriFlowAnalysis::UpdateRegister(uint32_t dex_register, int32_t value, const VeriClass* cls) {
-  current_registers_[dex_register] =
-      RegisterValue(RegisterSource::kConstant, value, DexFileReference(nullptr, 0), cls);
+  if (dex_register < current_registers_.size()) {
+    current_registers_[dex_register] =
+        RegisterValue(RegisterSource::kConstant, value, DexFileReference(nullptr, 0), cls);
+  }
 }
 
 const RegisterValue& VeriFlowAnalysis::GetRegister(uint32_t dex_register) const {
@@ -199,7 +217,12 @@
     work_list.pop_back();
     CHECK(IsBranchTarget(dex_pc));
     current_registers_ = *dex_registers_[dex_pc].get();
+    const uint32_t max_pc = code_item_accessor_.InsnsSizeInCodeUnits();
     while (true) {
+      if (dex_pc >= max_pc) {
+        // We need to prevent abnormal access for outside of code
+        break;
+      }
       const uint16_t* insns = code_item_accessor_.Insns() + dex_pc;
       const Instruction& inst = *Instruction::At(insns);
       ProcessDexInstruction(inst);
diff --git a/tools/veridex/hidden_api_finder.cc b/tools/veridex/hidden_api_finder.cc
index e740cf4..6a5c82e 100644
--- a/tools/veridex/hidden_api_finder.cc
+++ b/tools/veridex/hidden_api_finder.cc
@@ -61,7 +61,14 @@
   for (ClassAccessor accessor : dex_file.GetClasses()) {
     if (class_filter.Matches(accessor.GetDescriptor())) {
       for (const ClassAccessor::Method& method : accessor.GetMethods()) {
-        for (const DexInstructionPcPair& inst : method.GetInstructions()) {
+        CodeItemInstructionAccessor codes = method.GetInstructions();
+        const uint32_t max_pc = codes.InsnsSizeInCodeUnits();
+        for (const DexInstructionPcPair& inst : codes) {
+          if (inst.DexPc() >= max_pc) {
+            // We need to prevent abnormal access for outside of code
+            break;
+          }
+
           switch (inst->Opcode()) {
             case Instruction::CONST_STRING: {
               dex::StringIndex string_index(inst->VRegB_21c());