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