1/* 2 * Copyright (C) 2011 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#ifndef ART_RUNTIME_DEX_FILE_VERIFIER_H_ 18#define ART_RUNTIME_DEX_FILE_VERIFIER_H_ 19 20#include <unordered_set> 21 22#include "dex_file.h" 23#include "dex_file_types.h" 24#include "safe_map.h" 25 26namespace art { 27 28class DexFileVerifier { 29 public: 30 static bool Verify(const DexFile* dex_file, 31 const uint8_t* begin, 32 size_t size, 33 const char* location, 34 bool verify_checksum, 35 std::string* error_msg); 36 37 const std::string& FailureReason() const { 38 return failure_reason_; 39 } 40 41 private: 42 DexFileVerifier(const DexFile* dex_file, 43 const uint8_t* begin, 44 size_t size, 45 const char* location, 46 bool verify_checksum) 47 : dex_file_(dex_file), 48 begin_(begin), 49 size_(size), 50 location_(location), 51 verify_checksum_(verify_checksum), 52 header_(&dex_file->GetHeader()), 53 ptr_(nullptr), 54 previous_item_(nullptr) { 55 } 56 57 bool Verify(); 58 59 bool CheckShortyDescriptorMatch(char shorty_char, const char* descriptor, bool is_return_type); 60 bool CheckListSize(const void* start, size_t count, size_t element_size, const char* label); 61 // Check a list. The head is assumed to be at *ptr, and elements to be of size element_size. If 62 // successful, the ptr will be moved forward the amount covered by the list. 63 bool CheckList(size_t element_size, const char* label, const uint8_t* *ptr); 64 // Checks whether the offset is zero (when size is zero) or that the offset falls within the area 65 // claimed by the file. 66 bool CheckValidOffsetAndSize(uint32_t offset, uint32_t size, size_t alignment, const char* label); 67 // Checks whether the size is less than the limit. 68 bool CheckSizeLimit(uint32_t size, uint32_t limit, const char* label); 69 bool CheckIndex(uint32_t field, uint32_t limit, const char* label); 70 71 bool CheckHeader(); 72 bool CheckMap(); 73 74 uint32_t ReadUnsignedLittleEndian(uint32_t size); 75 bool CheckAndGetHandlerOffsets(const DexFile::CodeItem* code_item, 76 uint32_t* handler_offsets, uint32_t handlers_size); 77 bool CheckClassDataItemField(uint32_t idx, 78 uint32_t access_flags, 79 uint32_t class_access_flags, 80 dex::TypeIndex class_type_index, 81 bool expect_static); 82 bool CheckClassDataItemMethod(uint32_t idx, 83 uint32_t access_flags, 84 uint32_t class_access_flags, 85 dex::TypeIndex class_type_index, 86 uint32_t code_offset, 87 std::unordered_set<uint32_t>* direct_method_indexes, 88 bool expect_direct); 89 bool CheckOrderAndGetClassDef(bool is_field, 90 const char* type_descr, 91 uint32_t curr_index, 92 uint32_t prev_index, 93 bool* have_class, 94 dex::TypeIndex* class_type_index, 95 const DexFile::ClassDef** class_def); 96 bool CheckStaticFieldTypes(const DexFile::ClassDef* class_def); 97 98 bool CheckPadding(size_t offset, uint32_t aligned_offset); 99 bool CheckEncodedValue(); 100 bool CheckEncodedArray(); 101 bool CheckEncodedAnnotation(); 102 103 bool CheckIntraClassDataItem(); 104 // Check all fields of the given type from the given iterator. Load the class data from the first 105 // field, if necessary (and return it), or use the given values. 106 template <bool kStatic> 107 bool CheckIntraClassDataItemFields(ClassDataItemIterator* it, 108 bool* have_class, 109 dex::TypeIndex* class_type_index, 110 const DexFile::ClassDef** class_def); 111 // Check all methods of the given type from the given iterator. Load the class data from the first 112 // method, if necessary (and return it), or use the given values. 113 template <bool kDirect> 114 bool CheckIntraClassDataItemMethods(ClassDataItemIterator* it, 115 std::unordered_set<uint32_t>* direct_method_indexes, 116 bool* have_class, 117 dex::TypeIndex* class_type_index, 118 const DexFile::ClassDef** class_def); 119 120 bool CheckIntraCodeItem(); 121 bool CheckIntraStringDataItem(); 122 bool CheckIntraDebugInfoItem(); 123 bool CheckIntraAnnotationItem(); 124 bool CheckIntraAnnotationsDirectoryItem(); 125 126 bool CheckIntraSectionIterate(size_t offset, uint32_t count, DexFile::MapItemType type); 127 bool CheckIntraIdSection(size_t offset, uint32_t count, DexFile::MapItemType type); 128 bool CheckIntraDataSection(size_t offset, uint32_t count, DexFile::MapItemType type); 129 bool CheckIntraSection(); 130 131 bool CheckOffsetToTypeMap(size_t offset, uint16_t type); 132 133 // Note: as sometimes kDexNoIndex16, being 0xFFFF, is a valid return value, we need an 134 // additional out parameter to signal any errors loading an index. 135 dex::TypeIndex FindFirstClassDataDefiner(const uint8_t* ptr, bool* success); 136 dex::TypeIndex FindFirstAnnotationsDirectoryDefiner(const uint8_t* ptr, bool* success); 137 138 bool CheckInterStringIdItem(); 139 bool CheckInterTypeIdItem(); 140 bool CheckInterProtoIdItem(); 141 bool CheckInterFieldIdItem(); 142 bool CheckInterMethodIdItem(); 143 bool CheckInterClassDefItem(); 144 bool CheckInterCallSiteIdItem(); 145 bool CheckInterMethodHandleItem(); 146 bool CheckInterAnnotationSetRefList(); 147 bool CheckInterAnnotationSetItem(); 148 bool CheckInterClassDataItem(); 149 bool CheckInterAnnotationsDirectoryItem(); 150 151 bool CheckInterSectionIterate(size_t offset, uint32_t count, DexFile::MapItemType type); 152 bool CheckInterSection(); 153 154 // Load a string by (type) index. Checks whether the index is in bounds, printing the error if 155 // not. If there is an error, null is returned. 156 const char* CheckLoadStringByIdx(dex::StringIndex idx, const char* error_fmt); 157 const char* CheckLoadStringByTypeIdx(dex::TypeIndex type_idx, const char* error_fmt); 158 159 // Load a field/method/proto Id by index. Checks whether the index is in bounds, printing the 160 // error if not. If there is an error, null is returned. 161 const DexFile::FieldId* CheckLoadFieldId(uint32_t idx, const char* error_fmt); 162 const DexFile::MethodId* CheckLoadMethodId(uint32_t idx, const char* error_fmt); 163 const DexFile::ProtoId* CheckLoadProtoId(uint32_t idx, const char* error_fmt); 164 165 void ErrorStringPrintf(const char* fmt, ...) 166 __attribute__((__format__(__printf__, 2, 3))) COLD_ATTR; 167 bool FailureReasonIsSet() const { return failure_reason_.size() != 0; } 168 169 // Retrieve class index and class def from the given member. index is the member index, which is 170 // taken as either a field or a method index (as designated by is_field). The result, if the 171 // member and declaring class could be found, is stored in class_type_index and class_def. 172 // This is an expensive lookup, as we have to find the class def by type index, which is a 173 // linear search. The output values should thus be cached by the caller. 174 bool FindClassIndexAndDef(uint32_t index, 175 bool is_field, 176 dex::TypeIndex* class_type_index, 177 const DexFile::ClassDef** output_class_def); 178 179 // Check validity of the given access flags, interpreted for a field in the context of a class 180 // with the given second access flags. 181 bool CheckFieldAccessFlags(uint32_t idx, 182 uint32_t field_access_flags, 183 uint32_t class_access_flags, 184 std::string* error_message); 185 186 // Check validity of the given method and access flags, in the context of a class with the given 187 // second access flags. 188 bool CheckMethodAccessFlags(uint32_t method_index, 189 uint32_t method_access_flags, 190 uint32_t class_access_flags, 191 uint32_t constructor_flags_by_name, 192 bool has_code, 193 bool expect_direct, 194 std::string* error_message); 195 196 // Check validity of given method if it's a constructor or class initializer. 197 bool CheckConstructorProperties(uint32_t method_index, uint32_t constructor_flags); 198 199 const DexFile* const dex_file_; 200 const uint8_t* const begin_; 201 const size_t size_; 202 const char* const location_; 203 const bool verify_checksum_; 204 const DexFile::Header* const header_; 205 206 struct OffsetTypeMapEmptyFn { 207 // Make a hash map slot empty by making the offset 0. Offset 0 is a valid dex file offset that 208 // is in the offset of the dex file header. However, we only store data section items in the 209 // map, and these are after the header. 210 void MakeEmpty(std::pair<uint32_t, uint16_t>& pair) const { 211 pair.first = 0u; 212 } 213 // Check if a hash map slot is empty. 214 bool IsEmpty(const std::pair<uint32_t, uint16_t>& pair) const { 215 return pair.first == 0; 216 } 217 }; 218 struct OffsetTypeMapHashCompareFn { 219 // Hash function for offset. 220 size_t operator()(const uint32_t key) const { 221 return key; 222 } 223 // std::equal function for offset. 224 bool operator()(const uint32_t a, const uint32_t b) const { 225 return a == b; 226 } 227 }; 228 // Map from offset to dex file type, HashMap for performance reasons. 229 AllocationTrackingHashMap<uint32_t, 230 uint16_t, 231 OffsetTypeMapEmptyFn, 232 kAllocatorTagDexFileVerifier, 233 OffsetTypeMapHashCompareFn, 234 OffsetTypeMapHashCompareFn> offset_to_type_map_; 235 const uint8_t* ptr_; 236 const void* previous_item_; 237 238 std::string failure_reason_; 239 240 // Set of type ids for which there are ClassDef elements in the dex file. 241 std::unordered_set<decltype(DexFile::ClassDef::class_idx_)> defined_classes_; 242}; 243 244} // namespace art 245 246#endif // ART_RUNTIME_DEX_FILE_VERIFIER_H_ 247