Fix DexInstructionIterator overrun bug

Handle cases where the dex instructions can go past the end of the
code item in dexlayout.

Since dexlayout runs before method verification, we need to be
careful to not go past the end of the code item.

Added test.

Bug: 67104794
Test: test-art-host

Change-Id: Idf7d51344659b2c75207bdf444e39f271feb8d3a
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc
index 8c4ee6e..23c3a5c 100644
--- a/dexlayout/dex_ir.cc
+++ b/dexlayout/dex_ir.cc
@@ -167,10 +167,17 @@
                                std::vector<MethodId*>* method_ids,
                                std::vector<FieldId*>* field_ids) {
   bool has_id = false;
-  for (const Instruction& instruction : code->Instructions()) {
-    CHECK_GT(instruction.SizeInCodeUnits(), 0u);
+  IterationRange<DexInstructionIterator> instructions = code->Instructions();
+  SafeDexInstructionIterator it(instructions.begin(), instructions.end());
+  for (; !it.IsErrorState() && it < instructions.end(); ++it) {
+    // In case the instruction goes past the end of the code item, make sure to not process it.
+    SafeDexInstructionIterator next = it;
+    ++next;
+    if (next.IsErrorState() || next > instructions.end()) {
+      break;
+    }
     has_id |= GetIdFromInstruction(collections,
-                                   &instruction,
+                                   it.Inst(),
                                    type_ids,
                                    string_ids,
                                    method_ids,