1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2011 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include "dex_file_verifier.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include <algorithm>
20*795d594fSAndroid Build Coastguard Worker #include <bitset>
21*795d594fSAndroid Build Coastguard Worker #include <limits>
22*795d594fSAndroid Build Coastguard Worker #include <memory>
23*795d594fSAndroid Build Coastguard Worker #include <stack>
24*795d594fSAndroid Build Coastguard Worker
25*795d594fSAndroid Build Coastguard Worker #include "android-base/logging.h"
26*795d594fSAndroid Build Coastguard Worker #include "android-base/macros.h"
27*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/hash_map.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/leb128.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/safe_map.h"
31*795d594fSAndroid Build Coastguard Worker #include "class_accessor-inl.h"
32*795d594fSAndroid Build Coastguard Worker #include "code_item_accessors-inl.h"
33*795d594fSAndroid Build Coastguard Worker #include "descriptors_names.h"
34*795d594fSAndroid Build Coastguard Worker #include "dex_file-inl.h"
35*795d594fSAndroid Build Coastguard Worker #include "dex_file_types.h"
36*795d594fSAndroid Build Coastguard Worker #include "modifiers.h"
37*795d594fSAndroid Build Coastguard Worker #include "utf-inl.h"
38*795d594fSAndroid Build Coastguard Worker
39*795d594fSAndroid Build Coastguard Worker namespace art {
40*795d594fSAndroid Build Coastguard Worker namespace dex {
41*795d594fSAndroid Build Coastguard Worker
42*795d594fSAndroid Build Coastguard Worker using android::base::StringAppendV;
43*795d594fSAndroid Build Coastguard Worker using android::base::StringPrintf;
44*795d594fSAndroid Build Coastguard Worker
45*795d594fSAndroid Build Coastguard Worker namespace {
46*795d594fSAndroid Build Coastguard Worker
47*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kTypeIdLimit = std::numeric_limits<uint16_t>::max();
48*795d594fSAndroid Build Coastguard Worker
IsValidOrNoTypeId(uint16_t low,uint16_t high)49*795d594fSAndroid Build Coastguard Worker constexpr bool IsValidOrNoTypeId(uint16_t low, uint16_t high) {
50*795d594fSAndroid Build Coastguard Worker return (high == 0) || ((high == 0xffffU) && (low == 0xffffU));
51*795d594fSAndroid Build Coastguard Worker }
52*795d594fSAndroid Build Coastguard Worker
IsValidTypeId(uint16_t low,uint16_t high)53*795d594fSAndroid Build Coastguard Worker constexpr bool IsValidTypeId([[maybe_unused]] uint16_t low, uint16_t high) { return (high == 0); }
54*795d594fSAndroid Build Coastguard Worker
MapTypeToBitMask(DexFile::MapItemType map_item_type)55*795d594fSAndroid Build Coastguard Worker constexpr uint32_t MapTypeToBitMask(DexFile::MapItemType map_item_type) {
56*795d594fSAndroid Build Coastguard Worker switch (map_item_type) {
57*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeHeaderItem: return 1 << 0;
58*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeStringIdItem: return 1 << 1;
59*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeTypeIdItem: return 1 << 2;
60*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeProtoIdItem: return 1 << 3;
61*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeFieldIdItem: return 1 << 4;
62*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMethodIdItem: return 1 << 5;
63*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeClassDefItem: return 1 << 6;
64*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeCallSiteIdItem: return 1 << 7;
65*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMethodHandleItem: return 1 << 8;
66*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMapList: return 1 << 9;
67*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeTypeList: return 1 << 10;
68*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationSetRefList: return 1 << 11;
69*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationSetItem: return 1 << 12;
70*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeClassDataItem: return 1 << 13;
71*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeCodeItem: return 1 << 14;
72*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeStringDataItem: return 1 << 15;
73*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeDebugInfoItem: return 1 << 16;
74*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationItem: return 1 << 17;
75*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeEncodedArrayItem: return 1 << 18;
76*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationsDirectoryItem: return 1 << 19;
77*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeHiddenapiClassData: return 1 << 20;
78*795d594fSAndroid Build Coastguard Worker }
79*795d594fSAndroid Build Coastguard Worker return 0;
80*795d594fSAndroid Build Coastguard Worker }
81*795d594fSAndroid Build Coastguard Worker
IsDataSectionType(DexFile::MapItemType map_item_type)82*795d594fSAndroid Build Coastguard Worker constexpr bool IsDataSectionType(DexFile::MapItemType map_item_type) {
83*795d594fSAndroid Build Coastguard Worker switch (map_item_type) {
84*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeHeaderItem:
85*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeStringIdItem:
86*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeTypeIdItem:
87*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeProtoIdItem:
88*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeFieldIdItem:
89*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMethodIdItem:
90*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeClassDefItem:
91*795d594fSAndroid Build Coastguard Worker return false;
92*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeCallSiteIdItem:
93*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMethodHandleItem:
94*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMapList:
95*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeTypeList:
96*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationSetRefList:
97*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationSetItem:
98*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeClassDataItem:
99*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeCodeItem:
100*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeStringDataItem:
101*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeDebugInfoItem:
102*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationItem:
103*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeEncodedArrayItem:
104*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationsDirectoryItem:
105*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeHiddenapiClassData:
106*795d594fSAndroid Build Coastguard Worker return true;
107*795d594fSAndroid Build Coastguard Worker }
108*795d594fSAndroid Build Coastguard Worker return true;
109*795d594fSAndroid Build Coastguard Worker }
110*795d594fSAndroid Build Coastguard Worker
111*795d594fSAndroid Build Coastguard Worker // Fields and methods may have only one of public/protected/private.
112*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE
CheckAtMostOneOfPublicProtectedPrivate(uint32_t flags)113*795d594fSAndroid Build Coastguard Worker constexpr bool CheckAtMostOneOfPublicProtectedPrivate(uint32_t flags) {
114*795d594fSAndroid Build Coastguard Worker // Semantically we want 'return POPCOUNT(flags & kAcc) <= 1;'.
115*795d594fSAndroid Build Coastguard Worker static_assert(IsPowerOfTwo(0), "0 not marked as power of two");
116*795d594fSAndroid Build Coastguard Worker static_assert(IsPowerOfTwo(kAccPublic), "kAccPublic not marked as power of two");
117*795d594fSAndroid Build Coastguard Worker static_assert(IsPowerOfTwo(kAccProtected), "kAccProtected not marked as power of two");
118*795d594fSAndroid Build Coastguard Worker static_assert(IsPowerOfTwo(kAccPrivate), "kAccPrivate not marked as power of two");
119*795d594fSAndroid Build Coastguard Worker return IsPowerOfTwo(flags & (kAccPublic | kAccProtected | kAccPrivate));
120*795d594fSAndroid Build Coastguard Worker }
121*795d594fSAndroid Build Coastguard Worker
122*795d594fSAndroid Build Coastguard Worker } // namespace
123*795d594fSAndroid Build Coastguard Worker
124*795d594fSAndroid Build Coastguard Worker // Note: the anonymous namespace would be nice, but we need friend access into accessors.
125*795d594fSAndroid Build Coastguard Worker
126*795d594fSAndroid Build Coastguard Worker class DexFileVerifier {
127*795d594fSAndroid Build Coastguard Worker public:
DexFileVerifier(const DexFile * dex_file,const char * location,bool verify_checksum)128*795d594fSAndroid Build Coastguard Worker DexFileVerifier(const DexFile* dex_file, const char* location, bool verify_checksum)
129*795d594fSAndroid Build Coastguard Worker : dex_file_(dex_file),
130*795d594fSAndroid Build Coastguard Worker offset_base_address_(dex_file->DataBegin()),
131*795d594fSAndroid Build Coastguard Worker size_(dex_file->DataSize()),
132*795d594fSAndroid Build Coastguard Worker location_(location),
133*795d594fSAndroid Build Coastguard Worker verify_checksum_(verify_checksum),
134*795d594fSAndroid Build Coastguard Worker header_(&dex_file->GetHeader()),
135*795d594fSAndroid Build Coastguard Worker ptr_(nullptr),
136*795d594fSAndroid Build Coastguard Worker previous_item_(nullptr),
137*795d594fSAndroid Build Coastguard Worker init_indices_{std::numeric_limits<size_t>::max(),
138*795d594fSAndroid Build Coastguard Worker std::numeric_limits<size_t>::max(),
139*795d594fSAndroid Build Coastguard Worker std::numeric_limits<size_t>::max(),
140*795d594fSAndroid Build Coastguard Worker std::numeric_limits<size_t>::max()} {
141*795d594fSAndroid Build Coastguard Worker CHECK(!dex_file->IsCompactDexFile()) << "Not supported";
142*795d594fSAndroid Build Coastguard Worker }
143*795d594fSAndroid Build Coastguard Worker
144*795d594fSAndroid Build Coastguard Worker bool Verify();
145*795d594fSAndroid Build Coastguard Worker
FailureReason() const146*795d594fSAndroid Build Coastguard Worker const std::string& FailureReason() const {
147*795d594fSAndroid Build Coastguard Worker return failure_reason_;
148*795d594fSAndroid Build Coastguard Worker }
149*795d594fSAndroid Build Coastguard Worker
150*795d594fSAndroid Build Coastguard Worker private:
151*795d594fSAndroid Build Coastguard Worker template <class T = uint8_t>
OffsetToPtr(size_t offset)152*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE const T* OffsetToPtr(size_t offset) {
153*795d594fSAndroid Build Coastguard Worker DCHECK_GE(offset, static_cast<size_t>(dex_file_->Begin() - offset_base_address_));
154*795d594fSAndroid Build Coastguard Worker DCHECK_LE(offset, size_);
155*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<const T*>(offset_base_address_ + offset);
156*795d594fSAndroid Build Coastguard Worker }
157*795d594fSAndroid Build Coastguard Worker
PtrToOffset(const void * ptr)158*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE size_t PtrToOffset(const void* ptr) {
159*795d594fSAndroid Build Coastguard Worker DCHECK_GE(ptr, dex_file_->Begin());
160*795d594fSAndroid Build Coastguard Worker DCHECK_LE(ptr, EndOfFile());
161*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<const uint8_t*>(ptr) - offset_base_address_;
162*795d594fSAndroid Build Coastguard Worker }
163*795d594fSAndroid Build Coastguard Worker
164*795d594fSAndroid Build Coastguard Worker // Converts the pointer `ptr` into `offset`.
165*795d594fSAndroid Build Coastguard Worker // Returns `true` if the offset is within the bounds of the container.
166*795d594fSAndroid Build Coastguard Worker // TODO: Try to remove this overload. Avoid creating invalid pointers.
PtrToOffset(const void * ptr,size_t * offset)167*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE WARN_UNUSED bool PtrToOffset(const void* ptr, /*out*/ size_t* offset) {
168*795d594fSAndroid Build Coastguard Worker *offset = reinterpret_cast<const uint8_t*>(ptr) - offset_base_address_;
169*795d594fSAndroid Build Coastguard Worker return *offset <= size_;
170*795d594fSAndroid Build Coastguard Worker }
171*795d594fSAndroid Build Coastguard Worker
EndOfFile()172*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE const uint8_t* EndOfFile() {
173*795d594fSAndroid Build Coastguard Worker return OffsetToPtr(size_);
174*795d594fSAndroid Build Coastguard Worker }
175*795d594fSAndroid Build Coastguard Worker
176*795d594fSAndroid Build Coastguard Worker // Helper functions to retrieve names from the dex file. We do not want to rely on DexFile
177*795d594fSAndroid Build Coastguard Worker // functionality, as we're still verifying the dex file.
178*795d594fSAndroid Build Coastguard Worker
GetString(dex::StringIndex string_idx)179*795d594fSAndroid Build Coastguard Worker std::string GetString(dex::StringIndex string_idx) {
180*795d594fSAndroid Build Coastguard Worker // All sources of the `string_idx` have already been checked in CheckIntraSection().
181*795d594fSAndroid Build Coastguard Worker DCHECK_LT(string_idx.index_, header_->string_ids_size_);
182*795d594fSAndroid Build Coastguard Worker const dex::StringId& string_id =
183*795d594fSAndroid Build Coastguard Worker OffsetToPtr<dex::StringId>(header_->string_ids_off_)[string_idx.index_];
184*795d594fSAndroid Build Coastguard Worker
185*795d594fSAndroid Build Coastguard Worker // The string offset has been checked at the start of `CheckInterSection()`
186*795d594fSAndroid Build Coastguard Worker // to point to a string data item checked by `CheckIntraSection()`.
187*795d594fSAndroid Build Coastguard Worker const uint8_t* ptr = OffsetToPtr(string_id.string_data_off_);
188*795d594fSAndroid Build Coastguard Worker DecodeUnsignedLeb128(&ptr); // Ignore the result.
189*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<const char*>(ptr);
190*795d594fSAndroid Build Coastguard Worker }
191*795d594fSAndroid Build Coastguard Worker
GetClass(dex::TypeIndex class_idx)192*795d594fSAndroid Build Coastguard Worker std::string GetClass(dex::TypeIndex class_idx) {
193*795d594fSAndroid Build Coastguard Worker // All sources of `class_idx` have already been checked in CheckIntraSection().
194*795d594fSAndroid Build Coastguard Worker CHECK_LT(class_idx.index_, header_->type_ids_size_);
195*795d594fSAndroid Build Coastguard Worker
196*795d594fSAndroid Build Coastguard Worker const dex::TypeId& type_id = OffsetToPtr<dex::TypeId>(header_->type_ids_off_)[class_idx.index_];
197*795d594fSAndroid Build Coastguard Worker
198*795d594fSAndroid Build Coastguard Worker // The `type_id->descriptor_idx_` has already been checked in CheckIntraTypeIdItem().
199*795d594fSAndroid Build Coastguard Worker // However, it may not have been checked to be a valid descriptor, so return the raw
200*795d594fSAndroid Build Coastguard Worker // string without converting with `PrettyDescriptor()`.
201*795d594fSAndroid Build Coastguard Worker return GetString(type_id.descriptor_idx_);
202*795d594fSAndroid Build Coastguard Worker }
203*795d594fSAndroid Build Coastguard Worker
GetFieldDescription(uint32_t idx)204*795d594fSAndroid Build Coastguard Worker std::string GetFieldDescription(uint32_t idx) {
205*795d594fSAndroid Build Coastguard Worker // The `idx` has already been checked in `DexFileVerifier::CheckIntraClassDataItemFields()`.
206*795d594fSAndroid Build Coastguard Worker CHECK_LT(idx, header_->field_ids_size_);
207*795d594fSAndroid Build Coastguard Worker
208*795d594fSAndroid Build Coastguard Worker const dex::FieldId& field_id = OffsetToPtr<dex::FieldId>(header_->field_ids_off_)[idx];
209*795d594fSAndroid Build Coastguard Worker
210*795d594fSAndroid Build Coastguard Worker // Indexes in `*field_id` have already been checked in CheckIntraFieldIdItem().
211*795d594fSAndroid Build Coastguard Worker std::string class_name = GetClass(field_id.class_idx_);
212*795d594fSAndroid Build Coastguard Worker std::string field_name = GetString(field_id.name_idx_);
213*795d594fSAndroid Build Coastguard Worker return class_name + "." + field_name;
214*795d594fSAndroid Build Coastguard Worker }
215*795d594fSAndroid Build Coastguard Worker
GetMethodDescription(uint32_t idx)216*795d594fSAndroid Build Coastguard Worker std::string GetMethodDescription(uint32_t idx) {
217*795d594fSAndroid Build Coastguard Worker // The `idx` has already been checked in `DexFileVerifier::CheckIntraClassDataItemMethods()`.
218*795d594fSAndroid Build Coastguard Worker CHECK_LT(idx, header_->method_ids_size_);
219*795d594fSAndroid Build Coastguard Worker
220*795d594fSAndroid Build Coastguard Worker const dex::MethodId& method_id = OffsetToPtr<dex::MethodId>(header_->method_ids_off_)[idx];
221*795d594fSAndroid Build Coastguard Worker
222*795d594fSAndroid Build Coastguard Worker // Indexes in `method_id` have already been checked in CheckIntraMethodIdItem().
223*795d594fSAndroid Build Coastguard Worker std::string class_name = GetClass(method_id.class_idx_);
224*795d594fSAndroid Build Coastguard Worker std::string method_name = GetString(method_id.name_idx_);
225*795d594fSAndroid Build Coastguard Worker return class_name + "." + method_name;
226*795d594fSAndroid Build Coastguard Worker }
227*795d594fSAndroid Build Coastguard Worker
228*795d594fSAndroid Build Coastguard Worker bool CheckShortyDescriptorMatch(char shorty_char, const char* descriptor, bool is_return_type);
229*795d594fSAndroid Build Coastguard Worker bool CheckListSize(const void* start, size_t count, size_t element_size, const char* label);
230*795d594fSAndroid Build Coastguard Worker // Check a list. The head is assumed to be at *ptr, and elements to be of size element_size. If
231*795d594fSAndroid Build Coastguard Worker // successful, the ptr will be moved forward the amount covered by the list.
232*795d594fSAndroid Build Coastguard Worker bool CheckList(size_t element_size, const char* label, const uint8_t* *ptr);
233*795d594fSAndroid Build Coastguard Worker // Checks:
234*795d594fSAndroid Build Coastguard Worker // * the offset is zero (when size is zero),
235*795d594fSAndroid Build Coastguard Worker // * the offset falls within the area claimed by the file,
236*795d594fSAndroid Build Coastguard Worker // * the offset + size also falls within the area claimed by the file, and
237*795d594fSAndroid Build Coastguard Worker // * the alignment of the section
238*795d594fSAndroid Build Coastguard Worker bool CheckValidOffsetAndSize(uint32_t offset, uint32_t size, size_t alignment, const char* label);
239*795d594fSAndroid Build Coastguard Worker // Checks whether the size is less than the limit.
CheckSizeLimit(uint32_t size,uint32_t limit,const char * label)240*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE bool CheckSizeLimit(uint32_t size, uint32_t limit, const char* label) {
241*795d594fSAndroid Build Coastguard Worker if (size > limit) {
242*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Size(%u) should not exceed limit(%u) for %s.", size, limit, label);
243*795d594fSAndroid Build Coastguard Worker return false;
244*795d594fSAndroid Build Coastguard Worker }
245*795d594fSAndroid Build Coastguard Worker return true;
246*795d594fSAndroid Build Coastguard Worker }
CheckIndex(uint32_t field,uint32_t limit,const char * label)247*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE bool CheckIndex(uint32_t field, uint32_t limit, const char* label) {
248*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(field >= limit)) {
249*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad index for %s: %x >= %x", label, field, limit);
250*795d594fSAndroid Build Coastguard Worker return false;
251*795d594fSAndroid Build Coastguard Worker }
252*795d594fSAndroid Build Coastguard Worker return true;
253*795d594fSAndroid Build Coastguard Worker }
254*795d594fSAndroid Build Coastguard Worker
255*795d594fSAndroid Build Coastguard Worker bool CheckHeader();
256*795d594fSAndroid Build Coastguard Worker bool CheckMap();
257*795d594fSAndroid Build Coastguard Worker
ReadUnsignedLittleEndian(uint32_t size,uint32_t * result)258*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE bool ReadUnsignedLittleEndian(uint32_t size, /*out*/ uint32_t* result) {
259*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(ptr_, size, sizeof(uint8_t), "encoded_value")) {
260*795d594fSAndroid Build Coastguard Worker return false;
261*795d594fSAndroid Build Coastguard Worker }
262*795d594fSAndroid Build Coastguard Worker *result = 0;
263*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < size; i++) {
264*795d594fSAndroid Build Coastguard Worker *result |= ((uint32_t) * (ptr_++)) << (i * 8);
265*795d594fSAndroid Build Coastguard Worker }
266*795d594fSAndroid Build Coastguard Worker return true;
267*795d594fSAndroid Build Coastguard Worker }
268*795d594fSAndroid Build Coastguard Worker bool CheckAndGetHandlerOffsets(const dex::CodeItem* code_item,
269*795d594fSAndroid Build Coastguard Worker uint32_t* handler_offsets, uint32_t handlers_size);
270*795d594fSAndroid Build Coastguard Worker bool CheckClassDataItemField(uint32_t idx,
271*795d594fSAndroid Build Coastguard Worker uint32_t access_flags,
272*795d594fSAndroid Build Coastguard Worker uint32_t class_access_flags,
273*795d594fSAndroid Build Coastguard Worker dex::TypeIndex class_type_index);
274*795d594fSAndroid Build Coastguard Worker bool CheckClassDataItemMethod(uint32_t idx,
275*795d594fSAndroid Build Coastguard Worker uint32_t access_flags,
276*795d594fSAndroid Build Coastguard Worker uint32_t class_access_flags,
277*795d594fSAndroid Build Coastguard Worker dex::TypeIndex class_type_index,
278*795d594fSAndroid Build Coastguard Worker uint32_t code_offset,
279*795d594fSAndroid Build Coastguard Worker bool expect_direct);
280*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE
CheckOrder(const char * type_descr,uint32_t curr_index,uint32_t prev_index)281*795d594fSAndroid Build Coastguard Worker bool CheckOrder(const char* type_descr, uint32_t curr_index, uint32_t prev_index) {
282*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(curr_index < prev_index)) {
283*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("out-of-order %s indexes %" PRIu32 " and %" PRIu32,
284*795d594fSAndroid Build Coastguard Worker type_descr,
285*795d594fSAndroid Build Coastguard Worker prev_index,
286*795d594fSAndroid Build Coastguard Worker curr_index);
287*795d594fSAndroid Build Coastguard Worker return false;
288*795d594fSAndroid Build Coastguard Worker }
289*795d594fSAndroid Build Coastguard Worker return true;
290*795d594fSAndroid Build Coastguard Worker }
291*795d594fSAndroid Build Coastguard Worker bool CheckStaticFieldTypes(const dex::ClassDef& class_def);
292*795d594fSAndroid Build Coastguard Worker
293*795d594fSAndroid Build Coastguard Worker bool CheckPadding(uint32_t aligned_offset, DexFile::MapItemType type);
294*795d594fSAndroid Build Coastguard Worker
295*795d594fSAndroid Build Coastguard Worker // The encoded values, arrays and annotations are allowed to be very deeply nested,
296*795d594fSAndroid Build Coastguard Worker // so use heap todo-list instead of stack recursion (the work is done in LIFO order).
297*795d594fSAndroid Build Coastguard Worker struct ToDoItem {
298*795d594fSAndroid Build Coastguard Worker uint32_t array_size = 0; // CheckArrayElement.
299*795d594fSAndroid Build Coastguard Worker uint32_t annotation_size = 0; // CheckAnnotationElement.
300*795d594fSAndroid Build Coastguard Worker uint32_t last_idx = kDexNoIndex; // CheckAnnotationElement.
301*795d594fSAndroid Build Coastguard Worker };
302*795d594fSAndroid Build Coastguard Worker using ToDoList = std::stack<ToDoItem>;
303*795d594fSAndroid Build Coastguard Worker bool CheckEncodedValue();
304*795d594fSAndroid Build Coastguard Worker bool CheckEncodedArray();
305*795d594fSAndroid Build Coastguard Worker bool CheckArrayElement();
306*795d594fSAndroid Build Coastguard Worker bool CheckEncodedAnnotation();
307*795d594fSAndroid Build Coastguard Worker bool CheckAnnotationElement(/*inout*/ uint32_t* last_idx);
308*795d594fSAndroid Build Coastguard Worker bool FlushToDoList();
309*795d594fSAndroid Build Coastguard Worker
310*795d594fSAndroid Build Coastguard Worker bool CheckIntraTypeIdItem();
311*795d594fSAndroid Build Coastguard Worker bool CheckIntraProtoIdItem();
312*795d594fSAndroid Build Coastguard Worker bool CheckIntraFieldIdItem();
313*795d594fSAndroid Build Coastguard Worker bool CheckIntraMethodIdItem();
314*795d594fSAndroid Build Coastguard Worker bool CheckIntraClassDefItem(uint32_t class_def_index);
315*795d594fSAndroid Build Coastguard Worker bool CheckIntraMethodHandleItem();
316*795d594fSAndroid Build Coastguard Worker bool CheckIntraTypeList();
317*795d594fSAndroid Build Coastguard Worker // Check all fields of the given type, reading `encoded_field` entries from `ptr_`.
318*795d594fSAndroid Build Coastguard Worker template <bool kStatic>
319*795d594fSAndroid Build Coastguard Worker bool CheckIntraClassDataItemFields(size_t count);
320*795d594fSAndroid Build Coastguard Worker // Check direct or virtual methods, reading `encoded_method` entries from `ptr_`.
321*795d594fSAndroid Build Coastguard Worker // Check virtual methods against duplicates with direct methods.
322*795d594fSAndroid Build Coastguard Worker bool CheckIntraClassDataItemMethods(size_t num_methods,
323*795d594fSAndroid Build Coastguard Worker ClassAccessor::Method* direct_methods,
324*795d594fSAndroid Build Coastguard Worker size_t num_direct_methods);
325*795d594fSAndroid Build Coastguard Worker bool CheckIntraClassDataItem();
326*795d594fSAndroid Build Coastguard Worker
327*795d594fSAndroid Build Coastguard Worker bool CheckIntraCodeItem();
328*795d594fSAndroid Build Coastguard Worker bool CheckIntraStringDataItem();
329*795d594fSAndroid Build Coastguard Worker bool CheckIntraDebugInfoItem();
330*795d594fSAndroid Build Coastguard Worker bool CheckIntraAnnotationItem();
331*795d594fSAndroid Build Coastguard Worker bool CheckIntraAnnotationsDirectoryItem();
332*795d594fSAndroid Build Coastguard Worker bool CheckIntraHiddenapiClassData();
333*795d594fSAndroid Build Coastguard Worker
334*795d594fSAndroid Build Coastguard Worker template <DexFile::MapItemType kType>
335*795d594fSAndroid Build Coastguard Worker bool CheckIntraSectionIterate(uint32_t count);
336*795d594fSAndroid Build Coastguard Worker template <DexFile::MapItemType kType>
337*795d594fSAndroid Build Coastguard Worker bool CheckIntraIdSection(size_t offset, uint32_t count);
338*795d594fSAndroid Build Coastguard Worker template <DexFile::MapItemType kType>
339*795d594fSAndroid Build Coastguard Worker bool CheckIntraDataSection(size_t offset, uint32_t count);
340*795d594fSAndroid Build Coastguard Worker bool CheckIntraSection();
341*795d594fSAndroid Build Coastguard Worker
342*795d594fSAndroid Build Coastguard Worker bool CheckOffsetToTypeMap(size_t offset, uint16_t type);
343*795d594fSAndroid Build Coastguard Worker
344*795d594fSAndroid Build Coastguard Worker // Returns kDexNoIndex if there are no fields/methods, otherwise a 16-bit type index.
345*795d594fSAndroid Build Coastguard Worker uint32_t FindFirstClassDataDefiner(const ClassAccessor& accessor);
346*795d594fSAndroid Build Coastguard Worker uint32_t FindFirstAnnotationsDirectoryDefiner(const uint8_t* ptr);
347*795d594fSAndroid Build Coastguard Worker
348*795d594fSAndroid Build Coastguard Worker bool CheckInterHiddenapiClassData();
349*795d594fSAndroid Build Coastguard Worker bool CheckInterStringIdItem();
350*795d594fSAndroid Build Coastguard Worker bool CheckInterTypeIdItem();
351*795d594fSAndroid Build Coastguard Worker bool CheckInterProtoIdItem();
352*795d594fSAndroid Build Coastguard Worker bool CheckInterFieldIdItem();
353*795d594fSAndroid Build Coastguard Worker bool CheckInterMethodIdItem();
354*795d594fSAndroid Build Coastguard Worker bool CheckInterClassDefItem();
355*795d594fSAndroid Build Coastguard Worker bool CheckInterCallSiteIdItem();
356*795d594fSAndroid Build Coastguard Worker bool CheckInterAnnotationSetRefList();
357*795d594fSAndroid Build Coastguard Worker bool CheckInterAnnotationSetItem();
358*795d594fSAndroid Build Coastguard Worker bool CheckInterClassDataItem();
359*795d594fSAndroid Build Coastguard Worker bool CheckInterAnnotationsDirectoryItem();
360*795d594fSAndroid Build Coastguard Worker
361*795d594fSAndroid Build Coastguard Worker bool CheckInterSectionIterate(size_t offset, uint32_t count, DexFile::MapItemType type);
362*795d594fSAndroid Build Coastguard Worker bool CheckInterSection();
363*795d594fSAndroid Build Coastguard Worker
ErrorStringPrintf(const char * fmt,...)364*795d594fSAndroid Build Coastguard Worker void ErrorStringPrintf(const char* fmt, ...)
365*795d594fSAndroid Build Coastguard Worker __attribute__((__format__(__printf__, 2, 3))) COLD_ATTR {
366*795d594fSAndroid Build Coastguard Worker va_list ap;
367*795d594fSAndroid Build Coastguard Worker va_start(ap, fmt);
368*795d594fSAndroid Build Coastguard Worker DCHECK(failure_reason_.empty()) << failure_reason_;
369*795d594fSAndroid Build Coastguard Worker failure_reason_ = StringPrintf("Failure to verify dex file '%s': ", location_);
370*795d594fSAndroid Build Coastguard Worker StringAppendV(&failure_reason_, fmt, ap);
371*795d594fSAndroid Build Coastguard Worker va_end(ap);
372*795d594fSAndroid Build Coastguard Worker }
FailureReasonIsSet() const373*795d594fSAndroid Build Coastguard Worker bool FailureReasonIsSet() const { return failure_reason_.size() != 0; }
374*795d594fSAndroid Build Coastguard Worker
375*795d594fSAndroid Build Coastguard Worker // Check validity of the given access flags, interpreted for a field in the context of a class
376*795d594fSAndroid Build Coastguard Worker // with the given second access flags.
377*795d594fSAndroid Build Coastguard Worker bool CheckFieldAccessFlags(uint32_t idx,
378*795d594fSAndroid Build Coastguard Worker uint32_t field_access_flags,
379*795d594fSAndroid Build Coastguard Worker uint32_t class_access_flags,
380*795d594fSAndroid Build Coastguard Worker std::string* error_message);
381*795d594fSAndroid Build Coastguard Worker
382*795d594fSAndroid Build Coastguard Worker // Check validity of the given method and access flags, in the context of a class with the given
383*795d594fSAndroid Build Coastguard Worker // second access flags.
384*795d594fSAndroid Build Coastguard Worker bool CheckMethodAccessFlags(uint32_t method_index,
385*795d594fSAndroid Build Coastguard Worker uint32_t method_access_flags,
386*795d594fSAndroid Build Coastguard Worker uint32_t class_access_flags,
387*795d594fSAndroid Build Coastguard Worker uint32_t constructor_flags_by_name,
388*795d594fSAndroid Build Coastguard Worker bool has_code,
389*795d594fSAndroid Build Coastguard Worker bool expect_direct,
390*795d594fSAndroid Build Coastguard Worker std::string* error_message);
391*795d594fSAndroid Build Coastguard Worker
392*795d594fSAndroid Build Coastguard Worker // Check validity of given method if it's a constructor or class initializer.
393*795d594fSAndroid Build Coastguard Worker bool CheckConstructorProperties(uint32_t method_index, uint32_t constructor_flags);
394*795d594fSAndroid Build Coastguard Worker
395*795d594fSAndroid Build Coastguard Worker void FindStringRangesForMethodNames();
396*795d594fSAndroid Build Coastguard Worker
397*795d594fSAndroid Build Coastguard Worker template <typename ExtraCheckFn>
398*795d594fSAndroid Build Coastguard Worker bool VerifyTypeDescriptor(dex::TypeIndex idx, const char* error_msg, ExtraCheckFn extra_check);
399*795d594fSAndroid Build Coastguard Worker
400*795d594fSAndroid Build Coastguard Worker const DexFile* const dex_file_;
401*795d594fSAndroid Build Coastguard Worker const uint8_t* const offset_base_address_;
402*795d594fSAndroid Build Coastguard Worker const size_t size_;
403*795d594fSAndroid Build Coastguard Worker ArrayRef<const uint8_t> data_; // The "data" section of the dex file.
404*795d594fSAndroid Build Coastguard Worker const char* const location_;
405*795d594fSAndroid Build Coastguard Worker const bool verify_checksum_;
406*795d594fSAndroid Build Coastguard Worker const DexFile::Header* const header_;
407*795d594fSAndroid Build Coastguard Worker uint32_t dex_version_ = 0;
408*795d594fSAndroid Build Coastguard Worker
409*795d594fSAndroid Build Coastguard Worker struct OffsetTypeMapEmptyFn {
410*795d594fSAndroid Build Coastguard Worker // Make a hash map slot empty by making the offset 0. Offset 0 is a valid dex file offset that
411*795d594fSAndroid Build Coastguard Worker // is in the offset of the dex file header. However, we only store data section items in the
412*795d594fSAndroid Build Coastguard Worker // map, and these are after the header.
MakeEmptyart::dex::DexFileVerifier::OffsetTypeMapEmptyFn413*795d594fSAndroid Build Coastguard Worker void MakeEmpty(std::pair<uint32_t, uint16_t>& pair) const {
414*795d594fSAndroid Build Coastguard Worker pair.first = 0u;
415*795d594fSAndroid Build Coastguard Worker }
416*795d594fSAndroid Build Coastguard Worker // Check if a hash map slot is empty.
IsEmptyart::dex::DexFileVerifier::OffsetTypeMapEmptyFn417*795d594fSAndroid Build Coastguard Worker bool IsEmpty(const std::pair<uint32_t, uint16_t>& pair) const {
418*795d594fSAndroid Build Coastguard Worker return pair.first == 0;
419*795d594fSAndroid Build Coastguard Worker }
420*795d594fSAndroid Build Coastguard Worker };
421*795d594fSAndroid Build Coastguard Worker struct OffsetTypeMapHashCompareFn {
422*795d594fSAndroid Build Coastguard Worker // Hash function for offset.
operator ()art::dex::DexFileVerifier::OffsetTypeMapHashCompareFn423*795d594fSAndroid Build Coastguard Worker size_t operator()(const uint32_t key) const {
424*795d594fSAndroid Build Coastguard Worker return key;
425*795d594fSAndroid Build Coastguard Worker }
426*795d594fSAndroid Build Coastguard Worker // std::equal function for offset.
operator ()art::dex::DexFileVerifier::OffsetTypeMapHashCompareFn427*795d594fSAndroid Build Coastguard Worker bool operator()(const uint32_t a, const uint32_t b) const {
428*795d594fSAndroid Build Coastguard Worker return a == b;
429*795d594fSAndroid Build Coastguard Worker }
430*795d594fSAndroid Build Coastguard Worker };
431*795d594fSAndroid Build Coastguard Worker // Map from offset to dex file type, HashMap for performance reasons.
432*795d594fSAndroid Build Coastguard Worker HashMap<uint32_t,
433*795d594fSAndroid Build Coastguard Worker uint16_t,
434*795d594fSAndroid Build Coastguard Worker OffsetTypeMapEmptyFn,
435*795d594fSAndroid Build Coastguard Worker OffsetTypeMapHashCompareFn,
436*795d594fSAndroid Build Coastguard Worker OffsetTypeMapHashCompareFn> offset_to_type_map_;
437*795d594fSAndroid Build Coastguard Worker const uint8_t* ptr_;
438*795d594fSAndroid Build Coastguard Worker const void* previous_item_;
439*795d594fSAndroid Build Coastguard Worker
440*795d594fSAndroid Build Coastguard Worker std::string failure_reason_;
441*795d594fSAndroid Build Coastguard Worker
442*795d594fSAndroid Build Coastguard Worker // Cached string indices for "interesting" entries wrt/ method names. Will be populated by
443*795d594fSAndroid Build Coastguard Worker // FindStringRangesForMethodNames (which is automatically called before verifying the
444*795d594fSAndroid Build Coastguard Worker // classdataitem section).
445*795d594fSAndroid Build Coastguard Worker //
446*795d594fSAndroid Build Coastguard Worker // Strings starting with '<' are in the range
447*795d594fSAndroid Build Coastguard Worker // [angle_bracket_start_index_,angle_bracket_end_index_).
448*795d594fSAndroid Build Coastguard Worker // angle_init_angle_index_ and angle_clinit_angle_index_ denote the indices of "<init>" and
449*795d594fSAndroid Build Coastguard Worker // "<clinit>", respectively. If any value is not found, the corresponding index will be larger
450*795d594fSAndroid Build Coastguard Worker // than any valid string index for this dex file.
451*795d594fSAndroid Build Coastguard Worker struct {
452*795d594fSAndroid Build Coastguard Worker size_t angle_bracket_start_index;
453*795d594fSAndroid Build Coastguard Worker size_t angle_bracket_end_index;
454*795d594fSAndroid Build Coastguard Worker size_t angle_init_angle_index;
455*795d594fSAndroid Build Coastguard Worker size_t angle_clinit_angle_index;
456*795d594fSAndroid Build Coastguard Worker } init_indices_;
457*795d594fSAndroid Build Coastguard Worker
458*795d594fSAndroid Build Coastguard Worker // A bitvector for verified type descriptors. Each bit corresponds to a type index. A set
459*795d594fSAndroid Build Coastguard Worker // bit denotes that the descriptor has been verified wrt/ IsValidDescriptor.
460*795d594fSAndroid Build Coastguard Worker std::vector<char> verified_type_descriptors_;
461*795d594fSAndroid Build Coastguard Worker
462*795d594fSAndroid Build Coastguard Worker // Set of type ids for which there are ClassDef elements in the dex file. Using a bitset
463*795d594fSAndroid Build Coastguard Worker // avoids all allocations. The bitset should be implemented as 8K of storage, which is
464*795d594fSAndroid Build Coastguard Worker // tight enough for all callers.
465*795d594fSAndroid Build Coastguard Worker std::bitset<kTypeIdLimit + 1> defined_classes_;
466*795d594fSAndroid Build Coastguard Worker
467*795d594fSAndroid Build Coastguard Worker // Class definition indexes, valid only if corresponding `defined_classes_[.]` is true.
468*795d594fSAndroid Build Coastguard Worker std::vector<uint16_t> defined_class_indexes_;
469*795d594fSAndroid Build Coastguard Worker
470*795d594fSAndroid Build Coastguard Worker // Used by CheckEncodedValue to avoid recursion. Field so we can reuse allocated memory.
471*795d594fSAndroid Build Coastguard Worker ToDoList todo_;
472*795d594fSAndroid Build Coastguard Worker };
473*795d594fSAndroid Build Coastguard Worker
474*795d594fSAndroid Build Coastguard Worker template <typename ExtraCheckFn>
VerifyTypeDescriptor(dex::TypeIndex idx,const char * error_msg,ExtraCheckFn extra_check)475*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::VerifyTypeDescriptor(dex::TypeIndex idx,
476*795d594fSAndroid Build Coastguard Worker const char* error_msg,
477*795d594fSAndroid Build Coastguard Worker ExtraCheckFn extra_check) {
478*795d594fSAndroid Build Coastguard Worker // All sources of the `idx` have already been checked in CheckIntraSection().
479*795d594fSAndroid Build Coastguard Worker DCHECK_LT(idx.index_, header_->type_ids_size_);
480*795d594fSAndroid Build Coastguard Worker
481*795d594fSAndroid Build Coastguard Worker char cached_char = verified_type_descriptors_[idx.index_];
482*795d594fSAndroid Build Coastguard Worker if (cached_char != 0) {
483*795d594fSAndroid Build Coastguard Worker if (!extra_check(cached_char)) {
484*795d594fSAndroid Build Coastguard Worker const char* descriptor = dex_file_->GetTypeDescriptor(idx);
485*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("%s: '%s'", error_msg, descriptor);
486*795d594fSAndroid Build Coastguard Worker return false;
487*795d594fSAndroid Build Coastguard Worker }
488*795d594fSAndroid Build Coastguard Worker return true;
489*795d594fSAndroid Build Coastguard Worker }
490*795d594fSAndroid Build Coastguard Worker
491*795d594fSAndroid Build Coastguard Worker const char* descriptor = dex_file_->GetTypeDescriptor(idx);
492*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!IsValidDescriptor(descriptor))) {
493*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("%s: '%s'", error_msg, descriptor);
494*795d594fSAndroid Build Coastguard Worker return false;
495*795d594fSAndroid Build Coastguard Worker }
496*795d594fSAndroid Build Coastguard Worker verified_type_descriptors_[idx.index_] = descriptor[0];
497*795d594fSAndroid Build Coastguard Worker
498*795d594fSAndroid Build Coastguard Worker if (!extra_check(descriptor[0])) {
499*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("%s: '%s'", error_msg, descriptor);
500*795d594fSAndroid Build Coastguard Worker return false;
501*795d594fSAndroid Build Coastguard Worker }
502*795d594fSAndroid Build Coastguard Worker return true;
503*795d594fSAndroid Build Coastguard Worker }
504*795d594fSAndroid Build Coastguard Worker
CheckShortyDescriptorMatch(char shorty_char,const char * descriptor,bool is_return_type)505*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckShortyDescriptorMatch(char shorty_char, const char* descriptor,
506*795d594fSAndroid Build Coastguard Worker bool is_return_type) {
507*795d594fSAndroid Build Coastguard Worker switch (shorty_char) {
508*795d594fSAndroid Build Coastguard Worker case 'V':
509*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!is_return_type)) {
510*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid use of void");
511*795d594fSAndroid Build Coastguard Worker return false;
512*795d594fSAndroid Build Coastguard Worker }
513*795d594fSAndroid Build Coastguard Worker FALLTHROUGH_INTENDED;
514*795d594fSAndroid Build Coastguard Worker case 'B':
515*795d594fSAndroid Build Coastguard Worker case 'C':
516*795d594fSAndroid Build Coastguard Worker case 'D':
517*795d594fSAndroid Build Coastguard Worker case 'F':
518*795d594fSAndroid Build Coastguard Worker case 'I':
519*795d594fSAndroid Build Coastguard Worker case 'J':
520*795d594fSAndroid Build Coastguard Worker case 'S':
521*795d594fSAndroid Build Coastguard Worker case 'Z':
522*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((descriptor[0] != shorty_char) || (descriptor[1] != '\0'))) {
523*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Shorty vs. primitive type mismatch: '%c', '%s'",
524*795d594fSAndroid Build Coastguard Worker shorty_char, descriptor);
525*795d594fSAndroid Build Coastguard Worker return false;
526*795d594fSAndroid Build Coastguard Worker }
527*795d594fSAndroid Build Coastguard Worker break;
528*795d594fSAndroid Build Coastguard Worker case 'L':
529*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((descriptor[0] != 'L') && (descriptor[0] != '['))) {
530*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Shorty vs. type mismatch: '%c', '%s'", shorty_char, descriptor);
531*795d594fSAndroid Build Coastguard Worker return false;
532*795d594fSAndroid Build Coastguard Worker }
533*795d594fSAndroid Build Coastguard Worker break;
534*795d594fSAndroid Build Coastguard Worker default:
535*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad shorty character: '%c'", shorty_char);
536*795d594fSAndroid Build Coastguard Worker return false;
537*795d594fSAndroid Build Coastguard Worker }
538*795d594fSAndroid Build Coastguard Worker return true;
539*795d594fSAndroid Build Coastguard Worker }
540*795d594fSAndroid Build Coastguard Worker
CheckListSize(const void * start,size_t count,size_t elem_size,const char * label)541*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckListSize(const void* start, size_t count, size_t elem_size,
542*795d594fSAndroid Build Coastguard Worker const char* label) {
543*795d594fSAndroid Build Coastguard Worker // Check that element size is not 0.
544*795d594fSAndroid Build Coastguard Worker DCHECK_NE(elem_size, 0U);
545*795d594fSAndroid Build Coastguard Worker
546*795d594fSAndroid Build Coastguard Worker size_t offset;
547*795d594fSAndroid Build Coastguard Worker if (!PtrToOffset(start, &offset)) {
548*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Offset beyond end of file for %s: %zx to %zx", label, offset, size_);
549*795d594fSAndroid Build Coastguard Worker return false;
550*795d594fSAndroid Build Coastguard Worker }
551*795d594fSAndroid Build Coastguard Worker
552*795d594fSAndroid Build Coastguard Worker // Calculate the number of elements that fit until the end of file,
553*795d594fSAndroid Build Coastguard Worker // rather than calculating the end of the range as that could overflow.
554*795d594fSAndroid Build Coastguard Worker size_t max_elements = (size_ - offset) / elem_size;
555*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(max_elements < count)) {
556*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf(
557*795d594fSAndroid Build Coastguard Worker "List too large for %s: %zx+%zu*%zu > %zx", label, offset, count, elem_size, size_);
558*795d594fSAndroid Build Coastguard Worker return false;
559*795d594fSAndroid Build Coastguard Worker }
560*795d594fSAndroid Build Coastguard Worker
561*795d594fSAndroid Build Coastguard Worker return true;
562*795d594fSAndroid Build Coastguard Worker }
563*795d594fSAndroid Build Coastguard Worker
CheckList(size_t element_size,const char * label,const uint8_t ** ptr)564*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckList(size_t element_size, const char* label, const uint8_t* *ptr) {
565*795d594fSAndroid Build Coastguard Worker // Check that the list is available. The first 4B are the count.
566*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(*ptr, 1, 4U, label)) {
567*795d594fSAndroid Build Coastguard Worker return false;
568*795d594fSAndroid Build Coastguard Worker }
569*795d594fSAndroid Build Coastguard Worker
570*795d594fSAndroid Build Coastguard Worker uint32_t count = *reinterpret_cast<const uint32_t*>(*ptr);
571*795d594fSAndroid Build Coastguard Worker if (count > 0) {
572*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(*ptr + 4, count, element_size, label)) {
573*795d594fSAndroid Build Coastguard Worker return false;
574*795d594fSAndroid Build Coastguard Worker }
575*795d594fSAndroid Build Coastguard Worker }
576*795d594fSAndroid Build Coastguard Worker
577*795d594fSAndroid Build Coastguard Worker *ptr += 4 + count * element_size;
578*795d594fSAndroid Build Coastguard Worker return true;
579*795d594fSAndroid Build Coastguard Worker }
580*795d594fSAndroid Build Coastguard Worker
CheckValidOffsetAndSize(uint32_t offset,uint32_t size,size_t alignment,const char * label)581*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckValidOffsetAndSize(uint32_t offset,
582*795d594fSAndroid Build Coastguard Worker uint32_t size,
583*795d594fSAndroid Build Coastguard Worker size_t alignment,
584*795d594fSAndroid Build Coastguard Worker const char* label) {
585*795d594fSAndroid Build Coastguard Worker if (size == 0) {
586*795d594fSAndroid Build Coastguard Worker if (offset != 0) {
587*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Offset(%d) should be zero when size is zero for %s.", offset, label);
588*795d594fSAndroid Build Coastguard Worker return false;
589*795d594fSAndroid Build Coastguard Worker }
590*795d594fSAndroid Build Coastguard Worker return true;
591*795d594fSAndroid Build Coastguard Worker }
592*795d594fSAndroid Build Coastguard Worker size_t hdr_offset = PtrToOffset(header_);
593*795d594fSAndroid Build Coastguard Worker if (offset < hdr_offset) {
594*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Offset(%d) should be after header(%zu) for %s.", offset, hdr_offset, label);
595*795d594fSAndroid Build Coastguard Worker return false;
596*795d594fSAndroid Build Coastguard Worker }
597*795d594fSAndroid Build Coastguard Worker if (size_ <= offset) {
598*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Offset(%d) should be within file size(%zu) for %s.", offset, size_, label);
599*795d594fSAndroid Build Coastguard Worker return false;
600*795d594fSAndroid Build Coastguard Worker }
601*795d594fSAndroid Build Coastguard Worker // Check that offset + size is within the file size. Note that we use `<` to allow the section to
602*795d594fSAndroid Build Coastguard Worker // end at the same point as the file. Check written as a subtraction to be safe from overfow.
603*795d594fSAndroid Build Coastguard Worker if (size_ - offset < size) {
604*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf(
605*795d594fSAndroid Build Coastguard Worker "Section end(%d) should be within file size(%zu) for %s.", offset + size, size_, label);
606*795d594fSAndroid Build Coastguard Worker return false;
607*795d594fSAndroid Build Coastguard Worker }
608*795d594fSAndroid Build Coastguard Worker if (alignment != 0 && !IsAlignedParam(offset, alignment)) {
609*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Offset(%d) should be aligned by %zu for %s.", offset, alignment, label);
610*795d594fSAndroid Build Coastguard Worker return false;
611*795d594fSAndroid Build Coastguard Worker }
612*795d594fSAndroid Build Coastguard Worker return true;
613*795d594fSAndroid Build Coastguard Worker }
614*795d594fSAndroid Build Coastguard Worker
CheckHeader()615*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckHeader() {
616*795d594fSAndroid Build Coastguard Worker // Check magic.
617*795d594fSAndroid Build Coastguard Worker size_t size = dex_file_->GetContainer()->End() - dex_file_->Begin();
618*795d594fSAndroid Build Coastguard Worker if (size < sizeof(DexFile::Header)) {
619*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Empty or truncated file.");
620*795d594fSAndroid Build Coastguard Worker return false;
621*795d594fSAndroid Build Coastguard Worker }
622*795d594fSAndroid Build Coastguard Worker if (!StandardDexFile::IsMagicValid(header_->magic_.data())) {
623*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad file magic");
624*795d594fSAndroid Build Coastguard Worker return false;
625*795d594fSAndroid Build Coastguard Worker }
626*795d594fSAndroid Build Coastguard Worker if (!StandardDexFile::IsVersionValid(header_->magic_.data())) {
627*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Unknown dex version");
628*795d594fSAndroid Build Coastguard Worker return false;
629*795d594fSAndroid Build Coastguard Worker }
630*795d594fSAndroid Build Coastguard Worker dex_version_ = header_->GetVersion();
631*795d594fSAndroid Build Coastguard Worker
632*795d594fSAndroid Build Coastguard Worker // Check file size from the header.
633*795d594fSAndroid Build Coastguard Worker size_t file_size = header_->file_size_;
634*795d594fSAndroid Build Coastguard Worker size_t header_size = (dex_version_ >= 41) ? sizeof(DexFile::HeaderV41) : sizeof(DexFile::Header);
635*795d594fSAndroid Build Coastguard Worker if (file_size < header_size) {
636*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad file size (%zu, expected at least %zu)", file_size, header_size);
637*795d594fSAndroid Build Coastguard Worker return false;
638*795d594fSAndroid Build Coastguard Worker }
639*795d594fSAndroid Build Coastguard Worker if (file_size > size) {
640*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad file size (%zu, expected at most %zu)", file_size, size);
641*795d594fSAndroid Build Coastguard Worker return false;
642*795d594fSAndroid Build Coastguard Worker }
643*795d594fSAndroid Build Coastguard Worker CHECK_GE(size, header_size); // Implied by the two checks above.
644*795d594fSAndroid Build Coastguard Worker
645*795d594fSAndroid Build Coastguard Worker // Check header size.
646*795d594fSAndroid Build Coastguard Worker if (header_->header_size_ != header_size) {
647*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad header size: %ud expected %zud", header_->header_size_, header_size);
648*795d594fSAndroid Build Coastguard Worker return false;
649*795d594fSAndroid Build Coastguard Worker }
650*795d594fSAndroid Build Coastguard Worker
651*795d594fSAndroid Build Coastguard Worker // Check the endian.
652*795d594fSAndroid Build Coastguard Worker if (header_->endian_tag_ != DexFile::kDexEndianConstant) {
653*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Unexpected endian_tag: %x", header_->endian_tag_);
654*795d594fSAndroid Build Coastguard Worker return false;
655*795d594fSAndroid Build Coastguard Worker }
656*795d594fSAndroid Build Coastguard Worker
657*795d594fSAndroid Build Coastguard Worker // Compute and verify the checksum in the header.
658*795d594fSAndroid Build Coastguard Worker uint32_t adler_checksum = dex_file_->CalculateChecksum();
659*795d594fSAndroid Build Coastguard Worker if (adler_checksum != header_->checksum_) {
660*795d594fSAndroid Build Coastguard Worker if (verify_checksum_) {
661*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad checksum (%08x, expected %08x)", adler_checksum, header_->checksum_);
662*795d594fSAndroid Build Coastguard Worker return false;
663*795d594fSAndroid Build Coastguard Worker } else {
664*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << StringPrintf(
665*795d594fSAndroid Build Coastguard Worker "Ignoring bad checksum (%08x, expected %08x)", adler_checksum, header_->checksum_);
666*795d594fSAndroid Build Coastguard Worker }
667*795d594fSAndroid Build Coastguard Worker }
668*795d594fSAndroid Build Coastguard Worker
669*795d594fSAndroid Build Coastguard Worker if (dex_version_ >= 41) {
670*795d594fSAndroid Build Coastguard Worker auto headerV41 = reinterpret_cast<const DexFile::HeaderV41*>(header_);
671*795d594fSAndroid Build Coastguard Worker if (headerV41->container_size_ <= headerV41->header_offset_) {
672*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Dex container is too small: size=%ud header_offset=%ud",
673*795d594fSAndroid Build Coastguard Worker headerV41->container_size_,
674*795d594fSAndroid Build Coastguard Worker headerV41->header_offset_);
675*795d594fSAndroid Build Coastguard Worker return false;
676*795d594fSAndroid Build Coastguard Worker }
677*795d594fSAndroid Build Coastguard Worker uint32_t remainder = headerV41->container_size_ - headerV41->header_offset_;
678*795d594fSAndroid Build Coastguard Worker if (headerV41->file_size_ > remainder) {
679*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf(
680*795d594fSAndroid Build Coastguard Worker "Header file_size(%ud) is past multi-dex size(%ud)", headerV41->file_size_, remainder);
681*795d594fSAndroid Build Coastguard Worker return false;
682*795d594fSAndroid Build Coastguard Worker }
683*795d594fSAndroid Build Coastguard Worker }
684*795d594fSAndroid Build Coastguard Worker
685*795d594fSAndroid Build Coastguard Worker // Check that all offsets are inside the file.
686*795d594fSAndroid Build Coastguard Worker bool ok =
687*795d594fSAndroid Build Coastguard Worker CheckValidOffsetAndSize(header_->link_off_,
688*795d594fSAndroid Build Coastguard Worker header_->link_size_,
689*795d594fSAndroid Build Coastguard Worker /* alignment= */ 0,
690*795d594fSAndroid Build Coastguard Worker "link") &&
691*795d594fSAndroid Build Coastguard Worker CheckValidOffsetAndSize(header_->map_off_,
692*795d594fSAndroid Build Coastguard Worker sizeof(dex::MapList),
693*795d594fSAndroid Build Coastguard Worker /* alignment= */ 4,
694*795d594fSAndroid Build Coastguard Worker "map") &&
695*795d594fSAndroid Build Coastguard Worker CheckValidOffsetAndSize(header_->string_ids_off_,
696*795d594fSAndroid Build Coastguard Worker header_->string_ids_size_,
697*795d594fSAndroid Build Coastguard Worker /* alignment= */ 4,
698*795d594fSAndroid Build Coastguard Worker "string-ids") &&
699*795d594fSAndroid Build Coastguard Worker CheckValidOffsetAndSize(header_->type_ids_off_,
700*795d594fSAndroid Build Coastguard Worker header_->type_ids_size_,
701*795d594fSAndroid Build Coastguard Worker /* alignment= */ 4,
702*795d594fSAndroid Build Coastguard Worker "type-ids") &&
703*795d594fSAndroid Build Coastguard Worker CheckSizeLimit(header_->type_ids_size_, DexFile::kDexNoIndex16, "type-ids") &&
704*795d594fSAndroid Build Coastguard Worker CheckValidOffsetAndSize(header_->proto_ids_off_,
705*795d594fSAndroid Build Coastguard Worker header_->proto_ids_size_,
706*795d594fSAndroid Build Coastguard Worker /* alignment= */ 4,
707*795d594fSAndroid Build Coastguard Worker "proto-ids") &&
708*795d594fSAndroid Build Coastguard Worker CheckSizeLimit(header_->proto_ids_size_, DexFile::kDexNoIndex16, "proto-ids") &&
709*795d594fSAndroid Build Coastguard Worker CheckValidOffsetAndSize(header_->field_ids_off_,
710*795d594fSAndroid Build Coastguard Worker header_->field_ids_size_,
711*795d594fSAndroid Build Coastguard Worker /* alignment= */ 4,
712*795d594fSAndroid Build Coastguard Worker "field-ids") &&
713*795d594fSAndroid Build Coastguard Worker CheckValidOffsetAndSize(header_->method_ids_off_,
714*795d594fSAndroid Build Coastguard Worker header_->method_ids_size_,
715*795d594fSAndroid Build Coastguard Worker /* alignment= */ 4,
716*795d594fSAndroid Build Coastguard Worker "method-ids") &&
717*795d594fSAndroid Build Coastguard Worker CheckValidOffsetAndSize(header_->class_defs_off_,
718*795d594fSAndroid Build Coastguard Worker header_->class_defs_size_,
719*795d594fSAndroid Build Coastguard Worker /* alignment= */ 4,
720*795d594fSAndroid Build Coastguard Worker "class-defs") &&
721*795d594fSAndroid Build Coastguard Worker CheckValidOffsetAndSize(header_->data_off_,
722*795d594fSAndroid Build Coastguard Worker header_->data_size_,
723*795d594fSAndroid Build Coastguard Worker // Unaligned, spec doesn't talk about it, even though size
724*795d594fSAndroid Build Coastguard Worker // is supposed to be a multiple of 4.
725*795d594fSAndroid Build Coastguard Worker /* alignment= */ 0,
726*795d594fSAndroid Build Coastguard Worker "data");
727*795d594fSAndroid Build Coastguard Worker
728*795d594fSAndroid Build Coastguard Worker if (ok) {
729*795d594fSAndroid Build Coastguard Worker data_ = (dex_version_ >= 41)
730*795d594fSAndroid Build Coastguard Worker ? ArrayRef<const uint8_t>(dex_file_->Begin(), EndOfFile() - dex_file_->Begin())
731*795d594fSAndroid Build Coastguard Worker : ArrayRef<const uint8_t>(OffsetToPtr(header_->data_off_), header_->data_size_);
732*795d594fSAndroid Build Coastguard Worker }
733*795d594fSAndroid Build Coastguard Worker return ok;
734*795d594fSAndroid Build Coastguard Worker }
735*795d594fSAndroid Build Coastguard Worker
CheckMap()736*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckMap() {
737*795d594fSAndroid Build Coastguard Worker const dex::MapList* map = OffsetToPtr<dex::MapList>(header_->map_off_);
738*795d594fSAndroid Build Coastguard Worker // Check that map list content is available.
739*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(map, 1, sizeof(dex::MapList), "maplist content")) {
740*795d594fSAndroid Build Coastguard Worker return false;
741*795d594fSAndroid Build Coastguard Worker }
742*795d594fSAndroid Build Coastguard Worker
743*795d594fSAndroid Build Coastguard Worker const dex::MapItem* item = map->list_;
744*795d594fSAndroid Build Coastguard Worker
745*795d594fSAndroid Build Coastguard Worker uint32_t count = map->size_;
746*795d594fSAndroid Build Coastguard Worker uint32_t last_offset = 0;
747*795d594fSAndroid Build Coastguard Worker uint32_t last_type = 0;
748*795d594fSAndroid Build Coastguard Worker uint32_t data_item_count = 0;
749*795d594fSAndroid Build Coastguard Worker uint32_t data_items_left = data_.size();
750*795d594fSAndroid Build Coastguard Worker uint32_t used_bits = 0;
751*795d594fSAndroid Build Coastguard Worker
752*795d594fSAndroid Build Coastguard Worker // Check the validity of the size of the map list.
753*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(item, count, sizeof(dex::MapItem), "map size")) {
754*795d594fSAndroid Build Coastguard Worker return false;
755*795d594fSAndroid Build Coastguard Worker }
756*795d594fSAndroid Build Coastguard Worker
757*795d594fSAndroid Build Coastguard Worker // Check the items listed in the map.
758*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < count; i++) {
759*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(last_offset >= item->offset_ && i != 0)) {
760*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out of order map item: %x then %x for type %x last type was %x",
761*795d594fSAndroid Build Coastguard Worker last_offset,
762*795d594fSAndroid Build Coastguard Worker item->offset_,
763*795d594fSAndroid Build Coastguard Worker static_cast<uint32_t>(item->type_),
764*795d594fSAndroid Build Coastguard Worker last_type);
765*795d594fSAndroid Build Coastguard Worker return false;
766*795d594fSAndroid Build Coastguard Worker }
767*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(item->offset_ >= size_)) {
768*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Map item after end of file: %x, size %zx", item->offset_, size_);
769*795d594fSAndroid Build Coastguard Worker return false;
770*795d594fSAndroid Build Coastguard Worker }
771*795d594fSAndroid Build Coastguard Worker
772*795d594fSAndroid Build Coastguard Worker DexFile::MapItemType item_type = static_cast<DexFile::MapItemType>(item->type_);
773*795d594fSAndroid Build Coastguard Worker if (IsDataSectionType(item_type)) {
774*795d594fSAndroid Build Coastguard Worker uint32_t icount = item->size_;
775*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(icount > data_items_left)) {
776*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Too many items in data section: %ud item_type %zx",
777*795d594fSAndroid Build Coastguard Worker data_item_count + icount,
778*795d594fSAndroid Build Coastguard Worker static_cast<size_t>(item_type));
779*795d594fSAndroid Build Coastguard Worker return false;
780*795d594fSAndroid Build Coastguard Worker }
781*795d594fSAndroid Build Coastguard Worker data_items_left -= icount;
782*795d594fSAndroid Build Coastguard Worker data_item_count += icount;
783*795d594fSAndroid Build Coastguard Worker }
784*795d594fSAndroid Build Coastguard Worker
785*795d594fSAndroid Build Coastguard Worker uint32_t bit = MapTypeToBitMask(item_type);
786*795d594fSAndroid Build Coastguard Worker
787*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(bit == 0)) {
788*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Unknown map section type %x", item->type_);
789*795d594fSAndroid Build Coastguard Worker return false;
790*795d594fSAndroid Build Coastguard Worker }
791*795d594fSAndroid Build Coastguard Worker
792*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((used_bits & bit) != 0)) {
793*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Duplicate map section of type %x", item->type_);
794*795d594fSAndroid Build Coastguard Worker return false;
795*795d594fSAndroid Build Coastguard Worker }
796*795d594fSAndroid Build Coastguard Worker
797*795d594fSAndroid Build Coastguard Worker used_bits |= bit;
798*795d594fSAndroid Build Coastguard Worker last_offset = item->offset_;
799*795d594fSAndroid Build Coastguard Worker last_type = item->type_;
800*795d594fSAndroid Build Coastguard Worker item++;
801*795d594fSAndroid Build Coastguard Worker }
802*795d594fSAndroid Build Coastguard Worker
803*795d594fSAndroid Build Coastguard Worker // Check for missing sections in the map.
804*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeHeaderItem)) == 0)) {
805*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Map is missing header entry");
806*795d594fSAndroid Build Coastguard Worker return false;
807*795d594fSAndroid Build Coastguard Worker }
808*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeMapList)) == 0)) {
809*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Map is missing map_list entry");
810*795d594fSAndroid Build Coastguard Worker return false;
811*795d594fSAndroid Build Coastguard Worker }
812*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeStringIdItem)) == 0 &&
813*795d594fSAndroid Build Coastguard Worker ((header_->string_ids_off_ != 0) || (header_->string_ids_size_ != 0)))) {
814*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Map is missing string_ids entry");
815*795d594fSAndroid Build Coastguard Worker return false;
816*795d594fSAndroid Build Coastguard Worker }
817*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeTypeIdItem)) == 0 &&
818*795d594fSAndroid Build Coastguard Worker ((header_->type_ids_off_ != 0) || (header_->type_ids_size_ != 0)))) {
819*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Map is missing type_ids entry");
820*795d594fSAndroid Build Coastguard Worker return false;
821*795d594fSAndroid Build Coastguard Worker }
822*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeProtoIdItem)) == 0 &&
823*795d594fSAndroid Build Coastguard Worker ((header_->proto_ids_off_ != 0) || (header_->proto_ids_size_ != 0)))) {
824*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Map is missing proto_ids entry");
825*795d594fSAndroid Build Coastguard Worker return false;
826*795d594fSAndroid Build Coastguard Worker }
827*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeFieldIdItem)) == 0 &&
828*795d594fSAndroid Build Coastguard Worker ((header_->field_ids_off_ != 0) || (header_->field_ids_size_ != 0)))) {
829*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Map is missing field_ids entry");
830*795d594fSAndroid Build Coastguard Worker return false;
831*795d594fSAndroid Build Coastguard Worker }
832*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeMethodIdItem)) == 0 &&
833*795d594fSAndroid Build Coastguard Worker ((header_->method_ids_off_ != 0) || (header_->method_ids_size_ != 0)))) {
834*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Map is missing method_ids entry");
835*795d594fSAndroid Build Coastguard Worker return false;
836*795d594fSAndroid Build Coastguard Worker }
837*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeClassDefItem)) == 0 &&
838*795d594fSAndroid Build Coastguard Worker ((header_->class_defs_off_ != 0) || (header_->class_defs_size_ != 0)))) {
839*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Map is missing class_defs entry");
840*795d594fSAndroid Build Coastguard Worker return false;
841*795d594fSAndroid Build Coastguard Worker }
842*795d594fSAndroid Build Coastguard Worker return true;
843*795d594fSAndroid Build Coastguard Worker }
844*795d594fSAndroid Build Coastguard Worker
845*795d594fSAndroid Build Coastguard Worker #define DECODE_UNSIGNED_CHECKED_FROM(ptr, var) \
846*795d594fSAndroid Build Coastguard Worker uint32_t var; \
847*795d594fSAndroid Build Coastguard Worker if (!DecodeUnsignedLeb128Checked(&(ptr), EndOfFile(), &(var))) { \
848*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Read out of bounds"); \
849*795d594fSAndroid Build Coastguard Worker return false; \
850*795d594fSAndroid Build Coastguard Worker }
851*795d594fSAndroid Build Coastguard Worker
852*795d594fSAndroid Build Coastguard Worker #define DECODE_SIGNED_CHECKED_FROM(ptr, var) \
853*795d594fSAndroid Build Coastguard Worker int32_t var; \
854*795d594fSAndroid Build Coastguard Worker if (!DecodeSignedLeb128Checked(&(ptr), EndOfFile(), &(var))) { \
855*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Read out of bounds"); \
856*795d594fSAndroid Build Coastguard Worker return false; \
857*795d594fSAndroid Build Coastguard Worker }
858*795d594fSAndroid Build Coastguard Worker
CheckAndGetHandlerOffsets(const dex::CodeItem * code_item,uint32_t * handler_offsets,uint32_t handlers_size)859*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckAndGetHandlerOffsets(const dex::CodeItem* code_item,
860*795d594fSAndroid Build Coastguard Worker uint32_t* handler_offsets,
861*795d594fSAndroid Build Coastguard Worker uint32_t handlers_size) {
862*795d594fSAndroid Build Coastguard Worker CodeItemDataAccessor accessor(*dex_file_, code_item);
863*795d594fSAndroid Build Coastguard Worker const uint8_t* handlers_base = accessor.GetCatchHandlerData();
864*795d594fSAndroid Build Coastguard Worker
865*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < handlers_size; i++) {
866*795d594fSAndroid Build Coastguard Worker bool catch_all;
867*795d594fSAndroid Build Coastguard Worker size_t offset = ptr_ - handlers_base;
868*795d594fSAndroid Build Coastguard Worker DECODE_SIGNED_CHECKED_FROM(ptr_, size);
869*795d594fSAndroid Build Coastguard Worker
870*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((size < -65536) || (size > 65536))) {
871*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid exception handler size: %d", size);
872*795d594fSAndroid Build Coastguard Worker return false;
873*795d594fSAndroid Build Coastguard Worker }
874*795d594fSAndroid Build Coastguard Worker
875*795d594fSAndroid Build Coastguard Worker if (size <= 0) {
876*795d594fSAndroid Build Coastguard Worker catch_all = true;
877*795d594fSAndroid Build Coastguard Worker size = -size;
878*795d594fSAndroid Build Coastguard Worker } else {
879*795d594fSAndroid Build Coastguard Worker catch_all = false;
880*795d594fSAndroid Build Coastguard Worker }
881*795d594fSAndroid Build Coastguard Worker
882*795d594fSAndroid Build Coastguard Worker handler_offsets[i] = static_cast<uint32_t>(offset);
883*795d594fSAndroid Build Coastguard Worker
884*795d594fSAndroid Build Coastguard Worker while (size-- > 0) {
885*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, type_idx);
886*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(type_idx, header_->type_ids_size_, "handler type_idx")) {
887*795d594fSAndroid Build Coastguard Worker return false;
888*795d594fSAndroid Build Coastguard Worker }
889*795d594fSAndroid Build Coastguard Worker
890*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, addr);
891*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(addr >= accessor.InsnsSizeInCodeUnits())) {
892*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid handler addr: %x", addr);
893*795d594fSAndroid Build Coastguard Worker return false;
894*795d594fSAndroid Build Coastguard Worker }
895*795d594fSAndroid Build Coastguard Worker }
896*795d594fSAndroid Build Coastguard Worker
897*795d594fSAndroid Build Coastguard Worker if (catch_all) {
898*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, addr);
899*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(addr >= accessor.InsnsSizeInCodeUnits())) {
900*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid handler catch_all_addr: %x", addr);
901*795d594fSAndroid Build Coastguard Worker return false;
902*795d594fSAndroid Build Coastguard Worker }
903*795d594fSAndroid Build Coastguard Worker }
904*795d594fSAndroid Build Coastguard Worker }
905*795d594fSAndroid Build Coastguard Worker
906*795d594fSAndroid Build Coastguard Worker return true;
907*795d594fSAndroid Build Coastguard Worker }
908*795d594fSAndroid Build Coastguard Worker
CheckClassDataItemField(uint32_t idx,uint32_t access_flags,uint32_t class_access_flags,dex::TypeIndex class_type_index)909*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckClassDataItemField(uint32_t idx,
910*795d594fSAndroid Build Coastguard Worker uint32_t access_flags,
911*795d594fSAndroid Build Coastguard Worker uint32_t class_access_flags,
912*795d594fSAndroid Build Coastguard Worker dex::TypeIndex class_type_index) {
913*795d594fSAndroid Build Coastguard Worker // The `idx` has already been checked in `CheckIntraClassDataItemFields()`.
914*795d594fSAndroid Build Coastguard Worker DCHECK_LE(idx, header_->field_ids_size_);
915*795d594fSAndroid Build Coastguard Worker
916*795d594fSAndroid Build Coastguard Worker // Check that it's the right class.
917*795d594fSAndroid Build Coastguard Worker dex::TypeIndex my_class_index =
918*795d594fSAndroid Build Coastguard Worker OffsetToPtr<dex::FieldId>(header_->field_ids_off_)[idx].class_idx_;
919*795d594fSAndroid Build Coastguard Worker if (class_type_index != my_class_index) {
920*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Field's class index unexpected, %" PRIu16 "vs %" PRIu16,
921*795d594fSAndroid Build Coastguard Worker my_class_index.index_,
922*795d594fSAndroid Build Coastguard Worker class_type_index.index_);
923*795d594fSAndroid Build Coastguard Worker return false;
924*795d594fSAndroid Build Coastguard Worker }
925*795d594fSAndroid Build Coastguard Worker
926*795d594fSAndroid Build Coastguard Worker // Check field access flags.
927*795d594fSAndroid Build Coastguard Worker std::string error_msg;
928*795d594fSAndroid Build Coastguard Worker if (!CheckFieldAccessFlags(idx, access_flags, class_access_flags, &error_msg)) {
929*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("%s", error_msg.c_str());
930*795d594fSAndroid Build Coastguard Worker return false;
931*795d594fSAndroid Build Coastguard Worker }
932*795d594fSAndroid Build Coastguard Worker
933*795d594fSAndroid Build Coastguard Worker return true;
934*795d594fSAndroid Build Coastguard Worker }
935*795d594fSAndroid Build Coastguard Worker
CheckClassDataItemMethod(uint32_t idx,uint32_t access_flags,uint32_t class_access_flags,dex::TypeIndex class_type_index,uint32_t code_offset,bool expect_direct)936*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckClassDataItemMethod(uint32_t idx,
937*795d594fSAndroid Build Coastguard Worker uint32_t access_flags,
938*795d594fSAndroid Build Coastguard Worker uint32_t class_access_flags,
939*795d594fSAndroid Build Coastguard Worker dex::TypeIndex class_type_index,
940*795d594fSAndroid Build Coastguard Worker uint32_t code_offset,
941*795d594fSAndroid Build Coastguard Worker bool expect_direct) {
942*795d594fSAndroid Build Coastguard Worker // The `idx` has already been checked in `CheckIntraClassDataItemMethods()`.
943*795d594fSAndroid Build Coastguard Worker DCHECK_LT(idx, header_->method_ids_size_);
944*795d594fSAndroid Build Coastguard Worker
945*795d594fSAndroid Build Coastguard Worker const dex::MethodId& method_id = OffsetToPtr<dex::MethodId>(header_->method_ids_off_)[idx];
946*795d594fSAndroid Build Coastguard Worker
947*795d594fSAndroid Build Coastguard Worker // Check that it's the right class.
948*795d594fSAndroid Build Coastguard Worker dex::TypeIndex my_class_index = method_id.class_idx_;
949*795d594fSAndroid Build Coastguard Worker if (class_type_index != my_class_index) {
950*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Method's class index unexpected, %" PRIu16 " vs %" PRIu16,
951*795d594fSAndroid Build Coastguard Worker my_class_index.index_,
952*795d594fSAndroid Build Coastguard Worker class_type_index.index_);
953*795d594fSAndroid Build Coastguard Worker return false;
954*795d594fSAndroid Build Coastguard Worker }
955*795d594fSAndroid Build Coastguard Worker
956*795d594fSAndroid Build Coastguard Worker std::string error_msg;
957*795d594fSAndroid Build Coastguard Worker uint32_t constructor_flags_by_name = 0;
958*795d594fSAndroid Build Coastguard Worker {
959*795d594fSAndroid Build Coastguard Worker uint32_t string_idx = method_id.name_idx_.index_;
960*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(string_idx, header_->string_ids_size_, "method flags verification")) {
961*795d594fSAndroid Build Coastguard Worker return false;
962*795d594fSAndroid Build Coastguard Worker }
963*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(string_idx < init_indices_.angle_bracket_end_index) &&
964*795d594fSAndroid Build Coastguard Worker string_idx >= init_indices_.angle_bracket_start_index) {
965*795d594fSAndroid Build Coastguard Worker if (string_idx == init_indices_.angle_clinit_angle_index) {
966*795d594fSAndroid Build Coastguard Worker constructor_flags_by_name = kAccStatic | kAccConstructor;
967*795d594fSAndroid Build Coastguard Worker } else if (string_idx == init_indices_.angle_init_angle_index) {
968*795d594fSAndroid Build Coastguard Worker constructor_flags_by_name = kAccConstructor;
969*795d594fSAndroid Build Coastguard Worker } else {
970*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad method name for method index %u", idx);
971*795d594fSAndroid Build Coastguard Worker return false;
972*795d594fSAndroid Build Coastguard Worker }
973*795d594fSAndroid Build Coastguard Worker }
974*795d594fSAndroid Build Coastguard Worker }
975*795d594fSAndroid Build Coastguard Worker
976*795d594fSAndroid Build Coastguard Worker bool has_code = (code_offset != 0);
977*795d594fSAndroid Build Coastguard Worker if (!CheckMethodAccessFlags(idx,
978*795d594fSAndroid Build Coastguard Worker access_flags,
979*795d594fSAndroid Build Coastguard Worker class_access_flags,
980*795d594fSAndroid Build Coastguard Worker constructor_flags_by_name,
981*795d594fSAndroid Build Coastguard Worker has_code,
982*795d594fSAndroid Build Coastguard Worker expect_direct,
983*795d594fSAndroid Build Coastguard Worker &error_msg)) {
984*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("%s", error_msg.c_str());
985*795d594fSAndroid Build Coastguard Worker return false;
986*795d594fSAndroid Build Coastguard Worker }
987*795d594fSAndroid Build Coastguard Worker
988*795d594fSAndroid Build Coastguard Worker if (constructor_flags_by_name != 0) {
989*795d594fSAndroid Build Coastguard Worker if (!CheckConstructorProperties(idx, constructor_flags_by_name)) {
990*795d594fSAndroid Build Coastguard Worker DCHECK(FailureReasonIsSet());
991*795d594fSAndroid Build Coastguard Worker return false;
992*795d594fSAndroid Build Coastguard Worker }
993*795d594fSAndroid Build Coastguard Worker }
994*795d594fSAndroid Build Coastguard Worker
995*795d594fSAndroid Build Coastguard Worker return true;
996*795d594fSAndroid Build Coastguard Worker }
997*795d594fSAndroid Build Coastguard Worker
CheckPadding(uint32_t aligned_offset,DexFile::MapItemType type)998*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckPadding(uint32_t aligned_offset,
999*795d594fSAndroid Build Coastguard Worker DexFile::MapItemType type) {
1000*795d594fSAndroid Build Coastguard Worker size_t offset = PtrToOffset(ptr_);
1001*795d594fSAndroid Build Coastguard Worker if (offset < aligned_offset) {
1002*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(OffsetToPtr(offset), aligned_offset - offset, sizeof(uint8_t), "section")) {
1003*795d594fSAndroid Build Coastguard Worker return false;
1004*795d594fSAndroid Build Coastguard Worker }
1005*795d594fSAndroid Build Coastguard Worker if (dex_version_ >= 41) {
1006*795d594fSAndroid Build Coastguard Worker ptr_ += aligned_offset - offset;
1007*795d594fSAndroid Build Coastguard Worker return true;
1008*795d594fSAndroid Build Coastguard Worker }
1009*795d594fSAndroid Build Coastguard Worker while (offset < aligned_offset) {
1010*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(*ptr_ != '\0')) {
1011*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Non-zero padding %x before section of type %zu at offset 0x%zx",
1012*795d594fSAndroid Build Coastguard Worker *ptr_,
1013*795d594fSAndroid Build Coastguard Worker static_cast<size_t>(type),
1014*795d594fSAndroid Build Coastguard Worker offset);
1015*795d594fSAndroid Build Coastguard Worker return false;
1016*795d594fSAndroid Build Coastguard Worker }
1017*795d594fSAndroid Build Coastguard Worker ptr_++;
1018*795d594fSAndroid Build Coastguard Worker offset++;
1019*795d594fSAndroid Build Coastguard Worker }
1020*795d594fSAndroid Build Coastguard Worker }
1021*795d594fSAndroid Build Coastguard Worker return true;
1022*795d594fSAndroid Build Coastguard Worker }
1023*795d594fSAndroid Build Coastguard Worker
CheckEncodedValue()1024*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckEncodedValue() {
1025*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(ptr_, 1, sizeof(uint8_t), "encoded_value header")) {
1026*795d594fSAndroid Build Coastguard Worker return false;
1027*795d594fSAndroid Build Coastguard Worker }
1028*795d594fSAndroid Build Coastguard Worker
1029*795d594fSAndroid Build Coastguard Worker uint8_t header_byte = *(ptr_++);
1030*795d594fSAndroid Build Coastguard Worker uint32_t value_type = header_byte & DexFile::kDexAnnotationValueTypeMask;
1031*795d594fSAndroid Build Coastguard Worker uint32_t value_arg = header_byte >> DexFile::kDexAnnotationValueArgShift;
1032*795d594fSAndroid Build Coastguard Worker
1033*795d594fSAndroid Build Coastguard Worker switch (value_type) {
1034*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationByte: {
1035*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(value_arg != 0)) {
1036*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad encoded_value byte size %x", value_arg);
1037*795d594fSAndroid Build Coastguard Worker return false;
1038*795d594fSAndroid Build Coastguard Worker }
1039*795d594fSAndroid Build Coastguard Worker uint32_t value;
1040*795d594fSAndroid Build Coastguard Worker if (!ReadUnsignedLittleEndian(value_arg + 1, &value)) {
1041*795d594fSAndroid Build Coastguard Worker return false;
1042*795d594fSAndroid Build Coastguard Worker }
1043*795d594fSAndroid Build Coastguard Worker break;
1044*795d594fSAndroid Build Coastguard Worker }
1045*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationShort:
1046*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationChar: {
1047*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(value_arg > 1)) {
1048*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad encoded_value char/short size %x", value_arg);
1049*795d594fSAndroid Build Coastguard Worker return false;
1050*795d594fSAndroid Build Coastguard Worker }
1051*795d594fSAndroid Build Coastguard Worker uint32_t value;
1052*795d594fSAndroid Build Coastguard Worker if (!ReadUnsignedLittleEndian(value_arg + 1, &value)) {
1053*795d594fSAndroid Build Coastguard Worker return false;
1054*795d594fSAndroid Build Coastguard Worker }
1055*795d594fSAndroid Build Coastguard Worker break;
1056*795d594fSAndroid Build Coastguard Worker }
1057*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationInt:
1058*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationFloat: {
1059*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(value_arg > 3)) {
1060*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad encoded_value int/float size %x", value_arg);
1061*795d594fSAndroid Build Coastguard Worker return false;
1062*795d594fSAndroid Build Coastguard Worker }
1063*795d594fSAndroid Build Coastguard Worker uint32_t value;
1064*795d594fSAndroid Build Coastguard Worker if (!ReadUnsignedLittleEndian(value_arg + 1, &value)) {
1065*795d594fSAndroid Build Coastguard Worker return false;
1066*795d594fSAndroid Build Coastguard Worker }
1067*795d594fSAndroid Build Coastguard Worker break;
1068*795d594fSAndroid Build Coastguard Worker }
1069*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationLong:
1070*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationDouble: {
1071*795d594fSAndroid Build Coastguard Worker uint32_t value;
1072*795d594fSAndroid Build Coastguard Worker if (!ReadUnsignedLittleEndian(value_arg + 1, &value)) {
1073*795d594fSAndroid Build Coastguard Worker return false;
1074*795d594fSAndroid Build Coastguard Worker }
1075*795d594fSAndroid Build Coastguard Worker break;
1076*795d594fSAndroid Build Coastguard Worker }
1077*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationString: {
1078*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(value_arg > 3)) {
1079*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad encoded_value string size %x", value_arg);
1080*795d594fSAndroid Build Coastguard Worker return false;
1081*795d594fSAndroid Build Coastguard Worker }
1082*795d594fSAndroid Build Coastguard Worker uint32_t idx;
1083*795d594fSAndroid Build Coastguard Worker if (!ReadUnsignedLittleEndian(value_arg + 1, &idx)) {
1084*795d594fSAndroid Build Coastguard Worker return false;
1085*795d594fSAndroid Build Coastguard Worker }
1086*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(idx, header_->string_ids_size_, "encoded_value string")) {
1087*795d594fSAndroid Build Coastguard Worker return false;
1088*795d594fSAndroid Build Coastguard Worker }
1089*795d594fSAndroid Build Coastguard Worker break;
1090*795d594fSAndroid Build Coastguard Worker }
1091*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationType: {
1092*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(value_arg > 3)) {
1093*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad encoded_value type size %x", value_arg);
1094*795d594fSAndroid Build Coastguard Worker return false;
1095*795d594fSAndroid Build Coastguard Worker }
1096*795d594fSAndroid Build Coastguard Worker uint32_t idx;
1097*795d594fSAndroid Build Coastguard Worker if (!ReadUnsignedLittleEndian(value_arg + 1, &idx)) {
1098*795d594fSAndroid Build Coastguard Worker return false;
1099*795d594fSAndroid Build Coastguard Worker }
1100*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(idx, header_->type_ids_size_, "encoded_value type")) {
1101*795d594fSAndroid Build Coastguard Worker return false;
1102*795d594fSAndroid Build Coastguard Worker }
1103*795d594fSAndroid Build Coastguard Worker break;
1104*795d594fSAndroid Build Coastguard Worker }
1105*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationField:
1106*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationEnum: {
1107*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(value_arg > 3)) {
1108*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad encoded_value field/enum size %x", value_arg);
1109*795d594fSAndroid Build Coastguard Worker return false;
1110*795d594fSAndroid Build Coastguard Worker }
1111*795d594fSAndroid Build Coastguard Worker uint32_t idx;
1112*795d594fSAndroid Build Coastguard Worker if (!ReadUnsignedLittleEndian(value_arg + 1, &idx)) {
1113*795d594fSAndroid Build Coastguard Worker return false;
1114*795d594fSAndroid Build Coastguard Worker }
1115*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(idx, header_->field_ids_size_, "encoded_value field")) {
1116*795d594fSAndroid Build Coastguard Worker return false;
1117*795d594fSAndroid Build Coastguard Worker }
1118*795d594fSAndroid Build Coastguard Worker break;
1119*795d594fSAndroid Build Coastguard Worker }
1120*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationMethod: {
1121*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(value_arg > 3)) {
1122*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad encoded_value method size %x", value_arg);
1123*795d594fSAndroid Build Coastguard Worker return false;
1124*795d594fSAndroid Build Coastguard Worker }
1125*795d594fSAndroid Build Coastguard Worker uint32_t idx;
1126*795d594fSAndroid Build Coastguard Worker if (!ReadUnsignedLittleEndian(value_arg + 1, &idx)) {
1127*795d594fSAndroid Build Coastguard Worker return false;
1128*795d594fSAndroid Build Coastguard Worker }
1129*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(idx, header_->method_ids_size_, "encoded_value method")) {
1130*795d594fSAndroid Build Coastguard Worker return false;
1131*795d594fSAndroid Build Coastguard Worker }
1132*795d594fSAndroid Build Coastguard Worker break;
1133*795d594fSAndroid Build Coastguard Worker }
1134*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationArray:
1135*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(value_arg != 0)) {
1136*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad encoded_value array value_arg %x", value_arg);
1137*795d594fSAndroid Build Coastguard Worker return false;
1138*795d594fSAndroid Build Coastguard Worker }
1139*795d594fSAndroid Build Coastguard Worker if (!CheckEncodedArray()) {
1140*795d594fSAndroid Build Coastguard Worker return false;
1141*795d594fSAndroid Build Coastguard Worker }
1142*795d594fSAndroid Build Coastguard Worker break;
1143*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationAnnotation:
1144*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(value_arg != 0)) {
1145*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad encoded_value annotation value_arg %x", value_arg);
1146*795d594fSAndroid Build Coastguard Worker return false;
1147*795d594fSAndroid Build Coastguard Worker }
1148*795d594fSAndroid Build Coastguard Worker if (!CheckEncodedAnnotation()) {
1149*795d594fSAndroid Build Coastguard Worker return false;
1150*795d594fSAndroid Build Coastguard Worker }
1151*795d594fSAndroid Build Coastguard Worker break;
1152*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationNull:
1153*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(value_arg != 0)) {
1154*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad encoded_value null value_arg %x", value_arg);
1155*795d594fSAndroid Build Coastguard Worker return false;
1156*795d594fSAndroid Build Coastguard Worker }
1157*795d594fSAndroid Build Coastguard Worker break;
1158*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationBoolean:
1159*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(value_arg > 1)) {
1160*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad encoded_value boolean size %x", value_arg);
1161*795d594fSAndroid Build Coastguard Worker return false;
1162*795d594fSAndroid Build Coastguard Worker }
1163*795d594fSAndroid Build Coastguard Worker break;
1164*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationMethodType: {
1165*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(value_arg > 3)) {
1166*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad encoded_value method type size %x", value_arg);
1167*795d594fSAndroid Build Coastguard Worker return false;
1168*795d594fSAndroid Build Coastguard Worker }
1169*795d594fSAndroid Build Coastguard Worker uint32_t idx;
1170*795d594fSAndroid Build Coastguard Worker if (!ReadUnsignedLittleEndian(value_arg + 1, &idx)) {
1171*795d594fSAndroid Build Coastguard Worker return false;
1172*795d594fSAndroid Build Coastguard Worker }
1173*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(idx, header_->proto_ids_size_, "method_type value")) {
1174*795d594fSAndroid Build Coastguard Worker return false;
1175*795d594fSAndroid Build Coastguard Worker }
1176*795d594fSAndroid Build Coastguard Worker break;
1177*795d594fSAndroid Build Coastguard Worker }
1178*795d594fSAndroid Build Coastguard Worker case DexFile::kDexAnnotationMethodHandle: {
1179*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(value_arg > 3)) {
1180*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad encoded_value method handle size %x", value_arg);
1181*795d594fSAndroid Build Coastguard Worker return false;
1182*795d594fSAndroid Build Coastguard Worker }
1183*795d594fSAndroid Build Coastguard Worker uint32_t idx;
1184*795d594fSAndroid Build Coastguard Worker if (!ReadUnsignedLittleEndian(value_arg + 1, &idx)) {
1185*795d594fSAndroid Build Coastguard Worker return false;
1186*795d594fSAndroid Build Coastguard Worker }
1187*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(idx, dex_file_->NumMethodHandles(), "method_handle value")) {
1188*795d594fSAndroid Build Coastguard Worker return false;
1189*795d594fSAndroid Build Coastguard Worker }
1190*795d594fSAndroid Build Coastguard Worker break;
1191*795d594fSAndroid Build Coastguard Worker }
1192*795d594fSAndroid Build Coastguard Worker default:
1193*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bogus encoded_value value_type %x", value_type);
1194*795d594fSAndroid Build Coastguard Worker return false;
1195*795d594fSAndroid Build Coastguard Worker }
1196*795d594fSAndroid Build Coastguard Worker
1197*795d594fSAndroid Build Coastguard Worker return true;
1198*795d594fSAndroid Build Coastguard Worker }
1199*795d594fSAndroid Build Coastguard Worker
CheckEncodedArray()1200*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckEncodedArray() {
1201*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, size);
1202*795d594fSAndroid Build Coastguard Worker todo_.emplace(ToDoItem{.array_size = size});
1203*795d594fSAndroid Build Coastguard Worker return true;
1204*795d594fSAndroid Build Coastguard Worker }
1205*795d594fSAndroid Build Coastguard Worker
1206*795d594fSAndroid Build Coastguard Worker // Always called directly from FlushToDoList, which avoids recursion.
CheckArrayElement()1207*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckArrayElement() {
1208*795d594fSAndroid Build Coastguard Worker if (!CheckEncodedValue()) {
1209*795d594fSAndroid Build Coastguard Worker failure_reason_ = StringPrintf("Bad encoded_array value: %s", failure_reason_.c_str());
1210*795d594fSAndroid Build Coastguard Worker return false;
1211*795d594fSAndroid Build Coastguard Worker }
1212*795d594fSAndroid Build Coastguard Worker return true;
1213*795d594fSAndroid Build Coastguard Worker }
1214*795d594fSAndroid Build Coastguard Worker
CheckEncodedAnnotation()1215*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckEncodedAnnotation() {
1216*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, anno_idx);
1217*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(anno_idx, header_->type_ids_size_, "encoded_annotation type_idx")) {
1218*795d594fSAndroid Build Coastguard Worker return false;
1219*795d594fSAndroid Build Coastguard Worker }
1220*795d594fSAndroid Build Coastguard Worker
1221*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, size);
1222*795d594fSAndroid Build Coastguard Worker todo_.emplace(ToDoItem{.annotation_size = size, .last_idx = kDexNoIndex});
1223*795d594fSAndroid Build Coastguard Worker return true;
1224*795d594fSAndroid Build Coastguard Worker }
1225*795d594fSAndroid Build Coastguard Worker
1226*795d594fSAndroid Build Coastguard Worker // Always called directly from FlushToDoList, which avoids recursion.
CheckAnnotationElement(uint32_t * last_idx)1227*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckAnnotationElement(/*inout*/ uint32_t* last_idx) {
1228*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, idx);
1229*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(idx, header_->string_ids_size_, "annotation_element name_idx")) {
1230*795d594fSAndroid Build Coastguard Worker return false;
1231*795d594fSAndroid Build Coastguard Worker }
1232*795d594fSAndroid Build Coastguard Worker
1233*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(*last_idx >= idx && *last_idx != kDexNoIndex)) {
1234*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-order annotation_element name_idx: %x then %x", *last_idx, idx);
1235*795d594fSAndroid Build Coastguard Worker return false;
1236*795d594fSAndroid Build Coastguard Worker }
1237*795d594fSAndroid Build Coastguard Worker *last_idx = idx;
1238*795d594fSAndroid Build Coastguard Worker
1239*795d594fSAndroid Build Coastguard Worker return CheckEncodedValue();
1240*795d594fSAndroid Build Coastguard Worker }
1241*795d594fSAndroid Build Coastguard Worker
1242*795d594fSAndroid Build Coastguard Worker // Keep processing the rest of the to-do list until we are finished or encounter an error.
FlushToDoList()1243*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::FlushToDoList() {
1244*795d594fSAndroid Build Coastguard Worker while (!todo_.empty()) {
1245*795d594fSAndroid Build Coastguard Worker ToDoItem& item = todo_.top();
1246*795d594fSAndroid Build Coastguard Worker DCHECK(item.array_size == 0u || item.annotation_size == 0u);
1247*795d594fSAndroid Build Coastguard Worker if (item.array_size > 0) {
1248*795d594fSAndroid Build Coastguard Worker item.array_size--;
1249*795d594fSAndroid Build Coastguard Worker if (!CheckArrayElement()) {
1250*795d594fSAndroid Build Coastguard Worker return false;
1251*795d594fSAndroid Build Coastguard Worker }
1252*795d594fSAndroid Build Coastguard Worker } else if (item.annotation_size > 0) {
1253*795d594fSAndroid Build Coastguard Worker item.annotation_size--;
1254*795d594fSAndroid Build Coastguard Worker if (!CheckAnnotationElement(&item.last_idx)) {
1255*795d594fSAndroid Build Coastguard Worker return false;
1256*795d594fSAndroid Build Coastguard Worker }
1257*795d594fSAndroid Build Coastguard Worker } else {
1258*795d594fSAndroid Build Coastguard Worker todo_.pop();
1259*795d594fSAndroid Build Coastguard Worker }
1260*795d594fSAndroid Build Coastguard Worker }
1261*795d594fSAndroid Build Coastguard Worker return true;
1262*795d594fSAndroid Build Coastguard Worker }
1263*795d594fSAndroid Build Coastguard Worker
CheckStaticFieldTypes(const dex::ClassDef & class_def)1264*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckStaticFieldTypes(const dex::ClassDef& class_def) {
1265*795d594fSAndroid Build Coastguard Worker ClassAccessor accessor(*dex_file_, ptr_);
1266*795d594fSAndroid Build Coastguard Worker EncodedStaticFieldValueIterator array_it(*dex_file_, class_def);
1267*795d594fSAndroid Build Coastguard Worker
1268*795d594fSAndroid Build Coastguard Worker for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
1269*795d594fSAndroid Build Coastguard Worker if (!array_it.HasNext()) {
1270*795d594fSAndroid Build Coastguard Worker break;
1271*795d594fSAndroid Build Coastguard Worker }
1272*795d594fSAndroid Build Coastguard Worker uint32_t index = field.GetIndex();
1273*795d594fSAndroid Build Coastguard Worker // The `index` has already been checked in `CheckIntraClassDataItemFields()`.
1274*795d594fSAndroid Build Coastguard Worker DCHECK_LT(index, header_->field_ids_size_);
1275*795d594fSAndroid Build Coastguard Worker const dex::TypeId& type_id = dex_file_->GetTypeId(dex_file_->GetFieldId(index).type_idx_);
1276*795d594fSAndroid Build Coastguard Worker const char* field_type_name =
1277*795d594fSAndroid Build Coastguard Worker dex_file_->GetStringData(dex_file_->GetStringId(type_id.descriptor_idx_));
1278*795d594fSAndroid Build Coastguard Worker Primitive::Type field_type = Primitive::GetType(field_type_name[0]);
1279*795d594fSAndroid Build Coastguard Worker EncodedArrayValueIterator::ValueType array_type = array_it.GetValueType();
1280*795d594fSAndroid Build Coastguard Worker // Ensure this matches RuntimeEncodedStaticFieldValueIterator.
1281*795d594fSAndroid Build Coastguard Worker switch (array_type) {
1282*795d594fSAndroid Build Coastguard Worker case EncodedArrayValueIterator::ValueType::kBoolean:
1283*795d594fSAndroid Build Coastguard Worker if (field_type != Primitive::kPrimBoolean) {
1284*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("unexpected static field initial value type: 'Z' vs '%c'",
1285*795d594fSAndroid Build Coastguard Worker field_type_name[0]);
1286*795d594fSAndroid Build Coastguard Worker return false;
1287*795d594fSAndroid Build Coastguard Worker }
1288*795d594fSAndroid Build Coastguard Worker break;
1289*795d594fSAndroid Build Coastguard Worker case EncodedArrayValueIterator::ValueType::kByte:
1290*795d594fSAndroid Build Coastguard Worker if (field_type != Primitive::kPrimByte) {
1291*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("unexpected static field initial value type: 'B' vs '%c'",
1292*795d594fSAndroid Build Coastguard Worker field_type_name[0]);
1293*795d594fSAndroid Build Coastguard Worker return false;
1294*795d594fSAndroid Build Coastguard Worker }
1295*795d594fSAndroid Build Coastguard Worker break;
1296*795d594fSAndroid Build Coastguard Worker case EncodedArrayValueIterator::ValueType::kShort:
1297*795d594fSAndroid Build Coastguard Worker if (field_type != Primitive::kPrimShort) {
1298*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("unexpected static field initial value type: 'S' vs '%c'",
1299*795d594fSAndroid Build Coastguard Worker field_type_name[0]);
1300*795d594fSAndroid Build Coastguard Worker return false;
1301*795d594fSAndroid Build Coastguard Worker }
1302*795d594fSAndroid Build Coastguard Worker break;
1303*795d594fSAndroid Build Coastguard Worker case EncodedArrayValueIterator::ValueType::kChar:
1304*795d594fSAndroid Build Coastguard Worker if (field_type != Primitive::kPrimChar) {
1305*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("unexpected static field initial value type: 'C' vs '%c'",
1306*795d594fSAndroid Build Coastguard Worker field_type_name[0]);
1307*795d594fSAndroid Build Coastguard Worker return false;
1308*795d594fSAndroid Build Coastguard Worker }
1309*795d594fSAndroid Build Coastguard Worker break;
1310*795d594fSAndroid Build Coastguard Worker case EncodedArrayValueIterator::ValueType::kInt:
1311*795d594fSAndroid Build Coastguard Worker if (field_type != Primitive::kPrimInt) {
1312*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("unexpected static field initial value type: 'I' vs '%c'",
1313*795d594fSAndroid Build Coastguard Worker field_type_name[0]);
1314*795d594fSAndroid Build Coastguard Worker return false;
1315*795d594fSAndroid Build Coastguard Worker }
1316*795d594fSAndroid Build Coastguard Worker break;
1317*795d594fSAndroid Build Coastguard Worker case EncodedArrayValueIterator::ValueType::kLong:
1318*795d594fSAndroid Build Coastguard Worker if (field_type != Primitive::kPrimLong) {
1319*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("unexpected static field initial value type: 'J' vs '%c'",
1320*795d594fSAndroid Build Coastguard Worker field_type_name[0]);
1321*795d594fSAndroid Build Coastguard Worker return false;
1322*795d594fSAndroid Build Coastguard Worker }
1323*795d594fSAndroid Build Coastguard Worker break;
1324*795d594fSAndroid Build Coastguard Worker case EncodedArrayValueIterator::ValueType::kFloat:
1325*795d594fSAndroid Build Coastguard Worker if (field_type != Primitive::kPrimFloat) {
1326*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("unexpected static field initial value type: 'F' vs '%c'",
1327*795d594fSAndroid Build Coastguard Worker field_type_name[0]);
1328*795d594fSAndroid Build Coastguard Worker return false;
1329*795d594fSAndroid Build Coastguard Worker }
1330*795d594fSAndroid Build Coastguard Worker break;
1331*795d594fSAndroid Build Coastguard Worker case EncodedArrayValueIterator::ValueType::kDouble:
1332*795d594fSAndroid Build Coastguard Worker if (field_type != Primitive::kPrimDouble) {
1333*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("unexpected static field initial value type: 'D' vs '%c'",
1334*795d594fSAndroid Build Coastguard Worker field_type_name[0]);
1335*795d594fSAndroid Build Coastguard Worker return false;
1336*795d594fSAndroid Build Coastguard Worker }
1337*795d594fSAndroid Build Coastguard Worker break;
1338*795d594fSAndroid Build Coastguard Worker case EncodedArrayValueIterator::ValueType::kNull:
1339*795d594fSAndroid Build Coastguard Worker case EncodedArrayValueIterator::ValueType::kString:
1340*795d594fSAndroid Build Coastguard Worker case EncodedArrayValueIterator::ValueType::kType:
1341*795d594fSAndroid Build Coastguard Worker if (field_type != Primitive::kPrimNot) {
1342*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("unexpected static field initial value type: 'L' vs '%c'",
1343*795d594fSAndroid Build Coastguard Worker field_type_name[0]);
1344*795d594fSAndroid Build Coastguard Worker return false;
1345*795d594fSAndroid Build Coastguard Worker }
1346*795d594fSAndroid Build Coastguard Worker break;
1347*795d594fSAndroid Build Coastguard Worker default:
1348*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("unexpected static field initial value type: %x", array_type);
1349*795d594fSAndroid Build Coastguard Worker return false;
1350*795d594fSAndroid Build Coastguard Worker }
1351*795d594fSAndroid Build Coastguard Worker if (!array_it.MaybeNext()) {
1352*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("unexpected encoded value type: '%c'", array_it.GetValueType());
1353*795d594fSAndroid Build Coastguard Worker return false;
1354*795d594fSAndroid Build Coastguard Worker }
1355*795d594fSAndroid Build Coastguard Worker }
1356*795d594fSAndroid Build Coastguard Worker
1357*795d594fSAndroid Build Coastguard Worker if (array_it.HasNext()) {
1358*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("too many static field initial values");
1359*795d594fSAndroid Build Coastguard Worker return false;
1360*795d594fSAndroid Build Coastguard Worker }
1361*795d594fSAndroid Build Coastguard Worker return true;
1362*795d594fSAndroid Build Coastguard Worker }
1363*795d594fSAndroid Build Coastguard Worker
CheckIntraTypeIdItem()1364*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraTypeIdItem() {
1365*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(ptr_, 1, sizeof(dex::TypeId), "type_ids")) {
1366*795d594fSAndroid Build Coastguard Worker return false;
1367*795d594fSAndroid Build Coastguard Worker }
1368*795d594fSAndroid Build Coastguard Worker
1369*795d594fSAndroid Build Coastguard Worker const dex::TypeId* type_id = reinterpret_cast<const dex::TypeId*>(ptr_);
1370*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(type_id->descriptor_idx_.index_,
1371*795d594fSAndroid Build Coastguard Worker header_->string_ids_size_,
1372*795d594fSAndroid Build Coastguard Worker "type_id.descriptor")) {
1373*795d594fSAndroid Build Coastguard Worker return false;
1374*795d594fSAndroid Build Coastguard Worker }
1375*795d594fSAndroid Build Coastguard Worker
1376*795d594fSAndroid Build Coastguard Worker ptr_ += sizeof(dex::TypeId);
1377*795d594fSAndroid Build Coastguard Worker return true;
1378*795d594fSAndroid Build Coastguard Worker }
1379*795d594fSAndroid Build Coastguard Worker
CheckIntraProtoIdItem()1380*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraProtoIdItem() {
1381*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(ptr_, 1, sizeof(dex::ProtoId), "proto_ids")) {
1382*795d594fSAndroid Build Coastguard Worker return false;
1383*795d594fSAndroid Build Coastguard Worker }
1384*795d594fSAndroid Build Coastguard Worker
1385*795d594fSAndroid Build Coastguard Worker const dex::ProtoId* proto_id = reinterpret_cast<const dex::ProtoId*>(ptr_);
1386*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(proto_id->shorty_idx_.index_, header_->string_ids_size_, "proto_id.shorty") ||
1387*795d594fSAndroid Build Coastguard Worker !CheckIndex(proto_id->return_type_idx_.index_,
1388*795d594fSAndroid Build Coastguard Worker header_->type_ids_size_,
1389*795d594fSAndroid Build Coastguard Worker "proto_id.return_type")) {
1390*795d594fSAndroid Build Coastguard Worker return false;
1391*795d594fSAndroid Build Coastguard Worker }
1392*795d594fSAndroid Build Coastguard Worker
1393*795d594fSAndroid Build Coastguard Worker ptr_ += sizeof(dex::ProtoId);
1394*795d594fSAndroid Build Coastguard Worker return true;
1395*795d594fSAndroid Build Coastguard Worker }
1396*795d594fSAndroid Build Coastguard Worker
CheckIntraFieldIdItem()1397*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraFieldIdItem() {
1398*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(ptr_, 1, sizeof(dex::FieldId), "field_ids")) {
1399*795d594fSAndroid Build Coastguard Worker return false;
1400*795d594fSAndroid Build Coastguard Worker }
1401*795d594fSAndroid Build Coastguard Worker
1402*795d594fSAndroid Build Coastguard Worker const dex::FieldId* field_id = reinterpret_cast<const dex::FieldId*>(ptr_);
1403*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(field_id->class_idx_.index_, header_->type_ids_size_, "field_id.class") ||
1404*795d594fSAndroid Build Coastguard Worker !CheckIndex(field_id->type_idx_.index_, header_->type_ids_size_, "field_id.type") ||
1405*795d594fSAndroid Build Coastguard Worker !CheckIndex(field_id->name_idx_.index_, header_->string_ids_size_, "field_id.name")) {
1406*795d594fSAndroid Build Coastguard Worker return false;
1407*795d594fSAndroid Build Coastguard Worker }
1408*795d594fSAndroid Build Coastguard Worker
1409*795d594fSAndroid Build Coastguard Worker ptr_ += sizeof(dex::FieldId);
1410*795d594fSAndroid Build Coastguard Worker return true;
1411*795d594fSAndroid Build Coastguard Worker }
1412*795d594fSAndroid Build Coastguard Worker
CheckIntraMethodIdItem()1413*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraMethodIdItem() {
1414*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(ptr_, 1, sizeof(dex::MethodId), "method_ids")) {
1415*795d594fSAndroid Build Coastguard Worker return false;
1416*795d594fSAndroid Build Coastguard Worker }
1417*795d594fSAndroid Build Coastguard Worker
1418*795d594fSAndroid Build Coastguard Worker const dex::MethodId* method_id = reinterpret_cast<const dex::MethodId*>(ptr_);
1419*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(method_id->class_idx_.index_, header_->type_ids_size_, "method_id.class") ||
1420*795d594fSAndroid Build Coastguard Worker !CheckIndex(method_id->proto_idx_.index_, header_->proto_ids_size_, "method_id.proto") ||
1421*795d594fSAndroid Build Coastguard Worker !CheckIndex(method_id->name_idx_.index_, header_->string_ids_size_, "method_id.name")) {
1422*795d594fSAndroid Build Coastguard Worker return false;
1423*795d594fSAndroid Build Coastguard Worker }
1424*795d594fSAndroid Build Coastguard Worker
1425*795d594fSAndroid Build Coastguard Worker ptr_ += sizeof(dex::MethodId);
1426*795d594fSAndroid Build Coastguard Worker return true;
1427*795d594fSAndroid Build Coastguard Worker }
1428*795d594fSAndroid Build Coastguard Worker
CheckIntraClassDefItem(uint32_t class_def_index)1429*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraClassDefItem(uint32_t class_def_index) {
1430*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(ptr_, 1, sizeof(dex::ClassDef), "class_defs")) {
1431*795d594fSAndroid Build Coastguard Worker return false;
1432*795d594fSAndroid Build Coastguard Worker }
1433*795d594fSAndroid Build Coastguard Worker
1434*795d594fSAndroid Build Coastguard Worker const dex::ClassDef* class_def = reinterpret_cast<const dex::ClassDef*>(ptr_);
1435*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(class_def->class_idx_.index_, header_->type_ids_size_, "class_def.class")) {
1436*795d594fSAndroid Build Coastguard Worker return false;
1437*795d594fSAndroid Build Coastguard Worker }
1438*795d594fSAndroid Build Coastguard Worker
1439*795d594fSAndroid Build Coastguard Worker // Check superclass, if any.
1440*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(class_def->pad2_ != 0u)) {
1441*795d594fSAndroid Build Coastguard Worker uint32_t combined =
1442*795d594fSAndroid Build Coastguard Worker (static_cast<uint32_t>(class_def->pad2_) << 16) + class_def->superclass_idx_.index_;
1443*795d594fSAndroid Build Coastguard Worker if (combined != 0xffffffffu) {
1444*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid superclass type padding/index: %x", combined);
1445*795d594fSAndroid Build Coastguard Worker return false;
1446*795d594fSAndroid Build Coastguard Worker }
1447*795d594fSAndroid Build Coastguard Worker } else if (!CheckIndex(class_def->superclass_idx_.index_,
1448*795d594fSAndroid Build Coastguard Worker header_->type_ids_size_,
1449*795d594fSAndroid Build Coastguard Worker "class_def.superclass")) {
1450*795d594fSAndroid Build Coastguard Worker return false;
1451*795d594fSAndroid Build Coastguard Worker }
1452*795d594fSAndroid Build Coastguard Worker
1453*795d594fSAndroid Build Coastguard Worker DCHECK_LE(class_def->class_idx_.index_, kTypeIdLimit);
1454*795d594fSAndroid Build Coastguard Worker DCHECK_LT(kTypeIdLimit, defined_classes_.size());
1455*795d594fSAndroid Build Coastguard Worker if (defined_classes_[class_def->class_idx_.index_]) {
1456*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Redefinition of class with type idx: '%u'", class_def->class_idx_.index_);
1457*795d594fSAndroid Build Coastguard Worker return false;
1458*795d594fSAndroid Build Coastguard Worker }
1459*795d594fSAndroid Build Coastguard Worker defined_classes_[class_def->class_idx_.index_] = true;
1460*795d594fSAndroid Build Coastguard Worker DCHECK_LE(class_def->class_idx_.index_, defined_class_indexes_.size());
1461*795d594fSAndroid Build Coastguard Worker defined_class_indexes_[class_def->class_idx_.index_] = class_def_index;
1462*795d594fSAndroid Build Coastguard Worker
1463*795d594fSAndroid Build Coastguard Worker ptr_ += sizeof(dex::ClassDef);
1464*795d594fSAndroid Build Coastguard Worker return true;
1465*795d594fSAndroid Build Coastguard Worker }
1466*795d594fSAndroid Build Coastguard Worker
CheckIntraMethodHandleItem()1467*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraMethodHandleItem() {
1468*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(ptr_, 1, sizeof(dex::MethodHandleItem), "method_handles")) {
1469*795d594fSAndroid Build Coastguard Worker return false;
1470*795d594fSAndroid Build Coastguard Worker }
1471*795d594fSAndroid Build Coastguard Worker
1472*795d594fSAndroid Build Coastguard Worker const dex::MethodHandleItem* item = reinterpret_cast<const dex::MethodHandleItem*>(ptr_);
1473*795d594fSAndroid Build Coastguard Worker
1474*795d594fSAndroid Build Coastguard Worker DexFile::MethodHandleType method_handle_type =
1475*795d594fSAndroid Build Coastguard Worker static_cast<DexFile::MethodHandleType>(item->method_handle_type_);
1476*795d594fSAndroid Build Coastguard Worker if (method_handle_type > DexFile::MethodHandleType::kLast) {
1477*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad method handle type %x", item->method_handle_type_);
1478*795d594fSAndroid Build Coastguard Worker return false;
1479*795d594fSAndroid Build Coastguard Worker }
1480*795d594fSAndroid Build Coastguard Worker
1481*795d594fSAndroid Build Coastguard Worker uint32_t index = item->field_or_method_idx_;
1482*795d594fSAndroid Build Coastguard Worker switch (method_handle_type) {
1483*795d594fSAndroid Build Coastguard Worker case DexFile::MethodHandleType::kStaticPut:
1484*795d594fSAndroid Build Coastguard Worker case DexFile::MethodHandleType::kStaticGet:
1485*795d594fSAndroid Build Coastguard Worker case DexFile::MethodHandleType::kInstancePut:
1486*795d594fSAndroid Build Coastguard Worker case DexFile::MethodHandleType::kInstanceGet:
1487*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(index, header_->field_ids_size_, "method_handle_item field_idx")) {
1488*795d594fSAndroid Build Coastguard Worker return false;
1489*795d594fSAndroid Build Coastguard Worker }
1490*795d594fSAndroid Build Coastguard Worker break;
1491*795d594fSAndroid Build Coastguard Worker case DexFile::MethodHandleType::kInvokeStatic:
1492*795d594fSAndroid Build Coastguard Worker case DexFile::MethodHandleType::kInvokeInstance:
1493*795d594fSAndroid Build Coastguard Worker case DexFile::MethodHandleType::kInvokeConstructor:
1494*795d594fSAndroid Build Coastguard Worker case DexFile::MethodHandleType::kInvokeDirect:
1495*795d594fSAndroid Build Coastguard Worker case DexFile::MethodHandleType::kInvokeInterface: {
1496*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(index, header_->method_ids_size_, "method_handle_item method_idx")) {
1497*795d594fSAndroid Build Coastguard Worker return false;
1498*795d594fSAndroid Build Coastguard Worker }
1499*795d594fSAndroid Build Coastguard Worker break;
1500*795d594fSAndroid Build Coastguard Worker }
1501*795d594fSAndroid Build Coastguard Worker }
1502*795d594fSAndroid Build Coastguard Worker
1503*795d594fSAndroid Build Coastguard Worker ptr_ += sizeof(dex::MethodHandleItem);
1504*795d594fSAndroid Build Coastguard Worker return true;
1505*795d594fSAndroid Build Coastguard Worker }
1506*795d594fSAndroid Build Coastguard Worker
CheckIntraTypeList()1507*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraTypeList() {
1508*795d594fSAndroid Build Coastguard Worker const dex::TypeList* type_list = reinterpret_cast<const dex::TypeList*>(ptr_);
1509*795d594fSAndroid Build Coastguard Worker if (!CheckList(sizeof(dex::TypeItem), "type_list", &ptr_)) {
1510*795d594fSAndroid Build Coastguard Worker return false;
1511*795d594fSAndroid Build Coastguard Worker }
1512*795d594fSAndroid Build Coastguard Worker
1513*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0, size = type_list->Size(); i != size; ++i) {
1514*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(type_list->GetTypeItem(i).type_idx_.index_,
1515*795d594fSAndroid Build Coastguard Worker header_->type_ids_size_,
1516*795d594fSAndroid Build Coastguard Worker "type_list.type")) {
1517*795d594fSAndroid Build Coastguard Worker return false;
1518*795d594fSAndroid Build Coastguard Worker }
1519*795d594fSAndroid Build Coastguard Worker }
1520*795d594fSAndroid Build Coastguard Worker
1521*795d594fSAndroid Build Coastguard Worker return true;
1522*795d594fSAndroid Build Coastguard Worker }
1523*795d594fSAndroid Build Coastguard Worker
1524*795d594fSAndroid Build Coastguard Worker template <bool kStatic>
CheckIntraClassDataItemFields(size_t count)1525*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraClassDataItemFields(size_t count) {
1526*795d594fSAndroid Build Coastguard Worker constexpr const char* kTypeDescr = kStatic ? "static field" : "instance field";
1527*795d594fSAndroid Build Coastguard Worker
1528*795d594fSAndroid Build Coastguard Worker // We cannot use ClassAccessor::Field yet as it could read beyond the end of the data section.
1529*795d594fSAndroid Build Coastguard Worker const uint8_t* ptr = ptr_;
1530*795d594fSAndroid Build Coastguard Worker
1531*795d594fSAndroid Build Coastguard Worker uint32_t prev_index = 0;
1532*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i != count; ++i) {
1533*795d594fSAndroid Build Coastguard Worker uint32_t field_idx_diff, access_flags;
1534*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &field_idx_diff)) ||
1535*795d594fSAndroid Build Coastguard Worker UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &access_flags))) {
1536*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("encoded_field read out of bounds");
1537*795d594fSAndroid Build Coastguard Worker return false;
1538*795d594fSAndroid Build Coastguard Worker }
1539*795d594fSAndroid Build Coastguard Worker uint32_t curr_index = prev_index + field_idx_diff;
1540*795d594fSAndroid Build Coastguard Worker // Check for overflow.
1541*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(curr_index, header_->field_ids_size_, "class_data_item field_idx")) {
1542*795d594fSAndroid Build Coastguard Worker return false;
1543*795d594fSAndroid Build Coastguard Worker }
1544*795d594fSAndroid Build Coastguard Worker if (!CheckOrder(kTypeDescr, curr_index, prev_index)) {
1545*795d594fSAndroid Build Coastguard Worker return false;
1546*795d594fSAndroid Build Coastguard Worker }
1547*795d594fSAndroid Build Coastguard Worker // Check that it falls into the right class-data list.
1548*795d594fSAndroid Build Coastguard Worker bool is_static = (access_flags & kAccStatic) != 0;
1549*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(is_static != kStatic)) {
1550*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Static/instance field not in expected list");
1551*795d594fSAndroid Build Coastguard Worker return false;
1552*795d594fSAndroid Build Coastguard Worker }
1553*795d594fSAndroid Build Coastguard Worker
1554*795d594fSAndroid Build Coastguard Worker prev_index = curr_index;
1555*795d594fSAndroid Build Coastguard Worker }
1556*795d594fSAndroid Build Coastguard Worker
1557*795d594fSAndroid Build Coastguard Worker ptr_ = ptr;
1558*795d594fSAndroid Build Coastguard Worker return true;
1559*795d594fSAndroid Build Coastguard Worker }
1560*795d594fSAndroid Build Coastguard Worker
CheckIntraClassDataItemMethods(size_t num_methods,ClassAccessor::Method * direct_methods,size_t num_direct_methods)1561*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraClassDataItemMethods(size_t num_methods,
1562*795d594fSAndroid Build Coastguard Worker ClassAccessor::Method* direct_methods,
1563*795d594fSAndroid Build Coastguard Worker size_t num_direct_methods) {
1564*795d594fSAndroid Build Coastguard Worker DCHECK(num_direct_methods == 0u || direct_methods != nullptr);
1565*795d594fSAndroid Build Coastguard Worker const char* kTypeDescr = (direct_methods == nullptr) ? "direct method" : "virtual method";
1566*795d594fSAndroid Build Coastguard Worker
1567*795d594fSAndroid Build Coastguard Worker // We cannot use ClassAccessor::Method yet as it could read beyond the end of the data section.
1568*795d594fSAndroid Build Coastguard Worker const uint8_t* ptr = ptr_;
1569*795d594fSAndroid Build Coastguard Worker
1570*795d594fSAndroid Build Coastguard Worker // Load the first direct method for the check below.
1571*795d594fSAndroid Build Coastguard Worker size_t remaining_direct_methods = num_direct_methods;
1572*795d594fSAndroid Build Coastguard Worker if (remaining_direct_methods != 0u) {
1573*795d594fSAndroid Build Coastguard Worker DCHECK(direct_methods != nullptr);
1574*795d594fSAndroid Build Coastguard Worker direct_methods->Read();
1575*795d594fSAndroid Build Coastguard Worker }
1576*795d594fSAndroid Build Coastguard Worker
1577*795d594fSAndroid Build Coastguard Worker uint32_t prev_index = 0;
1578*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i != num_methods; ++i) {
1579*795d594fSAndroid Build Coastguard Worker uint32_t method_idx_diff, access_flags, code_off;
1580*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &method_idx_diff)) ||
1581*795d594fSAndroid Build Coastguard Worker UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &access_flags)) ||
1582*795d594fSAndroid Build Coastguard Worker UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &code_off))) {
1583*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("encoded_method read out of bounds");
1584*795d594fSAndroid Build Coastguard Worker return false;
1585*795d594fSAndroid Build Coastguard Worker }
1586*795d594fSAndroid Build Coastguard Worker uint32_t curr_index = prev_index + method_idx_diff;
1587*795d594fSAndroid Build Coastguard Worker // Check for overflow.
1588*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(curr_index, header_->method_ids_size_, "class_data_item method_idx")) {
1589*795d594fSAndroid Build Coastguard Worker return false;
1590*795d594fSAndroid Build Coastguard Worker }
1591*795d594fSAndroid Build Coastguard Worker if (!CheckOrder(kTypeDescr, curr_index, prev_index)) {
1592*795d594fSAndroid Build Coastguard Worker return false;
1593*795d594fSAndroid Build Coastguard Worker }
1594*795d594fSAndroid Build Coastguard Worker
1595*795d594fSAndroid Build Coastguard Worker // For virtual methods, we cross reference the method index to make sure
1596*795d594fSAndroid Build Coastguard Worker // it doesn't match any direct methods.
1597*795d594fSAndroid Build Coastguard Worker if (remaining_direct_methods != 0) {
1598*795d594fSAndroid Build Coastguard Worker // The direct methods are already known to be in ascending index order.
1599*795d594fSAndroid Build Coastguard Worker // So just keep up with the current index.
1600*795d594fSAndroid Build Coastguard Worker while (true) {
1601*795d594fSAndroid Build Coastguard Worker const uint32_t direct_idx = direct_methods->GetIndex();
1602*795d594fSAndroid Build Coastguard Worker if (direct_idx > curr_index) {
1603*795d594fSAndroid Build Coastguard Worker break;
1604*795d594fSAndroid Build Coastguard Worker }
1605*795d594fSAndroid Build Coastguard Worker if (direct_idx == curr_index) {
1606*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Found virtual method with same index as direct method: %u",
1607*795d594fSAndroid Build Coastguard Worker curr_index);
1608*795d594fSAndroid Build Coastguard Worker return false;
1609*795d594fSAndroid Build Coastguard Worker }
1610*795d594fSAndroid Build Coastguard Worker --remaining_direct_methods;
1611*795d594fSAndroid Build Coastguard Worker if (remaining_direct_methods == 0u) {
1612*795d594fSAndroid Build Coastguard Worker break;
1613*795d594fSAndroid Build Coastguard Worker }
1614*795d594fSAndroid Build Coastguard Worker direct_methods->Read();
1615*795d594fSAndroid Build Coastguard Worker }
1616*795d594fSAndroid Build Coastguard Worker }
1617*795d594fSAndroid Build Coastguard Worker
1618*795d594fSAndroid Build Coastguard Worker prev_index = curr_index;
1619*795d594fSAndroid Build Coastguard Worker }
1620*795d594fSAndroid Build Coastguard Worker
1621*795d594fSAndroid Build Coastguard Worker ptr_ = ptr;
1622*795d594fSAndroid Build Coastguard Worker return true;
1623*795d594fSAndroid Build Coastguard Worker }
1624*795d594fSAndroid Build Coastguard Worker
CheckIntraClassDataItem()1625*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraClassDataItem() {
1626*795d594fSAndroid Build Coastguard Worker // We cannot use ClassAccessor yet as it could read beyond the end of the data section.
1627*795d594fSAndroid Build Coastguard Worker const uint8_t* ptr = ptr_;
1628*795d594fSAndroid Build Coastguard Worker uint32_t static_fields_size, instance_fields_size, direct_methods_size, virtual_methods_size;
1629*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &static_fields_size)) ||
1630*795d594fSAndroid Build Coastguard Worker UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &instance_fields_size)) ||
1631*795d594fSAndroid Build Coastguard Worker UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &direct_methods_size)) ||
1632*795d594fSAndroid Build Coastguard Worker UNLIKELY(!DecodeUnsignedLeb128Checked(&ptr, data_.end(), &virtual_methods_size))) {
1633*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("class_data_item read out of bounds");
1634*795d594fSAndroid Build Coastguard Worker return false;
1635*795d594fSAndroid Build Coastguard Worker }
1636*795d594fSAndroid Build Coastguard Worker ptr_ = ptr;
1637*795d594fSAndroid Build Coastguard Worker
1638*795d594fSAndroid Build Coastguard Worker // Check fields.
1639*795d594fSAndroid Build Coastguard Worker if (!CheckIntraClassDataItemFields</*kStatic=*/ true>(static_fields_size)) {
1640*795d594fSAndroid Build Coastguard Worker return false;
1641*795d594fSAndroid Build Coastguard Worker }
1642*795d594fSAndroid Build Coastguard Worker if (!CheckIntraClassDataItemFields</*kStatic=*/ false>(instance_fields_size)) {
1643*795d594fSAndroid Build Coastguard Worker return false;
1644*795d594fSAndroid Build Coastguard Worker }
1645*795d594fSAndroid Build Coastguard Worker
1646*795d594fSAndroid Build Coastguard Worker // Check methods.
1647*795d594fSAndroid Build Coastguard Worker const uint8_t* direct_methods_ptr = ptr_;
1648*795d594fSAndroid Build Coastguard Worker if (!CheckIntraClassDataItemMethods(direct_methods_size,
1649*795d594fSAndroid Build Coastguard Worker /*direct_methods=*/ nullptr,
1650*795d594fSAndroid Build Coastguard Worker /*num_direct_methods=*/ 0u)) {
1651*795d594fSAndroid Build Coastguard Worker return false;
1652*795d594fSAndroid Build Coastguard Worker }
1653*795d594fSAndroid Build Coastguard Worker // Direct methods have been checked, so we can now use ClassAccessor::Method to read them again.
1654*795d594fSAndroid Build Coastguard Worker ClassAccessor::Method direct_methods(*dex_file_, direct_methods_ptr);
1655*795d594fSAndroid Build Coastguard Worker if (!CheckIntraClassDataItemMethods(virtual_methods_size, &direct_methods, direct_methods_size)) {
1656*795d594fSAndroid Build Coastguard Worker return false;
1657*795d594fSAndroid Build Coastguard Worker }
1658*795d594fSAndroid Build Coastguard Worker
1659*795d594fSAndroid Build Coastguard Worker return true;
1660*795d594fSAndroid Build Coastguard Worker }
1661*795d594fSAndroid Build Coastguard Worker
CheckIntraCodeItem()1662*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraCodeItem() {
1663*795d594fSAndroid Build Coastguard Worker const dex::CodeItem* code_item = reinterpret_cast<const dex::CodeItem*>(ptr_);
1664*795d594fSAndroid Build Coastguard Worker
1665*795d594fSAndroid Build Coastguard Worker DCHECK(dex_file_->IsStandardDexFile());
1666*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(code_item, 1, sizeof(StandardDexFile::CodeItem), "code")) {
1667*795d594fSAndroid Build Coastguard Worker return false;
1668*795d594fSAndroid Build Coastguard Worker }
1669*795d594fSAndroid Build Coastguard Worker
1670*795d594fSAndroid Build Coastguard Worker CodeItemDataAccessor accessor(*dex_file_, code_item);
1671*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(accessor.InsSize() > accessor.RegistersSize())) {
1672*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("ins_size (%ud) > registers_size (%ud)",
1673*795d594fSAndroid Build Coastguard Worker accessor.InsSize(), accessor.RegistersSize());
1674*795d594fSAndroid Build Coastguard Worker return false;
1675*795d594fSAndroid Build Coastguard Worker }
1676*795d594fSAndroid Build Coastguard Worker
1677*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(accessor.OutsSize() > 5 && accessor.OutsSize() > accessor.RegistersSize())) {
1678*795d594fSAndroid Build Coastguard Worker /*
1679*795d594fSAndroid Build Coastguard Worker * outs_size can be up to 5, even if registers_size is smaller, since the
1680*795d594fSAndroid Build Coastguard Worker * short forms of method invocation allow repetitions of a register multiple
1681*795d594fSAndroid Build Coastguard Worker * times within a single parameter list. However, longer parameter lists
1682*795d594fSAndroid Build Coastguard Worker * need to be represented in-order in the register file.
1683*795d594fSAndroid Build Coastguard Worker */
1684*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("outs_size (%ud) > registers_size (%ud)",
1685*795d594fSAndroid Build Coastguard Worker accessor.OutsSize(), accessor.RegistersSize());
1686*795d594fSAndroid Build Coastguard Worker return false;
1687*795d594fSAndroid Build Coastguard Worker }
1688*795d594fSAndroid Build Coastguard Worker
1689*795d594fSAndroid Build Coastguard Worker const uint16_t* insns = accessor.Insns();
1690*795d594fSAndroid Build Coastguard Worker uint32_t insns_size = accessor.InsnsSizeInCodeUnits();
1691*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(insns, insns_size, sizeof(uint16_t), "insns size")) {
1692*795d594fSAndroid Build Coastguard Worker return false;
1693*795d594fSAndroid Build Coastguard Worker }
1694*795d594fSAndroid Build Coastguard Worker
1695*795d594fSAndroid Build Coastguard Worker // Grab the end of the insns if there are no try_items.
1696*795d594fSAndroid Build Coastguard Worker uint32_t try_items_size = accessor.TriesSize();
1697*795d594fSAndroid Build Coastguard Worker if (try_items_size == 0) {
1698*795d594fSAndroid Build Coastguard Worker ptr_ = reinterpret_cast<const uint8_t*>(&insns[insns_size]);
1699*795d594fSAndroid Build Coastguard Worker return true;
1700*795d594fSAndroid Build Coastguard Worker }
1701*795d594fSAndroid Build Coastguard Worker
1702*795d594fSAndroid Build Coastguard Worker const dex::TryItem* try_items = accessor.TryItems().begin();
1703*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(try_items, try_items_size, sizeof(dex::TryItem), "try_items size")) {
1704*795d594fSAndroid Build Coastguard Worker return false;
1705*795d594fSAndroid Build Coastguard Worker }
1706*795d594fSAndroid Build Coastguard Worker
1707*795d594fSAndroid Build Coastguard Worker // try_items are 4-byte aligned. Verify the spacer is 0.
1708*795d594fSAndroid Build Coastguard Worker if (((reinterpret_cast<uintptr_t>(&insns[insns_size]) & 3) != 0) && (insns[insns_size] != 0)) {
1709*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Non-zero padding: %x", insns[insns_size]);
1710*795d594fSAndroid Build Coastguard Worker return false;
1711*795d594fSAndroid Build Coastguard Worker }
1712*795d594fSAndroid Build Coastguard Worker
1713*795d594fSAndroid Build Coastguard Worker ptr_ = accessor.GetCatchHandlerData();
1714*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, handlers_size);
1715*795d594fSAndroid Build Coastguard Worker
1716*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((handlers_size == 0) || (handlers_size >= 65536))) {
1717*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid handlers_size: %ud", handlers_size);
1718*795d594fSAndroid Build Coastguard Worker return false;
1719*795d594fSAndroid Build Coastguard Worker }
1720*795d594fSAndroid Build Coastguard Worker
1721*795d594fSAndroid Build Coastguard Worker // Avoid an expensive allocation, if possible.
1722*795d594fSAndroid Build Coastguard Worker std::unique_ptr<uint32_t[]> handler_offsets_uptr;
1723*795d594fSAndroid Build Coastguard Worker uint32_t* handler_offsets;
1724*795d594fSAndroid Build Coastguard Worker constexpr size_t kAllocaMaxSize = 1024;
1725*795d594fSAndroid Build Coastguard Worker if (handlers_size < kAllocaMaxSize/sizeof(uint32_t)) {
1726*795d594fSAndroid Build Coastguard Worker // Note: Clang does not specify alignment guarantees for alloca. So align by hand.
1727*795d594fSAndroid Build Coastguard Worker handler_offsets =
1728*795d594fSAndroid Build Coastguard Worker AlignUp(reinterpret_cast<uint32_t*>(alloca((handlers_size + 1) * sizeof(uint32_t))),
1729*795d594fSAndroid Build Coastguard Worker alignof(uint32_t[]));
1730*795d594fSAndroid Build Coastguard Worker } else {
1731*795d594fSAndroid Build Coastguard Worker handler_offsets_uptr.reset(new uint32_t[handlers_size]);
1732*795d594fSAndroid Build Coastguard Worker handler_offsets = handler_offsets_uptr.get();
1733*795d594fSAndroid Build Coastguard Worker }
1734*795d594fSAndroid Build Coastguard Worker
1735*795d594fSAndroid Build Coastguard Worker if (!CheckAndGetHandlerOffsets(code_item, &handler_offsets[0], handlers_size)) {
1736*795d594fSAndroid Build Coastguard Worker return false;
1737*795d594fSAndroid Build Coastguard Worker }
1738*795d594fSAndroid Build Coastguard Worker
1739*795d594fSAndroid Build Coastguard Worker uint32_t last_addr = 0;
1740*795d594fSAndroid Build Coastguard Worker for (; try_items_size != 0u; --try_items_size) {
1741*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(try_items->start_addr_ < last_addr)) {
1742*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of_order try_item with start_addr: %x", try_items->start_addr_);
1743*795d594fSAndroid Build Coastguard Worker return false;
1744*795d594fSAndroid Build Coastguard Worker }
1745*795d594fSAndroid Build Coastguard Worker
1746*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(try_items->start_addr_ >= insns_size)) {
1747*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid try_item start_addr: %x", try_items->start_addr_);
1748*795d594fSAndroid Build Coastguard Worker return false;
1749*795d594fSAndroid Build Coastguard Worker }
1750*795d594fSAndroid Build Coastguard Worker
1751*795d594fSAndroid Build Coastguard Worker uint32_t i;
1752*795d594fSAndroid Build Coastguard Worker for (i = 0; i < handlers_size; i++) {
1753*795d594fSAndroid Build Coastguard Worker if (try_items->handler_off_ == handler_offsets[i]) {
1754*795d594fSAndroid Build Coastguard Worker break;
1755*795d594fSAndroid Build Coastguard Worker }
1756*795d594fSAndroid Build Coastguard Worker }
1757*795d594fSAndroid Build Coastguard Worker
1758*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(i == handlers_size)) {
1759*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bogus handler offset: %x", try_items->handler_off_);
1760*795d594fSAndroid Build Coastguard Worker return false;
1761*795d594fSAndroid Build Coastguard Worker }
1762*795d594fSAndroid Build Coastguard Worker
1763*795d594fSAndroid Build Coastguard Worker last_addr = try_items->start_addr_ + try_items->insn_count_;
1764*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(last_addr > insns_size)) {
1765*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid try_item insn_count: %x", try_items->insn_count_);
1766*795d594fSAndroid Build Coastguard Worker return false;
1767*795d594fSAndroid Build Coastguard Worker }
1768*795d594fSAndroid Build Coastguard Worker
1769*795d594fSAndroid Build Coastguard Worker try_items++;
1770*795d594fSAndroid Build Coastguard Worker }
1771*795d594fSAndroid Build Coastguard Worker
1772*795d594fSAndroid Build Coastguard Worker return true;
1773*795d594fSAndroid Build Coastguard Worker }
1774*795d594fSAndroid Build Coastguard Worker
CheckIntraStringDataItem()1775*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraStringDataItem() {
1776*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, size);
1777*795d594fSAndroid Build Coastguard Worker const uint8_t* file_end = EndOfFile();
1778*795d594fSAndroid Build Coastguard Worker
1779*795d594fSAndroid Build Coastguard Worker size_t available_bytes = static_cast<size_t>(file_end - ptr_);
1780*795d594fSAndroid Build Coastguard Worker if (available_bytes < size) {
1781*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("String data would go beyond end-of-file");
1782*795d594fSAndroid Build Coastguard Worker return false;
1783*795d594fSAndroid Build Coastguard Worker }
1784*795d594fSAndroid Build Coastguard Worker // Eagerly subtract one byte per character.
1785*795d594fSAndroid Build Coastguard Worker available_bytes -= size;
1786*795d594fSAndroid Build Coastguard Worker
1787*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < size; i++) {
1788*795d594fSAndroid Build Coastguard Worker CHECK_LT(i, size); // b/15014252 Prevents hitting the impossible case below
1789*795d594fSAndroid Build Coastguard Worker uint8_t byte = *(ptr_++);
1790*795d594fSAndroid Build Coastguard Worker
1791*795d594fSAndroid Build Coastguard Worker // Switch on the high 4 bits.
1792*795d594fSAndroid Build Coastguard Worker switch (byte >> 4) {
1793*795d594fSAndroid Build Coastguard Worker case 0x00:
1794*795d594fSAndroid Build Coastguard Worker // Special case of bit pattern 0xxx.
1795*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(byte == 0)) {
1796*795d594fSAndroid Build Coastguard Worker CHECK_LT(i, size); // b/15014252 Actually hit this impossible case with clang
1797*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("String data shorter than indicated utf16_size %x", size);
1798*795d594fSAndroid Build Coastguard Worker return false;
1799*795d594fSAndroid Build Coastguard Worker }
1800*795d594fSAndroid Build Coastguard Worker break;
1801*795d594fSAndroid Build Coastguard Worker case 0x01:
1802*795d594fSAndroid Build Coastguard Worker case 0x02:
1803*795d594fSAndroid Build Coastguard Worker case 0x03:
1804*795d594fSAndroid Build Coastguard Worker case 0x04:
1805*795d594fSAndroid Build Coastguard Worker case 0x05:
1806*795d594fSAndroid Build Coastguard Worker case 0x06:
1807*795d594fSAndroid Build Coastguard Worker case 0x07:
1808*795d594fSAndroid Build Coastguard Worker // No extra checks necessary for bit pattern 0xxx.
1809*795d594fSAndroid Build Coastguard Worker break;
1810*795d594fSAndroid Build Coastguard Worker case 0x08:
1811*795d594fSAndroid Build Coastguard Worker case 0x09:
1812*795d594fSAndroid Build Coastguard Worker case 0x0a:
1813*795d594fSAndroid Build Coastguard Worker case 0x0b:
1814*795d594fSAndroid Build Coastguard Worker case 0x0f:
1815*795d594fSAndroid Build Coastguard Worker // Illegal bit patterns 10xx or 1111.
1816*795d594fSAndroid Build Coastguard Worker // Note: 1111 is valid for normal UTF-8, but not here.
1817*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Illegal start byte %x in string data", byte);
1818*795d594fSAndroid Build Coastguard Worker return false;
1819*795d594fSAndroid Build Coastguard Worker case 0x0c:
1820*795d594fSAndroid Build Coastguard Worker case 0x0d: {
1821*795d594fSAndroid Build Coastguard Worker // Bit pattern 110x has an additional byte.
1822*795d594fSAndroid Build Coastguard Worker if (available_bytes < 1u) {
1823*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("String data would go beyond end-of-file");
1824*795d594fSAndroid Build Coastguard Worker return false;
1825*795d594fSAndroid Build Coastguard Worker }
1826*795d594fSAndroid Build Coastguard Worker available_bytes -= 1u;
1827*795d594fSAndroid Build Coastguard Worker
1828*795d594fSAndroid Build Coastguard Worker uint8_t byte2 = *(ptr_++);
1829*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((byte2 & 0xc0) != 0x80)) {
1830*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Illegal continuation byte %x in string data", byte2);
1831*795d594fSAndroid Build Coastguard Worker return false;
1832*795d594fSAndroid Build Coastguard Worker }
1833*795d594fSAndroid Build Coastguard Worker uint16_t value = ((byte & 0x1f) << 6) | (byte2 & 0x3f);
1834*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((value != 0) && (value < 0x80))) {
1835*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Illegal representation for value %x in string data", value);
1836*795d594fSAndroid Build Coastguard Worker return false;
1837*795d594fSAndroid Build Coastguard Worker }
1838*795d594fSAndroid Build Coastguard Worker break;
1839*795d594fSAndroid Build Coastguard Worker }
1840*795d594fSAndroid Build Coastguard Worker case 0x0e: {
1841*795d594fSAndroid Build Coastguard Worker // Bit pattern 1110 has 2 additional bytes.
1842*795d594fSAndroid Build Coastguard Worker if (available_bytes < 2u) {
1843*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("String data would go beyond end-of-file");
1844*795d594fSAndroid Build Coastguard Worker return false;
1845*795d594fSAndroid Build Coastguard Worker }
1846*795d594fSAndroid Build Coastguard Worker available_bytes -= 2u;
1847*795d594fSAndroid Build Coastguard Worker
1848*795d594fSAndroid Build Coastguard Worker uint8_t byte2 = *(ptr_++);
1849*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((byte2 & 0xc0) != 0x80)) {
1850*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Illegal continuation byte %x in string data", byte2);
1851*795d594fSAndroid Build Coastguard Worker return false;
1852*795d594fSAndroid Build Coastguard Worker }
1853*795d594fSAndroid Build Coastguard Worker uint8_t byte3 = *(ptr_++);
1854*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((byte3 & 0xc0) != 0x80)) {
1855*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Illegal continuation byte %x in string data", byte3);
1856*795d594fSAndroid Build Coastguard Worker return false;
1857*795d594fSAndroid Build Coastguard Worker }
1858*795d594fSAndroid Build Coastguard Worker uint16_t value = ((byte & 0x0f) << 12) | ((byte2 & 0x3f) << 6) | (byte3 & 0x3f);
1859*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(value < 0x800)) {
1860*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Illegal representation for value %x in string data", value);
1861*795d594fSAndroid Build Coastguard Worker return false;
1862*795d594fSAndroid Build Coastguard Worker }
1863*795d594fSAndroid Build Coastguard Worker break;
1864*795d594fSAndroid Build Coastguard Worker }
1865*795d594fSAndroid Build Coastguard Worker }
1866*795d594fSAndroid Build Coastguard Worker }
1867*795d594fSAndroid Build Coastguard Worker
1868*795d594fSAndroid Build Coastguard Worker if (available_bytes < 1u) {
1869*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("String data would go beyond end-of-file");
1870*795d594fSAndroid Build Coastguard Worker return false;
1871*795d594fSAndroid Build Coastguard Worker }
1872*795d594fSAndroid Build Coastguard Worker available_bytes -= 1u;
1873*795d594fSAndroid Build Coastguard Worker
1874*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(*(ptr_++) != '\0')) {
1875*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("String longer than indicated size %x", size);
1876*795d594fSAndroid Build Coastguard Worker return false;
1877*795d594fSAndroid Build Coastguard Worker }
1878*795d594fSAndroid Build Coastguard Worker
1879*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(available_bytes, static_cast<size_t>(file_end - ptr_));
1880*795d594fSAndroid Build Coastguard Worker return true;
1881*795d594fSAndroid Build Coastguard Worker }
1882*795d594fSAndroid Build Coastguard Worker
CheckIntraDebugInfoItem()1883*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraDebugInfoItem() {
1884*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, unused_line_start);
1885*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, parameters_size);
1886*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(parameters_size > 65536)) {
1887*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid parameters_size: %x", parameters_size);
1888*795d594fSAndroid Build Coastguard Worker return false;
1889*795d594fSAndroid Build Coastguard Worker }
1890*795d594fSAndroid Build Coastguard Worker
1891*795d594fSAndroid Build Coastguard Worker for (uint32_t j = 0; j < parameters_size; j++) {
1892*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, parameter_name);
1893*795d594fSAndroid Build Coastguard Worker if (parameter_name != 0) {
1894*795d594fSAndroid Build Coastguard Worker parameter_name--;
1895*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(parameter_name, header_->string_ids_size_, "debug_info_item parameter_name")) {
1896*795d594fSAndroid Build Coastguard Worker return false;
1897*795d594fSAndroid Build Coastguard Worker }
1898*795d594fSAndroid Build Coastguard Worker }
1899*795d594fSAndroid Build Coastguard Worker }
1900*795d594fSAndroid Build Coastguard Worker
1901*795d594fSAndroid Build Coastguard Worker while (true) {
1902*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(ptr_ >= EndOfFile())) {
1903*795d594fSAndroid Build Coastguard Worker // Went past the end.
1904*795d594fSAndroid Build Coastguard Worker return false;
1905*795d594fSAndroid Build Coastguard Worker }
1906*795d594fSAndroid Build Coastguard Worker uint8_t opcode = *(ptr_++);
1907*795d594fSAndroid Build Coastguard Worker switch (opcode) {
1908*795d594fSAndroid Build Coastguard Worker case DexFile::DBG_END_SEQUENCE: {
1909*795d594fSAndroid Build Coastguard Worker return true;
1910*795d594fSAndroid Build Coastguard Worker }
1911*795d594fSAndroid Build Coastguard Worker case DexFile::DBG_ADVANCE_PC: {
1912*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, unused_advance_pc);
1913*795d594fSAndroid Build Coastguard Worker break;
1914*795d594fSAndroid Build Coastguard Worker }
1915*795d594fSAndroid Build Coastguard Worker case DexFile::DBG_ADVANCE_LINE: {
1916*795d594fSAndroid Build Coastguard Worker DECODE_SIGNED_CHECKED_FROM(ptr_, unused_advance_line);
1917*795d594fSAndroid Build Coastguard Worker break;
1918*795d594fSAndroid Build Coastguard Worker }
1919*795d594fSAndroid Build Coastguard Worker case DexFile::DBG_START_LOCAL: {
1920*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, reg_num);
1921*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(reg_num >= 65536)) {
1922*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad reg_num for opcode %x", opcode);
1923*795d594fSAndroid Build Coastguard Worker return false;
1924*795d594fSAndroid Build Coastguard Worker }
1925*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, name_idx);
1926*795d594fSAndroid Build Coastguard Worker if (name_idx != 0) {
1927*795d594fSAndroid Build Coastguard Worker name_idx--;
1928*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(name_idx, header_->string_ids_size_, "DBG_START_LOCAL name_idx")) {
1929*795d594fSAndroid Build Coastguard Worker return false;
1930*795d594fSAndroid Build Coastguard Worker }
1931*795d594fSAndroid Build Coastguard Worker }
1932*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, type_idx);
1933*795d594fSAndroid Build Coastguard Worker if (type_idx != 0) {
1934*795d594fSAndroid Build Coastguard Worker type_idx--;
1935*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(type_idx, header_->type_ids_size_, "DBG_START_LOCAL type_idx")) {
1936*795d594fSAndroid Build Coastguard Worker return false;
1937*795d594fSAndroid Build Coastguard Worker }
1938*795d594fSAndroid Build Coastguard Worker }
1939*795d594fSAndroid Build Coastguard Worker break;
1940*795d594fSAndroid Build Coastguard Worker }
1941*795d594fSAndroid Build Coastguard Worker case DexFile::DBG_END_LOCAL:
1942*795d594fSAndroid Build Coastguard Worker case DexFile::DBG_RESTART_LOCAL: {
1943*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, reg_num);
1944*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(reg_num >= 65536)) {
1945*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad reg_num for opcode %x", opcode);
1946*795d594fSAndroid Build Coastguard Worker return false;
1947*795d594fSAndroid Build Coastguard Worker }
1948*795d594fSAndroid Build Coastguard Worker break;
1949*795d594fSAndroid Build Coastguard Worker }
1950*795d594fSAndroid Build Coastguard Worker case DexFile::DBG_START_LOCAL_EXTENDED: {
1951*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, reg_num);
1952*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(reg_num >= 65536)) {
1953*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad reg_num for opcode %x", opcode);
1954*795d594fSAndroid Build Coastguard Worker return false;
1955*795d594fSAndroid Build Coastguard Worker }
1956*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, name_idx);
1957*795d594fSAndroid Build Coastguard Worker if (name_idx != 0) {
1958*795d594fSAndroid Build Coastguard Worker name_idx--;
1959*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(name_idx, header_->string_ids_size_, "DBG_START_LOCAL_EXTENDED name_idx")) {
1960*795d594fSAndroid Build Coastguard Worker return false;
1961*795d594fSAndroid Build Coastguard Worker }
1962*795d594fSAndroid Build Coastguard Worker }
1963*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, type_idx);
1964*795d594fSAndroid Build Coastguard Worker if (type_idx != 0) {
1965*795d594fSAndroid Build Coastguard Worker type_idx--;
1966*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(type_idx, header_->type_ids_size_, "DBG_START_LOCAL_EXTENDED type_idx")) {
1967*795d594fSAndroid Build Coastguard Worker return false;
1968*795d594fSAndroid Build Coastguard Worker }
1969*795d594fSAndroid Build Coastguard Worker }
1970*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, sig_idx);
1971*795d594fSAndroid Build Coastguard Worker if (sig_idx != 0) {
1972*795d594fSAndroid Build Coastguard Worker sig_idx--;
1973*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(sig_idx, header_->string_ids_size_, "DBG_START_LOCAL_EXTENDED sig_idx")) {
1974*795d594fSAndroid Build Coastguard Worker return false;
1975*795d594fSAndroid Build Coastguard Worker }
1976*795d594fSAndroid Build Coastguard Worker }
1977*795d594fSAndroid Build Coastguard Worker break;
1978*795d594fSAndroid Build Coastguard Worker }
1979*795d594fSAndroid Build Coastguard Worker case DexFile::DBG_SET_FILE: {
1980*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(ptr_, name_idx);
1981*795d594fSAndroid Build Coastguard Worker if (name_idx != 0) {
1982*795d594fSAndroid Build Coastguard Worker name_idx--;
1983*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(name_idx, header_->string_ids_size_, "DBG_SET_FILE name_idx")) {
1984*795d594fSAndroid Build Coastguard Worker return false;
1985*795d594fSAndroid Build Coastguard Worker }
1986*795d594fSAndroid Build Coastguard Worker }
1987*795d594fSAndroid Build Coastguard Worker break;
1988*795d594fSAndroid Build Coastguard Worker }
1989*795d594fSAndroid Build Coastguard Worker }
1990*795d594fSAndroid Build Coastguard Worker }
1991*795d594fSAndroid Build Coastguard Worker }
1992*795d594fSAndroid Build Coastguard Worker
CheckIntraAnnotationItem()1993*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraAnnotationItem() {
1994*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(ptr_, 1, sizeof(uint8_t), "annotation visibility")) {
1995*795d594fSAndroid Build Coastguard Worker return false;
1996*795d594fSAndroid Build Coastguard Worker }
1997*795d594fSAndroid Build Coastguard Worker
1998*795d594fSAndroid Build Coastguard Worker // Check visibility
1999*795d594fSAndroid Build Coastguard Worker uint8_t visibility = *(ptr_++);
2000*795d594fSAndroid Build Coastguard Worker switch (visibility) {
2001*795d594fSAndroid Build Coastguard Worker case DexFile::kDexVisibilityBuild:
2002*795d594fSAndroid Build Coastguard Worker case DexFile::kDexVisibilityRuntime:
2003*795d594fSAndroid Build Coastguard Worker case DexFile::kDexVisibilitySystem:
2004*795d594fSAndroid Build Coastguard Worker break;
2005*795d594fSAndroid Build Coastguard Worker default:
2006*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad annotation visibility: %x", visibility);
2007*795d594fSAndroid Build Coastguard Worker return false;
2008*795d594fSAndroid Build Coastguard Worker }
2009*795d594fSAndroid Build Coastguard Worker
2010*795d594fSAndroid Build Coastguard Worker CHECK(todo_.empty());
2011*795d594fSAndroid Build Coastguard Worker if (!CheckEncodedAnnotation() || !FlushToDoList()) {
2012*795d594fSAndroid Build Coastguard Worker return false;
2013*795d594fSAndroid Build Coastguard Worker }
2014*795d594fSAndroid Build Coastguard Worker
2015*795d594fSAndroid Build Coastguard Worker return true;
2016*795d594fSAndroid Build Coastguard Worker }
2017*795d594fSAndroid Build Coastguard Worker
CheckIntraHiddenapiClassData()2018*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraHiddenapiClassData() {
2019*795d594fSAndroid Build Coastguard Worker const dex::HiddenapiClassData* item = reinterpret_cast<const dex::HiddenapiClassData*>(ptr_);
2020*795d594fSAndroid Build Coastguard Worker
2021*795d594fSAndroid Build Coastguard Worker // Check expected header size.
2022*795d594fSAndroid Build Coastguard Worker uint32_t num_header_elems = dex_file_->NumClassDefs() + 1;
2023*795d594fSAndroid Build Coastguard Worker uint32_t elem_size = sizeof(uint32_t);
2024*795d594fSAndroid Build Coastguard Worker uint32_t header_size = num_header_elems * elem_size;
2025*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(item, num_header_elems, elem_size, "hiddenapi class data section header")) {
2026*795d594fSAndroid Build Coastguard Worker return false;
2027*795d594fSAndroid Build Coastguard Worker }
2028*795d594fSAndroid Build Coastguard Worker
2029*795d594fSAndroid Build Coastguard Worker // Check total size.
2030*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(item, item->size_, 1u, "hiddenapi class data section")) {
2031*795d594fSAndroid Build Coastguard Worker return false;
2032*795d594fSAndroid Build Coastguard Worker }
2033*795d594fSAndroid Build Coastguard Worker
2034*795d594fSAndroid Build Coastguard Worker // Check that total size can fit header.
2035*795d594fSAndroid Build Coastguard Worker if (item->size_ < header_size) {
2036*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf(
2037*795d594fSAndroid Build Coastguard Worker "Hiddenapi class data too short to store header (%u < %u)", item->size_, header_size);
2038*795d594fSAndroid Build Coastguard Worker return false;
2039*795d594fSAndroid Build Coastguard Worker }
2040*795d594fSAndroid Build Coastguard Worker
2041*795d594fSAndroid Build Coastguard Worker // The rest of the section depends on the class_data_item being verified first. We will finalize
2042*795d594fSAndroid Build Coastguard Worker // verifying the hiddenapi_class_data_item in CheckInterHiddenapiClassData.
2043*795d594fSAndroid Build Coastguard Worker const uint8_t* data_end = ptr_ + item->size_;
2044*795d594fSAndroid Build Coastguard Worker ptr_ = data_end;
2045*795d594fSAndroid Build Coastguard Worker return true;
2046*795d594fSAndroid Build Coastguard Worker }
2047*795d594fSAndroid Build Coastguard Worker
CheckIntraAnnotationsDirectoryItem()2048*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraAnnotationsDirectoryItem() {
2049*795d594fSAndroid Build Coastguard Worker const dex::AnnotationsDirectoryItem* item =
2050*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const dex::AnnotationsDirectoryItem*>(ptr_);
2051*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(item, 1, sizeof(dex::AnnotationsDirectoryItem), "annotations_directory")) {
2052*795d594fSAndroid Build Coastguard Worker return false;
2053*795d594fSAndroid Build Coastguard Worker }
2054*795d594fSAndroid Build Coastguard Worker
2055*795d594fSAndroid Build Coastguard Worker // Field annotations follow immediately after the annotations directory.
2056*795d594fSAndroid Build Coastguard Worker const dex::FieldAnnotationsItem* field_item =
2057*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const dex::FieldAnnotationsItem*>(item + 1);
2058*795d594fSAndroid Build Coastguard Worker uint32_t field_count = item->fields_size_;
2059*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(field_item,
2060*795d594fSAndroid Build Coastguard Worker field_count,
2061*795d594fSAndroid Build Coastguard Worker sizeof(dex::FieldAnnotationsItem),
2062*795d594fSAndroid Build Coastguard Worker "field_annotations list")) {
2063*795d594fSAndroid Build Coastguard Worker return false;
2064*795d594fSAndroid Build Coastguard Worker }
2065*795d594fSAndroid Build Coastguard Worker
2066*795d594fSAndroid Build Coastguard Worker uint32_t last_idx = 0;
2067*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < field_count; i++) {
2068*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(field_item->field_idx_, header_->field_ids_size_, "field annotation")) {
2069*795d594fSAndroid Build Coastguard Worker return false;
2070*795d594fSAndroid Build Coastguard Worker }
2071*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(last_idx >= field_item->field_idx_ && i != 0)) {
2072*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-order field_idx for annotation: %x then %x",
2073*795d594fSAndroid Build Coastguard Worker last_idx, field_item->field_idx_);
2074*795d594fSAndroid Build Coastguard Worker return false;
2075*795d594fSAndroid Build Coastguard Worker }
2076*795d594fSAndroid Build Coastguard Worker last_idx = field_item->field_idx_;
2077*795d594fSAndroid Build Coastguard Worker field_item++;
2078*795d594fSAndroid Build Coastguard Worker }
2079*795d594fSAndroid Build Coastguard Worker
2080*795d594fSAndroid Build Coastguard Worker // Method annotations follow immediately after field annotations.
2081*795d594fSAndroid Build Coastguard Worker const dex::MethodAnnotationsItem* method_item =
2082*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const dex::MethodAnnotationsItem*>(field_item);
2083*795d594fSAndroid Build Coastguard Worker uint32_t method_count = item->methods_size_;
2084*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(method_item,
2085*795d594fSAndroid Build Coastguard Worker method_count,
2086*795d594fSAndroid Build Coastguard Worker sizeof(dex::MethodAnnotationsItem),
2087*795d594fSAndroid Build Coastguard Worker "method_annotations list")) {
2088*795d594fSAndroid Build Coastguard Worker return false;
2089*795d594fSAndroid Build Coastguard Worker }
2090*795d594fSAndroid Build Coastguard Worker
2091*795d594fSAndroid Build Coastguard Worker last_idx = 0;
2092*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < method_count; i++) {
2093*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(method_item->method_idx_, header_->method_ids_size_, "method annotation")) {
2094*795d594fSAndroid Build Coastguard Worker return false;
2095*795d594fSAndroid Build Coastguard Worker }
2096*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(last_idx >= method_item->method_idx_ && i != 0)) {
2097*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-order method_idx for annotation: %x then %x",
2098*795d594fSAndroid Build Coastguard Worker last_idx, method_item->method_idx_);
2099*795d594fSAndroid Build Coastguard Worker return false;
2100*795d594fSAndroid Build Coastguard Worker }
2101*795d594fSAndroid Build Coastguard Worker last_idx = method_item->method_idx_;
2102*795d594fSAndroid Build Coastguard Worker method_item++;
2103*795d594fSAndroid Build Coastguard Worker }
2104*795d594fSAndroid Build Coastguard Worker
2105*795d594fSAndroid Build Coastguard Worker // Parameter annotations follow immediately after method annotations.
2106*795d594fSAndroid Build Coastguard Worker const dex::ParameterAnnotationsItem* parameter_item =
2107*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const dex::ParameterAnnotationsItem*>(method_item);
2108*795d594fSAndroid Build Coastguard Worker uint32_t parameter_count = item->parameters_size_;
2109*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(parameter_item, parameter_count, sizeof(dex::ParameterAnnotationsItem),
2110*795d594fSAndroid Build Coastguard Worker "parameter_annotations list")) {
2111*795d594fSAndroid Build Coastguard Worker return false;
2112*795d594fSAndroid Build Coastguard Worker }
2113*795d594fSAndroid Build Coastguard Worker
2114*795d594fSAndroid Build Coastguard Worker last_idx = 0;
2115*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < parameter_count; i++) {
2116*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(parameter_item->method_idx_,
2117*795d594fSAndroid Build Coastguard Worker header_->method_ids_size_,
2118*795d594fSAndroid Build Coastguard Worker "parameter annotation method")) {
2119*795d594fSAndroid Build Coastguard Worker return false;
2120*795d594fSAndroid Build Coastguard Worker }
2121*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(last_idx >= parameter_item->method_idx_ && i != 0)) {
2122*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-order method_idx for annotation: %x then %x",
2123*795d594fSAndroid Build Coastguard Worker last_idx, parameter_item->method_idx_);
2124*795d594fSAndroid Build Coastguard Worker return false;
2125*795d594fSAndroid Build Coastguard Worker }
2126*795d594fSAndroid Build Coastguard Worker last_idx = parameter_item->method_idx_;
2127*795d594fSAndroid Build Coastguard Worker parameter_item++;
2128*795d594fSAndroid Build Coastguard Worker }
2129*795d594fSAndroid Build Coastguard Worker
2130*795d594fSAndroid Build Coastguard Worker // Return a pointer to the end of the annotations.
2131*795d594fSAndroid Build Coastguard Worker ptr_ = reinterpret_cast<const uint8_t*>(parameter_item);
2132*795d594fSAndroid Build Coastguard Worker return true;
2133*795d594fSAndroid Build Coastguard Worker }
2134*795d594fSAndroid Build Coastguard Worker
2135*795d594fSAndroid Build Coastguard Worker template <DexFile::MapItemType kType>
CheckIntraSectionIterate(uint32_t section_count)2136*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraSectionIterate(uint32_t section_count) {
2137*795d594fSAndroid Build Coastguard Worker // Get the right alignment mask for the type of section.
2138*795d594fSAndroid Build Coastguard Worker size_t alignment_mask;
2139*795d594fSAndroid Build Coastguard Worker switch (kType) {
2140*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeClassDataItem:
2141*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeStringDataItem:
2142*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeDebugInfoItem:
2143*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationItem:
2144*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeEncodedArrayItem:
2145*795d594fSAndroid Build Coastguard Worker alignment_mask = sizeof(uint8_t) - 1;
2146*795d594fSAndroid Build Coastguard Worker break;
2147*795d594fSAndroid Build Coastguard Worker default:
2148*795d594fSAndroid Build Coastguard Worker alignment_mask = sizeof(uint32_t) - 1;
2149*795d594fSAndroid Build Coastguard Worker break;
2150*795d594fSAndroid Build Coastguard Worker }
2151*795d594fSAndroid Build Coastguard Worker
2152*795d594fSAndroid Build Coastguard Worker // Iterate through the items in the section.
2153*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < section_count; i++) {
2154*795d594fSAndroid Build Coastguard Worker size_t aligned_offset = (PtrToOffset(ptr_) + alignment_mask) & ~alignment_mask;
2155*795d594fSAndroid Build Coastguard Worker
2156*795d594fSAndroid Build Coastguard Worker // Check the padding between items.
2157*795d594fSAndroid Build Coastguard Worker if (!CheckPadding(aligned_offset, kType)) {
2158*795d594fSAndroid Build Coastguard Worker return false;
2159*795d594fSAndroid Build Coastguard Worker }
2160*795d594fSAndroid Build Coastguard Worker
2161*795d594fSAndroid Build Coastguard Worker // Check depending on the section type.
2162*795d594fSAndroid Build Coastguard Worker const uint8_t* start_ptr = ptr_;
2163*795d594fSAndroid Build Coastguard Worker switch (kType) {
2164*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeStringIdItem: {
2165*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(ptr_, 1, sizeof(dex::StringId), "string_ids")) {
2166*795d594fSAndroid Build Coastguard Worker return false;
2167*795d594fSAndroid Build Coastguard Worker }
2168*795d594fSAndroid Build Coastguard Worker ptr_ += sizeof(dex::StringId);
2169*795d594fSAndroid Build Coastguard Worker break;
2170*795d594fSAndroid Build Coastguard Worker }
2171*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeTypeIdItem: {
2172*795d594fSAndroid Build Coastguard Worker if (!CheckIntraTypeIdItem()) {
2173*795d594fSAndroid Build Coastguard Worker return false;
2174*795d594fSAndroid Build Coastguard Worker }
2175*795d594fSAndroid Build Coastguard Worker break;
2176*795d594fSAndroid Build Coastguard Worker }
2177*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeProtoIdItem: {
2178*795d594fSAndroid Build Coastguard Worker if (!CheckIntraProtoIdItem()) {
2179*795d594fSAndroid Build Coastguard Worker return false;
2180*795d594fSAndroid Build Coastguard Worker }
2181*795d594fSAndroid Build Coastguard Worker break;
2182*795d594fSAndroid Build Coastguard Worker }
2183*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeFieldIdItem: {
2184*795d594fSAndroid Build Coastguard Worker if (!CheckIntraFieldIdItem()) {
2185*795d594fSAndroid Build Coastguard Worker return false;
2186*795d594fSAndroid Build Coastguard Worker }
2187*795d594fSAndroid Build Coastguard Worker break;
2188*795d594fSAndroid Build Coastguard Worker }
2189*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMethodIdItem: {
2190*795d594fSAndroid Build Coastguard Worker if (!CheckIntraMethodIdItem()) {
2191*795d594fSAndroid Build Coastguard Worker return false;
2192*795d594fSAndroid Build Coastguard Worker }
2193*795d594fSAndroid Build Coastguard Worker break;
2194*795d594fSAndroid Build Coastguard Worker }
2195*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeClassDefItem: {
2196*795d594fSAndroid Build Coastguard Worker if (!CheckIntraClassDefItem(/*class_def_index=*/ i)) {
2197*795d594fSAndroid Build Coastguard Worker return false;
2198*795d594fSAndroid Build Coastguard Worker }
2199*795d594fSAndroid Build Coastguard Worker break;
2200*795d594fSAndroid Build Coastguard Worker }
2201*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeCallSiteIdItem: {
2202*795d594fSAndroid Build Coastguard Worker if (!CheckListSize(ptr_, 1, sizeof(dex::CallSiteIdItem), "call_site_ids")) {
2203*795d594fSAndroid Build Coastguard Worker return false;
2204*795d594fSAndroid Build Coastguard Worker }
2205*795d594fSAndroid Build Coastguard Worker ptr_ += sizeof(dex::CallSiteIdItem);
2206*795d594fSAndroid Build Coastguard Worker break;
2207*795d594fSAndroid Build Coastguard Worker }
2208*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMethodHandleItem: {
2209*795d594fSAndroid Build Coastguard Worker if (!CheckIntraMethodHandleItem()) {
2210*795d594fSAndroid Build Coastguard Worker return false;
2211*795d594fSAndroid Build Coastguard Worker }
2212*795d594fSAndroid Build Coastguard Worker break;
2213*795d594fSAndroid Build Coastguard Worker }
2214*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeTypeList: {
2215*795d594fSAndroid Build Coastguard Worker if (!CheckIntraTypeList()) {
2216*795d594fSAndroid Build Coastguard Worker return false;
2217*795d594fSAndroid Build Coastguard Worker }
2218*795d594fSAndroid Build Coastguard Worker break;
2219*795d594fSAndroid Build Coastguard Worker }
2220*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationSetRefList: {
2221*795d594fSAndroid Build Coastguard Worker if (!CheckList(sizeof(dex::AnnotationSetRefItem), "annotation_set_ref_list", &ptr_)) {
2222*795d594fSAndroid Build Coastguard Worker return false;
2223*795d594fSAndroid Build Coastguard Worker }
2224*795d594fSAndroid Build Coastguard Worker break;
2225*795d594fSAndroid Build Coastguard Worker }
2226*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationSetItem: {
2227*795d594fSAndroid Build Coastguard Worker if (!CheckList(sizeof(uint32_t), "annotation_set_item", &ptr_)) {
2228*795d594fSAndroid Build Coastguard Worker return false;
2229*795d594fSAndroid Build Coastguard Worker }
2230*795d594fSAndroid Build Coastguard Worker break;
2231*795d594fSAndroid Build Coastguard Worker }
2232*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeClassDataItem: {
2233*795d594fSAndroid Build Coastguard Worker if (!CheckIntraClassDataItem()) {
2234*795d594fSAndroid Build Coastguard Worker return false;
2235*795d594fSAndroid Build Coastguard Worker }
2236*795d594fSAndroid Build Coastguard Worker break;
2237*795d594fSAndroid Build Coastguard Worker }
2238*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeCodeItem: {
2239*795d594fSAndroid Build Coastguard Worker if (!CheckIntraCodeItem()) {
2240*795d594fSAndroid Build Coastguard Worker return false;
2241*795d594fSAndroid Build Coastguard Worker }
2242*795d594fSAndroid Build Coastguard Worker break;
2243*795d594fSAndroid Build Coastguard Worker }
2244*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeStringDataItem: {
2245*795d594fSAndroid Build Coastguard Worker if (!CheckIntraStringDataItem()) {
2246*795d594fSAndroid Build Coastguard Worker return false;
2247*795d594fSAndroid Build Coastguard Worker }
2248*795d594fSAndroid Build Coastguard Worker break;
2249*795d594fSAndroid Build Coastguard Worker }
2250*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeDebugInfoItem: {
2251*795d594fSAndroid Build Coastguard Worker if (!CheckIntraDebugInfoItem()) {
2252*795d594fSAndroid Build Coastguard Worker return false;
2253*795d594fSAndroid Build Coastguard Worker }
2254*795d594fSAndroid Build Coastguard Worker break;
2255*795d594fSAndroid Build Coastguard Worker }
2256*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationItem: {
2257*795d594fSAndroid Build Coastguard Worker if (!CheckIntraAnnotationItem()) {
2258*795d594fSAndroid Build Coastguard Worker return false;
2259*795d594fSAndroid Build Coastguard Worker }
2260*795d594fSAndroid Build Coastguard Worker break;
2261*795d594fSAndroid Build Coastguard Worker }
2262*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeEncodedArrayItem: {
2263*795d594fSAndroid Build Coastguard Worker CHECK(todo_.empty());
2264*795d594fSAndroid Build Coastguard Worker if (!CheckEncodedArray() || !FlushToDoList()) {
2265*795d594fSAndroid Build Coastguard Worker return false;
2266*795d594fSAndroid Build Coastguard Worker }
2267*795d594fSAndroid Build Coastguard Worker break;
2268*795d594fSAndroid Build Coastguard Worker }
2269*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationsDirectoryItem: {
2270*795d594fSAndroid Build Coastguard Worker if (!CheckIntraAnnotationsDirectoryItem()) {
2271*795d594fSAndroid Build Coastguard Worker return false;
2272*795d594fSAndroid Build Coastguard Worker }
2273*795d594fSAndroid Build Coastguard Worker break;
2274*795d594fSAndroid Build Coastguard Worker }
2275*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeHiddenapiClassData: {
2276*795d594fSAndroid Build Coastguard Worker if (!CheckIntraHiddenapiClassData()) {
2277*795d594fSAndroid Build Coastguard Worker return false;
2278*795d594fSAndroid Build Coastguard Worker }
2279*795d594fSAndroid Build Coastguard Worker break;
2280*795d594fSAndroid Build Coastguard Worker }
2281*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeHeaderItem:
2282*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMapList:
2283*795d594fSAndroid Build Coastguard Worker break;
2284*795d594fSAndroid Build Coastguard Worker }
2285*795d594fSAndroid Build Coastguard Worker
2286*795d594fSAndroid Build Coastguard Worker if (start_ptr == ptr_) {
2287*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Unknown map item type %x", kType);
2288*795d594fSAndroid Build Coastguard Worker return false;
2289*795d594fSAndroid Build Coastguard Worker }
2290*795d594fSAndroid Build Coastguard Worker
2291*795d594fSAndroid Build Coastguard Worker if (IsDataSectionType(kType)) {
2292*795d594fSAndroid Build Coastguard Worker if (aligned_offset == 0u) {
2293*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Item %d offset is 0", i);
2294*795d594fSAndroid Build Coastguard Worker return false;
2295*795d594fSAndroid Build Coastguard Worker }
2296*795d594fSAndroid Build Coastguard Worker DCHECK(offset_to_type_map_.find(aligned_offset) == offset_to_type_map_.end());
2297*795d594fSAndroid Build Coastguard Worker offset_to_type_map_.insert(std::pair<uint32_t, uint16_t>(aligned_offset, kType));
2298*795d594fSAndroid Build Coastguard Worker }
2299*795d594fSAndroid Build Coastguard Worker
2300*795d594fSAndroid Build Coastguard Worker if (!PtrToOffset(ptr_, &aligned_offset)) {
2301*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Item %d at ends out of bounds", i);
2302*795d594fSAndroid Build Coastguard Worker return false;
2303*795d594fSAndroid Build Coastguard Worker }
2304*795d594fSAndroid Build Coastguard Worker }
2305*795d594fSAndroid Build Coastguard Worker
2306*795d594fSAndroid Build Coastguard Worker return true;
2307*795d594fSAndroid Build Coastguard Worker }
2308*795d594fSAndroid Build Coastguard Worker
2309*795d594fSAndroid Build Coastguard Worker template <DexFile::MapItemType kType>
CheckIntraIdSection(size_t offset,uint32_t count)2310*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraIdSection(size_t offset, uint32_t count) {
2311*795d594fSAndroid Build Coastguard Worker uint32_t expected_offset;
2312*795d594fSAndroid Build Coastguard Worker uint32_t expected_size;
2313*795d594fSAndroid Build Coastguard Worker
2314*795d594fSAndroid Build Coastguard Worker // Get the expected offset and size from the header.
2315*795d594fSAndroid Build Coastguard Worker switch (kType) {
2316*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeStringIdItem:
2317*795d594fSAndroid Build Coastguard Worker expected_offset = header_->string_ids_off_;
2318*795d594fSAndroid Build Coastguard Worker expected_size = header_->string_ids_size_;
2319*795d594fSAndroid Build Coastguard Worker break;
2320*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeTypeIdItem:
2321*795d594fSAndroid Build Coastguard Worker expected_offset = header_->type_ids_off_;
2322*795d594fSAndroid Build Coastguard Worker expected_size = header_->type_ids_size_;
2323*795d594fSAndroid Build Coastguard Worker break;
2324*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeProtoIdItem:
2325*795d594fSAndroid Build Coastguard Worker expected_offset = header_->proto_ids_off_;
2326*795d594fSAndroid Build Coastguard Worker expected_size = header_->proto_ids_size_;
2327*795d594fSAndroid Build Coastguard Worker break;
2328*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeFieldIdItem:
2329*795d594fSAndroid Build Coastguard Worker expected_offset = header_->field_ids_off_;
2330*795d594fSAndroid Build Coastguard Worker expected_size = header_->field_ids_size_;
2331*795d594fSAndroid Build Coastguard Worker break;
2332*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMethodIdItem:
2333*795d594fSAndroid Build Coastguard Worker expected_offset = header_->method_ids_off_;
2334*795d594fSAndroid Build Coastguard Worker expected_size = header_->method_ids_size_;
2335*795d594fSAndroid Build Coastguard Worker break;
2336*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeClassDefItem:
2337*795d594fSAndroid Build Coastguard Worker expected_offset = header_->class_defs_off_;
2338*795d594fSAndroid Build Coastguard Worker expected_size = header_->class_defs_size_;
2339*795d594fSAndroid Build Coastguard Worker break;
2340*795d594fSAndroid Build Coastguard Worker default:
2341*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad type for id section: %x", kType);
2342*795d594fSAndroid Build Coastguard Worker return false;
2343*795d594fSAndroid Build Coastguard Worker }
2344*795d594fSAndroid Build Coastguard Worker
2345*795d594fSAndroid Build Coastguard Worker // Check that the offset and size are what were expected from the header.
2346*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(offset != expected_offset)) {
2347*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad offset for section: got %zx, expected %x", offset, expected_offset);
2348*795d594fSAndroid Build Coastguard Worker return false;
2349*795d594fSAndroid Build Coastguard Worker }
2350*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(count != expected_size)) {
2351*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad size for section: got %x, expected %x", count, expected_size);
2352*795d594fSAndroid Build Coastguard Worker return false;
2353*795d594fSAndroid Build Coastguard Worker }
2354*795d594fSAndroid Build Coastguard Worker
2355*795d594fSAndroid Build Coastguard Worker return CheckIntraSectionIterate<kType>(count);
2356*795d594fSAndroid Build Coastguard Worker }
2357*795d594fSAndroid Build Coastguard Worker
2358*795d594fSAndroid Build Coastguard Worker template <DexFile::MapItemType kType>
CheckIntraDataSection(size_t offset,uint32_t count)2359*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraDataSection(size_t offset, uint32_t count) {
2360*795d594fSAndroid Build Coastguard Worker size_t data_start = PtrToOffset(data_.begin());
2361*795d594fSAndroid Build Coastguard Worker size_t data_end = PtrToOffset(data_.end());
2362*795d594fSAndroid Build Coastguard Worker
2363*795d594fSAndroid Build Coastguard Worker // Check the validity of the offset of the section.
2364*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((offset < data_start) || (offset > data_end))) {
2365*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Bad offset for data subsection: %zx", offset);
2366*795d594fSAndroid Build Coastguard Worker return false;
2367*795d594fSAndroid Build Coastguard Worker }
2368*795d594fSAndroid Build Coastguard Worker
2369*795d594fSAndroid Build Coastguard Worker if (!CheckIntraSectionIterate<kType>(count)) {
2370*795d594fSAndroid Build Coastguard Worker return false;
2371*795d594fSAndroid Build Coastguard Worker }
2372*795d594fSAndroid Build Coastguard Worker
2373*795d594fSAndroid Build Coastguard Worker // FIXME: Doing this check late means we may have already read memory outside the
2374*795d594fSAndroid Build Coastguard Worker // data section and potentially outside the file, thus risking a segmentation fault.
2375*795d594fSAndroid Build Coastguard Worker size_t next_offset;
2376*795d594fSAndroid Build Coastguard Worker if (!PtrToOffset(ptr_, &next_offset) || next_offset > data_end) {
2377*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-bounds end of data subsection: %zu data_off=%u data_size=%u",
2378*795d594fSAndroid Build Coastguard Worker next_offset,
2379*795d594fSAndroid Build Coastguard Worker header_->data_off_,
2380*795d594fSAndroid Build Coastguard Worker header_->data_size_);
2381*795d594fSAndroid Build Coastguard Worker return false;
2382*795d594fSAndroid Build Coastguard Worker }
2383*795d594fSAndroid Build Coastguard Worker
2384*795d594fSAndroid Build Coastguard Worker return true;
2385*795d594fSAndroid Build Coastguard Worker }
2386*795d594fSAndroid Build Coastguard Worker
CheckIntraSection()2387*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckIntraSection() {
2388*795d594fSAndroid Build Coastguard Worker const dex::MapList* map = OffsetToPtr<dex::MapList>(header_->map_off_);
2389*795d594fSAndroid Build Coastguard Worker const dex::MapItem* item = map->list_;
2390*795d594fSAndroid Build Coastguard Worker uint32_t count = map->size_;
2391*795d594fSAndroid Build Coastguard Worker ptr_ = dex_file_->Begin();
2392*795d594fSAndroid Build Coastguard Worker
2393*795d594fSAndroid Build Coastguard Worker // Preallocate offset map to avoid some allocations. We can only guess from the list items,
2394*795d594fSAndroid Build Coastguard Worker // not derived things.
2395*795d594fSAndroid Build Coastguard Worker offset_to_type_map_.reserve(
2396*795d594fSAndroid Build Coastguard Worker std::min(header_->class_defs_size_, 65535u) +
2397*795d594fSAndroid Build Coastguard Worker std::min(header_->string_ids_size_, 65535u) +
2398*795d594fSAndroid Build Coastguard Worker 2 * std::min(header_->method_ids_size_, 65535u));
2399*795d594fSAndroid Build Coastguard Worker
2400*795d594fSAndroid Build Coastguard Worker // Check the items listed in the map.
2401*795d594fSAndroid Build Coastguard Worker for (; count != 0u; --count) {
2402*795d594fSAndroid Build Coastguard Worker const uint8_t* initial_ptr = ptr_;
2403*795d594fSAndroid Build Coastguard Worker uint32_t section_offset = item->offset_;
2404*795d594fSAndroid Build Coastguard Worker uint32_t section_count = item->size_;
2405*795d594fSAndroid Build Coastguard Worker DexFile::MapItemType type = static_cast<DexFile::MapItemType>(item->type_);
2406*795d594fSAndroid Build Coastguard Worker
2407*795d594fSAndroid Build Coastguard Worker // Check for padding and overlap between items.
2408*795d594fSAndroid Build Coastguard Worker size_t offset = PtrToOffset(ptr_);
2409*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(offset > section_offset)) {
2410*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Section overlap or out-of-order map: %zx, %x", offset, section_offset);
2411*795d594fSAndroid Build Coastguard Worker return false;
2412*795d594fSAndroid Build Coastguard Worker }
2413*795d594fSAndroid Build Coastguard Worker if (!CheckPadding(section_offset, type)) {
2414*795d594fSAndroid Build Coastguard Worker return false;
2415*795d594fSAndroid Build Coastguard Worker }
2416*795d594fSAndroid Build Coastguard Worker
2417*795d594fSAndroid Build Coastguard Worker // Check each item based on its type.
2418*795d594fSAndroid Build Coastguard Worker switch (type) {
2419*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeHeaderItem: {
2420*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(section_count != 1)) {
2421*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Multiple header items");
2422*795d594fSAndroid Build Coastguard Worker return false;
2423*795d594fSAndroid Build Coastguard Worker }
2424*795d594fSAndroid Build Coastguard Worker uint32_t expected = dex_version_ >= 41 ? PtrToOffset(dex_file_->Begin()) : 0;
2425*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(section_offset != expected)) {
2426*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Header at %x, expected %x", section_offset, expected);
2427*795d594fSAndroid Build Coastguard Worker return false;
2428*795d594fSAndroid Build Coastguard Worker }
2429*795d594fSAndroid Build Coastguard Worker ptr_ += header_->header_size_;
2430*795d594fSAndroid Build Coastguard Worker break;
2431*795d594fSAndroid Build Coastguard Worker }
2432*795d594fSAndroid Build Coastguard Worker
2433*795d594fSAndroid Build Coastguard Worker #define CHECK_INTRA_ID_SECTION_CASE(type) \
2434*795d594fSAndroid Build Coastguard Worker case type: \
2435*795d594fSAndroid Build Coastguard Worker if (!CheckIntraIdSection<type>(section_offset, section_count)) { \
2436*795d594fSAndroid Build Coastguard Worker return false; \
2437*795d594fSAndroid Build Coastguard Worker } \
2438*795d594fSAndroid Build Coastguard Worker break;
2439*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_ID_SECTION_CASE(DexFile::kDexTypeStringIdItem)
2440*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_ID_SECTION_CASE(DexFile::kDexTypeTypeIdItem)
2441*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_ID_SECTION_CASE(DexFile::kDexTypeProtoIdItem)
2442*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_ID_SECTION_CASE(DexFile::kDexTypeFieldIdItem)
2443*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_ID_SECTION_CASE(DexFile::kDexTypeMethodIdItem)
2444*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_ID_SECTION_CASE(DexFile::kDexTypeClassDefItem)
2445*795d594fSAndroid Build Coastguard Worker #undef CHECK_INTRA_ID_SECTION_CASE
2446*795d594fSAndroid Build Coastguard Worker
2447*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMapList:
2448*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(section_count != 1)) {
2449*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Multiple map list items");
2450*795d594fSAndroid Build Coastguard Worker return false;
2451*795d594fSAndroid Build Coastguard Worker }
2452*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(section_offset != header_->map_off_)) {
2453*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Map not at header-defined offset: %x, expected %x",
2454*795d594fSAndroid Build Coastguard Worker section_offset, header_->map_off_);
2455*795d594fSAndroid Build Coastguard Worker return false;
2456*795d594fSAndroid Build Coastguard Worker }
2457*795d594fSAndroid Build Coastguard Worker ptr_ += sizeof(uint32_t) + (map->size_ * sizeof(dex::MapItem));
2458*795d594fSAndroid Build Coastguard Worker break;
2459*795d594fSAndroid Build Coastguard Worker
2460*795d594fSAndroid Build Coastguard Worker #define CHECK_INTRA_SECTION_ITERATE_CASE(type) \
2461*795d594fSAndroid Build Coastguard Worker case type: \
2462*795d594fSAndroid Build Coastguard Worker if (!CheckIntraSectionIterate<type>(section_count)) { \
2463*795d594fSAndroid Build Coastguard Worker return false; \
2464*795d594fSAndroid Build Coastguard Worker } \
2465*795d594fSAndroid Build Coastguard Worker break;
2466*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_SECTION_ITERATE_CASE(DexFile::kDexTypeMethodHandleItem)
2467*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_SECTION_ITERATE_CASE(DexFile::kDexTypeCallSiteIdItem)
2468*795d594fSAndroid Build Coastguard Worker #undef CHECK_INTRA_SECTION_ITERATE_CASE
2469*795d594fSAndroid Build Coastguard Worker
2470*795d594fSAndroid Build Coastguard Worker #define CHECK_INTRA_DATA_SECTION_CASE(type) \
2471*795d594fSAndroid Build Coastguard Worker case type: \
2472*795d594fSAndroid Build Coastguard Worker if (!CheckIntraDataSection<type>(section_offset, section_count)) { \
2473*795d594fSAndroid Build Coastguard Worker return false; \
2474*795d594fSAndroid Build Coastguard Worker } \
2475*795d594fSAndroid Build Coastguard Worker break;
2476*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeTypeList)
2477*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeAnnotationSetRefList)
2478*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeAnnotationSetItem)
2479*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeClassDataItem)
2480*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeCodeItem)
2481*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeStringDataItem)
2482*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeDebugInfoItem)
2483*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeAnnotationItem)
2484*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeEncodedArrayItem)
2485*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeAnnotationsDirectoryItem)
2486*795d594fSAndroid Build Coastguard Worker CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeHiddenapiClassData)
2487*795d594fSAndroid Build Coastguard Worker #undef CHECK_INTRA_DATA_SECTION_CASE
2488*795d594fSAndroid Build Coastguard Worker }
2489*795d594fSAndroid Build Coastguard Worker
2490*795d594fSAndroid Build Coastguard Worker if (ptr_ == initial_ptr) {
2491*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Unknown map item type %x", type);
2492*795d594fSAndroid Build Coastguard Worker return false;
2493*795d594fSAndroid Build Coastguard Worker }
2494*795d594fSAndroid Build Coastguard Worker
2495*795d594fSAndroid Build Coastguard Worker item++;
2496*795d594fSAndroid Build Coastguard Worker }
2497*795d594fSAndroid Build Coastguard Worker
2498*795d594fSAndroid Build Coastguard Worker return true;
2499*795d594fSAndroid Build Coastguard Worker }
2500*795d594fSAndroid Build Coastguard Worker
CheckOffsetToTypeMap(size_t offset,uint16_t type)2501*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckOffsetToTypeMap(size_t offset, uint16_t type) {
2502*795d594fSAndroid Build Coastguard Worker DCHECK(offset_to_type_map_.find(0) == offset_to_type_map_.end());
2503*795d594fSAndroid Build Coastguard Worker auto it = offset_to_type_map_.find(offset);
2504*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(it == offset_to_type_map_.end())) {
2505*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("No data map entry found @ %zx; expected %x", offset, type);
2506*795d594fSAndroid Build Coastguard Worker return false;
2507*795d594fSAndroid Build Coastguard Worker }
2508*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(it->second != type)) {
2509*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Unexpected data map entry @ %zx; expected %x, found %x",
2510*795d594fSAndroid Build Coastguard Worker offset, type, it->second);
2511*795d594fSAndroid Build Coastguard Worker return false;
2512*795d594fSAndroid Build Coastguard Worker }
2513*795d594fSAndroid Build Coastguard Worker return true;
2514*795d594fSAndroid Build Coastguard Worker }
2515*795d594fSAndroid Build Coastguard Worker
FindFirstClassDataDefiner(const ClassAccessor & accessor)2516*795d594fSAndroid Build Coastguard Worker uint32_t DexFileVerifier::FindFirstClassDataDefiner(const ClassAccessor& accessor) {
2517*795d594fSAndroid Build Coastguard Worker // The data item and field/method indexes have already been checked in
2518*795d594fSAndroid Build Coastguard Worker // `CheckIntraClassDataItem()` or its helper functions.
2519*795d594fSAndroid Build Coastguard Worker if (accessor.NumFields() != 0) {
2520*795d594fSAndroid Build Coastguard Worker ClassAccessor::Field read_field(*dex_file_, accessor.ptr_pos_);
2521*795d594fSAndroid Build Coastguard Worker read_field.Read();
2522*795d594fSAndroid Build Coastguard Worker DCHECK_LE(read_field.GetIndex(), dex_file_->NumFieldIds());
2523*795d594fSAndroid Build Coastguard Worker return dex_file_->GetFieldId(read_field.GetIndex()).class_idx_.index_;
2524*795d594fSAndroid Build Coastguard Worker }
2525*795d594fSAndroid Build Coastguard Worker
2526*795d594fSAndroid Build Coastguard Worker if (accessor.NumMethods() != 0) {
2527*795d594fSAndroid Build Coastguard Worker ClassAccessor::Method read_method(*dex_file_, accessor.ptr_pos_);
2528*795d594fSAndroid Build Coastguard Worker read_method.Read();
2529*795d594fSAndroid Build Coastguard Worker DCHECK_LE(read_method.GetIndex(), dex_file_->NumMethodIds());
2530*795d594fSAndroid Build Coastguard Worker return dex_file_->GetMethodId(read_method.GetIndex()).class_idx_.index_;
2531*795d594fSAndroid Build Coastguard Worker }
2532*795d594fSAndroid Build Coastguard Worker
2533*795d594fSAndroid Build Coastguard Worker return kDexNoIndex;
2534*795d594fSAndroid Build Coastguard Worker }
2535*795d594fSAndroid Build Coastguard Worker
FindFirstAnnotationsDirectoryDefiner(const uint8_t * ptr)2536*795d594fSAndroid Build Coastguard Worker uint32_t DexFileVerifier::FindFirstAnnotationsDirectoryDefiner(const uint8_t* ptr) {
2537*795d594fSAndroid Build Coastguard Worker // The annotations directory and field/method indexes have already been checked in
2538*795d594fSAndroid Build Coastguard Worker // `CheckIntraAnnotationsDirectoryItem()`.
2539*795d594fSAndroid Build Coastguard Worker const dex::AnnotationsDirectoryItem* item =
2540*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const dex::AnnotationsDirectoryItem*>(ptr);
2541*795d594fSAndroid Build Coastguard Worker
2542*795d594fSAndroid Build Coastguard Worker if (item->fields_size_ != 0) {
2543*795d594fSAndroid Build Coastguard Worker dex::FieldAnnotationsItem* field_items = (dex::FieldAnnotationsItem*) (item + 1);
2544*795d594fSAndroid Build Coastguard Worker DCHECK_LE(field_items[0].field_idx_, dex_file_->NumFieldIds());
2545*795d594fSAndroid Build Coastguard Worker return dex_file_->GetFieldId(field_items[0].field_idx_).class_idx_.index_;
2546*795d594fSAndroid Build Coastguard Worker }
2547*795d594fSAndroid Build Coastguard Worker
2548*795d594fSAndroid Build Coastguard Worker if (item->methods_size_ != 0) {
2549*795d594fSAndroid Build Coastguard Worker dex::MethodAnnotationsItem* method_items = (dex::MethodAnnotationsItem*) (item + 1);
2550*795d594fSAndroid Build Coastguard Worker DCHECK_LE(method_items[0].method_idx_, dex_file_->NumMethodIds());
2551*795d594fSAndroid Build Coastguard Worker return dex_file_->GetMethodId(method_items[0].method_idx_).class_idx_.index_;
2552*795d594fSAndroid Build Coastguard Worker }
2553*795d594fSAndroid Build Coastguard Worker
2554*795d594fSAndroid Build Coastguard Worker if (item->parameters_size_ != 0) {
2555*795d594fSAndroid Build Coastguard Worker dex::ParameterAnnotationsItem* parameter_items = (dex::ParameterAnnotationsItem*) (item + 1);
2556*795d594fSAndroid Build Coastguard Worker DCHECK_LE(parameter_items[0].method_idx_, dex_file_->NumMethodIds());
2557*795d594fSAndroid Build Coastguard Worker return dex_file_->GetMethodId(parameter_items[0].method_idx_).class_idx_.index_;
2558*795d594fSAndroid Build Coastguard Worker }
2559*795d594fSAndroid Build Coastguard Worker
2560*795d594fSAndroid Build Coastguard Worker return kDexNoIndex;
2561*795d594fSAndroid Build Coastguard Worker }
2562*795d594fSAndroid Build Coastguard Worker
CheckInterHiddenapiClassData()2563*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckInterHiddenapiClassData() {
2564*795d594fSAndroid Build Coastguard Worker const dex::HiddenapiClassData* item = reinterpret_cast<const dex::HiddenapiClassData*>(ptr_);
2565*795d594fSAndroid Build Coastguard Worker
2566*795d594fSAndroid Build Coastguard Worker // Move pointer after the header. This data has been verified in CheckIntraHiddenapiClassData.
2567*795d594fSAndroid Build Coastguard Worker uint32_t num_header_elems = dex_file_->NumClassDefs() + 1;
2568*795d594fSAndroid Build Coastguard Worker uint32_t elem_size = sizeof(uint32_t);
2569*795d594fSAndroid Build Coastguard Worker uint32_t header_size = num_header_elems * elem_size;
2570*795d594fSAndroid Build Coastguard Worker const uint8_t* data_end = ptr_ + item->size_;
2571*795d594fSAndroid Build Coastguard Worker ptr_ += header_size;
2572*795d594fSAndroid Build Coastguard Worker
2573*795d594fSAndroid Build Coastguard Worker // Check offsets for each class def.
2574*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < dex_file_->NumClassDefs(); ++i) {
2575*795d594fSAndroid Build Coastguard Worker const dex::ClassDef& class_def = dex_file_->GetClassDef(i);
2576*795d594fSAndroid Build Coastguard Worker const uint8_t* class_data = dex_file_->GetClassData(class_def);
2577*795d594fSAndroid Build Coastguard Worker uint32_t offset = item->flags_offset_[i];
2578*795d594fSAndroid Build Coastguard Worker
2579*795d594fSAndroid Build Coastguard Worker if (offset == 0) {
2580*795d594fSAndroid Build Coastguard Worker continue;
2581*795d594fSAndroid Build Coastguard Worker }
2582*795d594fSAndroid Build Coastguard Worker
2583*795d594fSAndroid Build Coastguard Worker // Check that class defs with no class data do not have any hiddenapi class data.
2584*795d594fSAndroid Build Coastguard Worker if (class_data == nullptr) {
2585*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf(
2586*795d594fSAndroid Build Coastguard Worker "Hiddenapi class data offset not zero for class def %u with no class data", i);
2587*795d594fSAndroid Build Coastguard Worker return false;
2588*795d594fSAndroid Build Coastguard Worker }
2589*795d594fSAndroid Build Coastguard Worker
2590*795d594fSAndroid Build Coastguard Worker // Check that the offset is within the section.
2591*795d594fSAndroid Build Coastguard Worker if (offset > item->size_) {
2592*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf(
2593*795d594fSAndroid Build Coastguard Worker "Hiddenapi class data offset out of section bounds (%u > %u) for class def %u",
2594*795d594fSAndroid Build Coastguard Worker offset, item->size_, i);
2595*795d594fSAndroid Build Coastguard Worker return false;
2596*795d594fSAndroid Build Coastguard Worker }
2597*795d594fSAndroid Build Coastguard Worker
2598*795d594fSAndroid Build Coastguard Worker // Check that the offset matches current pointer position. We do not allow
2599*795d594fSAndroid Build Coastguard Worker // offsets into already parsed data, or gaps between class def data.
2600*795d594fSAndroid Build Coastguard Worker uint32_t ptr_offset = ptr_ - reinterpret_cast<const uint8_t*>(item);
2601*795d594fSAndroid Build Coastguard Worker if (offset != ptr_offset) {
2602*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf(
2603*795d594fSAndroid Build Coastguard Worker "Hiddenapi class data unexpected offset (%u != %u) for class def %u",
2604*795d594fSAndroid Build Coastguard Worker offset, ptr_offset, i);
2605*795d594fSAndroid Build Coastguard Worker return false;
2606*795d594fSAndroid Build Coastguard Worker }
2607*795d594fSAndroid Build Coastguard Worker
2608*795d594fSAndroid Build Coastguard Worker // Parse a uleb128 value for each field and method of this class.
2609*795d594fSAndroid Build Coastguard Worker bool failure = false;
2610*795d594fSAndroid Build Coastguard Worker auto fn_member = [&](const ClassAccessor::BaseItem& member, const char* member_type) {
2611*795d594fSAndroid Build Coastguard Worker if (failure) {
2612*795d594fSAndroid Build Coastguard Worker return;
2613*795d594fSAndroid Build Coastguard Worker }
2614*795d594fSAndroid Build Coastguard Worker uint32_t decoded_flags;
2615*795d594fSAndroid Build Coastguard Worker if (!DecodeUnsignedLeb128Checked(&ptr_, data_end, &decoded_flags)) {
2616*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Hiddenapi class data value out of bounds (%p > %p) for %s %i",
2617*795d594fSAndroid Build Coastguard Worker ptr_, data_end, member_type, member.GetIndex());
2618*795d594fSAndroid Build Coastguard Worker failure = true;
2619*795d594fSAndroid Build Coastguard Worker return;
2620*795d594fSAndroid Build Coastguard Worker }
2621*795d594fSAndroid Build Coastguard Worker if (!hiddenapi::ApiList(decoded_flags).IsValid()) {
2622*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Hiddenapi class data flags invalid (%u) for %s %i",
2623*795d594fSAndroid Build Coastguard Worker decoded_flags, member_type, member.GetIndex());
2624*795d594fSAndroid Build Coastguard Worker failure = true;
2625*795d594fSAndroid Build Coastguard Worker return;
2626*795d594fSAndroid Build Coastguard Worker }
2627*795d594fSAndroid Build Coastguard Worker };
2628*795d594fSAndroid Build Coastguard Worker auto fn_field = [&](const ClassAccessor::Field& field) { fn_member(field, "field"); };
2629*795d594fSAndroid Build Coastguard Worker auto fn_method = [&](const ClassAccessor::Method& method) { fn_member(method, "method"); };
2630*795d594fSAndroid Build Coastguard Worker ClassAccessor accessor(*dex_file_, class_data);
2631*795d594fSAndroid Build Coastguard Worker accessor.VisitFieldsAndMethods(fn_field, fn_field, fn_method, fn_method);
2632*795d594fSAndroid Build Coastguard Worker if (failure) {
2633*795d594fSAndroid Build Coastguard Worker return false;
2634*795d594fSAndroid Build Coastguard Worker }
2635*795d594fSAndroid Build Coastguard Worker }
2636*795d594fSAndroid Build Coastguard Worker
2637*795d594fSAndroid Build Coastguard Worker if (ptr_ != data_end) {
2638*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Hiddenapi class data wrong reported size (%u != %u)",
2639*795d594fSAndroid Build Coastguard Worker static_cast<uint32_t>(ptr_ - reinterpret_cast<const uint8_t*>(item)),
2640*795d594fSAndroid Build Coastguard Worker item->size_);
2641*795d594fSAndroid Build Coastguard Worker return false;
2642*795d594fSAndroid Build Coastguard Worker }
2643*795d594fSAndroid Build Coastguard Worker
2644*795d594fSAndroid Build Coastguard Worker return true;
2645*795d594fSAndroid Build Coastguard Worker }
2646*795d594fSAndroid Build Coastguard Worker
CheckInterStringIdItem()2647*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckInterStringIdItem() {
2648*795d594fSAndroid Build Coastguard Worker const dex::StringId* item = reinterpret_cast<const dex::StringId*>(ptr_);
2649*795d594fSAndroid Build Coastguard Worker
2650*795d594fSAndroid Build Coastguard Worker // Note: The mapping to string data items is eagerly verified at the start of CheckInterSection().
2651*795d594fSAndroid Build Coastguard Worker
2652*795d594fSAndroid Build Coastguard Worker // Check ordering between items.
2653*795d594fSAndroid Build Coastguard Worker if (previous_item_ != nullptr) {
2654*795d594fSAndroid Build Coastguard Worker const dex::StringId* prev_item = reinterpret_cast<const dex::StringId*>(previous_item_);
2655*795d594fSAndroid Build Coastguard Worker const char* prev_str = dex_file_->GetStringData(*prev_item);
2656*795d594fSAndroid Build Coastguard Worker const char* str = dex_file_->GetStringData(*item);
2657*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(prev_str, str) >= 0)) {
2658*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-order string_ids: '%s' then '%s'", prev_str, str);
2659*795d594fSAndroid Build Coastguard Worker return false;
2660*795d594fSAndroid Build Coastguard Worker }
2661*795d594fSAndroid Build Coastguard Worker }
2662*795d594fSAndroid Build Coastguard Worker
2663*795d594fSAndroid Build Coastguard Worker ptr_ += sizeof(dex::StringId);
2664*795d594fSAndroid Build Coastguard Worker return true;
2665*795d594fSAndroid Build Coastguard Worker }
2666*795d594fSAndroid Build Coastguard Worker
CheckInterTypeIdItem()2667*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckInterTypeIdItem() {
2668*795d594fSAndroid Build Coastguard Worker const dex::TypeId* item = reinterpret_cast<const dex::TypeId*>(ptr_);
2669*795d594fSAndroid Build Coastguard Worker
2670*795d594fSAndroid Build Coastguard Worker {
2671*795d594fSAndroid Build Coastguard Worker // Translate to index to potentially use cache.
2672*795d594fSAndroid Build Coastguard Worker // The check in `CheckIntraIdSection()` guarantees that this index is valid.
2673*795d594fSAndroid Build Coastguard Worker size_t index = item - OffsetToPtr<dex::TypeId>(header_->type_ids_off_);
2674*795d594fSAndroid Build Coastguard Worker DCHECK_LE(index, header_->type_ids_size_);
2675*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!VerifyTypeDescriptor(
2676*795d594fSAndroid Build Coastguard Worker dex::TypeIndex(static_cast<decltype(dex::TypeIndex::index_)>(index)),
2677*795d594fSAndroid Build Coastguard Worker "Invalid type descriptor",
2678*795d594fSAndroid Build Coastguard Worker [](char) { return true; }))) {
2679*795d594fSAndroid Build Coastguard Worker return false;
2680*795d594fSAndroid Build Coastguard Worker }
2681*795d594fSAndroid Build Coastguard Worker }
2682*795d594fSAndroid Build Coastguard Worker
2683*795d594fSAndroid Build Coastguard Worker // Check ordering between items.
2684*795d594fSAndroid Build Coastguard Worker if (previous_item_ != nullptr) {
2685*795d594fSAndroid Build Coastguard Worker const dex::TypeId* prev_item = reinterpret_cast<const dex::TypeId*>(previous_item_);
2686*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(prev_item->descriptor_idx_ >= item->descriptor_idx_)) {
2687*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-order type_ids: %x then %x",
2688*795d594fSAndroid Build Coastguard Worker prev_item->descriptor_idx_.index_,
2689*795d594fSAndroid Build Coastguard Worker item->descriptor_idx_.index_);
2690*795d594fSAndroid Build Coastguard Worker return false;
2691*795d594fSAndroid Build Coastguard Worker }
2692*795d594fSAndroid Build Coastguard Worker }
2693*795d594fSAndroid Build Coastguard Worker
2694*795d594fSAndroid Build Coastguard Worker ptr_ += sizeof(dex::TypeId);
2695*795d594fSAndroid Build Coastguard Worker return true;
2696*795d594fSAndroid Build Coastguard Worker }
2697*795d594fSAndroid Build Coastguard Worker
CheckInterProtoIdItem()2698*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckInterProtoIdItem() {
2699*795d594fSAndroid Build Coastguard Worker const dex::ProtoId* item = reinterpret_cast<const dex::ProtoId*>(ptr_);
2700*795d594fSAndroid Build Coastguard Worker
2701*795d594fSAndroid Build Coastguard Worker const char* shorty = dex_file_->GetStringData(item->shorty_idx_);
2702*795d594fSAndroid Build Coastguard Worker
2703*795d594fSAndroid Build Coastguard Worker if (item->parameters_off_ != 0 &&
2704*795d594fSAndroid Build Coastguard Worker !CheckOffsetToTypeMap(item->parameters_off_, DexFile::kDexTypeTypeList)) {
2705*795d594fSAndroid Build Coastguard Worker return false;
2706*795d594fSAndroid Build Coastguard Worker }
2707*795d594fSAndroid Build Coastguard Worker
2708*795d594fSAndroid Build Coastguard Worker // Check that return type is representable as a uint16_t;
2709*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!IsValidOrNoTypeId(item->return_type_idx_.index_, item->pad_))) {
2710*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("proto with return type idx outside uint16_t range '%x:%x'",
2711*795d594fSAndroid Build Coastguard Worker item->pad_, item->return_type_idx_.index_);
2712*795d594fSAndroid Build Coastguard Worker return false;
2713*795d594fSAndroid Build Coastguard Worker }
2714*795d594fSAndroid Build Coastguard Worker // Check the return type and advance the shorty.
2715*795d594fSAndroid Build Coastguard Worker const char* return_type = dex_file_->GetTypeDescriptor(item->return_type_idx_);
2716*795d594fSAndroid Build Coastguard Worker if (!CheckShortyDescriptorMatch(*shorty, return_type, true)) {
2717*795d594fSAndroid Build Coastguard Worker return false;
2718*795d594fSAndroid Build Coastguard Worker }
2719*795d594fSAndroid Build Coastguard Worker shorty++;
2720*795d594fSAndroid Build Coastguard Worker
2721*795d594fSAndroid Build Coastguard Worker DexFileParameterIterator it(*dex_file_, *item);
2722*795d594fSAndroid Build Coastguard Worker while (it.HasNext() && *shorty != '\0') {
2723*795d594fSAndroid Build Coastguard Worker if (!CheckIndex(it.GetTypeIdx().index_,
2724*795d594fSAndroid Build Coastguard Worker dex_file_->NumTypeIds(),
2725*795d594fSAndroid Build Coastguard Worker "inter_proto_id_item shorty type_idx")) {
2726*795d594fSAndroid Build Coastguard Worker return false;
2727*795d594fSAndroid Build Coastguard Worker }
2728*795d594fSAndroid Build Coastguard Worker const char* descriptor = it.GetDescriptor();
2729*795d594fSAndroid Build Coastguard Worker if (!CheckShortyDescriptorMatch(*shorty, descriptor, false)) {
2730*795d594fSAndroid Build Coastguard Worker return false;
2731*795d594fSAndroid Build Coastguard Worker }
2732*795d594fSAndroid Build Coastguard Worker it.Next();
2733*795d594fSAndroid Build Coastguard Worker shorty++;
2734*795d594fSAndroid Build Coastguard Worker }
2735*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(it.HasNext() || *shorty != '\0')) {
2736*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Mismatched length for parameters and shorty");
2737*795d594fSAndroid Build Coastguard Worker return false;
2738*795d594fSAndroid Build Coastguard Worker }
2739*795d594fSAndroid Build Coastguard Worker
2740*795d594fSAndroid Build Coastguard Worker // Check ordering between items. This relies on type_ids being in order.
2741*795d594fSAndroid Build Coastguard Worker if (previous_item_ != nullptr) {
2742*795d594fSAndroid Build Coastguard Worker const dex::ProtoId* prev = reinterpret_cast<const dex::ProtoId*>(previous_item_);
2743*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(prev->return_type_idx_ > item->return_type_idx_)) {
2744*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-order proto_id return types");
2745*795d594fSAndroid Build Coastguard Worker return false;
2746*795d594fSAndroid Build Coastguard Worker } else if (prev->return_type_idx_ == item->return_type_idx_) {
2747*795d594fSAndroid Build Coastguard Worker DexFileParameterIterator curr_it(*dex_file_, *item);
2748*795d594fSAndroid Build Coastguard Worker DexFileParameterIterator prev_it(*dex_file_, *prev);
2749*795d594fSAndroid Build Coastguard Worker
2750*795d594fSAndroid Build Coastguard Worker while (curr_it.HasNext() && prev_it.HasNext()) {
2751*795d594fSAndroid Build Coastguard Worker dex::TypeIndex prev_idx = prev_it.GetTypeIdx();
2752*795d594fSAndroid Build Coastguard Worker dex::TypeIndex curr_idx = curr_it.GetTypeIdx();
2753*795d594fSAndroid Build Coastguard Worker DCHECK_NE(prev_idx, dex::TypeIndex(DexFile::kDexNoIndex16));
2754*795d594fSAndroid Build Coastguard Worker DCHECK_NE(curr_idx, dex::TypeIndex(DexFile::kDexNoIndex16));
2755*795d594fSAndroid Build Coastguard Worker
2756*795d594fSAndroid Build Coastguard Worker if (prev_idx < curr_idx) {
2757*795d594fSAndroid Build Coastguard Worker break;
2758*795d594fSAndroid Build Coastguard Worker } else if (UNLIKELY(prev_idx > curr_idx)) {
2759*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-order proto_id arguments");
2760*795d594fSAndroid Build Coastguard Worker return false;
2761*795d594fSAndroid Build Coastguard Worker }
2762*795d594fSAndroid Build Coastguard Worker
2763*795d594fSAndroid Build Coastguard Worker prev_it.Next();
2764*795d594fSAndroid Build Coastguard Worker curr_it.Next();
2765*795d594fSAndroid Build Coastguard Worker }
2766*795d594fSAndroid Build Coastguard Worker if (!curr_it.HasNext()) {
2767*795d594fSAndroid Build Coastguard Worker // Either a duplicate ProtoId or a ProtoId with a shorter argument list follows
2768*795d594fSAndroid Build Coastguard Worker // a ProtoId with a longer one. Both cases are forbidden by the specification.
2769*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-order proto_id arguments");
2770*795d594fSAndroid Build Coastguard Worker return false;
2771*795d594fSAndroid Build Coastguard Worker }
2772*795d594fSAndroid Build Coastguard Worker }
2773*795d594fSAndroid Build Coastguard Worker }
2774*795d594fSAndroid Build Coastguard Worker
2775*795d594fSAndroid Build Coastguard Worker ptr_ += sizeof(dex::ProtoId);
2776*795d594fSAndroid Build Coastguard Worker return true;
2777*795d594fSAndroid Build Coastguard Worker }
2778*795d594fSAndroid Build Coastguard Worker
CheckInterFieldIdItem()2779*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckInterFieldIdItem() {
2780*795d594fSAndroid Build Coastguard Worker const dex::FieldId* item = reinterpret_cast<const dex::FieldId*>(ptr_);
2781*795d594fSAndroid Build Coastguard Worker
2782*795d594fSAndroid Build Coastguard Worker // Check that the class descriptor is valid.
2783*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!VerifyTypeDescriptor(item->class_idx_,
2784*795d594fSAndroid Build Coastguard Worker "Invalid descriptor for class_idx",
2785*795d594fSAndroid Build Coastguard Worker [](char d) { return d == 'L'; }))) {
2786*795d594fSAndroid Build Coastguard Worker return false;
2787*795d594fSAndroid Build Coastguard Worker }
2788*795d594fSAndroid Build Coastguard Worker
2789*795d594fSAndroid Build Coastguard Worker // Check that the type descriptor is a valid field name.
2790*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!VerifyTypeDescriptor(item->type_idx_,
2791*795d594fSAndroid Build Coastguard Worker "Invalid descriptor for type_idx",
2792*795d594fSAndroid Build Coastguard Worker [](char d) { return d != 'V'; }))) {
2793*795d594fSAndroid Build Coastguard Worker return false;
2794*795d594fSAndroid Build Coastguard Worker }
2795*795d594fSAndroid Build Coastguard Worker
2796*795d594fSAndroid Build Coastguard Worker // Check that the name is valid.
2797*795d594fSAndroid Build Coastguard Worker const char* field_name = dex_file_->GetStringData(item->name_idx_);
2798*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!IsValidMemberName(field_name))) {
2799*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid field name: '%s'", field_name);
2800*795d594fSAndroid Build Coastguard Worker return false;
2801*795d594fSAndroid Build Coastguard Worker }
2802*795d594fSAndroid Build Coastguard Worker
2803*795d594fSAndroid Build Coastguard Worker // Check ordering between items. This relies on the other sections being in order.
2804*795d594fSAndroid Build Coastguard Worker if (previous_item_ != nullptr) {
2805*795d594fSAndroid Build Coastguard Worker const dex::FieldId* prev_item = reinterpret_cast<const dex::FieldId*>(previous_item_);
2806*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(prev_item->class_idx_ > item->class_idx_)) {
2807*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-order field_ids");
2808*795d594fSAndroid Build Coastguard Worker return false;
2809*795d594fSAndroid Build Coastguard Worker } else if (prev_item->class_idx_ == item->class_idx_) {
2810*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(prev_item->name_idx_ > item->name_idx_)) {
2811*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-order field_ids");
2812*795d594fSAndroid Build Coastguard Worker return false;
2813*795d594fSAndroid Build Coastguard Worker } else if (prev_item->name_idx_ == item->name_idx_) {
2814*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(prev_item->type_idx_ >= item->type_idx_)) {
2815*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-order field_ids");
2816*795d594fSAndroid Build Coastguard Worker return false;
2817*795d594fSAndroid Build Coastguard Worker }
2818*795d594fSAndroid Build Coastguard Worker }
2819*795d594fSAndroid Build Coastguard Worker }
2820*795d594fSAndroid Build Coastguard Worker }
2821*795d594fSAndroid Build Coastguard Worker
2822*795d594fSAndroid Build Coastguard Worker ptr_ += sizeof(dex::FieldId);
2823*795d594fSAndroid Build Coastguard Worker return true;
2824*795d594fSAndroid Build Coastguard Worker }
2825*795d594fSAndroid Build Coastguard Worker
CheckInterMethodIdItem()2826*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckInterMethodIdItem() {
2827*795d594fSAndroid Build Coastguard Worker const dex::MethodId* item = reinterpret_cast<const dex::MethodId*>(ptr_);
2828*795d594fSAndroid Build Coastguard Worker
2829*795d594fSAndroid Build Coastguard Worker // Check that the class descriptor is a valid reference name.
2830*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!VerifyTypeDescriptor(item->class_idx_,
2831*795d594fSAndroid Build Coastguard Worker "Invalid descriptor for class_idx",
2832*795d594fSAndroid Build Coastguard Worker [](char d) { return d == 'L' || d == '['; }))) {
2833*795d594fSAndroid Build Coastguard Worker return false;
2834*795d594fSAndroid Build Coastguard Worker }
2835*795d594fSAndroid Build Coastguard Worker
2836*795d594fSAndroid Build Coastguard Worker // Check that the name is valid.
2837*795d594fSAndroid Build Coastguard Worker const char* method_name = dex_file_->GetStringData(item->name_idx_);
2838*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!IsValidMemberName(method_name))) {
2839*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid method name: '%s'", method_name);
2840*795d594fSAndroid Build Coastguard Worker return false;
2841*795d594fSAndroid Build Coastguard Worker }
2842*795d594fSAndroid Build Coastguard Worker
2843*795d594fSAndroid Build Coastguard Worker // Check that the proto id is valid.
2844*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!CheckIndex(item->proto_idx_.index_, dex_file_->NumProtoIds(),
2845*795d594fSAndroid Build Coastguard Worker "inter_method_id_item proto_idx"))) {
2846*795d594fSAndroid Build Coastguard Worker return false;
2847*795d594fSAndroid Build Coastguard Worker }
2848*795d594fSAndroid Build Coastguard Worker
2849*795d594fSAndroid Build Coastguard Worker // Check ordering between items. This relies on the other sections being in order.
2850*795d594fSAndroid Build Coastguard Worker if (previous_item_ != nullptr) {
2851*795d594fSAndroid Build Coastguard Worker const dex::MethodId* prev_item = reinterpret_cast<const dex::MethodId*>(previous_item_);
2852*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(prev_item->class_idx_ > item->class_idx_)) {
2853*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-order method_ids");
2854*795d594fSAndroid Build Coastguard Worker return false;
2855*795d594fSAndroid Build Coastguard Worker } else if (prev_item->class_idx_ == item->class_idx_) {
2856*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(prev_item->name_idx_ > item->name_idx_)) {
2857*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-order method_ids");
2858*795d594fSAndroid Build Coastguard Worker return false;
2859*795d594fSAndroid Build Coastguard Worker } else if (prev_item->name_idx_ == item->name_idx_) {
2860*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(prev_item->proto_idx_ >= item->proto_idx_)) {
2861*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-order method_ids");
2862*795d594fSAndroid Build Coastguard Worker return false;
2863*795d594fSAndroid Build Coastguard Worker }
2864*795d594fSAndroid Build Coastguard Worker }
2865*795d594fSAndroid Build Coastguard Worker }
2866*795d594fSAndroid Build Coastguard Worker }
2867*795d594fSAndroid Build Coastguard Worker
2868*795d594fSAndroid Build Coastguard Worker ptr_ += sizeof(dex::MethodId);
2869*795d594fSAndroid Build Coastguard Worker return true;
2870*795d594fSAndroid Build Coastguard Worker }
2871*795d594fSAndroid Build Coastguard Worker
CheckInterClassDefItem()2872*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckInterClassDefItem() {
2873*795d594fSAndroid Build Coastguard Worker const dex::ClassDef* item = reinterpret_cast<const dex::ClassDef*>(ptr_);
2874*795d594fSAndroid Build Coastguard Worker
2875*795d594fSAndroid Build Coastguard Worker // Check that class_idx_ is representable as a uint16_t;
2876*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!IsValidTypeId(item->class_idx_.index_, item->pad1_))) {
2877*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("class with type idx outside uint16_t range '%x:%x'", item->pad1_,
2878*795d594fSAndroid Build Coastguard Worker item->class_idx_.index_);
2879*795d594fSAndroid Build Coastguard Worker return false;
2880*795d594fSAndroid Build Coastguard Worker }
2881*795d594fSAndroid Build Coastguard Worker // Check that superclass_idx_ is representable as a uint16_t;
2882*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!IsValidOrNoTypeId(item->superclass_idx_.index_, item->pad2_))) {
2883*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("class with superclass type idx outside uint16_t range '%x:%x'", item->pad2_,
2884*795d594fSAndroid Build Coastguard Worker item->superclass_idx_.index_);
2885*795d594fSAndroid Build Coastguard Worker return false;
2886*795d594fSAndroid Build Coastguard Worker }
2887*795d594fSAndroid Build Coastguard Worker // Check for duplicate class def.
2888*795d594fSAndroid Build Coastguard Worker
2889*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!VerifyTypeDescriptor(item->class_idx_,
2890*795d594fSAndroid Build Coastguard Worker "Invalid class descriptor",
2891*795d594fSAndroid Build Coastguard Worker [](char d) { return d == 'L'; }))) {
2892*795d594fSAndroid Build Coastguard Worker return false;
2893*795d594fSAndroid Build Coastguard Worker }
2894*795d594fSAndroid Build Coastguard Worker
2895*795d594fSAndroid Build Coastguard Worker // Only allow non-runtime modifiers.
2896*795d594fSAndroid Build Coastguard Worker if ((item->access_flags_ & ~kAccJavaFlagsMask) != 0) {
2897*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid class flags: '%d'", item->access_flags_);
2898*795d594fSAndroid Build Coastguard Worker return false;
2899*795d594fSAndroid Build Coastguard Worker }
2900*795d594fSAndroid Build Coastguard Worker
2901*795d594fSAndroid Build Coastguard Worker if (item->interfaces_off_ != 0 &&
2902*795d594fSAndroid Build Coastguard Worker !CheckOffsetToTypeMap(item->interfaces_off_, DexFile::kDexTypeTypeList)) {
2903*795d594fSAndroid Build Coastguard Worker return false;
2904*795d594fSAndroid Build Coastguard Worker }
2905*795d594fSAndroid Build Coastguard Worker if (item->annotations_off_ != 0 &&
2906*795d594fSAndroid Build Coastguard Worker !CheckOffsetToTypeMap(item->annotations_off_, DexFile::kDexTypeAnnotationsDirectoryItem)) {
2907*795d594fSAndroid Build Coastguard Worker return false;
2908*795d594fSAndroid Build Coastguard Worker }
2909*795d594fSAndroid Build Coastguard Worker if (item->class_data_off_ != 0 &&
2910*795d594fSAndroid Build Coastguard Worker !CheckOffsetToTypeMap(item->class_data_off_, DexFile::kDexTypeClassDataItem)) {
2911*795d594fSAndroid Build Coastguard Worker return false;
2912*795d594fSAndroid Build Coastguard Worker }
2913*795d594fSAndroid Build Coastguard Worker if (item->static_values_off_ != 0 &&
2914*795d594fSAndroid Build Coastguard Worker !CheckOffsetToTypeMap(item->static_values_off_, DexFile::kDexTypeEncodedArrayItem)) {
2915*795d594fSAndroid Build Coastguard Worker return false;
2916*795d594fSAndroid Build Coastguard Worker }
2917*795d594fSAndroid Build Coastguard Worker
2918*795d594fSAndroid Build Coastguard Worker if (item->superclass_idx_.IsValid()) {
2919*795d594fSAndroid Build Coastguard Worker if (header_->GetVersion() >= DexFile::kClassDefinitionOrderEnforcedVersion) {
2920*795d594fSAndroid Build Coastguard Worker // Check that a class does not inherit from itself directly (by having
2921*795d594fSAndroid Build Coastguard Worker // the same type idx as its super class).
2922*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(item->superclass_idx_ == item->class_idx_)) {
2923*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Class with same type idx as its superclass: '%d'",
2924*795d594fSAndroid Build Coastguard Worker item->class_idx_.index_);
2925*795d594fSAndroid Build Coastguard Worker return false;
2926*795d594fSAndroid Build Coastguard Worker }
2927*795d594fSAndroid Build Coastguard Worker
2928*795d594fSAndroid Build Coastguard Worker // Check that a class is defined after its super class (if the
2929*795d594fSAndroid Build Coastguard Worker // latter is defined in the same Dex file).
2930*795d594fSAndroid Build Coastguard Worker uint16_t superclass_idx = item->superclass_idx_.index_;
2931*795d594fSAndroid Build Coastguard Worker if (defined_classes_[superclass_idx]) {
2932*795d594fSAndroid Build Coastguard Worker // The superclass is defined in this Dex file.
2933*795d594fSAndroid Build Coastguard Worker if (&dex_file_->GetClassDef(defined_class_indexes_[superclass_idx]) > item) {
2934*795d594fSAndroid Build Coastguard Worker // ClassDef item for super class appearing after the class' ClassDef item.
2935*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid class definition ordering:"
2936*795d594fSAndroid Build Coastguard Worker " class with type idx: '%d' defined before"
2937*795d594fSAndroid Build Coastguard Worker " superclass with type idx: '%d'",
2938*795d594fSAndroid Build Coastguard Worker item->class_idx_.index_,
2939*795d594fSAndroid Build Coastguard Worker superclass_idx);
2940*795d594fSAndroid Build Coastguard Worker return false;
2941*795d594fSAndroid Build Coastguard Worker }
2942*795d594fSAndroid Build Coastguard Worker }
2943*795d594fSAndroid Build Coastguard Worker }
2944*795d594fSAndroid Build Coastguard Worker
2945*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!VerifyTypeDescriptor(item->superclass_idx_,
2946*795d594fSAndroid Build Coastguard Worker "Invalid superclass",
2947*795d594fSAndroid Build Coastguard Worker [](char d) { return d == 'L'; }))) {
2948*795d594fSAndroid Build Coastguard Worker return false;
2949*795d594fSAndroid Build Coastguard Worker }
2950*795d594fSAndroid Build Coastguard Worker }
2951*795d594fSAndroid Build Coastguard Worker
2952*795d594fSAndroid Build Coastguard Worker // Check interfaces.
2953*795d594fSAndroid Build Coastguard Worker const dex::TypeList* interfaces = dex_file_->GetInterfacesList(*item);
2954*795d594fSAndroid Build Coastguard Worker if (interfaces != nullptr) {
2955*795d594fSAndroid Build Coastguard Worker uint32_t size = interfaces->Size();
2956*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < size; i++) {
2957*795d594fSAndroid Build Coastguard Worker if (header_->GetVersion() >= DexFile::kClassDefinitionOrderEnforcedVersion) {
2958*795d594fSAndroid Build Coastguard Worker // Check that a class does not implement itself directly (by having the
2959*795d594fSAndroid Build Coastguard Worker // same type idx as one of its immediate implemented interfaces).
2960*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(interfaces->GetTypeItem(i).type_idx_ == item->class_idx_)) {
2961*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Class with same type idx as implemented interface: '%d'",
2962*795d594fSAndroid Build Coastguard Worker item->class_idx_.index_);
2963*795d594fSAndroid Build Coastguard Worker return false;
2964*795d594fSAndroid Build Coastguard Worker }
2965*795d594fSAndroid Build Coastguard Worker
2966*795d594fSAndroid Build Coastguard Worker // Check that a class is defined after the interfaces it implements
2967*795d594fSAndroid Build Coastguard Worker // (if they are defined in the same Dex file).
2968*795d594fSAndroid Build Coastguard Worker uint16_t interface_idx = interfaces->GetTypeItem(i).type_idx_.index_;
2969*795d594fSAndroid Build Coastguard Worker if (defined_classes_[interface_idx]) {
2970*795d594fSAndroid Build Coastguard Worker // The interface is defined in this Dex file.
2971*795d594fSAndroid Build Coastguard Worker if (&dex_file_->GetClassDef(defined_class_indexes_[interface_idx]) > item) {
2972*795d594fSAndroid Build Coastguard Worker // ClassDef item for interface appearing after the class' ClassDef item.
2973*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid class definition ordering:"
2974*795d594fSAndroid Build Coastguard Worker " class with type idx: '%d' defined before"
2975*795d594fSAndroid Build Coastguard Worker " implemented interface with type idx: '%d'",
2976*795d594fSAndroid Build Coastguard Worker item->class_idx_.index_,
2977*795d594fSAndroid Build Coastguard Worker interface_idx);
2978*795d594fSAndroid Build Coastguard Worker return false;
2979*795d594fSAndroid Build Coastguard Worker }
2980*795d594fSAndroid Build Coastguard Worker }
2981*795d594fSAndroid Build Coastguard Worker }
2982*795d594fSAndroid Build Coastguard Worker
2983*795d594fSAndroid Build Coastguard Worker // Ensure that the interface refers to a class (not an array nor a primitive type).
2984*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!VerifyTypeDescriptor(interfaces->GetTypeItem(i).type_idx_,
2985*795d594fSAndroid Build Coastguard Worker "Invalid interface",
2986*795d594fSAndroid Build Coastguard Worker [](char d) { return d == 'L'; }))) {
2987*795d594fSAndroid Build Coastguard Worker return false;
2988*795d594fSAndroid Build Coastguard Worker }
2989*795d594fSAndroid Build Coastguard Worker }
2990*795d594fSAndroid Build Coastguard Worker
2991*795d594fSAndroid Build Coastguard Worker /*
2992*795d594fSAndroid Build Coastguard Worker * Ensure that there are no duplicates. This is an O(N^2) test, but in
2993*795d594fSAndroid Build Coastguard Worker * practice the number of interfaces implemented by any given class is low.
2994*795d594fSAndroid Build Coastguard Worker */
2995*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 1; i < size; i++) {
2996*795d594fSAndroid Build Coastguard Worker dex::TypeIndex idx1 = interfaces->GetTypeItem(i).type_idx_;
2997*795d594fSAndroid Build Coastguard Worker for (uint32_t j =0; j < i; j++) {
2998*795d594fSAndroid Build Coastguard Worker dex::TypeIndex idx2 = interfaces->GetTypeItem(j).type_idx_;
2999*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(idx1 == idx2)) {
3000*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Duplicate interface: '%s'", dex_file_->GetTypeDescriptor(idx1));
3001*795d594fSAndroid Build Coastguard Worker return false;
3002*795d594fSAndroid Build Coastguard Worker }
3003*795d594fSAndroid Build Coastguard Worker }
3004*795d594fSAndroid Build Coastguard Worker }
3005*795d594fSAndroid Build Coastguard Worker }
3006*795d594fSAndroid Build Coastguard Worker
3007*795d594fSAndroid Build Coastguard Worker // Check that references in class_data_item are to the right class.
3008*795d594fSAndroid Build Coastguard Worker if (item->class_data_off_ != 0) {
3009*795d594fSAndroid Build Coastguard Worker ClassAccessor accessor(*dex_file_, OffsetToPtr(item->class_data_off_));
3010*795d594fSAndroid Build Coastguard Worker uint32_t data_definer = FindFirstClassDataDefiner(accessor);
3011*795d594fSAndroid Build Coastguard Worker DCHECK(IsUint<16>(data_definer) || data_definer == kDexNoIndex) << data_definer;
3012*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((data_definer != item->class_idx_.index_) && (data_definer != kDexNoIndex))) {
3013*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid class_data_item");
3014*795d594fSAndroid Build Coastguard Worker return false;
3015*795d594fSAndroid Build Coastguard Worker }
3016*795d594fSAndroid Build Coastguard Worker }
3017*795d594fSAndroid Build Coastguard Worker
3018*795d594fSAndroid Build Coastguard Worker // Check that references in annotations_directory_item are to right class.
3019*795d594fSAndroid Build Coastguard Worker if (item->annotations_off_ != 0) {
3020*795d594fSAndroid Build Coastguard Worker // annotations_off_ is supposed to be aligned by 4.
3021*795d594fSAndroid Build Coastguard Worker if (!IsAlignedParam(item->annotations_off_, 4)) {
3022*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid annotations_off_, not aligned by 4");
3023*795d594fSAndroid Build Coastguard Worker return false;
3024*795d594fSAndroid Build Coastguard Worker }
3025*795d594fSAndroid Build Coastguard Worker const uint8_t* data = OffsetToPtr(item->annotations_off_);
3026*795d594fSAndroid Build Coastguard Worker uint32_t defining_class = FindFirstAnnotationsDirectoryDefiner(data);
3027*795d594fSAndroid Build Coastguard Worker DCHECK(IsUint<16>(defining_class) || defining_class == kDexNoIndex) << defining_class;
3028*795d594fSAndroid Build Coastguard Worker if (UNLIKELY((defining_class != item->class_idx_.index_) && (defining_class != kDexNoIndex))) {
3029*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Invalid annotations_directory_item");
3030*795d594fSAndroid Build Coastguard Worker return false;
3031*795d594fSAndroid Build Coastguard Worker }
3032*795d594fSAndroid Build Coastguard Worker }
3033*795d594fSAndroid Build Coastguard Worker
3034*795d594fSAndroid Build Coastguard Worker ptr_ += sizeof(dex::ClassDef);
3035*795d594fSAndroid Build Coastguard Worker return true;
3036*795d594fSAndroid Build Coastguard Worker }
3037*795d594fSAndroid Build Coastguard Worker
CheckInterCallSiteIdItem()3038*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckInterCallSiteIdItem() {
3039*795d594fSAndroid Build Coastguard Worker const dex::CallSiteIdItem* item = reinterpret_cast<const dex::CallSiteIdItem*>(ptr_);
3040*795d594fSAndroid Build Coastguard Worker
3041*795d594fSAndroid Build Coastguard Worker // Check call site referenced by item is in encoded array section.
3042*795d594fSAndroid Build Coastguard Worker if (!CheckOffsetToTypeMap(item->data_off_, DexFile::kDexTypeEncodedArrayItem)) {
3043*795d594fSAndroid Build Coastguard Worker DCHECK(!failure_reason_.empty()); // Error already set.
3044*795d594fSAndroid Build Coastguard Worker return false;
3045*795d594fSAndroid Build Coastguard Worker }
3046*795d594fSAndroid Build Coastguard Worker
3047*795d594fSAndroid Build Coastguard Worker CallSiteArrayValueIterator it(*dex_file_, *item);
3048*795d594fSAndroid Build Coastguard Worker
3049*795d594fSAndroid Build Coastguard Worker // Check Method Handle
3050*795d594fSAndroid Build Coastguard Worker if (!it.HasNext() || it.GetValueType() != EncodedArrayValueIterator::ValueType::kMethodHandle) {
3051*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("CallSiteArray missing method handle");
3052*795d594fSAndroid Build Coastguard Worker return false;
3053*795d594fSAndroid Build Coastguard Worker }
3054*795d594fSAndroid Build Coastguard Worker
3055*795d594fSAndroid Build Coastguard Worker uint32_t handle_index = static_cast<uint32_t>(it.GetJavaValue().i);
3056*795d594fSAndroid Build Coastguard Worker if (handle_index >= dex_file_->NumMethodHandles()) {
3057*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("CallSite has bad method handle id: %x", handle_index);
3058*795d594fSAndroid Build Coastguard Worker return false;
3059*795d594fSAndroid Build Coastguard Worker }
3060*795d594fSAndroid Build Coastguard Worker
3061*795d594fSAndroid Build Coastguard Worker // Check target method name.
3062*795d594fSAndroid Build Coastguard Worker if (!it.MaybeNext()) {
3063*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("unexpected encoded value type: '%c'", it.GetValueType());
3064*795d594fSAndroid Build Coastguard Worker return false;
3065*795d594fSAndroid Build Coastguard Worker }
3066*795d594fSAndroid Build Coastguard Worker if (!it.HasNext() ||
3067*795d594fSAndroid Build Coastguard Worker it.GetValueType() != EncodedArrayValueIterator::ValueType::kString) {
3068*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("CallSiteArray missing target method name");
3069*795d594fSAndroid Build Coastguard Worker return false;
3070*795d594fSAndroid Build Coastguard Worker }
3071*795d594fSAndroid Build Coastguard Worker
3072*795d594fSAndroid Build Coastguard Worker uint32_t name_index = static_cast<uint32_t>(it.GetJavaValue().i);
3073*795d594fSAndroid Build Coastguard Worker if (name_index >= dex_file_->NumStringIds()) {
3074*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("CallSite has bad method name id: %x", name_index);
3075*795d594fSAndroid Build Coastguard Worker return false;
3076*795d594fSAndroid Build Coastguard Worker }
3077*795d594fSAndroid Build Coastguard Worker
3078*795d594fSAndroid Build Coastguard Worker // Check method type.
3079*795d594fSAndroid Build Coastguard Worker if (!it.MaybeNext()) {
3080*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("unexpected encoded value type: '%c'", it.GetValueType());
3081*795d594fSAndroid Build Coastguard Worker return false;
3082*795d594fSAndroid Build Coastguard Worker }
3083*795d594fSAndroid Build Coastguard Worker if (!it.HasNext() ||
3084*795d594fSAndroid Build Coastguard Worker it.GetValueType() != EncodedArrayValueIterator::ValueType::kMethodType) {
3085*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("CallSiteArray missing method type");
3086*795d594fSAndroid Build Coastguard Worker return false;
3087*795d594fSAndroid Build Coastguard Worker }
3088*795d594fSAndroid Build Coastguard Worker
3089*795d594fSAndroid Build Coastguard Worker uint32_t proto_index = static_cast<uint32_t>(it.GetJavaValue().i);
3090*795d594fSAndroid Build Coastguard Worker if (proto_index >= dex_file_->NumProtoIds()) {
3091*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("CallSite has bad method type: %x", proto_index);
3092*795d594fSAndroid Build Coastguard Worker return false;
3093*795d594fSAndroid Build Coastguard Worker }
3094*795d594fSAndroid Build Coastguard Worker
3095*795d594fSAndroid Build Coastguard Worker ptr_ += sizeof(dex::CallSiteIdItem);
3096*795d594fSAndroid Build Coastguard Worker return true;
3097*795d594fSAndroid Build Coastguard Worker }
3098*795d594fSAndroid Build Coastguard Worker
CheckInterAnnotationSetRefList()3099*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckInterAnnotationSetRefList() {
3100*795d594fSAndroid Build Coastguard Worker const dex::AnnotationSetRefList* list = reinterpret_cast<const dex::AnnotationSetRefList*>(ptr_);
3101*795d594fSAndroid Build Coastguard Worker const dex::AnnotationSetRefItem* item = list->list_;
3102*795d594fSAndroid Build Coastguard Worker uint32_t count = list->size_;
3103*795d594fSAndroid Build Coastguard Worker
3104*795d594fSAndroid Build Coastguard Worker for (; count != 0u; --count) {
3105*795d594fSAndroid Build Coastguard Worker if (item->annotations_off_ != 0 &&
3106*795d594fSAndroid Build Coastguard Worker !CheckOffsetToTypeMap(item->annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
3107*795d594fSAndroid Build Coastguard Worker return false;
3108*795d594fSAndroid Build Coastguard Worker }
3109*795d594fSAndroid Build Coastguard Worker item++;
3110*795d594fSAndroid Build Coastguard Worker }
3111*795d594fSAndroid Build Coastguard Worker
3112*795d594fSAndroid Build Coastguard Worker ptr_ = reinterpret_cast<const uint8_t*>(item);
3113*795d594fSAndroid Build Coastguard Worker return true;
3114*795d594fSAndroid Build Coastguard Worker }
3115*795d594fSAndroid Build Coastguard Worker
CheckInterAnnotationSetItem()3116*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckInterAnnotationSetItem() {
3117*795d594fSAndroid Build Coastguard Worker const dex::AnnotationSetItem* set = reinterpret_cast<const dex::AnnotationSetItem*>(ptr_);
3118*795d594fSAndroid Build Coastguard Worker const uint32_t* offsets = set->entries_;
3119*795d594fSAndroid Build Coastguard Worker uint32_t count = set->size_;
3120*795d594fSAndroid Build Coastguard Worker uint32_t last_idx = 0;
3121*795d594fSAndroid Build Coastguard Worker
3122*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < count; i++) {
3123*795d594fSAndroid Build Coastguard Worker if (!CheckOffsetToTypeMap(*offsets, DexFile::kDexTypeAnnotationItem)) {
3124*795d594fSAndroid Build Coastguard Worker return false;
3125*795d594fSAndroid Build Coastguard Worker }
3126*795d594fSAndroid Build Coastguard Worker
3127*795d594fSAndroid Build Coastguard Worker // Get the annotation from the offset and the type index for the annotation.
3128*795d594fSAndroid Build Coastguard Worker const dex::AnnotationItem* annotation = OffsetToPtr<dex::AnnotationItem>(*offsets);
3129*795d594fSAndroid Build Coastguard Worker const uint8_t* data = annotation->annotation_;
3130*795d594fSAndroid Build Coastguard Worker DECODE_UNSIGNED_CHECKED_FROM(data, idx);
3131*795d594fSAndroid Build Coastguard Worker
3132*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(last_idx >= idx && i != 0)) {
3133*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Out-of-order entry types: %x then %x", last_idx, idx);
3134*795d594fSAndroid Build Coastguard Worker return false;
3135*795d594fSAndroid Build Coastguard Worker }
3136*795d594fSAndroid Build Coastguard Worker
3137*795d594fSAndroid Build Coastguard Worker last_idx = idx;
3138*795d594fSAndroid Build Coastguard Worker offsets++;
3139*795d594fSAndroid Build Coastguard Worker }
3140*795d594fSAndroid Build Coastguard Worker
3141*795d594fSAndroid Build Coastguard Worker ptr_ = reinterpret_cast<const uint8_t*>(offsets);
3142*795d594fSAndroid Build Coastguard Worker return true;
3143*795d594fSAndroid Build Coastguard Worker }
3144*795d594fSAndroid Build Coastguard Worker
CheckInterClassDataItem()3145*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckInterClassDataItem() {
3146*795d594fSAndroid Build Coastguard Worker ClassAccessor accessor(*dex_file_, ptr_);
3147*795d594fSAndroid Build Coastguard Worker uint32_t defining_class = FindFirstClassDataDefiner(accessor);
3148*795d594fSAndroid Build Coastguard Worker DCHECK(IsUint<16>(defining_class) || defining_class == kDexNoIndex) << defining_class;
3149*795d594fSAndroid Build Coastguard Worker if (defining_class == kDexNoIndex) {
3150*795d594fSAndroid Build Coastguard Worker return true; // Empty definitions are OK (but useless) and could be shared by multiple classes.
3151*795d594fSAndroid Build Coastguard Worker }
3152*795d594fSAndroid Build Coastguard Worker if (!defined_classes_[defining_class]) {
3153*795d594fSAndroid Build Coastguard Worker // Should really have a class definition for this class data item.
3154*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Could not find declaring class for non-empty class data item.");
3155*795d594fSAndroid Build Coastguard Worker return false;
3156*795d594fSAndroid Build Coastguard Worker }
3157*795d594fSAndroid Build Coastguard Worker const dex::TypeIndex class_type_index(defining_class);
3158*795d594fSAndroid Build Coastguard Worker const dex::ClassDef& class_def = dex_file_->GetClassDef(defined_class_indexes_[defining_class]);
3159*795d594fSAndroid Build Coastguard Worker
3160*795d594fSAndroid Build Coastguard Worker for (const ClassAccessor::Field& read_field : accessor.GetFields()) {
3161*795d594fSAndroid Build Coastguard Worker // The index has already been checked in `CheckIntraClassDataItemFields()`.
3162*795d594fSAndroid Build Coastguard Worker DCHECK_LE(read_field.GetIndex(), header_->field_ids_size_);
3163*795d594fSAndroid Build Coastguard Worker const dex::FieldId& field = dex_file_->GetFieldId(read_field.GetIndex());
3164*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(field.class_idx_ != class_type_index)) {
3165*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Mismatched defining class for class_data_item field");
3166*795d594fSAndroid Build Coastguard Worker return false;
3167*795d594fSAndroid Build Coastguard Worker }
3168*795d594fSAndroid Build Coastguard Worker if (!CheckClassDataItemField(read_field.GetIndex(),
3169*795d594fSAndroid Build Coastguard Worker read_field.GetAccessFlags(),
3170*795d594fSAndroid Build Coastguard Worker class_def.access_flags_,
3171*795d594fSAndroid Build Coastguard Worker class_type_index)) {
3172*795d594fSAndroid Build Coastguard Worker return false;
3173*795d594fSAndroid Build Coastguard Worker }
3174*795d594fSAndroid Build Coastguard Worker }
3175*795d594fSAndroid Build Coastguard Worker size_t num_direct_methods = accessor.NumDirectMethods();
3176*795d594fSAndroid Build Coastguard Worker size_t num_processed_methods = 0u;
3177*795d594fSAndroid Build Coastguard Worker auto methods = accessor.GetMethods();
3178*795d594fSAndroid Build Coastguard Worker auto it = methods.begin();
3179*795d594fSAndroid Build Coastguard Worker for (; it != methods.end(); ++it, ++num_processed_methods) {
3180*795d594fSAndroid Build Coastguard Worker uint32_t code_off = it->GetCodeItemOffset();
3181*795d594fSAndroid Build Coastguard Worker if (code_off != 0 && !CheckOffsetToTypeMap(code_off, DexFile::kDexTypeCodeItem)) {
3182*795d594fSAndroid Build Coastguard Worker return false;
3183*795d594fSAndroid Build Coastguard Worker }
3184*795d594fSAndroid Build Coastguard Worker // The index has already been checked in `CheckIntraClassDataItemMethods()`.
3185*795d594fSAndroid Build Coastguard Worker DCHECK_LE(it->GetIndex(), header_->method_ids_size_);
3186*795d594fSAndroid Build Coastguard Worker const dex::MethodId& method = dex_file_->GetMethodId(it->GetIndex());
3187*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(method.class_idx_ != class_type_index)) {
3188*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Mismatched defining class for class_data_item method");
3189*795d594fSAndroid Build Coastguard Worker return false;
3190*795d594fSAndroid Build Coastguard Worker }
3191*795d594fSAndroid Build Coastguard Worker bool expect_direct = num_processed_methods < num_direct_methods;
3192*795d594fSAndroid Build Coastguard Worker if (!CheckClassDataItemMethod(it->GetIndex(),
3193*795d594fSAndroid Build Coastguard Worker it->GetAccessFlags(),
3194*795d594fSAndroid Build Coastguard Worker class_def.access_flags_,
3195*795d594fSAndroid Build Coastguard Worker class_type_index,
3196*795d594fSAndroid Build Coastguard Worker it->GetCodeItemOffset(),
3197*795d594fSAndroid Build Coastguard Worker expect_direct)) {
3198*795d594fSAndroid Build Coastguard Worker return false;
3199*795d594fSAndroid Build Coastguard Worker }
3200*795d594fSAndroid Build Coastguard Worker }
3201*795d594fSAndroid Build Coastguard Worker
3202*795d594fSAndroid Build Coastguard Worker // Check static field types against initial static values in encoded array.
3203*795d594fSAndroid Build Coastguard Worker if (!CheckStaticFieldTypes(class_def)) {
3204*795d594fSAndroid Build Coastguard Worker return false;
3205*795d594fSAndroid Build Coastguard Worker }
3206*795d594fSAndroid Build Coastguard Worker
3207*795d594fSAndroid Build Coastguard Worker ptr_ = it.GetDataPointer();
3208*795d594fSAndroid Build Coastguard Worker return true;
3209*795d594fSAndroid Build Coastguard Worker }
3210*795d594fSAndroid Build Coastguard Worker
CheckInterAnnotationsDirectoryItem()3211*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckInterAnnotationsDirectoryItem() {
3212*795d594fSAndroid Build Coastguard Worker const dex::AnnotationsDirectoryItem* item =
3213*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const dex::AnnotationsDirectoryItem*>(ptr_);
3214*795d594fSAndroid Build Coastguard Worker uint32_t defining_class = FindFirstAnnotationsDirectoryDefiner(ptr_);
3215*795d594fSAndroid Build Coastguard Worker DCHECK(IsUint<16>(defining_class) || defining_class == kDexNoIndex) << defining_class;
3216*795d594fSAndroid Build Coastguard Worker
3217*795d594fSAndroid Build Coastguard Worker if (item->class_annotations_off_ != 0 &&
3218*795d594fSAndroid Build Coastguard Worker !CheckOffsetToTypeMap(item->class_annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
3219*795d594fSAndroid Build Coastguard Worker return false;
3220*795d594fSAndroid Build Coastguard Worker }
3221*795d594fSAndroid Build Coastguard Worker
3222*795d594fSAndroid Build Coastguard Worker // Field annotations follow immediately after the annotations directory.
3223*795d594fSAndroid Build Coastguard Worker const dex::FieldAnnotationsItem* field_item =
3224*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const dex::FieldAnnotationsItem*>(item + 1);
3225*795d594fSAndroid Build Coastguard Worker uint32_t field_count = item->fields_size_;
3226*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < field_count; i++) {
3227*795d594fSAndroid Build Coastguard Worker // The index has already been checked in `CheckIntraAnnotationsDirectoryItem()`.
3228*795d594fSAndroid Build Coastguard Worker DCHECK_LE(field_item->field_idx_, header_->field_ids_size_);
3229*795d594fSAndroid Build Coastguard Worker const dex::FieldId& field = dex_file_->GetFieldId(field_item->field_idx_);
3230*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(field.class_idx_.index_ != defining_class)) {
3231*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Mismatched defining class for field_annotation");
3232*795d594fSAndroid Build Coastguard Worker return false;
3233*795d594fSAndroid Build Coastguard Worker }
3234*795d594fSAndroid Build Coastguard Worker if (!CheckOffsetToTypeMap(field_item->annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
3235*795d594fSAndroid Build Coastguard Worker return false;
3236*795d594fSAndroid Build Coastguard Worker }
3237*795d594fSAndroid Build Coastguard Worker field_item++;
3238*795d594fSAndroid Build Coastguard Worker }
3239*795d594fSAndroid Build Coastguard Worker
3240*795d594fSAndroid Build Coastguard Worker // Method annotations follow immediately after field annotations.
3241*795d594fSAndroid Build Coastguard Worker const dex::MethodAnnotationsItem* method_item =
3242*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const dex::MethodAnnotationsItem*>(field_item);
3243*795d594fSAndroid Build Coastguard Worker uint32_t method_count = item->methods_size_;
3244*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < method_count; i++) {
3245*795d594fSAndroid Build Coastguard Worker // The index has already been checked in `CheckIntraAnnotationsDirectoryItem()`.
3246*795d594fSAndroid Build Coastguard Worker DCHECK_LE(method_item->method_idx_, header_->method_ids_size_);
3247*795d594fSAndroid Build Coastguard Worker const dex::MethodId& method = dex_file_->GetMethodId(method_item->method_idx_);
3248*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(method.class_idx_.index_ != defining_class)) {
3249*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Mismatched defining class for method_annotation");
3250*795d594fSAndroid Build Coastguard Worker return false;
3251*795d594fSAndroid Build Coastguard Worker }
3252*795d594fSAndroid Build Coastguard Worker if (!CheckOffsetToTypeMap(method_item->annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
3253*795d594fSAndroid Build Coastguard Worker return false;
3254*795d594fSAndroid Build Coastguard Worker }
3255*795d594fSAndroid Build Coastguard Worker method_item++;
3256*795d594fSAndroid Build Coastguard Worker }
3257*795d594fSAndroid Build Coastguard Worker
3258*795d594fSAndroid Build Coastguard Worker // Parameter annotations follow immediately after method annotations.
3259*795d594fSAndroid Build Coastguard Worker const dex::ParameterAnnotationsItem* parameter_item =
3260*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const dex::ParameterAnnotationsItem*>(method_item);
3261*795d594fSAndroid Build Coastguard Worker uint32_t parameter_count = item->parameters_size_;
3262*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < parameter_count; i++) {
3263*795d594fSAndroid Build Coastguard Worker // The index has already been checked in `CheckIntraAnnotationsDirectoryItem()`.
3264*795d594fSAndroid Build Coastguard Worker DCHECK_LE(parameter_item->method_idx_, header_->method_ids_size_);
3265*795d594fSAndroid Build Coastguard Worker const dex::MethodId& parameter_method = dex_file_->GetMethodId(parameter_item->method_idx_);
3266*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(parameter_method.class_idx_.index_ != defining_class)) {
3267*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Mismatched defining class for parameter_annotation");
3268*795d594fSAndroid Build Coastguard Worker return false;
3269*795d594fSAndroid Build Coastguard Worker }
3270*795d594fSAndroid Build Coastguard Worker if (!CheckOffsetToTypeMap(parameter_item->annotations_off_,
3271*795d594fSAndroid Build Coastguard Worker DexFile::kDexTypeAnnotationSetRefList)) {
3272*795d594fSAndroid Build Coastguard Worker return false;
3273*795d594fSAndroid Build Coastguard Worker }
3274*795d594fSAndroid Build Coastguard Worker parameter_item++;
3275*795d594fSAndroid Build Coastguard Worker }
3276*795d594fSAndroid Build Coastguard Worker
3277*795d594fSAndroid Build Coastguard Worker ptr_ = reinterpret_cast<const uint8_t*>(parameter_item);
3278*795d594fSAndroid Build Coastguard Worker return true;
3279*795d594fSAndroid Build Coastguard Worker }
3280*795d594fSAndroid Build Coastguard Worker
CheckInterSectionIterate(size_t offset,uint32_t count,DexFile::MapItemType type)3281*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckInterSectionIterate(size_t offset,
3282*795d594fSAndroid Build Coastguard Worker uint32_t count,
3283*795d594fSAndroid Build Coastguard Worker DexFile::MapItemType type) {
3284*795d594fSAndroid Build Coastguard Worker // Get the right alignment mask for the type of section.
3285*795d594fSAndroid Build Coastguard Worker size_t alignment_mask;
3286*795d594fSAndroid Build Coastguard Worker switch (type) {
3287*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeClassDataItem:
3288*795d594fSAndroid Build Coastguard Worker alignment_mask = sizeof(uint8_t) - 1;
3289*795d594fSAndroid Build Coastguard Worker break;
3290*795d594fSAndroid Build Coastguard Worker default:
3291*795d594fSAndroid Build Coastguard Worker alignment_mask = sizeof(uint32_t) - 1;
3292*795d594fSAndroid Build Coastguard Worker break;
3293*795d594fSAndroid Build Coastguard Worker }
3294*795d594fSAndroid Build Coastguard Worker
3295*795d594fSAndroid Build Coastguard Worker // Iterate through the items in the section.
3296*795d594fSAndroid Build Coastguard Worker previous_item_ = nullptr;
3297*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < count; i++) {
3298*795d594fSAndroid Build Coastguard Worker uint32_t new_offset = (offset + alignment_mask) & ~alignment_mask;
3299*795d594fSAndroid Build Coastguard Worker ptr_ = OffsetToPtr(new_offset);
3300*795d594fSAndroid Build Coastguard Worker const uint8_t* prev_ptr = ptr_;
3301*795d594fSAndroid Build Coastguard Worker
3302*795d594fSAndroid Build Coastguard Worker if (MapTypeToBitMask(type) == 0) {
3303*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Unknown map item type %x", type);
3304*795d594fSAndroid Build Coastguard Worker return false;
3305*795d594fSAndroid Build Coastguard Worker }
3306*795d594fSAndroid Build Coastguard Worker
3307*795d594fSAndroid Build Coastguard Worker // Check depending on the section type.
3308*795d594fSAndroid Build Coastguard Worker switch (type) {
3309*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeHeaderItem:
3310*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMethodHandleItem:
3311*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMapList:
3312*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeTypeList:
3313*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeCodeItem:
3314*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeStringDataItem:
3315*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeDebugInfoItem:
3316*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationItem:
3317*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeEncodedArrayItem:
3318*795d594fSAndroid Build Coastguard Worker break;
3319*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeHiddenapiClassData: {
3320*795d594fSAndroid Build Coastguard Worker if (!CheckIntraHiddenapiClassData()) {
3321*795d594fSAndroid Build Coastguard Worker return false;
3322*795d594fSAndroid Build Coastguard Worker }
3323*795d594fSAndroid Build Coastguard Worker break;
3324*795d594fSAndroid Build Coastguard Worker }
3325*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeStringIdItem: {
3326*795d594fSAndroid Build Coastguard Worker if (!CheckInterStringIdItem()) {
3327*795d594fSAndroid Build Coastguard Worker return false;
3328*795d594fSAndroid Build Coastguard Worker }
3329*795d594fSAndroid Build Coastguard Worker break;
3330*795d594fSAndroid Build Coastguard Worker }
3331*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeTypeIdItem: {
3332*795d594fSAndroid Build Coastguard Worker if (!CheckInterTypeIdItem()) {
3333*795d594fSAndroid Build Coastguard Worker return false;
3334*795d594fSAndroid Build Coastguard Worker }
3335*795d594fSAndroid Build Coastguard Worker break;
3336*795d594fSAndroid Build Coastguard Worker }
3337*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeProtoIdItem: {
3338*795d594fSAndroid Build Coastguard Worker if (!CheckInterProtoIdItem()) {
3339*795d594fSAndroid Build Coastguard Worker return false;
3340*795d594fSAndroid Build Coastguard Worker }
3341*795d594fSAndroid Build Coastguard Worker break;
3342*795d594fSAndroid Build Coastguard Worker }
3343*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeFieldIdItem: {
3344*795d594fSAndroid Build Coastguard Worker if (!CheckInterFieldIdItem()) {
3345*795d594fSAndroid Build Coastguard Worker return false;
3346*795d594fSAndroid Build Coastguard Worker }
3347*795d594fSAndroid Build Coastguard Worker break;
3348*795d594fSAndroid Build Coastguard Worker }
3349*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMethodIdItem: {
3350*795d594fSAndroid Build Coastguard Worker if (!CheckInterMethodIdItem()) {
3351*795d594fSAndroid Build Coastguard Worker return false;
3352*795d594fSAndroid Build Coastguard Worker }
3353*795d594fSAndroid Build Coastguard Worker break;
3354*795d594fSAndroid Build Coastguard Worker }
3355*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeClassDefItem: {
3356*795d594fSAndroid Build Coastguard Worker // There shouldn't be more class definitions than type ids allow.
3357*795d594fSAndroid Build Coastguard Worker // This is checked in `CheckIntraClassDefItem()` by checking the type
3358*795d594fSAndroid Build Coastguard Worker // index against `kTypeIdLimit` and rejecting dulicate definitions.
3359*795d594fSAndroid Build Coastguard Worker DCHECK_LE(i, kTypeIdLimit);
3360*795d594fSAndroid Build Coastguard Worker if (!CheckInterClassDefItem()) {
3361*795d594fSAndroid Build Coastguard Worker return false;
3362*795d594fSAndroid Build Coastguard Worker }
3363*795d594fSAndroid Build Coastguard Worker break;
3364*795d594fSAndroid Build Coastguard Worker }
3365*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeCallSiteIdItem: {
3366*795d594fSAndroid Build Coastguard Worker if (!CheckInterCallSiteIdItem()) {
3367*795d594fSAndroid Build Coastguard Worker return false;
3368*795d594fSAndroid Build Coastguard Worker }
3369*795d594fSAndroid Build Coastguard Worker break;
3370*795d594fSAndroid Build Coastguard Worker }
3371*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationSetRefList: {
3372*795d594fSAndroid Build Coastguard Worker if (!CheckInterAnnotationSetRefList()) {
3373*795d594fSAndroid Build Coastguard Worker return false;
3374*795d594fSAndroid Build Coastguard Worker }
3375*795d594fSAndroid Build Coastguard Worker break;
3376*795d594fSAndroid Build Coastguard Worker }
3377*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationSetItem: {
3378*795d594fSAndroid Build Coastguard Worker if (!CheckInterAnnotationSetItem()) {
3379*795d594fSAndroid Build Coastguard Worker return false;
3380*795d594fSAndroid Build Coastguard Worker }
3381*795d594fSAndroid Build Coastguard Worker break;
3382*795d594fSAndroid Build Coastguard Worker }
3383*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeClassDataItem: {
3384*795d594fSAndroid Build Coastguard Worker // There shouldn't be more class data than type ids allow.
3385*795d594fSAndroid Build Coastguard Worker // This check should be redundant, since there are checks that the
3386*795d594fSAndroid Build Coastguard Worker // class_idx_ is within range and that there is only one definition
3387*795d594fSAndroid Build Coastguard Worker // for a given type id.
3388*795d594fSAndroid Build Coastguard Worker if (i > kTypeIdLimit) {
3389*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Too many class data items");
3390*795d594fSAndroid Build Coastguard Worker return false;
3391*795d594fSAndroid Build Coastguard Worker }
3392*795d594fSAndroid Build Coastguard Worker if (!CheckInterClassDataItem()) {
3393*795d594fSAndroid Build Coastguard Worker return false;
3394*795d594fSAndroid Build Coastguard Worker }
3395*795d594fSAndroid Build Coastguard Worker break;
3396*795d594fSAndroid Build Coastguard Worker }
3397*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationsDirectoryItem: {
3398*795d594fSAndroid Build Coastguard Worker if (!CheckInterAnnotationsDirectoryItem()) {
3399*795d594fSAndroid Build Coastguard Worker return false;
3400*795d594fSAndroid Build Coastguard Worker }
3401*795d594fSAndroid Build Coastguard Worker break;
3402*795d594fSAndroid Build Coastguard Worker }
3403*795d594fSAndroid Build Coastguard Worker }
3404*795d594fSAndroid Build Coastguard Worker
3405*795d594fSAndroid Build Coastguard Worker previous_item_ = prev_ptr;
3406*795d594fSAndroid Build Coastguard Worker offset = PtrToOffset(ptr_);
3407*795d594fSAndroid Build Coastguard Worker }
3408*795d594fSAndroid Build Coastguard Worker
3409*795d594fSAndroid Build Coastguard Worker return true;
3410*795d594fSAndroid Build Coastguard Worker }
3411*795d594fSAndroid Build Coastguard Worker
CheckInterSection()3412*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckInterSection() {
3413*795d594fSAndroid Build Coastguard Worker // Eagerly verify that `StringId` offsets map to string data items to make sure
3414*795d594fSAndroid Build Coastguard Worker // we can retrieve the string data for verifying other items (types, shorties, etc.).
3415*795d594fSAndroid Build Coastguard Worker // After this we can safely use `DexFile` helpers such as `GetFieldId()` or `GetMethodId()`
3416*795d594fSAndroid Build Coastguard Worker // but not `PrettyMethod()` or `PrettyField()` as descriptors have not been verified yet.
3417*795d594fSAndroid Build Coastguard Worker const dex::StringId* string_ids = OffsetToPtr<dex::StringId>(header_->string_ids_off_);
3418*795d594fSAndroid Build Coastguard Worker for (size_t i = 0, num_strings = header_->string_ids_size_; i != num_strings; ++i) {
3419*795d594fSAndroid Build Coastguard Worker if (!CheckOffsetToTypeMap(string_ids[i].string_data_off_, DexFile::kDexTypeStringDataItem)) {
3420*795d594fSAndroid Build Coastguard Worker return false;
3421*795d594fSAndroid Build Coastguard Worker }
3422*795d594fSAndroid Build Coastguard Worker }
3423*795d594fSAndroid Build Coastguard Worker
3424*795d594fSAndroid Build Coastguard Worker const dex::MapList* map = OffsetToPtr<dex::MapList>(header_->map_off_);
3425*795d594fSAndroid Build Coastguard Worker const dex::MapItem* item = map->list_;
3426*795d594fSAndroid Build Coastguard Worker uint32_t count = map->size_;
3427*795d594fSAndroid Build Coastguard Worker
3428*795d594fSAndroid Build Coastguard Worker // Cross check the items listed in the map.
3429*795d594fSAndroid Build Coastguard Worker for (; count != 0u; --count) {
3430*795d594fSAndroid Build Coastguard Worker uint32_t section_offset = item->offset_;
3431*795d594fSAndroid Build Coastguard Worker uint32_t section_count = item->size_;
3432*795d594fSAndroid Build Coastguard Worker DexFile::MapItemType type = static_cast<DexFile::MapItemType>(item->type_);
3433*795d594fSAndroid Build Coastguard Worker bool found = false;
3434*795d594fSAndroid Build Coastguard Worker
3435*795d594fSAndroid Build Coastguard Worker if (type == DexFile::kDexTypeClassDataItem) {
3436*795d594fSAndroid Build Coastguard Worker FindStringRangesForMethodNames();
3437*795d594fSAndroid Build Coastguard Worker }
3438*795d594fSAndroid Build Coastguard Worker
3439*795d594fSAndroid Build Coastguard Worker switch (type) {
3440*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeHeaderItem:
3441*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMapList:
3442*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeTypeList:
3443*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeCodeItem:
3444*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeStringDataItem:
3445*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeDebugInfoItem:
3446*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationItem:
3447*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeEncodedArrayItem:
3448*795d594fSAndroid Build Coastguard Worker found = true;
3449*795d594fSAndroid Build Coastguard Worker break;
3450*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeStringIdItem:
3451*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeTypeIdItem:
3452*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeProtoIdItem:
3453*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeFieldIdItem:
3454*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMethodIdItem:
3455*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeClassDefItem:
3456*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeCallSiteIdItem:
3457*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeMethodHandleItem:
3458*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationSetRefList:
3459*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationSetItem:
3460*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeClassDataItem:
3461*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeAnnotationsDirectoryItem:
3462*795d594fSAndroid Build Coastguard Worker case DexFile::kDexTypeHiddenapiClassData: {
3463*795d594fSAndroid Build Coastguard Worker if (!CheckInterSectionIterate(section_offset, section_count, type)) {
3464*795d594fSAndroid Build Coastguard Worker return false;
3465*795d594fSAndroid Build Coastguard Worker }
3466*795d594fSAndroid Build Coastguard Worker found = true;
3467*795d594fSAndroid Build Coastguard Worker break;
3468*795d594fSAndroid Build Coastguard Worker }
3469*795d594fSAndroid Build Coastguard Worker }
3470*795d594fSAndroid Build Coastguard Worker
3471*795d594fSAndroid Build Coastguard Worker if (!found) {
3472*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Unknown map item type %x", item->type_);
3473*795d594fSAndroid Build Coastguard Worker return false;
3474*795d594fSAndroid Build Coastguard Worker }
3475*795d594fSAndroid Build Coastguard Worker
3476*795d594fSAndroid Build Coastguard Worker item++;
3477*795d594fSAndroid Build Coastguard Worker }
3478*795d594fSAndroid Build Coastguard Worker
3479*795d594fSAndroid Build Coastguard Worker return true;
3480*795d594fSAndroid Build Coastguard Worker }
3481*795d594fSAndroid Build Coastguard Worker
Verify()3482*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::Verify() {
3483*795d594fSAndroid Build Coastguard Worker // Check the header.
3484*795d594fSAndroid Build Coastguard Worker if (!CheckHeader()) {
3485*795d594fSAndroid Build Coastguard Worker return false;
3486*795d594fSAndroid Build Coastguard Worker }
3487*795d594fSAndroid Build Coastguard Worker
3488*795d594fSAndroid Build Coastguard Worker // Check the map section.
3489*795d594fSAndroid Build Coastguard Worker if (!CheckMap()) {
3490*795d594fSAndroid Build Coastguard Worker return false;
3491*795d594fSAndroid Build Coastguard Worker }
3492*795d594fSAndroid Build Coastguard Worker
3493*795d594fSAndroid Build Coastguard Worker DCHECK_LE(header_->type_ids_size_, kTypeIdLimit + 1u); // Checked in CheckHeader().
3494*795d594fSAndroid Build Coastguard Worker verified_type_descriptors_.resize(header_->type_ids_size_, 0);
3495*795d594fSAndroid Build Coastguard Worker defined_class_indexes_.resize(header_->type_ids_size_);
3496*795d594fSAndroid Build Coastguard Worker
3497*795d594fSAndroid Build Coastguard Worker // Check structure within remaining sections.
3498*795d594fSAndroid Build Coastguard Worker if (!CheckIntraSection()) {
3499*795d594fSAndroid Build Coastguard Worker return false;
3500*795d594fSAndroid Build Coastguard Worker }
3501*795d594fSAndroid Build Coastguard Worker
3502*795d594fSAndroid Build Coastguard Worker // Check references from one section to another.
3503*795d594fSAndroid Build Coastguard Worker if (!CheckInterSection()) {
3504*795d594fSAndroid Build Coastguard Worker return false;
3505*795d594fSAndroid Build Coastguard Worker }
3506*795d594fSAndroid Build Coastguard Worker
3507*795d594fSAndroid Build Coastguard Worker CHECK(todo_.empty()); // No unprocessed work left over.
3508*795d594fSAndroid Build Coastguard Worker return true;
3509*795d594fSAndroid Build Coastguard Worker }
3510*795d594fSAndroid Build Coastguard Worker
CheckFieldAccessFlags(uint32_t idx,uint32_t field_access_flags,uint32_t class_access_flags,std::string * error_msg)3511*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckFieldAccessFlags(uint32_t idx,
3512*795d594fSAndroid Build Coastguard Worker uint32_t field_access_flags,
3513*795d594fSAndroid Build Coastguard Worker uint32_t class_access_flags,
3514*795d594fSAndroid Build Coastguard Worker std::string* error_msg) {
3515*795d594fSAndroid Build Coastguard Worker // Generally sort out >16-bit flags.
3516*795d594fSAndroid Build Coastguard Worker if ((field_access_flags & ~kAccJavaFlagsMask) != 0) {
3517*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Bad field access_flags for %s: %x(%s)",
3518*795d594fSAndroid Build Coastguard Worker GetFieldDescription(idx).c_str(),
3519*795d594fSAndroid Build Coastguard Worker field_access_flags,
3520*795d594fSAndroid Build Coastguard Worker PrettyJavaAccessFlags(field_access_flags).c_str());
3521*795d594fSAndroid Build Coastguard Worker return false;
3522*795d594fSAndroid Build Coastguard Worker }
3523*795d594fSAndroid Build Coastguard Worker
3524*795d594fSAndroid Build Coastguard Worker // Flags allowed on fields, in general. Other lower-16-bit flags are to be ignored.
3525*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kFieldAccessFlags = kAccPublic |
3526*795d594fSAndroid Build Coastguard Worker kAccPrivate |
3527*795d594fSAndroid Build Coastguard Worker kAccProtected |
3528*795d594fSAndroid Build Coastguard Worker kAccStatic |
3529*795d594fSAndroid Build Coastguard Worker kAccFinal |
3530*795d594fSAndroid Build Coastguard Worker kAccVolatile |
3531*795d594fSAndroid Build Coastguard Worker kAccTransient |
3532*795d594fSAndroid Build Coastguard Worker kAccSynthetic |
3533*795d594fSAndroid Build Coastguard Worker kAccEnum;
3534*795d594fSAndroid Build Coastguard Worker
3535*795d594fSAndroid Build Coastguard Worker // Fields may have only one of public/protected/final.
3536*795d594fSAndroid Build Coastguard Worker if (!CheckAtMostOneOfPublicProtectedPrivate(field_access_flags)) {
3537*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Field may have only one of public/protected/private, %s: %x(%s)",
3538*795d594fSAndroid Build Coastguard Worker GetFieldDescription(idx).c_str(),
3539*795d594fSAndroid Build Coastguard Worker field_access_flags,
3540*795d594fSAndroid Build Coastguard Worker PrettyJavaAccessFlags(field_access_flags).c_str());
3541*795d594fSAndroid Build Coastguard Worker return false;
3542*795d594fSAndroid Build Coastguard Worker }
3543*795d594fSAndroid Build Coastguard Worker
3544*795d594fSAndroid Build Coastguard Worker // Interfaces have a pretty restricted list.
3545*795d594fSAndroid Build Coastguard Worker if ((class_access_flags & kAccInterface) != 0) {
3546*795d594fSAndroid Build Coastguard Worker // Interface fields must be public final static.
3547*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kPublicFinalStatic = kAccPublic | kAccFinal | kAccStatic;
3548*795d594fSAndroid Build Coastguard Worker if ((field_access_flags & kPublicFinalStatic) != kPublicFinalStatic) {
3549*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Interface field is not public final static, %s: %x(%s)",
3550*795d594fSAndroid Build Coastguard Worker GetFieldDescription(idx).c_str(),
3551*795d594fSAndroid Build Coastguard Worker field_access_flags,
3552*795d594fSAndroid Build Coastguard Worker PrettyJavaAccessFlags(field_access_flags).c_str());
3553*795d594fSAndroid Build Coastguard Worker if (dex_file_->SupportsDefaultMethods()) {
3554*795d594fSAndroid Build Coastguard Worker return false;
3555*795d594fSAndroid Build Coastguard Worker } else {
3556*795d594fSAndroid Build Coastguard Worker // Allow in older versions, but warn.
3557*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "This dex file is invalid and will be rejected in the future. Error is: "
3558*795d594fSAndroid Build Coastguard Worker << *error_msg;
3559*795d594fSAndroid Build Coastguard Worker }
3560*795d594fSAndroid Build Coastguard Worker }
3561*795d594fSAndroid Build Coastguard Worker // Interface fields may be synthetic, but may not have other flags.
3562*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kDisallowed = ~(kPublicFinalStatic | kAccSynthetic);
3563*795d594fSAndroid Build Coastguard Worker if ((field_access_flags & kFieldAccessFlags & kDisallowed) != 0) {
3564*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Interface field has disallowed flag, %s: %x(%s)",
3565*795d594fSAndroid Build Coastguard Worker GetFieldDescription(idx).c_str(),
3566*795d594fSAndroid Build Coastguard Worker field_access_flags,
3567*795d594fSAndroid Build Coastguard Worker PrettyJavaAccessFlags(field_access_flags).c_str());
3568*795d594fSAndroid Build Coastguard Worker if (dex_file_->SupportsDefaultMethods()) {
3569*795d594fSAndroid Build Coastguard Worker return false;
3570*795d594fSAndroid Build Coastguard Worker } else {
3571*795d594fSAndroid Build Coastguard Worker // Allow in older versions, but warn.
3572*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "This dex file is invalid and will be rejected in the future. Error is: "
3573*795d594fSAndroid Build Coastguard Worker << *error_msg;
3574*795d594fSAndroid Build Coastguard Worker }
3575*795d594fSAndroid Build Coastguard Worker }
3576*795d594fSAndroid Build Coastguard Worker return true;
3577*795d594fSAndroid Build Coastguard Worker }
3578*795d594fSAndroid Build Coastguard Worker
3579*795d594fSAndroid Build Coastguard Worker // Volatile fields may not be final.
3580*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kVolatileFinal = kAccVolatile | kAccFinal;
3581*795d594fSAndroid Build Coastguard Worker if ((field_access_flags & kVolatileFinal) == kVolatileFinal) {
3582*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Fields may not be volatile and final: %s",
3583*795d594fSAndroid Build Coastguard Worker GetFieldDescription(idx).c_str());
3584*795d594fSAndroid Build Coastguard Worker return false;
3585*795d594fSAndroid Build Coastguard Worker }
3586*795d594fSAndroid Build Coastguard Worker
3587*795d594fSAndroid Build Coastguard Worker return true;
3588*795d594fSAndroid Build Coastguard Worker }
3589*795d594fSAndroid Build Coastguard Worker
FindStringRangesForMethodNames()3590*795d594fSAndroid Build Coastguard Worker void DexFileVerifier::FindStringRangesForMethodNames() {
3591*795d594fSAndroid Build Coastguard Worker // Use DexFile::StringId* as RandomAccessIterator.
3592*795d594fSAndroid Build Coastguard Worker const dex::StringId* first = OffsetToPtr<dex::StringId>(header_->string_ids_off_);
3593*795d594fSAndroid Build Coastguard Worker const dex::StringId* last = first + header_->string_ids_size_;
3594*795d594fSAndroid Build Coastguard Worker
3595*795d594fSAndroid Build Coastguard Worker auto get_string = [this](const dex::StringId& id) {
3596*795d594fSAndroid Build Coastguard Worker const uint8_t* str_data_ptr = OffsetToPtr(id.string_data_off_);
3597*795d594fSAndroid Build Coastguard Worker DecodeUnsignedLeb128(&str_data_ptr);
3598*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<const char*>(str_data_ptr);
3599*795d594fSAndroid Build Coastguard Worker };
3600*795d594fSAndroid Build Coastguard Worker auto compare = [&get_string](const dex::StringId& lhs, const char* rhs) {
3601*795d594fSAndroid Build Coastguard Worker return CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(get_string(lhs), rhs) < 0;
3602*795d594fSAndroid Build Coastguard Worker };
3603*795d594fSAndroid Build Coastguard Worker
3604*795d594fSAndroid Build Coastguard Worker // '=' follows '<'
3605*795d594fSAndroid Build Coastguard Worker static_assert('<' + 1 == '=', "Unexpected character relation");
3606*795d594fSAndroid Build Coastguard Worker const auto angle_end = std::lower_bound(first, last, "=", compare);
3607*795d594fSAndroid Build Coastguard Worker init_indices_.angle_bracket_end_index = angle_end - first;
3608*795d594fSAndroid Build Coastguard Worker
3609*795d594fSAndroid Build Coastguard Worker const auto angle_start = std::lower_bound(first, angle_end, "<", compare);
3610*795d594fSAndroid Build Coastguard Worker init_indices_.angle_bracket_start_index = angle_start - first;
3611*795d594fSAndroid Build Coastguard Worker if (angle_start == angle_end) {
3612*795d594fSAndroid Build Coastguard Worker // No strings starting with '<'.
3613*795d594fSAndroid Build Coastguard Worker init_indices_.angle_init_angle_index = std::numeric_limits<size_t>::max();
3614*795d594fSAndroid Build Coastguard Worker init_indices_.angle_clinit_angle_index = std::numeric_limits<size_t>::max();
3615*795d594fSAndroid Build Coastguard Worker return;
3616*795d594fSAndroid Build Coastguard Worker }
3617*795d594fSAndroid Build Coastguard Worker
3618*795d594fSAndroid Build Coastguard Worker {
3619*795d594fSAndroid Build Coastguard Worker constexpr const char* kClinit = "<clinit>";
3620*795d594fSAndroid Build Coastguard Worker const auto it = std::lower_bound(angle_start, angle_end, kClinit, compare);
3621*795d594fSAndroid Build Coastguard Worker if (it != angle_end && strcmp(get_string(*it), kClinit) == 0) {
3622*795d594fSAndroid Build Coastguard Worker init_indices_.angle_clinit_angle_index = it - first;
3623*795d594fSAndroid Build Coastguard Worker } else {
3624*795d594fSAndroid Build Coastguard Worker init_indices_.angle_clinit_angle_index = std::numeric_limits<size_t>::max();
3625*795d594fSAndroid Build Coastguard Worker }
3626*795d594fSAndroid Build Coastguard Worker }
3627*795d594fSAndroid Build Coastguard Worker {
3628*795d594fSAndroid Build Coastguard Worker constexpr const char* kInit = "<init>";
3629*795d594fSAndroid Build Coastguard Worker const auto it = std::lower_bound(angle_start, angle_end, kInit, compare);
3630*795d594fSAndroid Build Coastguard Worker if (it != angle_end && strcmp(get_string(*it), kInit) == 0) {
3631*795d594fSAndroid Build Coastguard Worker init_indices_.angle_init_angle_index = it - first;
3632*795d594fSAndroid Build Coastguard Worker } else {
3633*795d594fSAndroid Build Coastguard Worker init_indices_.angle_init_angle_index = std::numeric_limits<size_t>::max();
3634*795d594fSAndroid Build Coastguard Worker }
3635*795d594fSAndroid Build Coastguard Worker }
3636*795d594fSAndroid Build Coastguard Worker }
3637*795d594fSAndroid Build Coastguard Worker
CheckMethodAccessFlags(uint32_t method_index,uint32_t method_access_flags,uint32_t class_access_flags,uint32_t constructor_flags_by_name,bool has_code,bool expect_direct,std::string * error_msg)3638*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckMethodAccessFlags(uint32_t method_index,
3639*795d594fSAndroid Build Coastguard Worker uint32_t method_access_flags,
3640*795d594fSAndroid Build Coastguard Worker uint32_t class_access_flags,
3641*795d594fSAndroid Build Coastguard Worker uint32_t constructor_flags_by_name,
3642*795d594fSAndroid Build Coastguard Worker bool has_code,
3643*795d594fSAndroid Build Coastguard Worker bool expect_direct,
3644*795d594fSAndroid Build Coastguard Worker std::string* error_msg) {
3645*795d594fSAndroid Build Coastguard Worker // Generally sort out >16-bit flags, except dex knows Constructor and DeclaredSynchronized.
3646*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kAllMethodFlags =
3647*795d594fSAndroid Build Coastguard Worker kAccJavaFlagsMask | kAccConstructor | kAccDeclaredSynchronized;
3648*795d594fSAndroid Build Coastguard Worker if ((method_access_flags & ~kAllMethodFlags) != 0) {
3649*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Bad method access_flags for %s: %x",
3650*795d594fSAndroid Build Coastguard Worker GetMethodDescription(method_index).c_str(),
3651*795d594fSAndroid Build Coastguard Worker method_access_flags);
3652*795d594fSAndroid Build Coastguard Worker return false;
3653*795d594fSAndroid Build Coastguard Worker }
3654*795d594fSAndroid Build Coastguard Worker
3655*795d594fSAndroid Build Coastguard Worker // Flags allowed on methods, in general. Other lower-16-bit flags are to be ignored.
3656*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kMethodAccessFlags = kAccPublic |
3657*795d594fSAndroid Build Coastguard Worker kAccPrivate |
3658*795d594fSAndroid Build Coastguard Worker kAccProtected |
3659*795d594fSAndroid Build Coastguard Worker kAccStatic |
3660*795d594fSAndroid Build Coastguard Worker kAccFinal |
3661*795d594fSAndroid Build Coastguard Worker kAccSynthetic |
3662*795d594fSAndroid Build Coastguard Worker kAccSynchronized |
3663*795d594fSAndroid Build Coastguard Worker kAccBridge |
3664*795d594fSAndroid Build Coastguard Worker kAccVarargs |
3665*795d594fSAndroid Build Coastguard Worker kAccNative |
3666*795d594fSAndroid Build Coastguard Worker kAccAbstract |
3667*795d594fSAndroid Build Coastguard Worker kAccStrict;
3668*795d594fSAndroid Build Coastguard Worker
3669*795d594fSAndroid Build Coastguard Worker // Methods may have only one of public/protected/final.
3670*795d594fSAndroid Build Coastguard Worker if (!CheckAtMostOneOfPublicProtectedPrivate(method_access_flags)) {
3671*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Method may have only one of public/protected/private, %s: %x",
3672*795d594fSAndroid Build Coastguard Worker GetMethodDescription(method_index).c_str(),
3673*795d594fSAndroid Build Coastguard Worker method_access_flags);
3674*795d594fSAndroid Build Coastguard Worker return false;
3675*795d594fSAndroid Build Coastguard Worker }
3676*795d594fSAndroid Build Coastguard Worker
3677*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kConstructorFlags = kAccStatic | kAccConstructor;
3678*795d594fSAndroid Build Coastguard Worker const bool is_constructor_by_name = (constructor_flags_by_name & kConstructorFlags) != 0;
3679*795d594fSAndroid Build Coastguard Worker const bool is_clinit_by_name = constructor_flags_by_name == kConstructorFlags;
3680*795d594fSAndroid Build Coastguard Worker
3681*795d594fSAndroid Build Coastguard Worker // Only methods named "<clinit>" or "<init>" may be marked constructor. Note: we cannot enforce
3682*795d594fSAndroid Build Coastguard Worker // the reverse for backwards compatibility reasons.
3683*795d594fSAndroid Build Coastguard Worker if (((method_access_flags & kAccConstructor) != 0) && !is_constructor_by_name) {
3684*795d594fSAndroid Build Coastguard Worker *error_msg =
3685*795d594fSAndroid Build Coastguard Worker StringPrintf("Method %" PRIu32 "(%s) is marked constructor, but doesn't match name",
3686*795d594fSAndroid Build Coastguard Worker method_index,
3687*795d594fSAndroid Build Coastguard Worker GetMethodDescription(method_index).c_str());
3688*795d594fSAndroid Build Coastguard Worker return false;
3689*795d594fSAndroid Build Coastguard Worker }
3690*795d594fSAndroid Build Coastguard Worker
3691*795d594fSAndroid Build Coastguard Worker if (is_constructor_by_name) {
3692*795d594fSAndroid Build Coastguard Worker // Check that the static constructor (= static initializer) is named "<clinit>" and that the
3693*795d594fSAndroid Build Coastguard Worker // instance constructor is called "<init>".
3694*795d594fSAndroid Build Coastguard Worker bool is_static = (method_access_flags & kAccStatic) != 0;
3695*795d594fSAndroid Build Coastguard Worker if (is_static ^ is_clinit_by_name) {
3696*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Constructor %" PRIu32 "(%s) is not flagged correctly wrt/ static.",
3697*795d594fSAndroid Build Coastguard Worker method_index,
3698*795d594fSAndroid Build Coastguard Worker GetMethodDescription(method_index).c_str());
3699*795d594fSAndroid Build Coastguard Worker if (dex_file_->SupportsDefaultMethods()) {
3700*795d594fSAndroid Build Coastguard Worker return false;
3701*795d594fSAndroid Build Coastguard Worker } else {
3702*795d594fSAndroid Build Coastguard Worker // Allow in older versions, but warn.
3703*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "This dex file is invalid and will be rejected in the future. Error is: "
3704*795d594fSAndroid Build Coastguard Worker << *error_msg;
3705*795d594fSAndroid Build Coastguard Worker }
3706*795d594fSAndroid Build Coastguard Worker }
3707*795d594fSAndroid Build Coastguard Worker }
3708*795d594fSAndroid Build Coastguard Worker
3709*795d594fSAndroid Build Coastguard Worker // Check that static and private methods, as well as constructors, are in the direct methods list,
3710*795d594fSAndroid Build Coastguard Worker // and other methods in the virtual methods list.
3711*795d594fSAndroid Build Coastguard Worker bool is_direct = ((method_access_flags & (kAccStatic | kAccPrivate)) != 0) ||
3712*795d594fSAndroid Build Coastguard Worker is_constructor_by_name;
3713*795d594fSAndroid Build Coastguard Worker if (is_direct != expect_direct) {
3714*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Direct/virtual method %" PRIu32 "(%s) not in expected list %d",
3715*795d594fSAndroid Build Coastguard Worker method_index,
3716*795d594fSAndroid Build Coastguard Worker GetMethodDescription(method_index).c_str(),
3717*795d594fSAndroid Build Coastguard Worker expect_direct);
3718*795d594fSAndroid Build Coastguard Worker return false;
3719*795d594fSAndroid Build Coastguard Worker }
3720*795d594fSAndroid Build Coastguard Worker
3721*795d594fSAndroid Build Coastguard Worker // From here on out it is easier to mask out the bits we're supposed to ignore.
3722*795d594fSAndroid Build Coastguard Worker method_access_flags &= kMethodAccessFlags;
3723*795d594fSAndroid Build Coastguard Worker
3724*795d594fSAndroid Build Coastguard Worker // Interfaces are special.
3725*795d594fSAndroid Build Coastguard Worker if ((class_access_flags & kAccInterface) != 0) {
3726*795d594fSAndroid Build Coastguard Worker // Non-static interface methods must be public or private.
3727*795d594fSAndroid Build Coastguard Worker uint32_t desired_flags = (kAccPublic | kAccStatic);
3728*795d594fSAndroid Build Coastguard Worker if (dex_file_->SupportsDefaultMethods()) {
3729*795d594fSAndroid Build Coastguard Worker desired_flags |= kAccPrivate;
3730*795d594fSAndroid Build Coastguard Worker }
3731*795d594fSAndroid Build Coastguard Worker if ((method_access_flags & desired_flags) == 0) {
3732*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Interface virtual method %" PRIu32 "(%s) is not public",
3733*795d594fSAndroid Build Coastguard Worker method_index,
3734*795d594fSAndroid Build Coastguard Worker GetMethodDescription(method_index).c_str());
3735*795d594fSAndroid Build Coastguard Worker if (dex_file_->SupportsDefaultMethods()) {
3736*795d594fSAndroid Build Coastguard Worker return false;
3737*795d594fSAndroid Build Coastguard Worker } else {
3738*795d594fSAndroid Build Coastguard Worker // Allow in older versions, but warn.
3739*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "This dex file is invalid and will be rejected in the future. Error is: "
3740*795d594fSAndroid Build Coastguard Worker << *error_msg;
3741*795d594fSAndroid Build Coastguard Worker }
3742*795d594fSAndroid Build Coastguard Worker }
3743*795d594fSAndroid Build Coastguard Worker }
3744*795d594fSAndroid Build Coastguard Worker
3745*795d594fSAndroid Build Coastguard Worker // If there aren't any instructions, make sure that's expected.
3746*795d594fSAndroid Build Coastguard Worker if (!has_code) {
3747*795d594fSAndroid Build Coastguard Worker // Only native or abstract methods may not have code.
3748*795d594fSAndroid Build Coastguard Worker if ((method_access_flags & (kAccNative | kAccAbstract)) == 0) {
3749*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Method %" PRIu32 "(%s) has no code, but is not marked native or "
3750*795d594fSAndroid Build Coastguard Worker "abstract",
3751*795d594fSAndroid Build Coastguard Worker method_index,
3752*795d594fSAndroid Build Coastguard Worker GetMethodDescription(method_index).c_str());
3753*795d594fSAndroid Build Coastguard Worker return false;
3754*795d594fSAndroid Build Coastguard Worker }
3755*795d594fSAndroid Build Coastguard Worker // Constructors must always have code.
3756*795d594fSAndroid Build Coastguard Worker if (is_constructor_by_name) {
3757*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Constructor %u(%s) must not be abstract or native",
3758*795d594fSAndroid Build Coastguard Worker method_index,
3759*795d594fSAndroid Build Coastguard Worker GetMethodDescription(method_index).c_str());
3760*795d594fSAndroid Build Coastguard Worker if (dex_file_->SupportsDefaultMethods()) {
3761*795d594fSAndroid Build Coastguard Worker return false;
3762*795d594fSAndroid Build Coastguard Worker } else {
3763*795d594fSAndroid Build Coastguard Worker // Allow in older versions, but warn.
3764*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "This dex file is invalid and will be rejected in the future. Error is: "
3765*795d594fSAndroid Build Coastguard Worker << *error_msg;
3766*795d594fSAndroid Build Coastguard Worker }
3767*795d594fSAndroid Build Coastguard Worker }
3768*795d594fSAndroid Build Coastguard Worker if ((method_access_flags & kAccAbstract) != 0) {
3769*795d594fSAndroid Build Coastguard Worker // Abstract methods are not allowed to have the following flags.
3770*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kForbidden =
3771*795d594fSAndroid Build Coastguard Worker kAccPrivate | kAccStatic | kAccFinal | kAccNative | kAccStrict | kAccSynchronized;
3772*795d594fSAndroid Build Coastguard Worker if ((method_access_flags & kForbidden) != 0) {
3773*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Abstract method %" PRIu32 "(%s) has disallowed access flags %x",
3774*795d594fSAndroid Build Coastguard Worker method_index,
3775*795d594fSAndroid Build Coastguard Worker GetMethodDescription(method_index).c_str(),
3776*795d594fSAndroid Build Coastguard Worker method_access_flags);
3777*795d594fSAndroid Build Coastguard Worker return false;
3778*795d594fSAndroid Build Coastguard Worker }
3779*795d594fSAndroid Build Coastguard Worker // Abstract methods should be in an abstract class or interface.
3780*795d594fSAndroid Build Coastguard Worker if ((class_access_flags & (kAccInterface | kAccAbstract)) == 0) {
3781*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "Method " << GetMethodDescription(method_index)
3782*795d594fSAndroid Build Coastguard Worker << " is abstract, but the declaring class is neither abstract nor an "
3783*795d594fSAndroid Build Coastguard Worker << "interface in dex file "
3784*795d594fSAndroid Build Coastguard Worker << dex_file_->GetLocation();
3785*795d594fSAndroid Build Coastguard Worker }
3786*795d594fSAndroid Build Coastguard Worker }
3787*795d594fSAndroid Build Coastguard Worker // Interfaces are special.
3788*795d594fSAndroid Build Coastguard Worker if ((class_access_flags & kAccInterface) != 0) {
3789*795d594fSAndroid Build Coastguard Worker // Interface methods without code must be abstract.
3790*795d594fSAndroid Build Coastguard Worker if ((method_access_flags & (kAccPublic | kAccAbstract)) != (kAccPublic | kAccAbstract)) {
3791*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Interface method %" PRIu32 "(%s) is not public and abstract",
3792*795d594fSAndroid Build Coastguard Worker method_index,
3793*795d594fSAndroid Build Coastguard Worker GetMethodDescription(method_index).c_str());
3794*795d594fSAndroid Build Coastguard Worker if (dex_file_->SupportsDefaultMethods()) {
3795*795d594fSAndroid Build Coastguard Worker return false;
3796*795d594fSAndroid Build Coastguard Worker } else {
3797*795d594fSAndroid Build Coastguard Worker // Allow in older versions, but warn.
3798*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "This dex file is invalid and will be rejected in the future. Error is: "
3799*795d594fSAndroid Build Coastguard Worker << *error_msg;
3800*795d594fSAndroid Build Coastguard Worker }
3801*795d594fSAndroid Build Coastguard Worker }
3802*795d594fSAndroid Build Coastguard Worker // At this point, we know the method is public and abstract. This means that all the checks
3803*795d594fSAndroid Build Coastguard Worker // for invalid combinations above applies. In addition, interface methods must not be
3804*795d594fSAndroid Build Coastguard Worker // protected. This is caught by the check for only-one-of-public-protected-private.
3805*795d594fSAndroid Build Coastguard Worker }
3806*795d594fSAndroid Build Coastguard Worker return true;
3807*795d594fSAndroid Build Coastguard Worker }
3808*795d594fSAndroid Build Coastguard Worker
3809*795d594fSAndroid Build Coastguard Worker // When there's code, the method must not be native or abstract.
3810*795d594fSAndroid Build Coastguard Worker if ((method_access_flags & (kAccNative | kAccAbstract)) != 0) {
3811*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Method %" PRIu32 "(%s) has code, but is marked native or abstract",
3812*795d594fSAndroid Build Coastguard Worker method_index,
3813*795d594fSAndroid Build Coastguard Worker GetMethodDescription(method_index).c_str());
3814*795d594fSAndroid Build Coastguard Worker return false;
3815*795d594fSAndroid Build Coastguard Worker }
3816*795d594fSAndroid Build Coastguard Worker
3817*795d594fSAndroid Build Coastguard Worker // Instance constructors must not be synchronized and a few other flags.
3818*795d594fSAndroid Build Coastguard Worker if (constructor_flags_by_name == kAccConstructor) {
3819*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kInitAllowed =
3820*795d594fSAndroid Build Coastguard Worker kAccPrivate | kAccProtected | kAccPublic | kAccStrict | kAccVarargs | kAccSynthetic;
3821*795d594fSAndroid Build Coastguard Worker if ((method_access_flags & ~kInitAllowed) != 0) {
3822*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Constructor %" PRIu32 "(%s) flagged inappropriately %x",
3823*795d594fSAndroid Build Coastguard Worker method_index,
3824*795d594fSAndroid Build Coastguard Worker GetMethodDescription(method_index).c_str(),
3825*795d594fSAndroid Build Coastguard Worker method_access_flags);
3826*795d594fSAndroid Build Coastguard Worker return false;
3827*795d594fSAndroid Build Coastguard Worker }
3828*795d594fSAndroid Build Coastguard Worker }
3829*795d594fSAndroid Build Coastguard Worker
3830*795d594fSAndroid Build Coastguard Worker return true;
3831*795d594fSAndroid Build Coastguard Worker }
3832*795d594fSAndroid Build Coastguard Worker
CheckConstructorProperties(uint32_t method_index,uint32_t constructor_flags)3833*795d594fSAndroid Build Coastguard Worker bool DexFileVerifier::CheckConstructorProperties(
3834*795d594fSAndroid Build Coastguard Worker uint32_t method_index,
3835*795d594fSAndroid Build Coastguard Worker uint32_t constructor_flags) {
3836*795d594fSAndroid Build Coastguard Worker DCHECK(constructor_flags == kAccConstructor ||
3837*795d594fSAndroid Build Coastguard Worker constructor_flags == (kAccConstructor | kAccStatic));
3838*795d594fSAndroid Build Coastguard Worker
3839*795d594fSAndroid Build Coastguard Worker // Check signature matches expectations.
3840*795d594fSAndroid Build Coastguard Worker // The `method_index` has already been checked in `CheckIntraClassDataItemMethods()`.
3841*795d594fSAndroid Build Coastguard Worker CHECK_LT(method_index, header_->method_ids_size_);
3842*795d594fSAndroid Build Coastguard Worker const dex::MethodId& method_id = dex_file_->GetMethodId(method_index);
3843*795d594fSAndroid Build Coastguard Worker
3844*795d594fSAndroid Build Coastguard Worker // The `method_id.proto_idx_` has already been checked in `CheckIntraMethodIdItem()`
3845*795d594fSAndroid Build Coastguard Worker DCHECK_LE(method_id.proto_idx_.index_, header_->proto_ids_size_);
3846*795d594fSAndroid Build Coastguard Worker
3847*795d594fSAndroid Build Coastguard Worker Signature signature = dex_file_->GetMethodSignature(method_id);
3848*795d594fSAndroid Build Coastguard Worker if (constructor_flags == (kAccStatic | kAccConstructor)) {
3849*795d594fSAndroid Build Coastguard Worker if (!signature.IsVoid() || signature.GetNumberOfParameters() != 0) {
3850*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("<clinit> must have descriptor ()V");
3851*795d594fSAndroid Build Coastguard Worker return false;
3852*795d594fSAndroid Build Coastguard Worker }
3853*795d594fSAndroid Build Coastguard Worker } else if (!signature.IsVoid()) {
3854*795d594fSAndroid Build Coastguard Worker ErrorStringPrintf("Constructor %u(%s) must be void",
3855*795d594fSAndroid Build Coastguard Worker method_index,
3856*795d594fSAndroid Build Coastguard Worker GetMethodDescription(method_index).c_str());
3857*795d594fSAndroid Build Coastguard Worker return false;
3858*795d594fSAndroid Build Coastguard Worker }
3859*795d594fSAndroid Build Coastguard Worker
3860*795d594fSAndroid Build Coastguard Worker return true;
3861*795d594fSAndroid Build Coastguard Worker }
3862*795d594fSAndroid Build Coastguard Worker
Verify(const DexFile * dex_file,const char * location,bool verify_checksum,std::string * error_msg)3863*795d594fSAndroid Build Coastguard Worker bool Verify(const DexFile* dex_file,
3864*795d594fSAndroid Build Coastguard Worker const char* location,
3865*795d594fSAndroid Build Coastguard Worker bool verify_checksum,
3866*795d594fSAndroid Build Coastguard Worker std::string* error_msg) {
3867*795d594fSAndroid Build Coastguard Worker std::unique_ptr<DexFileVerifier> verifier(
3868*795d594fSAndroid Build Coastguard Worker new DexFileVerifier(dex_file, location, verify_checksum));
3869*795d594fSAndroid Build Coastguard Worker if (!verifier->Verify()) {
3870*795d594fSAndroid Build Coastguard Worker *error_msg = verifier->FailureReason();
3871*795d594fSAndroid Build Coastguard Worker return false;
3872*795d594fSAndroid Build Coastguard Worker }
3873*795d594fSAndroid Build Coastguard Worker return true;
3874*795d594fSAndroid Build Coastguard Worker }
3875*795d594fSAndroid Build Coastguard Worker
3876*795d594fSAndroid Build Coastguard Worker } // namespace dex
3877*795d594fSAndroid Build Coastguard Worker } // namespace art
3878