xref: /aosp_15_r20/art/libdexfile/dex/dex_file_verifier.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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