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