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