ART: Add DEX support for MethodHandle and CallSite info.
Adds new DEX file map items for CallSiteIds and MethodHandles.
Initializes CallSiteIds and MethodHandles from the DEX file map_list.
Bug: 33191717,30550796
Test: m test-art-host-gtest-dex_file_verifier_test
Change-Id: I3ad9c7342b661c3f6a8264709412650eee6bde01
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index f59420d..02ba33c 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -497,9 +497,14 @@
method_ids_(reinterpret_cast<const MethodId*>(base + header_->method_ids_off_)),
proto_ids_(reinterpret_cast<const ProtoId*>(base + header_->proto_ids_off_)),
class_defs_(reinterpret_cast<const ClassDef*>(base + header_->class_defs_off_)),
+ method_handles_(nullptr),
+ num_method_handles_(0),
+ call_site_ids_(nullptr),
+ num_call_site_ids_(0),
oat_dex_file_(oat_dex_file) {
CHECK(begin_ != nullptr) << GetLocation();
CHECK_GT(size_, 0U) << GetLocation();
+ InitializeSectionsFromMapList();
}
DexFile::~DexFile() {
@@ -540,6 +545,29 @@
return true;
}
+void DexFile::InitializeSectionsFromMapList() {
+ const MapList* map_list = reinterpret_cast<const MapList*>(begin_ + header_->map_off_);
+ const size_t count = map_list->size_;
+
+ size_t map_limit = header_->map_off_ + count * sizeof(MapItem);
+ if (header_->map_off_ >= map_limit || map_limit > size_) {
+ // Overflow or out out of bounds. The dex file verifier runs after
+ // this method and will reject the file as it is malformed.
+ return;
+ }
+
+ for (size_t i = 0; i < count; ++i) {
+ const MapItem& map_item = map_list->list_[i];
+ if (map_item.type_ == kDexTypeMethodHandleItem) {
+ method_handles_ = reinterpret_cast<const MethodHandleItem*>(begin_ + map_item.offset_);
+ num_method_handles_ = map_item.size_;
+ } else if (map_item.type_ == kDexTypeCallSiteIdItem) {
+ call_site_ids_ = reinterpret_cast<const CallSiteIdItem*>(begin_ + map_item.offset_);
+ num_call_site_ids_ = map_item.size_;
+ }
+ }
+}
+
bool DexFile::IsMagicValid(const uint8_t* magic) {
return (memcmp(magic, kDexMagic, sizeof(kDexMagic)) == 0);
}
@@ -1339,24 +1367,20 @@
}
}
-EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file,
- const DexFile::ClassDef& class_def)
+EncodedArrayValueIterator::EncodedArrayValueIterator(const DexFile& dex_file,
+ const uint8_t* array_data)
: dex_file_(dex_file),
array_size_(),
pos_(-1),
+ ptr_(array_data),
type_(kByte) {
- ptr_ = dex_file_.GetEncodedStaticFieldValuesArray(class_def);
- if (ptr_ == nullptr) {
- array_size_ = 0;
- } else {
- array_size_ = DecodeUnsignedLeb128(&ptr_);
- }
+ array_size_ = (ptr_ != nullptr) ? DecodeUnsignedLeb128(&ptr_) : 0;
if (array_size_ > 0) {
Next();
}
}
-void EncodedStaticFieldValueIterator::Next() {
+void EncodedArrayValueIterator::Next() {
pos_++;
if (pos_ >= array_size_) {
return;
@@ -1396,6 +1420,8 @@
break;
case kString:
case kType:
+ case kMethodType:
+ case kMethodHandle:
jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, false);
break;
case kField:
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index cb7f174..cf90bca 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -103,7 +103,7 @@
};
// Map item type codes.
- enum {
+ enum MapItemType : uint16_t { // private
kDexTypeHeaderItem = 0x0000,
kDexTypeStringIdItem = 0x0001,
kDexTypeTypeIdItem = 0x0002,
@@ -111,6 +111,8 @@
kDexTypeFieldIdItem = 0x0004,
kDexTypeMethodIdItem = 0x0005,
kDexTypeClassDefItem = 0x0006,
+ kDexTypeCallSiteIdItem = 0x0007,
+ kDexTypeMethodHandleItem = 0x0008,
kDexTypeMapList = 0x1000,
kDexTypeTypeList = 0x1001,
kDexTypeAnnotationSetRefList = 0x1002,
@@ -260,6 +262,37 @@
DISALLOW_COPY_AND_ASSIGN(TypeList);
};
+ // MethodHandle Types
+ enum class MethodHandleType : uint16_t { // private
+ kPutStatic = 0x0000, // a setter for a given static field.
+ kGetStatic = 0x0001, // a getter for a given static field.
+ kPutInstance = 0x0002, // a setter for a given instance field.
+ kGetInstance = 0x0003, // a getter for a given instance field.
+ kInvokeStatic = 0x0004, // an invoker for a given static method
+ kInvokeInstance = 0x0005, // invoke_instance : an invoker for a given instance method. This
+ // can be any non-static method on any class (or interface) except
+ // for “<init>”.
+ kInvokeConstructor = 0x0006, // an invoker for a given constructor.
+ kLast = kInvokeConstructor
+ };
+
+ // raw method_handle_item
+ struct MethodHandleItem {
+ uint16_t method_handle_type_;
+ uint16_t reserved1_; // Reserved for future use.
+ uint16_t field_or_method_idx_;
+ uint16_t reserved2_; // Reserved for future use.
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MethodHandleItem);
+ };
+
+ // raw call_site_id_item
+ struct CallSiteIdItem {
+ uint32_t data_off_; // Offset into data section pointing to encoded array items.
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CallSiteIdItem);
+ };
+
// Raw code_item.
struct CodeItem {
uint16_t registers_size_; // the number of registers used by this code
@@ -302,6 +335,8 @@
kDexAnnotationLong = 0x06,
kDexAnnotationFloat = 0x10,
kDexAnnotationDouble = 0x11,
+ kDexAnnotationMethodType = 0x15,
+ kDexAnnotationMethodHandle = 0x16,
kDexAnnotationString = 0x17,
kDexAnnotationType = 0x18,
kDexAnnotationField = 0x19,
@@ -683,6 +718,10 @@
}
}
+ uint32_t NumMethodHandles() const {
+ return num_method_handles_;
+ }
+
// Returns a pointer to the raw memory mapped class_data_item
const uint8_t* GetClassData(const ClassDef& class_def) const {
if (class_def.class_data_off_ == 0) {
@@ -761,6 +800,10 @@
}
}
+ const uint8_t* GetCallSiteEncodedValuesArray(const CallSiteIdItem& call_site_id) const {
+ return begin_ + call_site_id.data_off_;
+ }
+
static const TryItem* GetTryItems(const CodeItem& code_item, uint32_t offset);
// Get the base of the encoded data for the given DexCode.
@@ -1101,6 +1144,9 @@
// Returns true if the header magic and version numbers are of the expected values.
bool CheckMagicAndVersion(std::string* error_msg) const;
+ // Initialize section info for sections only found in map. Returns true on success.
+ void InitializeSectionsFromMapList();
+
// Check whether a location denotes a multidex dex file. This is a very simple check: returns
// whether the string contains the separator character.
static bool IsMultiDexLocation(const char* location);
@@ -1143,6 +1189,18 @@
// Points to the base of the class definition list.
const ClassDef* const class_defs_;
+ // Points to the base of the method handles list.
+ const MethodHandleItem* method_handles_;
+
+ // Number of elements in the method handles list.
+ size_t num_method_handles_;
+
+ // Points to the base of the call sites id list.
+ const CallSiteIdItem* call_site_ids_;
+
+ // Number of elements in the call sites list.
+ size_t num_call_site_ids_;
+
// If this dex file was loaded from an oat file, oat_dex_file_ contains a
// pointer to the OatDexFile it was loaded from. Otherwise oat_dex_file_ is
// null.
@@ -1409,32 +1467,33 @@
DISALLOW_IMPLICIT_CONSTRUCTORS(ClassDataItemIterator);
};
-class EncodedStaticFieldValueIterator {
+class EncodedArrayValueIterator {
public:
- EncodedStaticFieldValueIterator(const DexFile& dex_file,
- const DexFile::ClassDef& class_def);
+ EncodedArrayValueIterator(const DexFile& dex_file, const uint8_t* array_data);
bool HasNext() const { return pos_ < array_size_; }
void Next();
enum ValueType {
- kByte = 0x00,
- kShort = 0x02,
- kChar = 0x03,
- kInt = 0x04,
- kLong = 0x06,
- kFloat = 0x10,
- kDouble = 0x11,
- kString = 0x17,
- kType = 0x18,
- kField = 0x19,
- kMethod = 0x1a,
- kEnum = 0x1b,
- kArray = 0x1c,
- kAnnotation = 0x1d,
- kNull = 0x1e,
- kBoolean = 0x1f
+ kByte = 0x00,
+ kShort = 0x02,
+ kChar = 0x03,
+ kInt = 0x04,
+ kLong = 0x06,
+ kFloat = 0x10,
+ kDouble = 0x11,
+ kMethodType = 0x15,
+ kMethodHandle = 0x16,
+ kString = 0x17,
+ kType = 0x18,
+ kField = 0x19,
+ kMethod = 0x1a,
+ kEnum = 0x1b,
+ kArray = 0x1c,
+ kAnnotation = 0x1d,
+ kNull = 0x1e,
+ kBoolean = 0x1f,
};
ValueType GetValueType() const { return type_; }
@@ -1452,10 +1511,38 @@
jvalue jval_; // Value of current encoded value.
private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(EncodedArrayValueIterator);
+};
+std::ostream& operator<<(std::ostream& os, const EncodedArrayValueIterator::ValueType& code);
+
+class EncodedStaticFieldValueIterator : public EncodedArrayValueIterator {
+ public:
+ EncodedStaticFieldValueIterator(const DexFile& dex_file,
+ const DexFile::ClassDef& class_def)
+ : EncodedArrayValueIterator(dex_file,
+ dex_file.GetEncodedStaticFieldValuesArray(class_def))
+ {}
+
+ private:
DISALLOW_IMPLICIT_CONSTRUCTORS(EncodedStaticFieldValueIterator);
};
std::ostream& operator<<(std::ostream& os, const EncodedStaticFieldValueIterator::ValueType& code);
+class CallSiteArrayValueIterator : public EncodedArrayValueIterator {
+ public:
+ CallSiteArrayValueIterator(const DexFile& dex_file,
+ const DexFile::CallSiteIdItem& call_site_id)
+ : EncodedArrayValueIterator(dex_file,
+ dex_file.GetCallSiteEncodedValuesArray(call_site_id))
+ {}
+
+ uint32_t Size() const { return array_size_; }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(CallSiteArrayValueIterator);
+};
+std::ostream& operator<<(std::ostream& os, const CallSiteArrayValueIterator::ValueType& code);
+
class CatchHandlerIterator {
public:
CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address);
diff --git a/runtime/dex_file_verifier.cc b/runtime/dex_file_verifier.cc
index 318123e..d870e52 100644
--- a/runtime/dex_file_verifier.cc
+++ b/runtime/dex_file_verifier.cc
@@ -46,8 +46,8 @@
return (high == 0);
}
-static uint32_t MapTypeToBitMask(uint32_t map_type) {
- switch (map_type) {
+static uint32_t MapTypeToBitMask(DexFile::MapItemType map_item_type) {
+ switch (map_item_type) {
case DexFile::kDexTypeHeaderItem: return 1 << 0;
case DexFile::kDexTypeStringIdItem: return 1 << 1;
case DexFile::kDexTypeTypeIdItem: return 1 << 2;
@@ -55,23 +55,25 @@
case DexFile::kDexTypeFieldIdItem: return 1 << 4;
case DexFile::kDexTypeMethodIdItem: return 1 << 5;
case DexFile::kDexTypeClassDefItem: return 1 << 6;
- case DexFile::kDexTypeMapList: return 1 << 7;
- case DexFile::kDexTypeTypeList: return 1 << 8;
- case DexFile::kDexTypeAnnotationSetRefList: return 1 << 9;
- case DexFile::kDexTypeAnnotationSetItem: return 1 << 10;
- case DexFile::kDexTypeClassDataItem: return 1 << 11;
- case DexFile::kDexTypeCodeItem: return 1 << 12;
- case DexFile::kDexTypeStringDataItem: return 1 << 13;
- case DexFile::kDexTypeDebugInfoItem: return 1 << 14;
- case DexFile::kDexTypeAnnotationItem: return 1 << 15;
- case DexFile::kDexTypeEncodedArrayItem: return 1 << 16;
- case DexFile::kDexTypeAnnotationsDirectoryItem: return 1 << 17;
+ case DexFile::kDexTypeCallSiteIdItem: return 1 << 7;
+ case DexFile::kDexTypeMethodHandleItem: return 1 << 8;
+ case DexFile::kDexTypeMapList: return 1 << 9;
+ case DexFile::kDexTypeTypeList: return 1 << 10;
+ case DexFile::kDexTypeAnnotationSetRefList: return 1 << 11;
+ case DexFile::kDexTypeAnnotationSetItem: return 1 << 12;
+ case DexFile::kDexTypeClassDataItem: return 1 << 13;
+ case DexFile::kDexTypeCodeItem: return 1 << 14;
+ case DexFile::kDexTypeStringDataItem: return 1 << 15;
+ case DexFile::kDexTypeDebugInfoItem: return 1 << 16;
+ case DexFile::kDexTypeAnnotationItem: return 1 << 17;
+ case DexFile::kDexTypeEncodedArrayItem: return 1 << 18;
+ case DexFile::kDexTypeAnnotationsDirectoryItem: return 1 << 19;
}
return 0;
}
-static bool IsDataSectionType(uint32_t map_type) {
- switch (map_type) {
+static bool IsDataSectionType(DexFile::MapItemType map_item_type) {
+ switch (map_item_type) {
case DexFile::kDexTypeHeaderItem:
case DexFile::kDexTypeStringIdItem:
case DexFile::kDexTypeTypeIdItem:
@@ -80,6 +82,20 @@
case DexFile::kDexTypeMethodIdItem:
case DexFile::kDexTypeClassDefItem:
return false;
+ case DexFile::kDexTypeCallSiteIdItem:
+ case DexFile::kDexTypeMethodHandleItem:
+ case DexFile::kDexTypeMapList:
+ case DexFile::kDexTypeTypeList:
+ case DexFile::kDexTypeAnnotationSetRefList:
+ case DexFile::kDexTypeAnnotationSetItem:
+ case DexFile::kDexTypeClassDataItem:
+ case DexFile::kDexTypeCodeItem:
+ case DexFile::kDexTypeStringDataItem:
+ case DexFile::kDexTypeDebugInfoItem:
+ case DexFile::kDexTypeAnnotationItem:
+ case DexFile::kDexTypeEncodedArrayItem:
+ case DexFile::kDexTypeAnnotationsDirectoryItem:
+ return true;
}
return true;
}
@@ -455,7 +471,8 @@
return false;
}
- if (IsDataSectionType(item->type_)) {
+ DexFile::MapItemType item_type = static_cast<DexFile::MapItemType>(item->type_);
+ if (IsDataSectionType(item_type)) {
uint32_t icount = item->size_;
if (UNLIKELY(icount > data_items_left)) {
ErrorStringPrintf("Too many items in data section: %ud", data_item_count + icount);
@@ -465,7 +482,7 @@
data_item_count += icount;
}
- uint32_t bit = MapTypeToBitMask(item->type_);
+ uint32_t bit = MapTypeToBitMask(item_type);
if (UNLIKELY(bit == 0)) {
ErrorStringPrintf("Unknown map section type %x", item->type_);
@@ -837,6 +854,28 @@
return false;
}
break;
+ case DexFile::kDexAnnotationMethodType: {
+ if (UNLIKELY(value_arg > 3)) {
+ ErrorStringPrintf("Bad encoded_value method type size %x", value_arg);
+ return false;
+ }
+ uint32_t idx = ReadUnsignedLittleEndian(value_arg + 1);
+ if (!CheckIndex(idx, header_->proto_ids_size_, "method_type value")) {
+ return false;
+ }
+ break;
+ }
+ case DexFile::kDexAnnotationMethodHandle: {
+ if (UNLIKELY(value_arg > 3)) {
+ ErrorStringPrintf("Bad encoded_value method handle size %x", value_arg);
+ return false;
+ }
+ uint32_t idx = ReadUnsignedLittleEndian(value_arg + 1);
+ if (!CheckIndex(idx, dex_file_->NumMethodHandles(), "method_handle value")) {
+ return false;
+ }
+ break;
+ }
default:
ErrorStringPrintf("Bogus encoded_value value_type %x", value_type);
return false;
@@ -1455,7 +1494,7 @@
}
bool DexFileVerifier::CheckIntraSectionIterate(size_t offset, uint32_t section_count,
- uint16_t type) {
+ DexFile::MapItemType type) {
// Get the right alignment mask for the type of section.
size_t alignment_mask;
switch (type) {
@@ -1481,6 +1520,7 @@
}
// Check depending on the section type.
+ const uint8_t* start_ptr = ptr_;
switch (type) {
case DexFile::kDexTypeStringIdItem: {
if (!CheckListSize(ptr_, 1, sizeof(DexFile::StringId), "string_ids")) {
@@ -1524,6 +1564,20 @@
ptr_ += sizeof(DexFile::ClassDef);
break;
}
+ case DexFile::kDexTypeCallSiteIdItem: {
+ if (!CheckListSize(ptr_, 1, sizeof(DexFile::CallSiteIdItem), "call_site_ids")) {
+ return false;
+ }
+ ptr_ += sizeof(DexFile::CallSiteIdItem);
+ break;
+ }
+ case DexFile::kDexTypeMethodHandleItem: {
+ if (!CheckListSize(ptr_, 1, sizeof(DexFile::MethodHandleItem), "method_handles")) {
+ return false;
+ }
+ ptr_ += sizeof(DexFile::MethodHandleItem);
+ break;
+ }
case DexFile::kDexTypeTypeList: {
if (!CheckList(sizeof(DexFile::TypeItem), "type_list", &ptr_)) {
return false;
@@ -1584,9 +1638,14 @@
}
break;
}
- default:
- ErrorStringPrintf("Unknown map item type %x", type);
- return false;
+ case DexFile::kDexTypeHeaderItem:
+ case DexFile::kDexTypeMapList:
+ break;
+ }
+
+ if (start_ptr == ptr_) {
+ ErrorStringPrintf("Unknown map item type %x", type);
+ return false;
}
if (IsDataSectionType(type)) {
@@ -1610,7 +1669,9 @@
return true;
}
-bool DexFileVerifier::CheckIntraIdSection(size_t offset, uint32_t count, uint16_t type) {
+bool DexFileVerifier::CheckIntraIdSection(size_t offset,
+ uint32_t count,
+ DexFile::MapItemType type) {
uint32_t expected_offset;
uint32_t expected_size;
@@ -1658,7 +1719,9 @@
return CheckIntraSectionIterate(offset, count, type);
}
-bool DexFileVerifier::CheckIntraDataSection(size_t offset, uint32_t count, uint16_t type) {
+bool DexFileVerifier::CheckIntraDataSection(size_t offset,
+ uint32_t count,
+ DexFile::MapItemType type) {
size_t data_start = header_->data_off_;
size_t data_end = data_start + header_->data_size_;
@@ -1684,16 +1747,16 @@
bool DexFileVerifier::CheckIntraSection() {
const DexFile::MapList* map = reinterpret_cast<const DexFile::MapList*>(begin_ + header_->map_off_);
const DexFile::MapItem* item = map->list_;
-
- uint32_t count = map->size_;
size_t offset = 0;
+ uint32_t count = map->size_;
ptr_ = begin_;
// Check the items listed in the map.
while (count--) {
+ const size_t current_offset = offset;
uint32_t section_offset = item->offset_;
uint32_t section_count = item->size_;
- uint16_t type = item->type_;
+ DexFile::MapItemType type = static_cast<DexFile::MapItemType>(item->type_);
// Check for padding and overlap between items.
if (!CheckPadding(offset, section_offset)) {
@@ -1741,6 +1804,11 @@
ptr_ += sizeof(uint32_t) + (map->size_ * sizeof(DexFile::MapItem));
offset = section_offset + sizeof(uint32_t) + (map->size_ * sizeof(DexFile::MapItem));
break;
+ case DexFile::kDexTypeMethodHandleItem:
+ case DexFile::kDexTypeCallSiteIdItem:
+ CheckIntraSectionIterate(section_offset, section_count, type);
+ offset = ptr_ - begin_;
+ break;
case DexFile::kDexTypeTypeList:
case DexFile::kDexTypeAnnotationSetRefList:
case DexFile::kDexTypeAnnotationSetItem:
@@ -1756,7 +1824,9 @@
}
offset = ptr_ - begin_;
break;
- default:
+ }
+
+ if (offset == current_offset) {
ErrorStringPrintf("Unknown map item type %x", type);
return false;
}
@@ -2237,6 +2307,92 @@
return true;
}
+bool DexFileVerifier::CheckInterCallSiteIdItem() {
+ const DexFile::CallSiteIdItem* item = reinterpret_cast<const DexFile::CallSiteIdItem*>(ptr_);
+
+ // Check call site referenced by item is in encoded array section.
+ if (!CheckOffsetToTypeMap(item->data_off_, DexFile::kDexTypeEncodedArrayItem)) {
+ ErrorStringPrintf("Invalid offset in CallSideIdItem");
+ return false;
+ }
+
+ CallSiteArrayValueIterator it(*dex_file_, *item);
+
+ // Check Method Handle
+ if (!it.HasNext() || it.GetValueType() != EncodedArrayValueIterator::ValueType::kMethodHandle) {
+ ErrorStringPrintf("CallSiteArray missing method handle");
+ return false;
+ }
+
+ uint32_t handle_index = static_cast<uint32_t>(it.GetJavaValue().i);
+ if (handle_index >= dex_file_->NumMethodHandles()) {
+ ErrorStringPrintf("CallSite has bad method handle id: %x", handle_index);
+ return false;
+ }
+
+ // Check target method name.
+ it.Next();
+ if (!it.HasNext() ||
+ it.GetValueType() != EncodedArrayValueIterator::ValueType::kString) {
+ ErrorStringPrintf("CallSiteArray missing target method name");
+ return false;
+ }
+
+ uint32_t name_index = static_cast<uint32_t>(it.GetJavaValue().i);
+ if (name_index >= dex_file_->NumStringIds()) {
+ ErrorStringPrintf("CallSite has bad method name id: %x", name_index);
+ return false;
+ }
+
+ // Check method type.
+ it.Next();
+ if (!it.HasNext() ||
+ it.GetValueType() != EncodedArrayValueIterator::ValueType::kMethodType) {
+ ErrorStringPrintf("CallSiteArray missing method type");
+ return false;
+ }
+
+ uint32_t proto_index = static_cast<uint32_t>(it.GetJavaValue().i);
+ if (proto_index >= dex_file_->NumProtoIds()) {
+ ErrorStringPrintf("CallSite has bad method type: %x", proto_index);
+ return false;
+ }
+
+ ptr_ += sizeof(DexFile::CallSiteIdItem);
+ return true;
+}
+
+bool DexFileVerifier::CheckInterMethodHandleItem() {
+ const DexFile::MethodHandleItem* item = reinterpret_cast<const DexFile::MethodHandleItem*>(ptr_);
+
+ DexFile::MethodHandleType method_handle_type =
+ static_cast<DexFile::MethodHandleType>(item->method_handle_type_);
+ if (method_handle_type > DexFile::MethodHandleType::kLast) {
+ ErrorStringPrintf("Bad method handle type %x", item->method_handle_type_);
+ return false;
+ }
+
+ uint32_t index = item->field_or_method_idx_;
+ switch (method_handle_type) {
+ case DexFile::MethodHandleType::kPutStatic:
+ case DexFile::MethodHandleType::kGetStatic:
+ case DexFile::MethodHandleType::kPutInstance:
+ case DexFile::MethodHandleType::kGetInstance: {
+ LOAD_FIELD(field, index, "method_handle_item field_idx", return false);
+ break;
+ }
+ case DexFile::MethodHandleType::kInvokeStatic:
+ case DexFile::MethodHandleType::kInvokeInstance:
+ case DexFile::MethodHandleType::kInvokeConstructor: {
+ LOAD_METHOD(method, index, "method_handle_item method_idx", return false);
+ break;
+ }
+ }
+
+ ptr_ += sizeof(DexFile::MethodHandleItem);
+ return true;
+}
+
bool DexFileVerifier::CheckInterAnnotationSetRefList() {
const DexFile::AnnotationSetRefList* list =
reinterpret_cast<const DexFile::AnnotationSetRefList*>(ptr_);
@@ -2386,7 +2542,9 @@
return true;
}
-bool DexFileVerifier::CheckInterSectionIterate(size_t offset, uint32_t count, uint16_t type) {
+bool DexFileVerifier::CheckInterSectionIterate(size_t offset,
+ uint32_t count,
+ DexFile::MapItemType type) {
// Get the right alignment mask for the type of section.
size_t alignment_mask;
switch (type) {
@@ -2405,8 +2563,22 @@
ptr_ = begin_ + new_offset;
const uint8_t* prev_ptr = ptr_;
+ if (MapTypeToBitMask(type) == 0) {
+ ErrorStringPrintf("Unknown map item type %x", type);
+ return false;
+ }
+
// Check depending on the section type.
switch (type) {
+ case DexFile::kDexTypeHeaderItem:
+ case DexFile::kDexTypeMapList:
+ case DexFile::kDexTypeTypeList:
+ case DexFile::kDexTypeCodeItem:
+ case DexFile::kDexTypeStringDataItem:
+ case DexFile::kDexTypeDebugInfoItem:
+ case DexFile::kDexTypeAnnotationItem:
+ case DexFile::kDexTypeEncodedArrayItem:
+ break;
case DexFile::kDexTypeStringIdItem: {
if (!CheckInterStringIdItem()) {
return false;
@@ -2451,6 +2623,18 @@
}
break;
}
+ case DexFile::kDexTypeCallSiteIdItem: {
+ if (!CheckInterCallSiteIdItem()) {
+ return false;
+ }
+ break;
+ }
+ case DexFile::kDexTypeMethodHandleItem: {
+ if (!CheckInterMethodHandleItem()) {
+ return false;
+ }
+ break;
+ }
case DexFile::kDexTypeAnnotationSetRefList: {
if (!CheckInterAnnotationSetRefList()) {
return false;
@@ -2483,9 +2667,6 @@
}
break;
}
- default:
- ErrorStringPrintf("Unknown map item type %x", type);
- return false;
}
previous_item_ = prev_ptr;
@@ -2504,7 +2685,8 @@
while (count--) {
uint32_t section_offset = item->offset_;
uint32_t section_count = item->size_;
- uint16_t type = item->type_;
+ DexFile::MapItemType type = static_cast<DexFile::MapItemType>(item->type_);
+ bool found = false;
switch (type) {
case DexFile::kDexTypeHeaderItem:
@@ -2515,6 +2697,7 @@
case DexFile::kDexTypeDebugInfoItem:
case DexFile::kDexTypeAnnotationItem:
case DexFile::kDexTypeEncodedArrayItem:
+ found = true;
break;
case DexFile::kDexTypeStringIdItem:
case DexFile::kDexTypeTypeIdItem:
@@ -2522,6 +2705,8 @@
case DexFile::kDexTypeFieldIdItem:
case DexFile::kDexTypeMethodIdItem:
case DexFile::kDexTypeClassDefItem:
+ case DexFile::kDexTypeCallSiteIdItem:
+ case DexFile::kDexTypeMethodHandleItem:
case DexFile::kDexTypeAnnotationSetRefList:
case DexFile::kDexTypeAnnotationSetItem:
case DexFile::kDexTypeClassDataItem:
@@ -2529,11 +2714,14 @@
if (!CheckInterSectionIterate(section_offset, section_count, type)) {
return false;
}
+ found = true;
break;
}
- default:
- ErrorStringPrintf("Unknown map item type %x", type);
- return false;
+ }
+
+ if (!found) {
+ ErrorStringPrintf("Unknown map item type %x", item->type_);
+ return false;
}
item++;
diff --git a/runtime/dex_file_verifier.h b/runtime/dex_file_verifier.h
index ae20613..71b316c 100644
--- a/runtime/dex_file_verifier.h
+++ b/runtime/dex_file_verifier.h
@@ -122,9 +122,9 @@
bool CheckIntraAnnotationItem();
bool CheckIntraAnnotationsDirectoryItem();
- bool CheckIntraSectionIterate(size_t offset, uint32_t count, uint16_t type);
- bool CheckIntraIdSection(size_t offset, uint32_t count, uint16_t type);
- bool CheckIntraDataSection(size_t offset, uint32_t count, uint16_t type);
+ bool CheckIntraSectionIterate(size_t offset, uint32_t count, DexFile::MapItemType type);
+ bool CheckIntraIdSection(size_t offset, uint32_t count, DexFile::MapItemType type);
+ bool CheckIntraDataSection(size_t offset, uint32_t count, DexFile::MapItemType type);
bool CheckIntraSection();
bool CheckOffsetToTypeMap(size_t offset, uint16_t type);
@@ -140,12 +140,14 @@
bool CheckInterFieldIdItem();
bool CheckInterMethodIdItem();
bool CheckInterClassDefItem();
+ bool CheckInterCallSiteIdItem();
+ bool CheckInterMethodHandleItem();
bool CheckInterAnnotationSetRefList();
bool CheckInterAnnotationSetItem();
bool CheckInterClassDataItem();
bool CheckInterAnnotationsDirectoryItem();
- bool CheckInterSectionIterate(size_t offset, uint32_t count, uint16_t type);
+ bool CheckInterSectionIterate(size_t offset, uint32_t count, DexFile::MapItemType type);
bool CheckInterSection();
// Load a string by (type) index. Checks whether the index is in bounds, printing the error if
diff --git a/runtime/dex_file_verifier_test.cc b/runtime/dex_file_verifier_test.cc
index c56b200..7736f3d 100644
--- a/runtime/dex_file_verifier_test.cc
+++ b/runtime/dex_file_verifier_test.cc
@@ -1885,4 +1885,209 @@
&error_msg));
}
+static const char* kInvokeCustomDexFiles[] = {
+ // TODO(oth): Revisit this test when we have smali / dx support.
+ // https://cs.corp.google.com/android/toolchain/jack/jack-tests/tests/com/android/jack/java7/invokecustom/test001/Tests.java
+ "ZGV4CjAzOAAEj12s/acmmdGuDL92SWSBh6iLBjxgomWkCAAAcAAAAHhWNBIAAAAAAAAAALwHAAAx"
+ "AAAAcAAAABYAAAA0AQAACQAAAIwBAAADAAAA+AEAAAsAAAAQAgAAAQAAAHACAAAMBgAAmAIAAMID"
+ "AADKAwAAzQMAANIDAADhAwAA5AMAAOoDAAAfBAAAUgQAAIMEAAC4BAAA1AQAAOsEAAD+BAAAEgUA"
+ "ACYFAAA6BQAAUQUAAG4FAACTBQAAtAUAAN0FAAD/BQAAHgYAADgGAABKBgAAVgYAAFkGAABdBgAA"
+ "YgYAAGYGAAB7BgAAgAYAAI8GAACdBgAAtAYAAMMGAADSBgAA3gYAAPIGAAD4BgAABgcAAA4HAAAU"
+ "BwAAGgcAAB8HAAAoBwAANAcAADoHAAABAAAABgAAAAcAAAAIAAAACQAAAAoAAAALAAAADAAAAA0A"
+ "AAAOAAAADwAAABAAAAARAAAAEgAAABMAAAAUAAAAFQAAABYAAAAXAAAAGAAAABoAAAAeAAAAAgAA"
+ "AAAAAACMAwAABQAAAAwAAACUAwAABQAAAA4AAACgAwAABAAAAA8AAAAAAAAAGgAAABQAAAAAAAAA"
+ "GwAAABQAAACsAwAAHAAAABQAAACMAwAAHQAAABQAAAC0AwAAHQAAABQAAAC8AwAAAwADAAMAAAAE"
+ "AAwAJAAAAAoABgAsAAAABAAEAAAAAAAEAAAAHwAAAAQAAQAoAAAABAAIACoAAAAEAAQALwAAAAYA"
+ "BQAtAAAACAAEAAAAAAANAAcAAAAAAA8AAgAlAAAAEAADACkAAAASAAYAIQAAAJYHAACWBwAABAAA"
+ "AAEAAAAIAAAAAAAAABkAAABkAwAAnQcAAAAAAAAEAAAAAgAAAAEAAABjBwAAAQAAAIsHAAACAAAA"
+ "iwcAAJMHAAABAAEAAQAAAEEHAAAEAAAAcBAGAAAADgADAAIAAAAAAEYHAAADAAAAkAABAg8AAAAF"
+ "AAMABAAAAE0HAAAQAAAAcQAJAAAADAAcAQQAbkAIABBDDAAiAQ0AcCAHAAEAEQEEAAEAAgAAAFYH"
+ "AAAMAAAAYgACABIhEjL8IAAAIQAKAW4gBQAQAA4AAwABAAIAAABdBwAACwAAABIgEjH8IAEAEAAK"
+ "ABJRcSAKAAEADgAAAAAAAAAAAAAAAwAAAAAAAAABAAAAmAIAAAIAAACgAgAABAAAAKgCAAACAAAA"
+ "AAAAAAMAAAAPAAkAEQAAAAMAAAAHAAkAEQAAAAEAAAAAAAAAAQAAAA4AAAABAAAAFQAGPGluaXQ+"
+ "AAFJAANJSUkADUlOVk9LRV9TVEFUSUMAAUwABExMTEwAM0xjb20vYW5kcm9pZC9qYWNrL2Fubm90"
+ "YXRpb25zL0NhbGxlZEJ5SW52b2tlQ3VzdG9tOwAxTGNvbS9hbmRyb2lkL2phY2svYW5ub3RhdGlv"
+ "bnMvTGlua2VyTWV0aG9kSGFuZGxlOwAvTGNvbS9hbmRyb2lkL2phY2svYW5ub3RhdGlvbnMvTWV0"
+ "aG9kSGFuZGxlS2luZDsAM0xjb20vYW5kcm9pZC9qYWNrL2phdmE3L2ludm9rZWN1c3RvbS90ZXN0"
+ "MDAxL1Rlc3RzOwAaTGRhbHZpay9hbm5vdGF0aW9uL1Rocm93czsAFUxqYXZhL2lvL1ByaW50U3Ry"
+ "ZWFtOwARTGphdmEvbGFuZy9DbGFzczsAEkxqYXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9T"
+ "dHJpbmc7ABJMamF2YS9sYW5nL1N5c3RlbTsAFUxqYXZhL2xhbmcvVGhyb3dhYmxlOwAbTGphdmEv"
+ "bGFuZy9pbnZva2UvQ2FsbFNpdGU7ACNMamF2YS9sYW5nL2ludm9rZS9Db25zdGFudENhbGxTaXRl"
+ "OwAfTGphdmEvbGFuZy9pbnZva2UvTWV0aG9kSGFuZGxlOwAnTGphdmEvbGFuZy9pbnZva2UvTWV0"
+ "aG9kSGFuZGxlcyRMb29rdXA7ACBMamF2YS9sYW5nL2ludm9rZS9NZXRob2RIYW5kbGVzOwAdTGph"
+ "dmEvbGFuZy9pbnZva2UvTWV0aG9kVHlwZTsAGExqdW5pdC9mcmFtZXdvcmsvQXNzZXJ0OwAQTG9y"
+ "Zy9qdW5pdC9UZXN0OwAKVGVzdHMuamF2YQABVgACVkkAA1ZJSQACVkwAE1tMamF2YS9sYW5nL1N0"
+ "cmluZzsAA2FkZAANYXJndW1lbnRUeXBlcwAMYXNzZXJ0RXF1YWxzABVlbWl0dGVyOiBqYWNrLTQu"
+ "MC1lbmcADWVuY2xvc2luZ1R5cGUADWZpZWxkQ2FsbFNpdGUACmZpbmRTdGF0aWMAEmludm9rZU1l"
+ "dGhvZEhhbmRsZQAEa2luZAAMbGlua2VyTWV0aG9kAAZsb29rdXAABG1haW4ABG5hbWUAA291dAAH"
+ "cHJpbnRsbgAKcmV0dXJuVHlwZQAEdGVzdAAFdmFsdWUAIgAHDgAvAgAABw4ANQMAAAAHDqUAPwEA"
+ "Bw60ADsABw6lAAABBCAcAhgAGAAmHAEdAgQgHAMYDxgJGBEjGAQnGwArFygrFx8uGAACBQEwHAEY"
+ "CwETAAMWABcfFQABAAQBAQkAgYAEtAUBCswFAQrkBQEJlAYEAbwGAAAAEwAAAAAAAAABAAAAAAAA"
+ "AAEAAAAxAAAAcAAAAAIAAAAWAAAANAEAAAMAAAAJAAAAjAEAAAQAAAADAAAA+AEAAAUAAAALAAAA"
+ "EAIAAAcAAAACAAAAaAIAAAYAAAABAAAAcAIAAAgAAAABAAAAkAIAAAMQAAADAAAAmAIAAAEgAAAF"
+ "AAAAtAIAAAYgAAABAAAAZAMAAAEQAAAGAAAAjAMAAAIgAAAxAAAAwgMAAAMgAAAFAAAAQQcAAAQg"
+ "AAADAAAAYwcAAAUgAAABAAAAlgcAAAAgAAABAAAAnQcAAAAQAAABAAAAvAcAAA==",
+ // https://cs.corp.google.com/android/toolchain/jack/jack-tests/tests/com/android/jack/java7/invokecustom/test002/Tests.java
+ "ZGV4CjAzOAAzq3aGAwKhT4QQj4lqNfZJAO8Tm24uTyNICQAAcAAAAHhWNBIAAAAAAAAAAGAIAAA2"
+ "AAAAcAAAABgAAABIAQAACQAAAKgBAAAEAAAAFAIAAA0AAAA0AgAAAQAAAKQCAAB8BgAAzAIAACYE"
+ "AAAwBAAAOAQAAEQEAABHBAAATAQAAE8EAABVBAAAigQAALwEAADtBAAAIgUAAD4FAABVBQAAaAUA"
+ "AH0FAACRBQAApQUAALkFAADQBQAA7QUAABIGAAAzBgAAXAYAAH4GAACdBgAAtwYAAMkGAADPBgAA"
+ "2wYAAN4GAADiBgAA5wYAAOsGAAD/BgAAFAcAABkHAAAoBwAANgcAAE0HAABcBwAAawcAAH4HAACK"
+ "BwAAkAcAAJgHAACeBwAAqgcAALAHAAC1BwAAxgcAAM8HAADbBwAA4QcAAAMAAAAHAAAACAAAAAkA"
+ "AAAKAAAACwAAAAwAAAANAAAADgAAAA8AAAAQAAAAEQAAABIAAAATAAAAFAAAABUAAAAWAAAAFwAA"
+ "ABgAAAAZAAAAGgAAAB0AAAAhAAAAIgAAAAQAAAAAAAAA8AMAAAYAAAAPAAAA+AMAAAUAAAAQAAAA"
+ "AAAAAAYAAAASAAAABAQAAB0AAAAVAAAAAAAAAB4AAAAVAAAAEAQAAB8AAAAVAAAA8AMAACAAAAAV"
+ "AAAAGAQAACAAAAAVAAAAIAQAAAMAAwACAAAABAANACgAAAAIAAcAGwAAAAsABgAwAAAABAAEAAAA"
+ "AAAEAAQAAQAAAAQAAAAjAAAABAAIAC0AAAAEAAQANAAAAAYABQAyAAAACQAEAAEAAAAMAAQAMQAA"
+ "AA4ABwABAAAAEAABACoAAAARAAIALAAAABIAAwAuAAAAEwAGACUAAAA4CAAAOAgAAAQAAAABAAAA"
+ "CQAAAAAAAAAcAAAA0AMAAD8IAAAAAAAAAQAAAAEAAAABAAAADggAAAIAAAAtCAAANQgAAAgAAAAE"
+ "AAEA6AcAACoAAABxAAoAAAAMABwBBAAbAiMAAABiAwIAYgQCABIVI1UWAGIGAgASB00GBQdxMAsA"
+ "QwUMA25ACQAQMgwAIgEOAHAgCAABAGkBAQAOAA0AbhAHAAAAKPsAAAAAJAABAAEBDCUBAAEAAQAA"
+ "APUHAAAEAAAAcBAGAAAADgADAAIAAAAAAPoHAAADAAAAkAABAg8AAAAEAAEAAgAAAAEIAAAMAAAA"
+ "YgADABIhEjL8IAAAIQAKAW4gBQAQAA4AAwABAAIAAAAICAAACwAAABIgEjH8IAEAEAAKABJRcSAM"
+ "AAEADgAAAAAAAAAAAAAAAgAAAAAAAAACAAAAzAIAAAQAAADUAgAAAgAAAAAAAAADAAAABwAKABIA"
+ "AAADAAAABwAHABYAAAABAAAAAAAAAAEAAAAPAAAAAQAAABcACDxjbGluaXQ+AAY8aW5pdD4ACkdF"
+ "VF9TVEFUSUMAAUkAA0lJSQABTAAETExMTAAzTGNvbS9hbmRyb2lkL2phY2svYW5ub3RhdGlvbnMv"
+ "Q2FsbGVkQnlJbnZva2VDdXN0b207ADBMY29tL2FuZHJvaWQvamFjay9hbm5vdGF0aW9ucy9MaW5r"
+ "ZXJGaWVsZEhhbmRsZTsAL0xjb20vYW5kcm9pZC9qYWNrL2Fubm90YXRpb25zL01ldGhvZEhhbmRs"
+ "ZUtpbmQ7ADNMY29tL2FuZHJvaWQvamFjay9qYXZhNy9pbnZva2VjdXN0b20vdGVzdDAwMi9UZXN0"
+ "czsAGkxkYWx2aWsvYW5ub3RhdGlvbi9UaHJvd3M7ABVMamF2YS9pby9QcmludFN0cmVhbTsAEUxq"
+ "YXZhL2xhbmcvQ2xhc3M7ABNMamF2YS9sYW5nL0ludGVnZXI7ABJMamF2YS9sYW5nL09iamVjdDsA"
+ "EkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07ABVMamF2YS9sYW5nL1Rocm93"
+ "YWJsZTsAG0xqYXZhL2xhbmcvaW52b2tlL0NhbGxTaXRlOwAjTGphdmEvbGFuZy9pbnZva2UvQ29u"
+ "c3RhbnRDYWxsU2l0ZTsAH0xqYXZhL2xhbmcvaW52b2tlL01ldGhvZEhhbmRsZTsAJ0xqYXZhL2xh"
+ "bmcvaW52b2tlL01ldGhvZEhhbmRsZXMkTG9va3VwOwAgTGphdmEvbGFuZy9pbnZva2UvTWV0aG9k"
+ "SGFuZGxlczsAHUxqYXZhL2xhbmcvaW52b2tlL01ldGhvZFR5cGU7ABhManVuaXQvZnJhbWV3b3Jr"
+ "L0Fzc2VydDsAEExvcmcvanVuaXQvVGVzdDsABFRZUEUAClRlc3RzLmphdmEAAVYAAlZJAANWSUkA"
+ "AlZMABJbTGphdmEvbGFuZy9DbGFzczsAE1tMamF2YS9sYW5nL1N0cmluZzsAA2FkZAANYXJndW1l"
+ "bnRUeXBlcwAMYXNzZXJ0RXF1YWxzABVlbWl0dGVyOiBqYWNrLTQuMC1lbmcADWVuY2xvc2luZ1R5"
+ "cGUADWZpZWxkQ2FsbFNpdGUAEWZpZWxkTWV0aG9kSGFuZGxlAApmaW5kU3RhdGljAARraW5kAAZs"
+ "b29rdXAABG1haW4ACm1ldGhvZFR5cGUABG5hbWUAA291dAAPcHJpbnRTdGFja1RyYWNlAAdwcmlu"
+ "dGxuAApyZXR1cm5UeXBlAAR0ZXN0AAV2YWx1ZQAoAAcOAR0PAnh3Jh4AIQAHDgA2AgAABw4APwEA"
+ "Bw60ADsABw6lAAABBCQcAhgAGAApHAEdAgMnGAQrGwAvFygvFyMzGAACBQE1HAEYDAEUAAMWABcj"
+ "FQABAAQBAQkAiIAE4AUBgYAE0AYBCugGAQmABwQBqAcAAAATAAAAAAAAAAEAAAAAAAAAAQAAADYA"
+ "AABwAAAAAgAAABgAAABIAQAAAwAAAAkAAACoAQAABAAAAAQAAAAUAgAABQAAAA0AAAA0AgAABwAA"
+ "AAIAAACcAgAABgAAAAEAAACkAgAACAAAAAEAAADEAgAAAxAAAAIAAADMAgAAASAAAAUAAADgAgAA"
+ "BiAAAAEAAADQAwAAARAAAAYAAADwAwAAAiAAADYAAAAmBAAAAyAAAAUAAADoBwAABCAAAAMAAAAO"
+ "CAAABSAAAAEAAAA4CAAAACAAAAEAAAA/CAAAABAAAAEAAABgCAAA",
+ // https://cs.corp.google.com/android/toolchain/jack/jack-tests/tests/com/android/jack/java7/invokecustom/test003/Tests.java
+ "ZGV4CjAzOABjnhkFatj30/7cHTCJsfr7vAjz9/p+Y+TcCAAAcAAAAHhWNBIAAAAAAAAAAPQHAAAx"
+ "AAAAcAAAABYAAAA0AQAACQAAAIwBAAADAAAA+AEAAAsAAAAQAgAAAQAAAHACAABEBgAAmAIAAOoD"
+ "AADyAwAA9QMAAP4DAAANBAAAEAQAABYEAABLBAAAfgQAAK8EAADkBAAAAAUAABcFAAAqBQAAPgUA"
+ "AFIFAABmBQAAfQUAAJoFAAC/BQAA4AUAAAkGAAArBgAASgYAAGQGAAB2BgAAggYAAIUGAACJBgAA"
+ "jgYAAJIGAACnBgAArAYAALsGAADJBgAA4AYAAO8GAAD+BgAACgcAAB4HAAAkBwAAMgcAADoHAABA"
+ "BwAARgcAAEsHAABUBwAAYAcAAGYHAAABAAAABgAAAAcAAAAIAAAACQAAAAoAAAALAAAADAAAAA0A"
+ "AAAOAAAADwAAABAAAAARAAAAEgAAABMAAAAUAAAAFQAAABYAAAAXAAAAGAAAABoAAAAeAAAAAgAA"
+ "AAAAAACkAwAABQAAAAwAAAC0AwAABQAAAA4AAADAAwAABAAAAA8AAAAAAAAAGgAAABQAAAAAAAAA"
+ "GwAAABQAAADMAwAAHAAAABQAAADUAwAAHQAAABQAAADcAwAAHQAAABQAAADkAwAAAwADAAMAAAAE"
+ "AAwAJAAAAAoABgAsAAAABAAEAAAAAAAEAAAAHwAAAAQAAQAoAAAABAAIACoAAAAEAAQALwAAAAYA"
+ "BQAtAAAACAAEAAAAAAANAAcAAAAAAA8AAgAlAAAAEAADACkAAAASAAYAIQAAAM4HAADOBwAABAAA"
+ "AAEAAAAIAAAAAAAAABkAAAB8AwAA1QcAAAAAAAAEAAAAAgAAAAEAAACTBwAAAQAAAMMHAAACAAAA"
+ "wwcAAMsHAAABAAEAAQAAAG0HAAAEAAAAcBAGAAAADgAHAAYAAAAAAHIHAAAHAAAAkAABArAwsECw"
+ "ULBgDwAAAAUAAwAEAAAAfQcAABAAAABxAAkAAAAMABwBBABuQAgAEEMMACIBDQBwIAcAAQARAQgA"
+ "AQACAAAAhgcAABAAAABiBgIAEhASIRIyEkMSVBJl/QYAAAAACgBuIAUABgAOAAcAAQACAAAAjQcA"
+ "ABAAAAASEBIhEjISQxJUEmX9BgEAAAAKABMBFQBxIAoAAQAOAAAAAAAAAAAAAwAAAAAAAAABAAAA"
+ "mAIAAAIAAACgAgAABAAAAKgCAAAGAAAAAAAAAAAAAAAAAAAAAwAAAA8ACQARAAAAAwAAAAcACQAR"
+ "AAAAAQAAAAAAAAACAAAAAAAAAAEAAAAOAAAAAQAAABUABjxpbml0PgABSQAHSUlJSUlJSQANSU5W"
+ "T0tFX1NUQVRJQwABTAAETExMTAAzTGNvbS9hbmRyb2lkL2phY2svYW5ub3RhdGlvbnMvQ2FsbGVk"
+ "QnlJbnZva2VDdXN0b207ADFMY29tL2FuZHJvaWQvamFjay9hbm5vdGF0aW9ucy9MaW5rZXJNZXRo"
+ "b2RIYW5kbGU7AC9MY29tL2FuZHJvaWQvamFjay9hbm5vdGF0aW9ucy9NZXRob2RIYW5kbGVLaW5k"
+ "OwAzTGNvbS9hbmRyb2lkL2phY2svamF2YTcvaW52b2tlY3VzdG9tL3Rlc3QwMDMvVGVzdHM7ABpM"
+ "ZGFsdmlrL2Fubm90YXRpb24vVGhyb3dzOwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABFMamF2YS9s"
+ "YW5nL0NsYXNzOwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAEkxqYXZh"
+ "L2xhbmcvU3lzdGVtOwAVTGphdmEvbGFuZy9UaHJvd2FibGU7ABtMamF2YS9sYW5nL2ludm9rZS9D"
+ "YWxsU2l0ZTsAI0xqYXZhL2xhbmcvaW52b2tlL0NvbnN0YW50Q2FsbFNpdGU7AB9MamF2YS9sYW5n"
+ "L2ludm9rZS9NZXRob2RIYW5kbGU7ACdMamF2YS9sYW5nL2ludm9rZS9NZXRob2RIYW5kbGVzJExv"
+ "b2t1cDsAIExqYXZhL2xhbmcvaW52b2tlL01ldGhvZEhhbmRsZXM7AB1MamF2YS9sYW5nL2ludm9r"
+ "ZS9NZXRob2RUeXBlOwAYTGp1bml0L2ZyYW1ld29yay9Bc3NlcnQ7ABBMb3JnL2p1bml0L1Rlc3Q7"
+ "AApUZXN0cy5qYXZhAAFWAAJWSQADVklJAAJWTAATW0xqYXZhL2xhbmcvU3RyaW5nOwADYWRkAA1h"
+ "cmd1bWVudFR5cGVzAAxhc3NlcnRFcXVhbHMAFWVtaXR0ZXI6IGphY2stNC4wLWVuZwANZW5jbG9z"
+ "aW5nVHlwZQANZmllbGRDYWxsU2l0ZQAKZmluZFN0YXRpYwASaW52b2tlTWV0aG9kSGFuZGxlAARr"
+ "aW5kAAxsaW5rZXJNZXRob2QABmxvb2t1cAAEbWFpbgAEbmFtZQADb3V0AAdwcmludGxuAApyZXR1"
+ "cm5UeXBlAAR0ZXN0AAV2YWx1ZQAiAAcOAC8GAAAAAAAABw4ANQMAAAAHDqUAPwEABw7wADsABw7w"
+ "AAABBCAcBhgAGAAYABgAGAAYACYcAR0CBCAcAxgPGAkYESMYBCcbACsXKCsXHy4YAAIFATAcARgL"
+ "ARMAAxYAFx8VAAEABAEBCQCBgAS0BQEKzAUBCuwFAQmcBgQBzAYAAAATAAAAAAAAAAEAAAAAAAAA"
+ "AQAAADEAAABwAAAAAgAAABYAAAA0AQAAAwAAAAkAAACMAQAABAAAAAMAAAD4AQAABQAAAAsAAAAQ"
+ "AgAABwAAAAIAAABoAgAABgAAAAEAAABwAgAACAAAAAEAAACQAgAAAxAAAAMAAACYAgAAASAAAAUA"
+ "AAC0AgAABiAAAAEAAAB8AwAAARAAAAcAAACkAwAAAiAAADEAAADqAwAAAyAAAAUAAABtBwAABCAA"
+ "AAMAAACTBwAABSAAAAEAAADOBwAAACAAAAEAAADVBwAAABAAAAEAAAD0BwAA",
+ // https://cs.corp.google.com/android/toolchain/jack/jack-tests/tests/com/android/jack/java7/invokecustom/test004/Tests.java
+ "ZGV4CjAzOABvUVfbV74qWbSOEsgKP+EzahlNQLW2/8TMDAAAcAAAAHhWNBIAAAAAAAAAAOQLAABS"
+ "AAAAcAAAAB8AAAC4AQAAEAAAADQCAAADAAAA9AIAABIAAAAMAwAAAQAAAKQDAAAACQAAzAMAANYF"
+ "AADZBQAA4QUAAOkFAADsBQAA7wUAAPIFAAD1BQAA/AUAAP8FAAAEBgAAEwYAABYGAAAZBgAAHwYA"
+ "AC8GAABkBgAAjQYAAMAGAADxBgAAJgcAAEUHAABhBwAAeAcAAIoHAACdBwAAsQcAAMUHAADZBwAA"
+ "8AcAAA0IAAAyCAAAUwgAAHwIAACeCAAAvQgAANcIAADpCAAA7AgAAPgIAAD7CAAAAAkAAAYJAAAM"
+ "CQAAEAkAABUJAAAaCQAAHgkAACMJAAAnCQAAKgkAADMJAABICQAATQkAAFwJAABqCQAAdgkAAIQJ"
+ "AACPCQAAmgkAAKYJAACzCQAAygkAANkJAADoCQAA9AkAAAAKAAAKCgAAHgoAACQKAAAyCgAAPQoA"
+ "AEUKAABLCgAAYgoAAGgKAABtCgAAdgoAAIIKAACOCgAAmwoAAKEKAAADAAAABAAAAAUAAAAGAAAA"
+ "CAAAAAsAAAAPAAAAEAAAABEAAAASAAAAEwAAABQAAAAVAAAAFgAAABgAAAAZAAAAGgAAABsAAAAc"
+ "AAAAHQAAAB4AAAAfAAAAIAAAACEAAAAiAAAAIwAAACQAAAAlAAAAJwAAADEAAAAzAAAACQAAAAQA"
+ "AABMBQAADgAAABMAAABUBQAADQAAABUAAAB0BQAADAAAABYAAAAAAAAAJwAAABwAAAAAAAAAKAAA"
+ "ABwAAACABQAAKQAAABwAAACIBQAAKgAAABwAAACUBQAAKwAAABwAAACgBQAALAAAABwAAABMBQAA"
+ "LQAAABwAAACoBQAALwAAABwAAACwBQAALwAAABwAAAC4BQAALgAAABwAAADABQAAMAAAABwAAADI"
+ "BQAALgAAABwAAADQBQAACQAJAAoAAAAKABMAPwAAABEADQBLAAAACgAEAAIAAAAKAAAANAAAAAoA"
+ "AQBFAAAACgAPAEgAAAAKAAQAUAAAAA0ACABMAAAADwAEAAIAAAAUAA0AAgAAABYAAgBAAAAAFwAD"
+ "AEcAAAAZAAUANgAAABkABgA2AAAAGQAHADYAAAAZAAkANgAAABkACgA2AAAAGQALADYAAAAZAAwA"
+ "NgAAABkADgA3AAAAnQsAAJ0LAAAKAAAAAQAAAA8AAAAAAAAAJgAAACQFAADGCwAAAAAAAAQAAAAC"
+ "AAAAAQAAAN4KAAACAAAAegsAAJILAAACAAAAkgsAAJoLAAABAAEAAQAAAKgKAAAEAAAAcBAGAAAA"
+ "DgADAAIAAAAAAK0KAAADAAAAkAABAg8AAAAYAA8ABgAAALQKAABTAAAAcRARAAwAEhJxIA0A0gAT"
+ "AmEAcSAKAOIAEwIABHEgDQDyABISAgAQAHEgDQACABICFAOamTFBAgARAHEwDAADAhYGAAAYApqZ"
+ "mZmZmQFABQQSAHcGCwACABsCBwAAAAgAFABxIBAAAgAcAgoACAAVAHEgDwACABcCFc1bBwUAFgBx"
+ "QA4AMhBxAAkAAAAMAhwDCgBuQAgAMroMAiIDFABwIAcAIwARAwAABAABAAIAAADRCgAADAAAAGIA"
+ "AgASIRIy/CAAACEACgFuIAUAEAAOAAMAAQACAAAA2AoAAAsAAAASIBIx/CABABAACgASUXEgDQAB"
+ "AA4AAAAAAAAAAAAAAAMAAAAAAAAAAQAAAMwDAAACAAAA1AMAAAQAAADgAwAAAgAAAAQABAANAAAA"
+ "FgAQABgAHQAAAAEAGwAEAAMAAgAQAA4ABQAAAAMAAAAOABAAGAAAAAIAAAABAAEAAwAAAAIAAgAC"
+ "AAAAAwAAAAMAAwADAAAAAQAAAAQAAAACAAAABQAFAAIAAAAPAA8AAgAAABAAEAABAAAAFQAAAAEA"
+ "AAAdAAAAAQAAAB4AASgABjwqPjtKKQAGPGluaXQ+AAFCAAFDAAFEAAFGAAVIZWxsbwABSQADSUlJ"
+ "AA1JTlZPS0VfU1RBVElDAAFKAAFMAARMTExMAA5MTExMWkJDU0lGRExMSgAzTGNvbS9hbmRyb2lk"
+ "L2phY2svYW5ub3RhdGlvbnMvQ2FsbGVkQnlJbnZva2VDdXN0b207ACdMY29tL2FuZHJvaWQvamFj"
+ "ay9hbm5vdGF0aW9ucy9Db25zdGFudDsAMUxjb20vYW5kcm9pZC9qYWNrL2Fubm90YXRpb25zL0xp"
+ "bmtlck1ldGhvZEhhbmRsZTsAL0xjb20vYW5kcm9pZC9qYWNrL2Fubm90YXRpb25zL01ldGhvZEhh"
+ "bmRsZUtpbmQ7ADNMY29tL2FuZHJvaWQvamFjay9qYXZhNy9pbnZva2VjdXN0b20vdGVzdDAwNC9U"
+ "ZXN0czsAHUxkYWx2aWsvYW5ub3RhdGlvbi9TaWduYXR1cmU7ABpMZGFsdmlrL2Fubm90YXRpb24v"
+ "VGhyb3dzOwAVTGphdmEvaW8vUHJpbnRTdHJlYW07ABBMamF2YS9sYW5nL0NsYXNzABFMamF2YS9s"
+ "YW5nL0NsYXNzOwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAEkxqYXZh"
+ "L2xhbmcvU3lzdGVtOwAVTGphdmEvbGFuZy9UaHJvd2FibGU7ABtMamF2YS9sYW5nL2ludm9rZS9D"
+ "YWxsU2l0ZTsAI0xqYXZhL2xhbmcvaW52b2tlL0NvbnN0YW50Q2FsbFNpdGU7AB9MamF2YS9sYW5n"
+ "L2ludm9rZS9NZXRob2RIYW5kbGU7ACdMamF2YS9sYW5nL2ludm9rZS9NZXRob2RIYW5kbGVzJExv"
+ "b2t1cDsAIExqYXZhL2xhbmcvaW52b2tlL01ldGhvZEhhbmRsZXM7AB1MamF2YS9sYW5nL2ludm9r"
+ "ZS9NZXRob2RUeXBlOwAYTGp1bml0L2ZyYW1ld29yay9Bc3NlcnQ7ABBMb3JnL2p1bml0L1Rlc3Q7"
+ "AAFTAApUZXN0cy5qYXZhAAFWAANWQ0MABFZEREQABFZGRkYAAlZJAANWSUkAA1ZKSgACVkwAA1ZM"
+ "TAACVloAAVoAB1pCQ1NJRkQAE1tMamF2YS9sYW5nL1N0cmluZzsAA2FkZAANYXJndW1lbnRUeXBl"
+ "cwAMYXNzZXJ0RXF1YWxzAAphc3NlcnRUcnVlAAxib29sZWFuVmFsdWUACWJ5dGVWYWx1ZQAJY2hh"
+ "clZhbHVlAApjbGFzc1ZhbHVlAAtkb3VibGVWYWx1ZQAVZW1pdHRlcjogamFjay00LjAtZW5nAA1l"
+ "bmNsb3NpbmdUeXBlAA1maWVsZENhbGxTaXRlAApmaW5kU3RhdGljAApmbG9hdFZhbHVlAAhpbnRW"
+ "YWx1ZQASaW52b2tlTWV0aG9kSGFuZGxlAARraW5kAAxsaW5rZXJNZXRob2QACWxvbmdWYWx1ZQAG"
+ "bG9va3VwAARtYWluABVtZXRob2RIYW5kbGVFeHRyYUFyZ3MABG5hbWUAA291dAAHcHJpbnRsbgAK"
+ "cmV0dXJuVHlwZQAKc2hvcnRWYWx1ZQALc3RyaW5nVmFsdWUABHRlc3QABXZhbHVlACMABw4ANwIA"
+ "AAcOAD4NAAAAAAAAAAAAAAAAAAcOPEtaWmmWw4d4h6UAUgEABw60AE4ABw6lAAAGBTUcAhgEGARD"
+ "HAEdCAQ1HA0YFhgQGBgYHRgAGAEYGxgEGAMYAhgQGA4YBT4YCkQbAEoXRUkcCh0HATgcAT8dBwE5"
+ "HAEAAR0HATocAQNhHQcBThwBIgAEHQcBQhwBBAEdBwFBHAFwmpkxQR0HATwcAfGamZmZmZkBQB0H"
+ "AU8cARcHHQcBOxwBGAodBwFGHAFmFc1bB0oXNE0YBAILAVEcCRcAFyAXGhciFzIXGhcXFwEXHQIM"
+ "AVEcARgSARoADRYAFzQVAAQBBAEEYSQABAQBcJqZMUHxmpmZmZmZAUAXBxgKZhXNWwcBAAQBAQkA"
+ "gYAE7AcBCoQIAQqcCAEJ1AkEAfwJAAATAAAAAAAAAAEAAAAAAAAAAQAAAFIAAABwAAAAAgAAAB8A"
+ "AAC4AQAAAwAAABAAAAA0AgAABAAAAAMAAAD0AgAABQAAABIAAAAMAwAABwAAAAIAAACcAwAABgAA"
+ "AAEAAACkAwAACAAAAAEAAADEAwAAAxAAAAMAAADMAwAAASAAAAUAAADsAwAABiAAAAEAAAAkBQAA"
+ "ARAAAA0AAABMBQAAAiAAAFIAAADWBQAAAyAAAAUAAACoCgAABCAAAAQAAADeCgAABSAAAAEAAACd"
+ "CwAAACAAAAEAAADGCwAAABAAAAEAAADkCwAA"
+};
+
+TEST_F(DexFileVerifierTest, InvokeCustomDexSamples) {
+ for (size_t i = 0; i < arraysize(kInvokeCustomDexFiles); ++i) {
+ size_t length;
+ std::unique_ptr<uint8_t[]> dex_bytes(DecodeBase64(kInvokeCustomDexFiles[i], &length));
+ CHECK(dex_bytes != nullptr);
+ // Note: `dex_file` will be destroyed before `dex_bytes`.
+ std::unique_ptr<DexFile> dex_file(GetDexFile(dex_bytes.get(), length));
+ std::string error_msg;
+ EXPECT_TRUE(DexFileVerifier::Verify(dex_file.get(),
+ dex_file->Begin(),
+ dex_file->Size(),
+ "good checksum, verify",
+ /*verify_checksum*/ true,
+ &error_msg));
+ // TODO(oth): Test corruptions (b/35308502)
+ }
+}
+
} // namespace art