Merge "Verify for type_id out of range errors"
diff --git a/runtime/dex_file_verifier.cc b/runtime/dex_file_verifier.cc
index 68e9f73..4effed4 100644
--- a/runtime/dex_file_verifier.cc
+++ b/runtime/dex_file_verifier.cc
@@ -19,6 +19,7 @@
 #include <inttypes.h>
 #include <zlib.h>
 
+#include <limits>
 #include <memory>
 
 #include "base/stringprintf.h"
@@ -31,6 +32,16 @@
 
 namespace art {
 
+static constexpr uint32_t kTypeIdLimit = std::numeric_limits<uint16_t>::max();
+
+static bool IsValidOrNoTypeId(uint16_t low, uint16_t high) {
+  return (high == 0) || ((high == 0xffffU) && (low == 0xffffU));
+}
+
+static bool IsValidTypeId(uint16_t low ATTRIBUTE_UNUSED, uint16_t high) {
+  return (high == 0);
+}
+
 static uint32_t MapTypeToBitMask(uint32_t map_type) {
   switch (map_type) {
     case DexFile::kDexTypeHeaderItem:               return 1 << 0;
@@ -1790,6 +1801,12 @@
     return false;
   }
 
+  // Check that return type is representable as a uint16_t;
+  if (UNLIKELY(!IsValidOrNoTypeId(item->return_type_idx_.index_, item->pad_))) {
+    ErrorStringPrintf("proto with return type idx outside uint16_t range '%x:%x'",
+                      item->pad_, item->return_type_idx_.index_);
+    return false;
+  }
   // Check the return type and advance the shorty.
   LOAD_STRING_BY_TYPE(return_type, item->return_type_idx_, "inter_proto_id_item return_type_idx")
   if (!CheckShortyDescriptorMatch(*shorty, return_type, true)) {
@@ -1952,6 +1969,18 @@
 bool DexFileVerifier::CheckInterClassDefItem() {
   const DexFile::ClassDef* item = reinterpret_cast<const DexFile::ClassDef*>(ptr_);
 
+  // Check that class_idx_ is representable as a uint16_t;
+  if (UNLIKELY(!IsValidTypeId(item->class_idx_.index_, item->pad1_))) {
+    ErrorStringPrintf("class with type idx outside uint16_t range '%x:%x'", item->pad1_,
+                      item->class_idx_.index_);
+    return false;
+  }
+  // Check that superclass_idx_ is representable as a uint16_t;
+  if (UNLIKELY(!IsValidOrNoTypeId(item->superclass_idx_.index_, item->pad2_))) {
+    ErrorStringPrintf("class with superclass type idx outside uint16_t range '%x:%x'", item->pad2_,
+                      item->superclass_idx_.index_);
+    return false;
+  }
   // Check for duplicate class def.
   if (defined_classes_.find(item->class_idx_) != defined_classes_.end()) {
     ErrorStringPrintf("Redefinition of class with type idx: '%d'", item->class_idx_.index_);
@@ -2320,6 +2349,14 @@
         break;
       }
       case DexFile::kDexTypeClassDefItem: {
+        // There shouldn't be more class definitions than type ids allow.
+        // This check should be redundant, since there are checks that the
+        // class_idx_ is within range and that there is only one definition
+        // for a given type id.
+        if (i > kTypeIdLimit) {
+          ErrorStringPrintf("Too many class definition items");
+          return false;
+        }
         if (!CheckInterClassDefItem()) {
           return false;
         }
@@ -2338,6 +2375,14 @@
         break;
       }
       case DexFile::kDexTypeClassDataItem: {
+        // There shouldn't be more class data than type ids allow.
+        // This check should be redundant, since there are checks that the
+        // class_idx_ is within range and that there is only one definition
+        // for a given type id.
+        if (i > kTypeIdLimit) {
+          ErrorStringPrintf("Too many class data items");
+          return false;
+        }
         if (!CheckInterClassDataItem()) {
           return false;
         }