blob: 23089fa215f03a907bd3cda68261726ca9d6c25a [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
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 */
jeffhao10037c82012-01-23 15:06:23 -080016
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_DEX_FILE_VERIFIER_H_
18#define ART_RUNTIME_DEX_FILE_VERIFIER_H_
jeffhao10037c82012-01-23 15:06:23 -080019
Andreas Gampe0ba238d2014-07-29 01:22:07 -070020#include <unordered_set>
21
Andreas Gampe3b7dc352017-06-06 20:02:03 -070022#include "base/allocator.h"
23#include "base/hash_map.h"
jeffhao10037c82012-01-23 15:06:23 -080024#include "dex_file.h"
Andreas Gampea5b09a62016-11-17 15:21:22 -080025#include "dex_file_types.h"
Elliott Hughesa0e18062012-04-13 15:59:59 -070026#include "safe_map.h"
jeffhao10037c82012-01-23 15:06:23 -080027
28namespace art {
29
30class DexFileVerifier {
31 public:
Aart Bik37d6a3b2016-06-21 18:30:10 -070032 static bool Verify(const DexFile* dex_file,
33 const uint8_t* begin,
34 size_t size,
35 const char* location,
36 bool verify_checksum,
37 std::string* error_msg);
Ian Rogers8d31bbd2013-10-13 10:44:14 -070038
39 const std::string& FailureReason() const {
40 return failure_reason_;
41 }
jeffhao10037c82012-01-23 15:06:23 -080042
43 private:
Aart Bik37d6a3b2016-06-21 18:30:10 -070044 DexFileVerifier(const DexFile* dex_file,
45 const uint8_t* begin,
46 size_t size,
47 const char* location,
48 bool verify_checksum)
49 : dex_file_(dex_file),
50 begin_(begin),
51 size_(size),
52 location_(location),
53 verify_checksum_(verify_checksum),
54 header_(&dex_file->GetHeader()),
55 ptr_(nullptr),
56 previous_item_(nullptr) {
jeffhao10037c82012-01-23 15:06:23 -080057 }
58
59 bool Verify();
60
Ian Rogers8d31bbd2013-10-13 10:44:14 -070061 bool CheckShortyDescriptorMatch(char shorty_char, const char* descriptor, bool is_return_type);
Andreas Gampe50d1bc12014-07-17 21:49:24 -070062 bool CheckListSize(const void* start, size_t count, size_t element_size, const char* label);
Andreas Gamped4ae41f2014-09-02 11:17:34 -070063 // Check a list. The head is assumed to be at *ptr, and elements to be of size element_size. If
64 // successful, the ptr will be moved forward the amount covered by the list.
Ian Rogers13735952014-10-08 12:43:28 -070065 bool CheckList(size_t element_size, const char* label, const uint8_t* *ptr);
Andreas Gamped4ae41f2014-09-02 11:17:34 -070066 // Checks whether the offset is zero (when size is zero) or that the offset falls within the area
67 // claimed by the file.
Andreas Gampeb512c0e2016-02-19 19:45:34 -080068 bool CheckValidOffsetAndSize(uint32_t offset, uint32_t size, size_t alignment, const char* label);
Vladimir Marko0ca8add2016-05-03 17:17:50 +010069 // Checks whether the size is less than the limit.
70 bool CheckSizeLimit(uint32_t size, uint32_t limit, const char* label);
Ian Rogers8d31bbd2013-10-13 10:44:14 -070071 bool CheckIndex(uint32_t field, uint32_t limit, const char* label);
jeffhao10037c82012-01-23 15:06:23 -080072
Ian Rogers8d31bbd2013-10-13 10:44:14 -070073 bool CheckHeader();
74 bool CheckMap();
jeffhao10037c82012-01-23 15:06:23 -080075
76 uint32_t ReadUnsignedLittleEndian(uint32_t size);
77 bool CheckAndGetHandlerOffsets(const DexFile::CodeItem* code_item,
Ian Rogers8d31bbd2013-10-13 10:44:14 -070078 uint32_t* handler_offsets, uint32_t handlers_size);
Andreas Gampee6215c02015-08-31 18:54:38 -070079 bool CheckClassDataItemField(uint32_t idx,
80 uint32_t access_flags,
81 uint32_t class_access_flags,
Andreas Gampea5b09a62016-11-17 15:21:22 -080082 dex::TypeIndex class_type_index,
Andreas Gampee6215c02015-08-31 18:54:38 -070083 bool expect_static);
84 bool CheckClassDataItemMethod(uint32_t idx,
85 uint32_t access_flags,
86 uint32_t class_access_flags,
Andreas Gampea5b09a62016-11-17 15:21:22 -080087 dex::TypeIndex class_type_index,
Andreas Gampee6215c02015-08-31 18:54:38 -070088 uint32_t code_offset,
89 std::unordered_set<uint32_t>* direct_method_indexes,
Ian Rogers8d31bbd2013-10-13 10:44:14 -070090 bool expect_direct);
Jeff Hao326c1a22017-05-04 14:12:56 -070091 bool CheckOrderAndGetClassDef(bool is_field,
92 const char* type_descr,
93 uint32_t curr_index,
94 uint32_t prev_index,
95 bool* have_class,
96 dex::TypeIndex* class_type_index,
97 const DexFile::ClassDef** class_def);
98 bool CheckStaticFieldTypes(const DexFile::ClassDef* class_def);
Andreas Gampee6215c02015-08-31 18:54:38 -070099
Mathieu Chartier24066ec2017-10-21 16:01:08 -0700100 bool CheckPadding(size_t offset, uint32_t aligned_offset, DexFile::MapItemType type);
jeffhao10037c82012-01-23 15:06:23 -0800101 bool CheckEncodedValue();
102 bool CheckEncodedArray();
103 bool CheckEncodedAnnotation();
104
105 bool CheckIntraClassDataItem();
Andreas Gampee6215c02015-08-31 18:54:38 -0700106 // 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(ClassDataItemIterator* it,
110 bool* have_class,
Andreas Gampea5b09a62016-11-17 15:21:22 -0800111 dex::TypeIndex* class_type_index,
Jeff Hao326c1a22017-05-04 14:12:56 -0700112 const DexFile::ClassDef** class_def);
Andreas Gampee6215c02015-08-31 18:54:38 -0700113 // Check all methods of the given type from the given iterator. Load the class data from the first
114 // method, if necessary (and return it), or use the given values.
115 template <bool kDirect>
116 bool CheckIntraClassDataItemMethods(ClassDataItemIterator* it,
117 std::unordered_set<uint32_t>* direct_method_indexes,
118 bool* have_class,
Andreas Gampea5b09a62016-11-17 15:21:22 -0800119 dex::TypeIndex* class_type_index,
Jeff Hao326c1a22017-05-04 14:12:56 -0700120 const DexFile::ClassDef** class_def);
Andreas Gampee6215c02015-08-31 18:54:38 -0700121
jeffhao10037c82012-01-23 15:06:23 -0800122 bool CheckIntraCodeItem();
123 bool CheckIntraStringDataItem();
124 bool CheckIntraDebugInfoItem();
125 bool CheckIntraAnnotationItem();
126 bool CheckIntraAnnotationsDirectoryItem();
127
Orion Hodson12f4ff42017-01-13 16:43:12 +0000128 bool CheckIntraSectionIterate(size_t offset, uint32_t count, DexFile::MapItemType type);
129 bool CheckIntraIdSection(size_t offset, uint32_t count, DexFile::MapItemType type);
130 bool CheckIntraDataSection(size_t offset, uint32_t count, DexFile::MapItemType type);
jeffhao10037c82012-01-23 15:06:23 -0800131 bool CheckIntraSection();
132
Ian Rogers8a6bbfc2014-01-23 13:29:07 -0800133 bool CheckOffsetToTypeMap(size_t offset, uint16_t type);
Andreas Gampee09269c2014-06-06 18:45:35 -0700134
Andreas Gampe5e31dda2014-06-13 11:35:12 -0700135 // Note: as sometimes kDexNoIndex16, being 0xFFFF, is a valid return value, we need an
136 // additional out parameter to signal any errors loading an index.
Andreas Gampea5b09a62016-11-17 15:21:22 -0800137 dex::TypeIndex FindFirstClassDataDefiner(const uint8_t* ptr, bool* success);
138 dex::TypeIndex FindFirstAnnotationsDirectoryDefiner(const uint8_t* ptr, bool* success);
jeffhao10037c82012-01-23 15:06:23 -0800139
140 bool CheckInterStringIdItem();
141 bool CheckInterTypeIdItem();
142 bool CheckInterProtoIdItem();
143 bool CheckInterFieldIdItem();
144 bool CheckInterMethodIdItem();
145 bool CheckInterClassDefItem();
Orion Hodson12f4ff42017-01-13 16:43:12 +0000146 bool CheckInterCallSiteIdItem();
147 bool CheckInterMethodHandleItem();
jeffhao10037c82012-01-23 15:06:23 -0800148 bool CheckInterAnnotationSetRefList();
149 bool CheckInterAnnotationSetItem();
150 bool CheckInterClassDataItem();
151 bool CheckInterAnnotationsDirectoryItem();
152
Orion Hodson12f4ff42017-01-13 16:43:12 +0000153 bool CheckInterSectionIterate(size_t offset, uint32_t count, DexFile::MapItemType type);
jeffhao10037c82012-01-23 15:06:23 -0800154 bool CheckInterSection();
155
Andreas Gampee09269c2014-06-06 18:45:35 -0700156 // Load a string by (type) index. Checks whether the index is in bounds, printing the error if
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700157 // not. If there is an error, null is returned.
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800158 const char* CheckLoadStringByIdx(dex::StringIndex idx, const char* error_fmt);
Andreas Gampea5b09a62016-11-17 15:21:22 -0800159 const char* CheckLoadStringByTypeIdx(dex::TypeIndex type_idx, const char* error_fmt);
Andreas Gampee09269c2014-06-06 18:45:35 -0700160
Orion Hodson6c4921b2016-09-21 15:41:06 +0100161 // Load a field/method/proto Id by index. Checks whether the index is in bounds, printing the
162 // error if not. If there is an error, null is returned.
Andreas Gampee09269c2014-06-06 18:45:35 -0700163 const DexFile::FieldId* CheckLoadFieldId(uint32_t idx, const char* error_fmt);
164 const DexFile::MethodId* CheckLoadMethodId(uint32_t idx, const char* error_fmt);
Orion Hodson6c4921b2016-09-21 15:41:06 +0100165 const DexFile::ProtoId* CheckLoadProtoId(uint32_t idx, const char* error_fmt);
Andreas Gampee09269c2014-06-06 18:45:35 -0700166
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700167 void ErrorStringPrintf(const char* fmt, ...)
168 __attribute__((__format__(__printf__, 2, 3))) COLD_ATTR;
Orion Hodson6c4921b2016-09-21 15:41:06 +0100169 bool FailureReasonIsSet() const { return failure_reason_.size() != 0; }
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700170
Jeff Hao326c1a22017-05-04 14:12:56 -0700171 // Retrieve class index and class def from the given member. index is the member index, which is
172 // taken as either a field or a method index (as designated by is_field). The result, if the
173 // member and declaring class could be found, is stored in class_type_index and class_def.
174 // This is an expensive lookup, as we have to find the class def by type index, which is a
Andreas Gampee6215c02015-08-31 18:54:38 -0700175 // linear search. The output values should thus be cached by the caller.
Jeff Hao326c1a22017-05-04 14:12:56 -0700176 bool FindClassIndexAndDef(uint32_t index,
177 bool is_field,
178 dex::TypeIndex* class_type_index,
179 const DexFile::ClassDef** output_class_def);
Andreas Gampee6215c02015-08-31 18:54:38 -0700180
181 // Check validity of the given access flags, interpreted for a field in the context of a class
182 // with the given second access flags.
Andreas Gampec9f0ba12016-02-09 09:21:04 -0800183 bool CheckFieldAccessFlags(uint32_t idx,
184 uint32_t field_access_flags,
185 uint32_t class_access_flags,
Orion Hodson6c4921b2016-09-21 15:41:06 +0100186 std::string* error_message);
187
Andreas Gampee6215c02015-08-31 18:54:38 -0700188 // Check validity of the given method and access flags, in the context of a class with the given
189 // second access flags.
190 bool CheckMethodAccessFlags(uint32_t method_index,
191 uint32_t method_access_flags,
192 uint32_t class_access_flags,
Orion Hodson6c4921b2016-09-21 15:41:06 +0100193 uint32_t constructor_flags_by_name,
Andreas Gampee6215c02015-08-31 18:54:38 -0700194 bool has_code,
195 bool expect_direct,
Orion Hodson6c4921b2016-09-21 15:41:06 +0100196 std::string* error_message);
197
198 // Check validity of given method if it's a constructor or class initializer.
199 bool CheckConstructorProperties(uint32_t method_index, uint32_t constructor_flags);
Andreas Gampee6215c02015-08-31 18:54:38 -0700200
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700201 const DexFile* const dex_file_;
Ian Rogers13735952014-10-08 12:43:28 -0700202 const uint8_t* const begin_;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700203 const size_t size_;
204 const char* const location_;
Aart Bik37d6a3b2016-06-21 18:30:10 -0700205 const bool verify_checksum_;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700206 const DexFile::Header* const header_;
jeffhao10037c82012-01-23 15:06:23 -0800207
Mathieu Chartier0f8e0722015-10-26 14:52:42 -0700208 struct OffsetTypeMapEmptyFn {
209 // Make a hash map slot empty by making the offset 0. Offset 0 is a valid dex file offset that
210 // is in the offset of the dex file header. However, we only store data section items in the
211 // map, and these are after the header.
212 void MakeEmpty(std::pair<uint32_t, uint16_t>& pair) const {
213 pair.first = 0u;
214 }
215 // Check if a hash map slot is empty.
216 bool IsEmpty(const std::pair<uint32_t, uint16_t>& pair) const {
217 return pair.first == 0;
218 }
219 };
220 struct OffsetTypeMapHashCompareFn {
221 // Hash function for offset.
222 size_t operator()(const uint32_t key) const {
223 return key;
224 }
225 // std::equal function for offset.
226 bool operator()(const uint32_t a, const uint32_t b) const {
227 return a == b;
228 }
229 };
230 // Map from offset to dex file type, HashMap for performance reasons.
Andreas Gampe3b7dc352017-06-06 20:02:03 -0700231 template<class Key,
232 class T,
233 class EmptyFn,
234 AllocatorTag kTag,
235 class Hash = std::hash<Key>,
236 class Pred = std::equal_to<Key>>
237 using AllocationTrackingHashMap = HashMap<
238 Key, T, EmptyFn, Hash, Pred, TrackingAllocator<std::pair<Key, T>, kTag>>;
239
Mathieu Chartier0f8e0722015-10-26 14:52:42 -0700240 AllocationTrackingHashMap<uint32_t,
241 uint16_t,
242 OffsetTypeMapEmptyFn,
243 kAllocatorTagDexFileVerifier,
244 OffsetTypeMapHashCompareFn,
245 OffsetTypeMapHashCompareFn> offset_to_type_map_;
Ian Rogers13735952014-10-08 12:43:28 -0700246 const uint8_t* ptr_;
jeffhao10037c82012-01-23 15:06:23 -0800247 const void* previous_item_;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700248
249 std::string failure_reason_;
Andreas Gampe0ba238d2014-07-29 01:22:07 -0700250
251 // Set of type ids for which there are ClassDef elements in the dex file.
252 std::unordered_set<decltype(DexFile::ClassDef::class_idx_)> defined_classes_;
jeffhao10037c82012-01-23 15:06:23 -0800253};
254
255} // namespace art
256
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700257#endif // ART_RUNTIME_DEX_FILE_VERIFIER_H_