blob: 56bf21d2cb8b1933f8b6d27bdc253e8620d7e2e3 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
jeffhao10037c82012-01-23 15:06:23 -080016
17#include "dex_file_verifier.h"
18
Elliott Hughese222ee02012-12-13 14:41:43 -080019#include "base/stringprintf.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070020#include "dex_file-inl.h"
jeffhao10037c82012-01-23 15:06:23 -080021#include "leb128.h"
Elliott Hughesa0e18062012-04-13 15:59:59 -070022#include "safe_map.h"
Elliott Hughesa0e18062012-04-13 15:59:59 -070023#include "UniquePtr.h"
Ian Rogersa6724902013-09-23 09:23:37 -070024#include "utf-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080025#include "utils.h"
jeffhao10037c82012-01-23 15:06:23 -080026#include "zip_archive.h"
27
28namespace art {
29
30static uint32_t MapTypeToBitMask(uint32_t map_type) {
31 switch (map_type) {
32 case DexFile::kDexTypeHeaderItem: return 1 << 0;
33 case DexFile::kDexTypeStringIdItem: return 1 << 1;
34 case DexFile::kDexTypeTypeIdItem: return 1 << 2;
35 case DexFile::kDexTypeProtoIdItem: return 1 << 3;
36 case DexFile::kDexTypeFieldIdItem: return 1 << 4;
37 case DexFile::kDexTypeMethodIdItem: return 1 << 5;
38 case DexFile::kDexTypeClassDefItem: return 1 << 6;
39 case DexFile::kDexTypeMapList: return 1 << 7;
40 case DexFile::kDexTypeTypeList: return 1 << 8;
41 case DexFile::kDexTypeAnnotationSetRefList: return 1 << 9;
42 case DexFile::kDexTypeAnnotationSetItem: return 1 << 10;
43 case DexFile::kDexTypeClassDataItem: return 1 << 11;
44 case DexFile::kDexTypeCodeItem: return 1 << 12;
45 case DexFile::kDexTypeStringDataItem: return 1 << 13;
46 case DexFile::kDexTypeDebugInfoItem: return 1 << 14;
47 case DexFile::kDexTypeAnnotationItem: return 1 << 15;
48 case DexFile::kDexTypeEncodedArrayItem: return 1 << 16;
49 case DexFile::kDexTypeAnnotationsDirectoryItem: return 1 << 17;
50 }
51 return 0;
52}
53
54static bool IsDataSectionType(uint32_t map_type) {
55 switch (map_type) {
56 case DexFile::kDexTypeHeaderItem:
57 case DexFile::kDexTypeStringIdItem:
58 case DexFile::kDexTypeTypeIdItem:
59 case DexFile::kDexTypeProtoIdItem:
60 case DexFile::kDexTypeFieldIdItem:
61 case DexFile::kDexTypeMethodIdItem:
62 case DexFile::kDexTypeClassDefItem:
63 return false;
64 }
65 return true;
66}
67
Ian Rogers8d31bbd2013-10-13 10:44:14 -070068bool DexFileVerifier::Verify(const DexFile* dex_file, const byte* begin, size_t size,
69 const char* location, std::string* error_msg) {
70 UniquePtr<DexFileVerifier> verifier(new DexFileVerifier(dex_file, begin, size, location));
71 if (!verifier->Verify()) {
72 *error_msg = verifier->FailureReason();
73 return false;
74 }
75 return true;
76}
77
78bool DexFileVerifier::CheckShortyDescriptorMatch(char shorty_char, const char* descriptor,
79 bool is_return_type) {
jeffhao10037c82012-01-23 15:06:23 -080080 switch (shorty_char) {
81 case 'V':
Ian Rogers8d31bbd2013-10-13 10:44:14 -070082 if (UNLIKELY(!is_return_type)) {
83 ErrorStringPrintf("Invalid use of void");
jeffhao10037c82012-01-23 15:06:23 -080084 return false;
85 }
86 // Intentional fallthrough.
87 case 'B':
88 case 'C':
89 case 'D':
90 case 'F':
91 case 'I':
92 case 'J':
93 case 'S':
94 case 'Z':
Ian Rogers8d31bbd2013-10-13 10:44:14 -070095 if (UNLIKELY((descriptor[0] != shorty_char) || (descriptor[1] != '\0'))) {
96 ErrorStringPrintf("Shorty vs. primitive type mismatch: '%c', '%s'",
97 shorty_char, descriptor);
jeffhao10037c82012-01-23 15:06:23 -080098 return false;
99 }
100 break;
101 case 'L':
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700102 if (UNLIKELY((descriptor[0] != 'L') && (descriptor[0] != '['))) {
103 ErrorStringPrintf("Shorty vs. type mismatch: '%c', '%s'", shorty_char, descriptor);
jeffhao10037c82012-01-23 15:06:23 -0800104 return false;
105 }
106 break;
107 default:
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700108 ErrorStringPrintf("Bad shorty character: '%c'", shorty_char);
jeffhao10037c82012-01-23 15:06:23 -0800109 return false;
110 }
111 return true;
112}
113
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700114bool DexFileVerifier::CheckPointerRange(const void* start, const void* end, const char* label) {
jeffhao10037c82012-01-23 15:06:23 -0800115 uint32_t range_start = reinterpret_cast<uint32_t>(start);
116 uint32_t range_end = reinterpret_cast<uint32_t>(end);
Ian Rogers30fab402012-01-23 15:43:46 -0800117 uint32_t file_start = reinterpret_cast<uint32_t>(begin_);
jeffhaof6174e82012-01-31 16:14:17 -0800118 uint32_t file_end = file_start + size_;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700119 if (UNLIKELY((range_start < file_start) || (range_start > file_end) ||
120 (range_end < file_start) || (range_end > file_end))) {
121 ErrorStringPrintf("Bad range for %s: %x to %x", label,
122 range_start - file_start, range_end - file_start);
jeffhao10037c82012-01-23 15:06:23 -0800123 return false;
124 }
125 return true;
126}
127
128bool DexFileVerifier::CheckListSize(const void* start, uint32_t count,
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700129 uint32_t element_size, const char* label) {
jeffhao10037c82012-01-23 15:06:23 -0800130 const byte* list_start = reinterpret_cast<const byte*>(start);
131 return CheckPointerRange(list_start, list_start + (count * element_size), label);
132}
133
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700134bool DexFileVerifier::CheckIndex(uint32_t field, uint32_t limit, const char* label) {
135 if (UNLIKELY(field >= limit)) {
136 ErrorStringPrintf("Bad index for %s: %x >= %x", label, field, limit);
jeffhao10037c82012-01-23 15:06:23 -0800137 return false;
138 }
139 return true;
140}
141
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700142bool DexFileVerifier::CheckHeader() {
jeffhaof6174e82012-01-31 16:14:17 -0800143 // Check file size from the header.
144 uint32_t expected_size = header_->file_size_;
145 if (size_ != expected_size) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700146 ErrorStringPrintf("Bad file size (%zd, expected %ud)", size_, expected_size);
jeffhao10037c82012-01-23 15:06:23 -0800147 return false;
148 }
149
150 // Compute and verify the checksum in the header.
151 uint32_t adler_checksum = adler32(0L, Z_NULL, 0);
152 const uint32_t non_sum = sizeof(header_->magic_) + sizeof(header_->checksum_);
153 const byte* non_sum_ptr = reinterpret_cast<const byte*>(header_) + non_sum;
jeffhaof6174e82012-01-31 16:14:17 -0800154 adler_checksum = adler32(adler_checksum, non_sum_ptr, expected_size - non_sum);
jeffhao10037c82012-01-23 15:06:23 -0800155 if (adler_checksum != header_->checksum_) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700156 ErrorStringPrintf("Bad checksum (%08x, expected %08x)", adler_checksum, header_->checksum_);
jeffhao10037c82012-01-23 15:06:23 -0800157 return false;
158 }
159
160 // Check the contents of the header.
161 if (header_->endian_tag_ != DexFile::kDexEndianConstant) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700162 ErrorStringPrintf("Unexpected endian_tag: %x", header_->endian_tag_);
jeffhao10037c82012-01-23 15:06:23 -0800163 return false;
164 }
165
166 if (header_->header_size_ != sizeof(DexFile::Header)) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700167 ErrorStringPrintf("Bad header size: %ud", header_->header_size_);
jeffhao10037c82012-01-23 15:06:23 -0800168 return false;
169 }
170
171 return true;
172}
173
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700174bool DexFileVerifier::CheckMap() {
Ian Rogers30fab402012-01-23 15:43:46 -0800175 const DexFile::MapList* map = reinterpret_cast<const DexFile::MapList*>(begin_ + header_->map_off_);
jeffhao10037c82012-01-23 15:06:23 -0800176 const DexFile::MapItem* item = map->list_;
177
178 uint32_t count = map->size_;
179 uint32_t last_offset = 0;
180 uint32_t data_item_count = 0;
181 uint32_t data_items_left = header_->data_size_;
182 uint32_t used_bits = 0;
183
184 // Sanity check the size of the map list.
185 if (!CheckListSize(item, count, sizeof(DexFile::MapItem), "map size")) {
186 return false;
187 }
188
189 // Check the items listed in the map.
190 for (uint32_t i = 0; i < count; i++) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700191 if (UNLIKELY(last_offset >= item->offset_ && i != 0)) {
192 ErrorStringPrintf("Out of order map item: %x then %x", last_offset, item->offset_);
jeffhao10037c82012-01-23 15:06:23 -0800193 return false;
194 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700195 if (UNLIKELY(item->offset_ >= header_->file_size_)) {
196 ErrorStringPrintf("Map item after end of file: %x, size %x",
197 item->offset_, header_->file_size_);
jeffhao10037c82012-01-23 15:06:23 -0800198 return false;
199 }
200
201 if (IsDataSectionType(item->type_)) {
202 uint32_t icount = item->size_;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700203 if (UNLIKELY(icount > data_items_left)) {
204 ErrorStringPrintf("Too many items in data section: %ud", data_item_count + icount);
jeffhao10037c82012-01-23 15:06:23 -0800205 return false;
206 }
207 data_items_left -= icount;
208 data_item_count += icount;
209 }
210
211 uint32_t bit = MapTypeToBitMask(item->type_);
212
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700213 if (UNLIKELY(bit == 0)) {
214 ErrorStringPrintf("Unknown map section type %x", item->type_);
jeffhao10037c82012-01-23 15:06:23 -0800215 return false;
216 }
217
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700218 if (UNLIKELY((used_bits & bit) != 0)) {
219 ErrorStringPrintf("Duplicate map section of type %x", item->type_);
jeffhao10037c82012-01-23 15:06:23 -0800220 return false;
221 }
222
223 used_bits |= bit;
224 last_offset = item->offset_;
225 item++;
226 }
227
228 // Check for missing sections in the map.
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700229 if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeHeaderItem)) == 0)) {
230 ErrorStringPrintf("Map is missing header entry");
jeffhao10037c82012-01-23 15:06:23 -0800231 return false;
232 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700233 if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeMapList)) == 0)) {
234 ErrorStringPrintf("Map is missing map_list entry");
jeffhao10037c82012-01-23 15:06:23 -0800235 return false;
236 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700237 if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeStringIdItem)) == 0 &&
238 ((header_->string_ids_off_ != 0) || (header_->string_ids_size_ != 0)))) {
239 ErrorStringPrintf("Map is missing string_ids entry");
jeffhao10037c82012-01-23 15:06:23 -0800240 return false;
241 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700242 if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeTypeIdItem)) == 0 &&
243 ((header_->type_ids_off_ != 0) || (header_->type_ids_size_ != 0)))) {
244 ErrorStringPrintf("Map is missing type_ids entry");
jeffhao10037c82012-01-23 15:06:23 -0800245 return false;
246 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700247 if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeProtoIdItem)) == 0 &&
248 ((header_->proto_ids_off_ != 0) || (header_->proto_ids_size_ != 0)))) {
249 ErrorStringPrintf("Map is missing proto_ids entry");
jeffhao10037c82012-01-23 15:06:23 -0800250 return false;
251 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700252 if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeFieldIdItem)) == 0 &&
253 ((header_->field_ids_off_ != 0) || (header_->field_ids_size_ != 0)))) {
254 ErrorStringPrintf("Map is missing field_ids entry");
jeffhao10037c82012-01-23 15:06:23 -0800255 return false;
256 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700257 if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeMethodIdItem)) == 0 &&
258 ((header_->method_ids_off_ != 0) || (header_->method_ids_size_ != 0)))) {
259 ErrorStringPrintf("Map is missing method_ids entry");
jeffhao10037c82012-01-23 15:06:23 -0800260 return false;
261 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700262 if (UNLIKELY((used_bits & MapTypeToBitMask(DexFile::kDexTypeClassDefItem)) == 0 &&
263 ((header_->class_defs_off_ != 0) || (header_->class_defs_size_ != 0)))) {
264 ErrorStringPrintf("Map is missing class_defs entry");
jeffhao10037c82012-01-23 15:06:23 -0800265 return false;
266 }
jeffhao10037c82012-01-23 15:06:23 -0800267 return true;
268}
269
270uint32_t DexFileVerifier::ReadUnsignedLittleEndian(uint32_t size) {
271 uint32_t result = 0;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700272 if (LIKELY(CheckPointerRange(ptr_, ptr_ + size, "encoded_value"))) {
273 for (uint32_t i = 0; i < size; i++) {
274 result |= ((uint32_t) *(ptr_++)) << (i * 8);
275 }
jeffhao10037c82012-01-23 15:06:23 -0800276 }
jeffhao10037c82012-01-23 15:06:23 -0800277 return result;
278}
279
280bool DexFileVerifier::CheckAndGetHandlerOffsets(const DexFile::CodeItem* code_item,
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700281 uint32_t* handler_offsets, uint32_t handlers_size) {
jeffhao10037c82012-01-23 15:06:23 -0800282 const byte* handlers_base = DexFile::GetCatchHandlerData(*code_item, 0);
283
284 for (uint32_t i = 0; i < handlers_size; i++) {
285 bool catch_all;
286 uint32_t offset = reinterpret_cast<uint32_t>(ptr_) - reinterpret_cast<uint32_t>(handlers_base);
287 int32_t size = DecodeSignedLeb128(&ptr_);
288
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700289 if (UNLIKELY((size < -65536) || (size > 65536))) {
290 ErrorStringPrintf("Invalid exception handler size: %d", size);
jeffhao10037c82012-01-23 15:06:23 -0800291 return false;
292 }
293
294 if (size <= 0) {
295 catch_all = true;
296 size = -size;
297 } else {
298 catch_all = false;
299 }
300
301 handler_offsets[i] = offset;
302
303 while (size-- > 0) {
304 uint32_t type_idx = DecodeUnsignedLeb128(&ptr_);
305 if (!CheckIndex(type_idx, header_->type_ids_size_, "handler type_idx")) {
306 return false;
307 }
308
309 uint32_t addr = DecodeUnsignedLeb128(&ptr_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700310 if (UNLIKELY(addr >= code_item->insns_size_in_code_units_)) {
311 ErrorStringPrintf("Invalid handler addr: %x", addr);
jeffhao10037c82012-01-23 15:06:23 -0800312 return false;
313 }
314 }
315
316 if (catch_all) {
317 uint32_t addr = DecodeUnsignedLeb128(&ptr_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700318 if (UNLIKELY(addr >= code_item->insns_size_in_code_units_)) {
319 ErrorStringPrintf("Invalid handler catch_all_addr: %x", addr);
jeffhao10037c82012-01-23 15:06:23 -0800320 return false;
321 }
322 }
323 }
324
325 return true;
326}
327
328bool DexFileVerifier::CheckClassDataItemField(uint32_t idx, uint32_t access_flags,
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700329 bool expect_static) {
jeffhao10037c82012-01-23 15:06:23 -0800330 if (!CheckIndex(idx, header_->field_ids_size_, "class_data_item field_idx")) {
331 return false;
332 }
333
334 bool is_static = (access_flags & kAccStatic) != 0;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700335 if (UNLIKELY(is_static != expect_static)) {
336 ErrorStringPrintf("Static/instance field not in expected list");
jeffhao10037c82012-01-23 15:06:23 -0800337 return false;
338 }
339
340 uint32_t access_field_mask = kAccPublic | kAccPrivate | kAccProtected | kAccStatic |
341 kAccFinal | kAccVolatile | kAccTransient | kAccSynthetic | kAccEnum;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700342 if (UNLIKELY((access_flags & ~access_field_mask) != 0)) {
343 ErrorStringPrintf("Bad class_data_item field access_flags %x", access_flags);
jeffhao10037c82012-01-23 15:06:23 -0800344 return false;
345 }
346
347 return true;
348}
349
350bool DexFileVerifier::CheckClassDataItemMethod(uint32_t idx, uint32_t access_flags,
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700351 uint32_t code_offset, bool expect_direct) {
jeffhao10037c82012-01-23 15:06:23 -0800352 if (!CheckIndex(idx, header_->method_ids_size_, "class_data_item method_idx")) {
353 return false;
354 }
355
356 bool is_direct = (access_flags & (kAccStatic | kAccPrivate | kAccConstructor)) != 0;
357 bool expect_code = (access_flags & (kAccNative | kAccAbstract)) == 0;
358 bool is_synchronized = (access_flags & kAccSynchronized) != 0;
359 bool allow_synchronized = (access_flags & kAccNative) != 0;
360
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700361 if (UNLIKELY(is_direct != expect_direct)) {
362 ErrorStringPrintf("Direct/virtual method not in expected list");
jeffhao10037c82012-01-23 15:06:23 -0800363 return false;
364 }
365
366 uint32_t access_method_mask = kAccPublic | kAccPrivate | kAccProtected | kAccStatic |
367 kAccFinal | kAccSynchronized | kAccBridge | kAccVarargs | kAccNative | kAccAbstract |
368 kAccStrict | kAccSynthetic | kAccConstructor | kAccDeclaredSynchronized;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700369 if (UNLIKELY(((access_flags & ~access_method_mask) != 0) ||
370 (is_synchronized && !allow_synchronized))) {
371 ErrorStringPrintf("Bad class_data_item method access_flags %x", access_flags);
jeffhao10037c82012-01-23 15:06:23 -0800372 return false;
373 }
374
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700375 if (UNLIKELY(expect_code && (code_offset == 0))) {
376 ErrorStringPrintf("Unexpected zero value for class_data_item method code_off with access "
377 "flags %x", access_flags);
jeffhao10037c82012-01-23 15:06:23 -0800378 return false;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700379 } else if (UNLIKELY(!expect_code && (code_offset != 0))) {
380 ErrorStringPrintf("Unexpected non-zero value %x for class_data_item method code_off"
381 " with access flags %x", code_offset, access_flags);
jeffhao10037c82012-01-23 15:06:23 -0800382 return false;
383 }
384
385 return true;
386}
387
388bool DexFileVerifier::CheckPadding(uint32_t offset, uint32_t aligned_offset) {
389 if (offset < aligned_offset) {
Ian Rogers30fab402012-01-23 15:43:46 -0800390 if (!CheckPointerRange(begin_ + offset, begin_ + aligned_offset, "section")) {
jeffhao10037c82012-01-23 15:06:23 -0800391 return false;
392 }
393 while (offset < aligned_offset) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700394 if (UNLIKELY(*ptr_ != '\0')) {
395 ErrorStringPrintf("Non-zero padding %x before section start at %x", *ptr_, offset);
jeffhao10037c82012-01-23 15:06:23 -0800396 return false;
397 }
398 ptr_++;
399 offset++;
400 }
401 }
402 return true;
403}
404
405bool DexFileVerifier::CheckEncodedValue() {
406 if (!CheckPointerRange(ptr_, ptr_ + 1, "encoded_value header")) {
407 return false;
408 }
409
410 uint8_t header_byte = *(ptr_++);
411 uint32_t value_type = header_byte & DexFile::kDexAnnotationValueTypeMask;
412 uint32_t value_arg = header_byte >> DexFile::kDexAnnotationValueArgShift;
413
414 switch (value_type) {
415 case DexFile::kDexAnnotationByte:
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700416 if (UNLIKELY(value_arg != 0)) {
417 ErrorStringPrintf("Bad encoded_value byte size %x", value_arg);
jeffhao10037c82012-01-23 15:06:23 -0800418 return false;
419 }
420 ptr_++;
421 break;
422 case DexFile::kDexAnnotationShort:
423 case DexFile::kDexAnnotationChar:
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700424 if (UNLIKELY(value_arg > 1)) {
425 ErrorStringPrintf("Bad encoded_value char/short size %x", value_arg);
jeffhao10037c82012-01-23 15:06:23 -0800426 return false;
427 }
428 ptr_ += value_arg + 1;
429 break;
430 case DexFile::kDexAnnotationInt:
431 case DexFile::kDexAnnotationFloat:
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700432 if (UNLIKELY(value_arg > 3)) {
433 ErrorStringPrintf("Bad encoded_value int/float size %x", value_arg);
jeffhao10037c82012-01-23 15:06:23 -0800434 return false;
435 }
436 ptr_ += value_arg + 1;
437 break;
438 case DexFile::kDexAnnotationLong:
439 case DexFile::kDexAnnotationDouble:
440 ptr_ += value_arg + 1;
441 break;
442 case DexFile::kDexAnnotationString: {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700443 if (UNLIKELY(value_arg > 3)) {
444 ErrorStringPrintf("Bad encoded_value string size %x", value_arg);
jeffhao10037c82012-01-23 15:06:23 -0800445 return false;
446 }
447 uint32_t idx = ReadUnsignedLittleEndian(value_arg + 1);
448 if (!CheckIndex(idx, header_->string_ids_size_, "encoded_value string")) {
449 return false;
450 }
451 break;
452 }
453 case DexFile::kDexAnnotationType: {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700454 if (UNLIKELY(value_arg > 3)) {
455 ErrorStringPrintf("Bad encoded_value type size %x", value_arg);
jeffhao10037c82012-01-23 15:06:23 -0800456 return false;
457 }
458 uint32_t idx = ReadUnsignedLittleEndian(value_arg + 1);
459 if (!CheckIndex(idx, header_->type_ids_size_, "encoded_value type")) {
460 return false;
461 }
462 break;
463 }
464 case DexFile::kDexAnnotationField:
465 case DexFile::kDexAnnotationEnum: {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700466 if (UNLIKELY(value_arg > 3)) {
467 ErrorStringPrintf("Bad encoded_value field/enum size %x", value_arg);
jeffhao10037c82012-01-23 15:06:23 -0800468 return false;
469 }
470 uint32_t idx = ReadUnsignedLittleEndian(value_arg + 1);
471 if (!CheckIndex(idx, header_->field_ids_size_, "encoded_value field")) {
472 return false;
473 }
474 break;
475 }
476 case DexFile::kDexAnnotationMethod: {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700477 if (UNLIKELY(value_arg > 3)) {
478 ErrorStringPrintf("Bad encoded_value method size %x", value_arg);
jeffhao10037c82012-01-23 15:06:23 -0800479 return false;
480 }
481 uint32_t idx = ReadUnsignedLittleEndian(value_arg + 1);
482 if (!CheckIndex(idx, header_->method_ids_size_, "encoded_value method")) {
483 return false;
484 }
485 break;
486 }
487 case DexFile::kDexAnnotationArray:
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700488 if (UNLIKELY(value_arg != 0)) {
489 ErrorStringPrintf("Bad encoded_value array value_arg %x", value_arg);
jeffhao10037c82012-01-23 15:06:23 -0800490 return false;
491 }
492 if (!CheckEncodedArray()) {
493 return false;
494 }
495 break;
496 case DexFile::kDexAnnotationAnnotation:
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700497 if (UNLIKELY(value_arg != 0)) {
498 ErrorStringPrintf("Bad encoded_value annotation value_arg %x", value_arg);
jeffhao10037c82012-01-23 15:06:23 -0800499 return false;
500 }
501 if (!CheckEncodedAnnotation()) {
502 return false;
503 }
504 break;
505 case DexFile::kDexAnnotationNull:
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700506 if (UNLIKELY(value_arg != 0)) {
507 ErrorStringPrintf("Bad encoded_value null value_arg %x", value_arg);
jeffhao10037c82012-01-23 15:06:23 -0800508 return false;
509 }
510 break;
511 case DexFile::kDexAnnotationBoolean:
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700512 if (UNLIKELY(value_arg > 1)) {
513 ErrorStringPrintf("Bad encoded_value boolean size %x", value_arg);
jeffhao10037c82012-01-23 15:06:23 -0800514 return false;
515 }
516 break;
517 default:
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700518 ErrorStringPrintf("Bogus encoded_value value_type %x", value_type);
jeffhao10037c82012-01-23 15:06:23 -0800519 return false;
520 }
521
522 return true;
523}
524
525bool DexFileVerifier::CheckEncodedArray() {
526 uint32_t size = DecodeUnsignedLeb128(&ptr_);
527
528 while (size--) {
529 if (!CheckEncodedValue()) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700530 failure_reason_ = StringPrintf("Bad encoded_array value: %s", failure_reason_.c_str());
jeffhao10037c82012-01-23 15:06:23 -0800531 return false;
532 }
533 }
534 return true;
535}
536
537bool DexFileVerifier::CheckEncodedAnnotation() {
538 uint32_t idx = DecodeUnsignedLeb128(&ptr_);
539 if (!CheckIndex(idx, header_->type_ids_size_, "encoded_annotation type_idx")) {
540 return false;
541 }
542
543 uint32_t size = DecodeUnsignedLeb128(&ptr_);
544 uint32_t last_idx = 0;
545
546 for (uint32_t i = 0; i < size; i++) {
547 idx = DecodeUnsignedLeb128(&ptr_);
548 if (!CheckIndex(idx, header_->string_ids_size_, "annotation_element name_idx")) {
549 return false;
550 }
551
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700552 if (UNLIKELY(last_idx >= idx && i != 0)) {
553 ErrorStringPrintf("Out-of-order annotation_element name_idx: %x then %x",
554 last_idx, idx);
jeffhao10037c82012-01-23 15:06:23 -0800555 return false;
556 }
557
558 if (!CheckEncodedValue()) {
559 return false;
560 }
561
562 last_idx = idx;
563 }
564 return true;
565}
566
567bool DexFileVerifier::CheckIntraClassDataItem() {
568 ClassDataItemIterator it(*dex_file_, ptr_);
569
570 for (; it.HasNextStaticField(); it.Next()) {
571 if (!CheckClassDataItemField(it.GetMemberIndex(), it.GetMemberAccessFlags(), true)) {
572 return false;
573 }
574 }
575 for (; it.HasNextInstanceField(); it.Next()) {
576 if (!CheckClassDataItemField(it.GetMemberIndex(), it.GetMemberAccessFlags(), false)) {
577 return false;
578 }
579 }
580 for (; it.HasNextDirectMethod(); it.Next()) {
581 if (!CheckClassDataItemMethod(it.GetMemberIndex(), it.GetMemberAccessFlags(),
582 it.GetMethodCodeItemOffset(), true)) {
583 return false;
584 }
585 }
586 for (; it.HasNextVirtualMethod(); it.Next()) {
587 if (!CheckClassDataItemMethod(it.GetMemberIndex(), it.GetMemberAccessFlags(),
588 it.GetMethodCodeItemOffset(), false)) {
589 return false;
590 }
591 }
592
593 ptr_ = it.EndDataPointer();
594 return true;
595}
596
597bool DexFileVerifier::CheckIntraCodeItem() {
598 const DexFile::CodeItem* code_item = reinterpret_cast<const DexFile::CodeItem*>(ptr_);
599 if (!CheckPointerRange(code_item, code_item + 1, "code")) {
600 return false;
601 }
602
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700603 if (UNLIKELY(code_item->ins_size_ > code_item->registers_size_)) {
604 ErrorStringPrintf("ins_size (%ud) > registers_size (%ud)",
605 code_item->ins_size_, code_item->registers_size_);
jeffhao10037c82012-01-23 15:06:23 -0800606 return false;
607 }
608
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700609 if (UNLIKELY((code_item->outs_size_ > 5) &&
610 (code_item->outs_size_ > code_item->registers_size_))) {
jeffhao10037c82012-01-23 15:06:23 -0800611 /*
612 * outs_size can be up to 5, even if registers_size is smaller, since the
613 * short forms of method invocation allow repetitions of a register multiple
614 * times within a single parameter list. However, longer parameter lists
615 * need to be represented in-order in the register file.
616 */
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700617 ErrorStringPrintf("outs_size (%ud) > registers_size (%ud)",
618 code_item->outs_size_, code_item->registers_size_);
jeffhao10037c82012-01-23 15:06:23 -0800619 return false;
620 }
621
622 const uint16_t* insns = code_item->insns_;
623 uint32_t insns_size = code_item->insns_size_in_code_units_;
624 if (!CheckListSize(insns, insns_size, sizeof(uint16_t), "insns size")) {
625 return false;
626 }
627
628 // Grab the end of the insns if there are no try_items.
629 uint32_t try_items_size = code_item->tries_size_;
630 if (try_items_size == 0) {
631 ptr_ = reinterpret_cast<const byte*>(&insns[insns_size]);
632 return true;
633 }
634
635 // try_items are 4-byte aligned. Verify the spacer is 0.
636 if ((((uint32_t) &insns[insns_size] & 3) != 0) && (insns[insns_size] != 0)) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700637 ErrorStringPrintf("Non-zero padding: %x", insns[insns_size]);
jeffhao10037c82012-01-23 15:06:23 -0800638 return false;
639 }
640
641 const DexFile::TryItem* try_items = DexFile::GetTryItems(*code_item, 0);
642 ptr_ = DexFile::GetCatchHandlerData(*code_item, 0);
643 uint32_t handlers_size = DecodeUnsignedLeb128(&ptr_);
644
645 if (!CheckListSize(try_items, try_items_size, sizeof(DexFile::TryItem), "try_items size")) {
646 return false;
647 }
648
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700649 if (UNLIKELY((handlers_size == 0) || (handlers_size >= 65536))) {
650 ErrorStringPrintf("Invalid handlers_size: %ud", handlers_size);
jeffhao10037c82012-01-23 15:06:23 -0800651 return false;
652 }
653
Elliott Hughesee0fa762012-03-26 17:12:41 -0700654 UniquePtr<uint32_t[]> handler_offsets(new uint32_t[handlers_size]);
655 if (!CheckAndGetHandlerOffsets(code_item, &handler_offsets[0], handlers_size)) {
jeffhao10037c82012-01-23 15:06:23 -0800656 return false;
657 }
658
659 uint32_t last_addr = 0;
660 while (try_items_size--) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700661 if (UNLIKELY(try_items->start_addr_ < last_addr)) {
662 ErrorStringPrintf("Out-of_order try_item with start_addr: %x", try_items->start_addr_);
jeffhao10037c82012-01-23 15:06:23 -0800663 return false;
664 }
665
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700666 if (UNLIKELY(try_items->start_addr_ >= insns_size)) {
667 ErrorStringPrintf("Invalid try_item start_addr: %x", try_items->start_addr_);
jeffhao10037c82012-01-23 15:06:23 -0800668 return false;
669 }
670
671 uint32_t i;
672 for (i = 0; i < handlers_size; i++) {
673 if (try_items->handler_off_ == handler_offsets[i]) {
674 break;
675 }
676 }
677
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700678 if (UNLIKELY(i == handlers_size)) {
679 ErrorStringPrintf("Bogus handler offset: %x", try_items->handler_off_);
jeffhao10037c82012-01-23 15:06:23 -0800680 return false;
681 }
682
683 last_addr = try_items->start_addr_ + try_items->insn_count_;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700684 if (UNLIKELY(last_addr > insns_size)) {
685 ErrorStringPrintf("Invalid try_item insn_count: %x", try_items->insn_count_);
jeffhao10037c82012-01-23 15:06:23 -0800686 return false;
687 }
688
689 try_items++;
690 }
691
692 return true;
693}
694
695bool DexFileVerifier::CheckIntraStringDataItem() {
696 uint32_t size = DecodeUnsignedLeb128(&ptr_);
jeffhaof6174e82012-01-31 16:14:17 -0800697 const byte* file_end = begin_ + size_;
jeffhao10037c82012-01-23 15:06:23 -0800698
699 for (uint32_t i = 0; i < size; i++) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700700 if (UNLIKELY(ptr_ >= file_end)) {
701 ErrorStringPrintf("String data would go beyond end-of-file");
jeffhao10037c82012-01-23 15:06:23 -0800702 return false;
703 }
704
705 uint8_t byte = *(ptr_++);
706
707 // Switch on the high 4 bits.
708 switch (byte >> 4) {
709 case 0x00:
710 // Special case of bit pattern 0xxx.
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700711 if (UNLIKELY(byte == 0)) {
712 ErrorStringPrintf("String data shorter than indicated utf16_size %x", size);
jeffhao10037c82012-01-23 15:06:23 -0800713 return false;
714 }
715 break;
716 case 0x01:
717 case 0x02:
718 case 0x03:
719 case 0x04:
720 case 0x05:
721 case 0x06:
722 case 0x07:
723 // No extra checks necessary for bit pattern 0xxx.
724 break;
725 case 0x08:
726 case 0x09:
727 case 0x0a:
728 case 0x0b:
729 case 0x0f:
730 // Illegal bit patterns 10xx or 1111.
731 // Note: 1111 is valid for normal UTF-8, but not here.
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700732 ErrorStringPrintf("Illegal start byte %x in string data", byte);
jeffhao10037c82012-01-23 15:06:23 -0800733 return false;
734 case 0x0c:
735 case 0x0d: {
736 // Bit pattern 110x has an additional byte.
737 uint8_t byte2 = *(ptr_++);
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700738 if (UNLIKELY((byte2 & 0xc0) != 0x80)) {
739 ErrorStringPrintf("Illegal continuation byte %x in string data", byte2);
jeffhao10037c82012-01-23 15:06:23 -0800740 return false;
741 }
742 uint16_t value = ((byte & 0x1f) << 6) | (byte2 & 0x3f);
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700743 if (UNLIKELY((value != 0) && (value < 0x80))) {
744 ErrorStringPrintf("Illegal representation for value %x in string data", value);
jeffhao10037c82012-01-23 15:06:23 -0800745 return false;
746 }
747 break;
748 }
749 case 0x0e: {
750 // Bit pattern 1110 has 2 additional bytes.
751 uint8_t byte2 = *(ptr_++);
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700752 if (UNLIKELY((byte2 & 0xc0) != 0x80)) {
753 ErrorStringPrintf("Illegal continuation byte %x in string data", byte2);
jeffhao10037c82012-01-23 15:06:23 -0800754 return false;
755 }
756 uint8_t byte3 = *(ptr_++);
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700757 if (UNLIKELY((byte3 & 0xc0) != 0x80)) {
758 ErrorStringPrintf("Illegal continuation byte %x in string data", byte3);
jeffhao10037c82012-01-23 15:06:23 -0800759 return false;
760 }
761 uint16_t value = ((byte & 0x0f) << 12) | ((byte2 & 0x3f) << 6) | (byte3 & 0x3f);
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700762 if (UNLIKELY(value < 0x800)) {
763 ErrorStringPrintf("Illegal representation for value %x in string data", value);
jeffhao10037c82012-01-23 15:06:23 -0800764 return false;
765 }
766 break;
767 }
768 }
769 }
770
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700771 if (UNLIKELY(*(ptr_++) != '\0')) {
772 ErrorStringPrintf("String longer than indicated size %x", size);
jeffhao10037c82012-01-23 15:06:23 -0800773 return false;
774 }
775
776 return true;
777}
778
779bool DexFileVerifier::CheckIntraDebugInfoItem() {
780 DecodeUnsignedLeb128(&ptr_);
781 uint32_t parameters_size = DecodeUnsignedLeb128(&ptr_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700782 if (UNLIKELY(parameters_size > 65536)) {
783 ErrorStringPrintf("Invalid parameters_size: %x", parameters_size);
jeffhao10037c82012-01-23 15:06:23 -0800784 return false;
785 }
786
787 for (uint32_t j = 0; j < parameters_size; j++) {
788 uint32_t parameter_name = DecodeUnsignedLeb128(&ptr_);
789 if (parameter_name != 0) {
790 parameter_name--;
791 if (!CheckIndex(parameter_name, header_->string_ids_size_, "debug_info_item parameter_name")) {
792 return false;
793 }
794 }
795 }
796
797 while (true) {
798 uint8_t opcode = *(ptr_++);
799 switch (opcode) {
800 case DexFile::DBG_END_SEQUENCE: {
801 return true;
802 }
803 case DexFile::DBG_ADVANCE_PC: {
804 DecodeUnsignedLeb128(&ptr_);
805 break;
806 }
807 case DexFile::DBG_ADVANCE_LINE: {
808 DecodeSignedLeb128(&ptr_);
809 break;
810 }
811 case DexFile::DBG_START_LOCAL: {
812 uint32_t reg_num = DecodeUnsignedLeb128(&ptr_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700813 if (UNLIKELY(reg_num >= 65536)) {
814 ErrorStringPrintf("Bad reg_num for opcode %x", opcode);
jeffhao10037c82012-01-23 15:06:23 -0800815 return false;
816 }
817 uint32_t name_idx = DecodeUnsignedLeb128(&ptr_);
818 if (name_idx != 0) {
819 name_idx--;
820 if (!CheckIndex(name_idx, header_->string_ids_size_, "DBG_START_LOCAL name_idx")) {
821 return false;
822 }
823 }
824 uint32_t type_idx = DecodeUnsignedLeb128(&ptr_);
825 if (type_idx != 0) {
826 type_idx--;
827 if (!CheckIndex(type_idx, header_->string_ids_size_, "DBG_START_LOCAL type_idx")) {
828 return false;
829 }
830 }
831 break;
832 }
833 case DexFile::DBG_END_LOCAL:
834 case DexFile::DBG_RESTART_LOCAL: {
835 uint32_t reg_num = DecodeUnsignedLeb128(&ptr_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700836 if (UNLIKELY(reg_num >= 65536)) {
837 ErrorStringPrintf("Bad reg_num for opcode %x", opcode);
jeffhao10037c82012-01-23 15:06:23 -0800838 return false;
839 }
840 break;
841 }
842 case DexFile::DBG_START_LOCAL_EXTENDED: {
843 uint32_t reg_num = DecodeUnsignedLeb128(&ptr_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700844 if (UNLIKELY(reg_num >= 65536)) {
845 ErrorStringPrintf("Bad reg_num for opcode %x", opcode);
jeffhao10037c82012-01-23 15:06:23 -0800846 return false;
847 }
848 uint32_t name_idx = DecodeUnsignedLeb128(&ptr_);
849 if (name_idx != 0) {
850 name_idx--;
851 if (!CheckIndex(name_idx, header_->string_ids_size_, "DBG_START_LOCAL_EXTENDED name_idx")) {
852 return false;
853 }
854 }
855 uint32_t type_idx = DecodeUnsignedLeb128(&ptr_);
856 if (type_idx != 0) {
857 type_idx--;
858 if (!CheckIndex(type_idx, header_->string_ids_size_, "DBG_START_LOCAL_EXTENDED type_idx")) {
859 return false;
860 }
861 }
862 uint32_t sig_idx = DecodeUnsignedLeb128(&ptr_);
863 if (sig_idx != 0) {
864 sig_idx--;
865 if (!CheckIndex(sig_idx, header_->string_ids_size_, "DBG_START_LOCAL_EXTENDED sig_idx")) {
866 return false;
867 }
868 }
869 break;
870 }
871 case DexFile::DBG_SET_FILE: {
872 uint32_t name_idx = DecodeUnsignedLeb128(&ptr_);
873 if (name_idx != 0) {
874 name_idx--;
875 if (!CheckIndex(name_idx, header_->string_ids_size_, "DBG_SET_FILE name_idx")) {
876 return false;
877 }
878 }
879 break;
880 }
881 }
882 }
883}
884
885bool DexFileVerifier::CheckIntraAnnotationItem() {
886 if (!CheckPointerRange(ptr_, ptr_ + 1, "annotation visibility")) {
887 return false;
888 }
889
890 // Check visibility
891 switch (*(ptr_++)) {
892 case DexFile::kDexVisibilityBuild:
893 case DexFile::kDexVisibilityRuntime:
894 case DexFile::kDexVisibilitySystem:
895 break;
896 default:
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700897 ErrorStringPrintf("Bad annotation visibility: %x", *ptr_);
jeffhao10037c82012-01-23 15:06:23 -0800898 return false;
899 }
900
901 if (!CheckEncodedAnnotation()) {
902 return false;
903 }
904
905 return true;
906}
907
908bool DexFileVerifier::CheckIntraAnnotationsDirectoryItem() {
909 const DexFile::AnnotationsDirectoryItem* item =
910 reinterpret_cast<const DexFile::AnnotationsDirectoryItem*>(ptr_);
911 if (!CheckPointerRange(item, item + 1, "annotations_directory")) {
912 return false;
913 }
914
915 // Field annotations follow immediately after the annotations directory.
916 const DexFile::FieldAnnotationsItem* field_item =
917 reinterpret_cast<const DexFile::FieldAnnotationsItem*>(item + 1);
918 uint32_t field_count = item->fields_size_;
919 if (!CheckListSize(field_item, field_count, sizeof(DexFile::FieldAnnotationsItem), "field_annotations list")) {
920 return false;
921 }
922
923 uint32_t last_idx = 0;
924 for (uint32_t i = 0; i < field_count; i++) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700925 if (UNLIKELY(last_idx >= field_item->field_idx_ && i != 0)) {
926 ErrorStringPrintf("Out-of-order field_idx for annotation: %x then %x", last_idx, field_item->field_idx_);
jeffhao10037c82012-01-23 15:06:23 -0800927 return false;
928 }
929 last_idx = field_item->field_idx_;
930 field_item++;
931 }
932
933 // Method annotations follow immediately after field annotations.
934 const DexFile::MethodAnnotationsItem* method_item =
935 reinterpret_cast<const DexFile::MethodAnnotationsItem*>(field_item);
936 uint32_t method_count = item->methods_size_;
937 if (!CheckListSize(method_item, method_count, sizeof(DexFile::MethodAnnotationsItem), "method_annotations list")) {
938 return false;
939 }
940
941 last_idx = 0;
942 for (uint32_t i = 0; i < method_count; i++) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700943 if (UNLIKELY(last_idx >= method_item->method_idx_ && i != 0)) {
944 ErrorStringPrintf("Out-of-order method_idx for annotation: %x then %x",
945 last_idx, method_item->method_idx_);
jeffhao10037c82012-01-23 15:06:23 -0800946 return false;
947 }
948 last_idx = method_item->method_idx_;
949 method_item++;
950 }
951
952 // Parameter annotations follow immediately after method annotations.
953 const DexFile::ParameterAnnotationsItem* parameter_item =
954 reinterpret_cast<const DexFile::ParameterAnnotationsItem*>(method_item);
955 uint32_t parameter_count = item->parameters_size_;
Dragos Sbirlea2b87ddf2013-05-28 14:14:12 -0700956 if (!CheckListSize(parameter_item, parameter_count, sizeof(DexFile::ParameterAnnotationsItem),
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700957 "parameter_annotations list")) {
jeffhao10037c82012-01-23 15:06:23 -0800958 return false;
959 }
960
961 last_idx = 0;
962 for (uint32_t i = 0; i < parameter_count; i++) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700963 if (UNLIKELY(last_idx >= parameter_item->method_idx_ && i != 0)) {
964 ErrorStringPrintf("Out-of-order method_idx for annotation: %x then %x",
965 last_idx, parameter_item->method_idx_);
jeffhao10037c82012-01-23 15:06:23 -0800966 return false;
967 }
968 last_idx = parameter_item->method_idx_;
969 parameter_item++;
970 }
971
972 // Return a pointer to the end of the annotations.
973 ptr_ = reinterpret_cast<const byte*>(parameter_item);
974 return true;
975}
976
977bool DexFileVerifier::CheckIntraSectionIterate(uint32_t offset, uint32_t count, uint16_t type) {
978 // Get the right alignment mask for the type of section.
979 uint32_t alignment_mask;
980 switch (type) {
981 case DexFile::kDexTypeClassDataItem:
982 case DexFile::kDexTypeStringDataItem:
983 case DexFile::kDexTypeDebugInfoItem:
984 case DexFile::kDexTypeAnnotationItem:
985 case DexFile::kDexTypeEncodedArrayItem:
986 alignment_mask = sizeof(uint8_t) - 1;
987 break;
988 default:
989 alignment_mask = sizeof(uint32_t) - 1;
990 break;
991 }
992
993 // Iterate through the items in the section.
994 for (uint32_t i = 0; i < count; i++) {
995 uint32_t aligned_offset = (offset + alignment_mask) & ~alignment_mask;
996
997 // Check the padding between items.
998 if (!CheckPadding(offset, aligned_offset)) {
999 return false;
1000 }
1001
1002 // Check depending on the section type.
1003 switch (type) {
1004 case DexFile::kDexTypeStringIdItem: {
1005 if (!CheckPointerRange(ptr_, ptr_ + sizeof(DexFile::StringId), "string_ids")) {
1006 return false;
1007 }
1008 ptr_ += sizeof(DexFile::StringId);
1009 break;
1010 }
1011 case DexFile::kDexTypeTypeIdItem: {
1012 if (!CheckPointerRange(ptr_, ptr_ + sizeof(DexFile::TypeId), "type_ids")) {
1013 return false;
1014 }
1015 ptr_ += sizeof(DexFile::TypeId);
1016 break;
1017 }
1018 case DexFile::kDexTypeProtoIdItem: {
1019 if (!CheckPointerRange(ptr_, ptr_ + sizeof(DexFile::ProtoId), "proto_ids")) {
1020 return false;
1021 }
1022 ptr_ += sizeof(DexFile::ProtoId);
1023 break;
1024 }
1025 case DexFile::kDexTypeFieldIdItem: {
1026 if (!CheckPointerRange(ptr_, ptr_ + sizeof(DexFile::FieldId), "field_ids")) {
1027 return false;
1028 }
1029 ptr_ += sizeof(DexFile::FieldId);
1030 break;
1031 }
1032 case DexFile::kDexTypeMethodIdItem: {
1033 if (!CheckPointerRange(ptr_, ptr_ + sizeof(DexFile::MethodId), "method_ids")) {
1034 return false;
1035 }
1036 ptr_ += sizeof(DexFile::MethodId);
1037 break;
1038 }
1039 case DexFile::kDexTypeClassDefItem: {
1040 if (!CheckPointerRange(ptr_, ptr_ + sizeof(DexFile::ClassDef), "class_defs")) {
1041 return false;
1042 }
1043 ptr_ += sizeof(DexFile::ClassDef);
1044 break;
1045 }
1046 case DexFile::kDexTypeTypeList: {
1047 const DexFile::TypeList* list = reinterpret_cast<const DexFile::TypeList*>(ptr_);
1048 const DexFile::TypeItem* item = &list->GetTypeItem(0);
1049 uint32_t count = list->Size();
1050
1051 if (!CheckPointerRange(list, list + 1, "type_list") ||
1052 !CheckListSize(item, count, sizeof(DexFile::TypeItem), "type_list size")) {
1053 return false;
1054 }
1055 ptr_ = reinterpret_cast<const byte*>(item + count);
1056 break;
1057 }
1058 case DexFile::kDexTypeAnnotationSetRefList: {
1059 const DexFile::AnnotationSetRefList* list =
1060 reinterpret_cast<const DexFile::AnnotationSetRefList*>(ptr_);
1061 const DexFile::AnnotationSetRefItem* item = list->list_;
1062 uint32_t count = list->size_;
1063
1064 if (!CheckPointerRange(list, list + 1, "annotation_set_ref_list") ||
Dragos Sbirlea2b87ddf2013-05-28 14:14:12 -07001065 !CheckListSize(item, count, sizeof(DexFile::AnnotationSetRefItem),
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001066 "annotation_set_ref_list size")) {
jeffhao10037c82012-01-23 15:06:23 -08001067 return false;
1068 }
1069 ptr_ = reinterpret_cast<const byte*>(item + count);
1070 break;
1071 }
1072 case DexFile::kDexTypeAnnotationSetItem: {
1073 const DexFile::AnnotationSetItem* set =
1074 reinterpret_cast<const DexFile::AnnotationSetItem*>(ptr_);
1075 const uint32_t* item = set->entries_;
1076 uint32_t count = set->size_;
1077
1078 if (!CheckPointerRange(set, set + 1, "annotation_set_item") ||
1079 !CheckListSize(item, count, sizeof(uint32_t), "annotation_set_item size")) {
1080 return false;
1081 }
1082 ptr_ = reinterpret_cast<const byte*>(item + count);
1083 break;
1084 }
1085 case DexFile::kDexTypeClassDataItem: {
1086 if (!CheckIntraClassDataItem()) {
1087 return false;
1088 }
1089 break;
1090 }
1091 case DexFile::kDexTypeCodeItem: {
1092 if (!CheckIntraCodeItem()) {
1093 return false;
1094 }
1095 break;
1096 }
1097 case DexFile::kDexTypeStringDataItem: {
1098 if (!CheckIntraStringDataItem()) {
1099 return false;
1100 }
1101 break;
1102 }
1103 case DexFile::kDexTypeDebugInfoItem: {
1104 if (!CheckIntraDebugInfoItem()) {
1105 return false;
1106 }
1107 break;
1108 }
1109 case DexFile::kDexTypeAnnotationItem: {
1110 if (!CheckIntraAnnotationItem()) {
1111 return false;
1112 }
1113 break;
1114 }
1115 case DexFile::kDexTypeEncodedArrayItem: {
1116 if (!CheckEncodedArray()) {
1117 return false;
1118 }
1119 break;
1120 }
1121 case DexFile::kDexTypeAnnotationsDirectoryItem: {
1122 if (!CheckIntraAnnotationsDirectoryItem()) {
1123 return false;
1124 }
1125 break;
1126 }
1127 default:
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001128 ErrorStringPrintf("Unknown map item type %x", type);
jeffhao10037c82012-01-23 15:06:23 -08001129 return false;
1130 }
1131
1132 if (IsDataSectionType(type)) {
Elliott Hughesa0e18062012-04-13 15:59:59 -07001133 offset_to_type_map_.Put(aligned_offset, type);
jeffhao10037c82012-01-23 15:06:23 -08001134 }
1135
Ian Rogers30fab402012-01-23 15:43:46 -08001136 aligned_offset = reinterpret_cast<uint32_t>(ptr_) - reinterpret_cast<uint32_t>(begin_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001137 if (UNLIKELY(aligned_offset > size_)) {
1138 ErrorStringPrintf("Item %d at ends out of bounds", i);
jeffhao10037c82012-01-23 15:06:23 -08001139 return false;
1140 }
1141
1142 offset = aligned_offset;
1143 }
1144
1145 return true;
1146}
1147
1148bool DexFileVerifier::CheckIntraIdSection(uint32_t offset, uint32_t count, uint16_t type) {
1149 uint32_t expected_offset;
1150 uint32_t expected_size;
1151
1152 // Get the expected offset and size from the header.
1153 switch (type) {
1154 case DexFile::kDexTypeStringIdItem:
1155 expected_offset = header_->string_ids_off_;
1156 expected_size = header_->string_ids_size_;
1157 break;
1158 case DexFile::kDexTypeTypeIdItem:
1159 expected_offset = header_->type_ids_off_;
1160 expected_size = header_->type_ids_size_;
1161 break;
1162 case DexFile::kDexTypeProtoIdItem:
1163 expected_offset = header_->proto_ids_off_;
1164 expected_size = header_->proto_ids_size_;
1165 break;
1166 case DexFile::kDexTypeFieldIdItem:
1167 expected_offset = header_->field_ids_off_;
1168 expected_size = header_->field_ids_size_;
1169 break;
1170 case DexFile::kDexTypeMethodIdItem:
1171 expected_offset = header_->method_ids_off_;
1172 expected_size = header_->method_ids_size_;
1173 break;
1174 case DexFile::kDexTypeClassDefItem:
1175 expected_offset = header_->class_defs_off_;
1176 expected_size = header_->class_defs_size_;
1177 break;
1178 default:
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001179 ErrorStringPrintf("Bad type for id section: %x", type);
jeffhao10037c82012-01-23 15:06:23 -08001180 return false;
1181 }
1182
1183 // Check that the offset and size are what were expected from the header.
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001184 if (UNLIKELY(offset != expected_offset)) {
1185 ErrorStringPrintf("Bad offset for section: got %x, expected %x", offset, expected_offset);
jeffhao10037c82012-01-23 15:06:23 -08001186 return false;
1187 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001188 if (UNLIKELY(count != expected_size)) {
1189 ErrorStringPrintf("Bad size for section: got %x, expected %x", count, expected_size);
jeffhao10037c82012-01-23 15:06:23 -08001190 return false;
1191 }
1192
1193 return CheckIntraSectionIterate(offset, count, type);
1194}
1195
1196bool DexFileVerifier::CheckIntraDataSection(uint32_t offset, uint32_t count, uint16_t type) {
1197 uint32_t data_start = header_->data_off_;
1198 uint32_t data_end = data_start + header_->data_size_;
1199
1200 // Sanity check the offset of the section.
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001201 if (UNLIKELY((offset < data_start) || (offset > data_end))) {
1202 ErrorStringPrintf("Bad offset for data subsection: %x", offset);
jeffhao10037c82012-01-23 15:06:23 -08001203 return false;
1204 }
1205
1206 if (!CheckIntraSectionIterate(offset, count, type)) {
1207 return false;
1208 }
1209
Ian Rogers30fab402012-01-23 15:43:46 -08001210 uint32_t next_offset = reinterpret_cast<uint32_t>(ptr_) - reinterpret_cast<uint32_t>(begin_);
jeffhao10037c82012-01-23 15:06:23 -08001211 if (next_offset > data_end) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001212 ErrorStringPrintf("Out-of-bounds end of data subsection: %x", next_offset);
jeffhao10037c82012-01-23 15:06:23 -08001213 return false;
1214 }
1215
1216 return true;
1217}
1218
1219bool DexFileVerifier::CheckIntraSection() {
Ian Rogers30fab402012-01-23 15:43:46 -08001220 const DexFile::MapList* map = reinterpret_cast<const DexFile::MapList*>(begin_ + header_->map_off_);
jeffhao10037c82012-01-23 15:06:23 -08001221 const DexFile::MapItem* item = map->list_;
1222
1223 uint32_t count = map->size_;
1224 uint32_t offset = 0;
Ian Rogers30fab402012-01-23 15:43:46 -08001225 ptr_ = begin_;
jeffhao10037c82012-01-23 15:06:23 -08001226
1227 // Check the items listed in the map.
1228 while (count--) {
1229 uint32_t section_offset = item->offset_;
1230 uint32_t section_count = item->size_;
1231 uint16_t type = item->type_;
1232
1233 // Check for padding and overlap between items.
1234 if (!CheckPadding(offset, section_offset)) {
1235 return false;
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001236 } else if (UNLIKELY(offset > section_offset)) {
1237 ErrorStringPrintf("Section overlap or out-of-order map: %x, %x", offset, section_offset);
jeffhao10037c82012-01-23 15:06:23 -08001238 return false;
1239 }
1240
1241 // Check each item based on its type.
1242 switch (type) {
1243 case DexFile::kDexTypeHeaderItem:
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001244 if (UNLIKELY(section_count != 1)) {
1245 ErrorStringPrintf("Multiple header items");
jeffhao10037c82012-01-23 15:06:23 -08001246 return false;
1247 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001248 if (UNLIKELY(section_offset != 0)) {
1249 ErrorStringPrintf("Header at %x, not at start of file", section_offset);
jeffhao10037c82012-01-23 15:06:23 -08001250 return false;
1251 }
Ian Rogers30fab402012-01-23 15:43:46 -08001252 ptr_ = begin_ + header_->header_size_;
jeffhao10037c82012-01-23 15:06:23 -08001253 offset = header_->header_size_;
1254 break;
1255 case DexFile::kDexTypeStringIdItem:
1256 case DexFile::kDexTypeTypeIdItem:
1257 case DexFile::kDexTypeProtoIdItem:
1258 case DexFile::kDexTypeFieldIdItem:
1259 case DexFile::kDexTypeMethodIdItem:
1260 case DexFile::kDexTypeClassDefItem:
1261 if (!CheckIntraIdSection(section_offset, section_count, type)) {
1262 return false;
1263 }
Ian Rogers30fab402012-01-23 15:43:46 -08001264 offset = reinterpret_cast<uint32_t>(ptr_) - reinterpret_cast<uint32_t>(begin_);
jeffhao10037c82012-01-23 15:06:23 -08001265 break;
1266 case DexFile::kDexTypeMapList:
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001267 if (UNLIKELY(section_count != 1)) {
1268 ErrorStringPrintf("Multiple map list items");
jeffhao10037c82012-01-23 15:06:23 -08001269 return false;
1270 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001271 if (UNLIKELY(section_offset != header_->map_off_)) {
1272 ErrorStringPrintf("Map not at header-defined offset: %x, expected %x",
1273 section_offset, header_->map_off_);
jeffhao10037c82012-01-23 15:06:23 -08001274 return false;
1275 }
1276 ptr_ += sizeof(uint32_t) + (map->size_ * sizeof(DexFile::MapItem));
1277 offset = section_offset + sizeof(uint32_t) + (map->size_ * sizeof(DexFile::MapItem));
1278 break;
1279 case DexFile::kDexTypeTypeList:
1280 case DexFile::kDexTypeAnnotationSetRefList:
1281 case DexFile::kDexTypeAnnotationSetItem:
1282 case DexFile::kDexTypeClassDataItem:
1283 case DexFile::kDexTypeCodeItem:
1284 case DexFile::kDexTypeStringDataItem:
1285 case DexFile::kDexTypeDebugInfoItem:
1286 case DexFile::kDexTypeAnnotationItem:
1287 case DexFile::kDexTypeEncodedArrayItem:
1288 case DexFile::kDexTypeAnnotationsDirectoryItem:
1289 if (!CheckIntraDataSection(section_offset, section_count, type)) {
1290 return false;
1291 }
Ian Rogers30fab402012-01-23 15:43:46 -08001292 offset = reinterpret_cast<uint32_t>(ptr_) - reinterpret_cast<uint32_t>(begin_);
jeffhao10037c82012-01-23 15:06:23 -08001293 break;
1294 default:
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001295 ErrorStringPrintf("Unknown map item type %x", type);
jeffhao10037c82012-01-23 15:06:23 -08001296 return false;
1297 }
1298
1299 item++;
1300 }
1301
1302 return true;
1303}
1304
1305bool DexFileVerifier::CheckOffsetToTypeMap(uint32_t offset, uint16_t type) {
Mathieu Chartier02e25112013-08-14 16:14:24 -07001306 auto it = offset_to_type_map_.find(offset);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001307 if (UNLIKELY(it == offset_to_type_map_.end())) {
1308 ErrorStringPrintf("No data map entry found @ %x; expected %x", offset, type);
jeffhao10037c82012-01-23 15:06:23 -08001309 return false;
1310 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001311 if (UNLIKELY(it->second != type)) {
1312 ErrorStringPrintf("Unexpected data map entry @ %x; expected %x, found %x",
1313 offset, type, it->second);
jeffhao10037c82012-01-23 15:06:23 -08001314 return false;
1315 }
1316 return true;
1317}
1318
1319uint16_t DexFileVerifier::FindFirstClassDataDefiner(const byte* ptr) const {
1320 ClassDataItemIterator it(*dex_file_, ptr);
1321
1322 if (it.HasNextStaticField() || it.HasNextInstanceField()) {
1323 const DexFile::FieldId& field = dex_file_->GetFieldId(it.GetMemberIndex());
1324 return field.class_idx_;
1325 }
1326
1327 if (it.HasNextDirectMethod() || it.HasNextVirtualMethod()) {
1328 const DexFile::MethodId& method = dex_file_->GetMethodId(it.GetMemberIndex());
1329 return method.class_idx_;
1330 }
1331
1332 return DexFile::kDexNoIndex16;
1333}
1334
1335uint16_t DexFileVerifier::FindFirstAnnotationsDirectoryDefiner(const byte* ptr) const {
1336 const DexFile::AnnotationsDirectoryItem* item =
1337 reinterpret_cast<const DexFile::AnnotationsDirectoryItem*>(ptr);
1338 if (item->fields_size_ != 0) {
1339 DexFile::FieldAnnotationsItem* field_items = (DexFile::FieldAnnotationsItem*) (item + 1);
1340 const DexFile::FieldId& field = dex_file_->GetFieldId(field_items[0].field_idx_);
1341 return field.class_idx_;
1342 }
1343
1344 if (item->methods_size_ != 0) {
1345 DexFile::MethodAnnotationsItem* method_items = (DexFile::MethodAnnotationsItem*) (item + 1);
1346 const DexFile::MethodId& method = dex_file_->GetMethodId(method_items[0].method_idx_);
1347 return method.class_idx_;
1348 }
1349
1350 if (item->parameters_size_ != 0) {
1351 DexFile::ParameterAnnotationsItem* parameter_items = (DexFile::ParameterAnnotationsItem*) (item + 1);
1352 const DexFile::MethodId& method = dex_file_->GetMethodId(parameter_items[0].method_idx_);
1353 return method.class_idx_;
1354 }
1355
1356 return DexFile::kDexNoIndex16;
1357}
1358
1359bool DexFileVerifier::CheckInterStringIdItem() {
1360 const DexFile::StringId* item = reinterpret_cast<const DexFile::StringId*>(ptr_);
1361
1362 // Check the map to make sure it has the right offset->type.
1363 if (!CheckOffsetToTypeMap(item->string_data_off_, DexFile::kDexTypeStringDataItem)) {
1364 return false;
1365 }
1366
1367 // Check ordering between items.
1368 if (previous_item_ != NULL) {
1369 const DexFile::StringId* prev_item = reinterpret_cast<const DexFile::StringId*>(previous_item_);
1370 const char* prev_str = dex_file_->GetStringData(*prev_item);
1371 const char* str = dex_file_->GetStringData(*item);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001372 if (UNLIKELY(CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(prev_str, str) >= 0)) {
1373 ErrorStringPrintf("Out-of-order string_ids: '%s' then '%s'", prev_str, str);
jeffhao10037c82012-01-23 15:06:23 -08001374 return false;
1375 }
1376 }
1377
1378 ptr_ += sizeof(DexFile::StringId);
1379 return true;
1380}
1381
1382bool DexFileVerifier::CheckInterTypeIdItem() {
1383 const DexFile::TypeId* item = reinterpret_cast<const DexFile::TypeId*>(ptr_);
1384 const char* descriptor = dex_file_->StringDataByIdx(item->descriptor_idx_);
1385
1386 // Check that the descriptor is a valid type.
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001387 if (UNLIKELY(!IsValidDescriptor(descriptor))) {
1388 ErrorStringPrintf("Invalid type descriptor: '%s'", descriptor);
jeffhao10037c82012-01-23 15:06:23 -08001389 return false;
1390 }
1391
1392 // Check ordering between items.
1393 if (previous_item_ != NULL) {
1394 const DexFile::TypeId* prev_item = reinterpret_cast<const DexFile::TypeId*>(previous_item_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001395 if (UNLIKELY(prev_item->descriptor_idx_ >= item->descriptor_idx_)) {
1396 ErrorStringPrintf("Out-of-order type_ids: %x then %x",
1397 prev_item->descriptor_idx_, item->descriptor_idx_);
jeffhao10037c82012-01-23 15:06:23 -08001398 return false;
1399 }
1400 }
1401
1402 ptr_ += sizeof(DexFile::TypeId);
1403 return true;
1404}
1405
1406bool DexFileVerifier::CheckInterProtoIdItem() {
1407 const DexFile::ProtoId* item = reinterpret_cast<const DexFile::ProtoId*>(ptr_);
1408 const char* shorty = dex_file_->StringDataByIdx(item->shorty_idx_);
1409 if (item->parameters_off_ != 0 &&
1410 !CheckOffsetToTypeMap(item->parameters_off_, DexFile::kDexTypeTypeList)) {
1411 return false;
1412 }
1413
1414 // Check the return type and advance the shorty.
1415 if (!CheckShortyDescriptorMatch(*shorty, dex_file_->StringByTypeIdx(item->return_type_idx_), true)) {
1416 return false;
1417 }
1418 shorty++;
1419
1420 DexFileParameterIterator it(*dex_file_, *item);
1421 while (it.HasNext() && *shorty != '\0') {
1422 const char* descriptor = it.GetDescriptor();
1423 if (!CheckShortyDescriptorMatch(*shorty, descriptor, false)) {
1424 return false;
1425 }
1426 it.Next();
1427 shorty++;
1428 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001429 if (UNLIKELY(it.HasNext() || *shorty != '\0')) {
1430 ErrorStringPrintf("Mismatched length for parameters and shorty");
jeffhao10037c82012-01-23 15:06:23 -08001431 return false;
1432 }
1433
1434 // Check ordering between items. This relies on type_ids being in order.
1435 if (previous_item_ != NULL) {
1436 const DexFile::ProtoId* prev = reinterpret_cast<const DexFile::ProtoId*>(previous_item_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001437 if (UNLIKELY(prev->return_type_idx_ > item->return_type_idx_)) {
1438 ErrorStringPrintf("Out-of-order proto_id return types");
jeffhao10037c82012-01-23 15:06:23 -08001439 return false;
1440 } else if (prev->return_type_idx_ == item->return_type_idx_) {
1441 DexFileParameterIterator curr_it(*dex_file_, *item);
1442 DexFileParameterIterator prev_it(*dex_file_, *prev);
1443
1444 while (curr_it.HasNext() && prev_it.HasNext()) {
1445 uint16_t prev_idx = prev_it.GetTypeIdx();
1446 uint16_t curr_idx = curr_it.GetTypeIdx();
1447 if (prev_idx == DexFile::kDexNoIndex16) {
1448 break;
1449 }
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001450 if (UNLIKELY(curr_idx == DexFile::kDexNoIndex16)) {
1451 ErrorStringPrintf("Out-of-order proto_id arguments");
jeffhao10037c82012-01-23 15:06:23 -08001452 return false;
1453 }
1454
1455 if (prev_idx < curr_idx) {
1456 break;
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001457 } else if (UNLIKELY(prev_idx > curr_idx)) {
1458 ErrorStringPrintf("Out-of-order proto_id arguments");
jeffhao10037c82012-01-23 15:06:23 -08001459 return false;
1460 }
1461
1462 prev_it.Next();
1463 curr_it.Next();
1464 }
1465 }
1466 }
1467
1468 ptr_ += sizeof(DexFile::ProtoId);
1469 return true;
1470}
1471
1472bool DexFileVerifier::CheckInterFieldIdItem() {
1473 const DexFile::FieldId* item = reinterpret_cast<const DexFile::FieldId*>(ptr_);
1474
1475 // Check that the class descriptor is valid.
1476 const char* descriptor = dex_file_->StringByTypeIdx(item->class_idx_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001477 if (UNLIKELY(!IsValidDescriptor(descriptor) || descriptor[0] != 'L')) {
1478 ErrorStringPrintf("Invalid descriptor for class_idx: '%s'", descriptor);
jeffhao10037c82012-01-23 15:06:23 -08001479 return false;
1480 }
1481
1482 // Check that the type descriptor is a valid field name.
1483 descriptor = dex_file_->StringByTypeIdx(item->type_idx_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001484 if (UNLIKELY(!IsValidDescriptor(descriptor) || descriptor[0] == 'V')) {
1485 ErrorStringPrintf("Invalid descriptor for type_idx: '%s'", descriptor);
jeffhao10037c82012-01-23 15:06:23 -08001486 return false;
1487 }
1488
1489 // Check that the name is valid.
1490 descriptor = dex_file_->StringDataByIdx(item->name_idx_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001491 if (UNLIKELY(!IsValidMemberName(descriptor))) {
1492 ErrorStringPrintf("Invalid field name: '%s'", descriptor);
jeffhao10037c82012-01-23 15:06:23 -08001493 return false;
1494 }
1495
1496 // Check ordering between items. This relies on the other sections being in order.
1497 if (previous_item_ != NULL) {
1498 const DexFile::FieldId* prev_item = reinterpret_cast<const DexFile::FieldId*>(previous_item_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001499 if (UNLIKELY(prev_item->class_idx_ > item->class_idx_)) {
1500 ErrorStringPrintf("Out-of-order field_ids");
jeffhao10037c82012-01-23 15:06:23 -08001501 return false;
1502 } else if (prev_item->class_idx_ == item->class_idx_) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001503 if (UNLIKELY(prev_item->name_idx_ > item->name_idx_)) {
1504 ErrorStringPrintf("Out-of-order field_ids");
jeffhao10037c82012-01-23 15:06:23 -08001505 return false;
1506 } else if (prev_item->name_idx_ == item->name_idx_) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001507 if (UNLIKELY(prev_item->type_idx_ >= item->type_idx_)) {
1508 ErrorStringPrintf("Out-of-order field_ids");
jeffhao10037c82012-01-23 15:06:23 -08001509 return false;
1510 }
1511 }
1512 }
1513 }
1514
1515 ptr_ += sizeof(DexFile::FieldId);
1516 return true;
1517}
1518
1519bool DexFileVerifier::CheckInterMethodIdItem() {
1520 const DexFile::MethodId* item = reinterpret_cast<const DexFile::MethodId*>(ptr_);
1521
1522 // Check that the class descriptor is a valid reference name.
1523 const char* descriptor = dex_file_->StringByTypeIdx(item->class_idx_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001524 if (UNLIKELY(!IsValidDescriptor(descriptor) || (descriptor[0] != 'L' && descriptor[0] != '['))) {
1525 ErrorStringPrintf("Invalid descriptor for class_idx: '%s'", descriptor);
jeffhao10037c82012-01-23 15:06:23 -08001526 return false;
1527 }
1528
1529 // Check that the name is valid.
1530 descriptor = dex_file_->StringDataByIdx(item->name_idx_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001531 if (UNLIKELY(!IsValidMemberName(descriptor))) {
1532 ErrorStringPrintf("Invalid method name: '%s'", descriptor);
jeffhao10037c82012-01-23 15:06:23 -08001533 return false;
1534 }
1535
1536 // Check ordering between items. This relies on the other sections being in order.
1537 if (previous_item_ != NULL) {
1538 const DexFile::MethodId* prev_item = reinterpret_cast<const DexFile::MethodId*>(previous_item_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001539 if (UNLIKELY(prev_item->class_idx_ > item->class_idx_)) {
1540 ErrorStringPrintf("Out-of-order method_ids");
jeffhao10037c82012-01-23 15:06:23 -08001541 return false;
1542 } else if (prev_item->class_idx_ == item->class_idx_) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001543 if (UNLIKELY(prev_item->name_idx_ > item->name_idx_)) {
1544 ErrorStringPrintf("Out-of-order method_ids");
jeffhao10037c82012-01-23 15:06:23 -08001545 return false;
1546 } else if (prev_item->name_idx_ == item->name_idx_) {
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001547 if (UNLIKELY(prev_item->proto_idx_ >= item->proto_idx_)) {
1548 ErrorStringPrintf("Out-of-order method_ids");
jeffhao10037c82012-01-23 15:06:23 -08001549 return false;
1550 }
1551 }
1552 }
1553 }
1554
1555 ptr_ += sizeof(DexFile::MethodId);
1556 return true;
1557}
1558
1559bool DexFileVerifier::CheckInterClassDefItem() {
1560 const DexFile::ClassDef* item = reinterpret_cast<const DexFile::ClassDef*>(ptr_);
1561 uint32_t class_idx = item->class_idx_;
1562 const char* descriptor = dex_file_->StringByTypeIdx(class_idx);
1563
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001564 if (UNLIKELY(!IsValidDescriptor(descriptor) || descriptor[0] != 'L')) {
1565 ErrorStringPrintf("Invalid class descriptor: '%s'", descriptor);
jeffhao10037c82012-01-23 15:06:23 -08001566 return false;
1567 }
1568
1569 if (item->interfaces_off_ != 0 &&
1570 !CheckOffsetToTypeMap(item->interfaces_off_, DexFile::kDexTypeTypeList)) {
1571 return false;
1572 }
1573 if (item->annotations_off_ != 0 &&
1574 !CheckOffsetToTypeMap(item->annotations_off_, DexFile::kDexTypeAnnotationsDirectoryItem)) {
1575 return false;
1576 }
1577 if (item->class_data_off_ != 0 &&
1578 !CheckOffsetToTypeMap(item->class_data_off_, DexFile::kDexTypeClassDataItem)) {
1579 return false;
1580 }
1581 if (item->static_values_off_ != 0 &&
1582 !CheckOffsetToTypeMap(item->static_values_off_, DexFile::kDexTypeEncodedArrayItem)) {
1583 return false;
1584 }
1585
1586 if (item->superclass_idx_ != DexFile::kDexNoIndex16) {
1587 descriptor = dex_file_->StringByTypeIdx(item->superclass_idx_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001588 if (UNLIKELY(!IsValidDescriptor(descriptor) || descriptor[0] != 'L')) {
1589 ErrorStringPrintf("Invalid superclass: '%s'", descriptor);
jeffhao10037c82012-01-23 15:06:23 -08001590 return false;
1591 }
1592 }
1593
1594 const DexFile::TypeList* interfaces = dex_file_->GetInterfacesList(*item);
1595 if (interfaces != NULL) {
1596 uint32_t size = interfaces->Size();
1597
1598 // Ensure that all interfaces refer to classes (not arrays or primitives).
1599 for (uint32_t i = 0; i < size; i++) {
1600 descriptor = dex_file_->StringByTypeIdx(interfaces->GetTypeItem(i).type_idx_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001601 if (UNLIKELY(!IsValidDescriptor(descriptor) || descriptor[0] != 'L')) {
1602 ErrorStringPrintf("Invalid interface: '%s'", descriptor);
jeffhao10037c82012-01-23 15:06:23 -08001603 return false;
1604 }
1605 }
1606
1607 /*
1608 * Ensure that there are no duplicates. This is an O(N^2) test, but in
1609 * practice the number of interfaces implemented by any given class is low.
1610 */
1611 for (uint32_t i = 1; i < size; i++) {
1612 uint32_t idx1 = interfaces->GetTypeItem(i).type_idx_;
1613 for (uint32_t j =0; j < i; j++) {
1614 uint32_t idx2 = interfaces->GetTypeItem(j).type_idx_;
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001615 if (UNLIKELY(idx1 == idx2)) {
1616 ErrorStringPrintf("Duplicate interface: '%s'", dex_file_->StringByTypeIdx(idx1));
jeffhao10037c82012-01-23 15:06:23 -08001617 return false;
1618 }
1619 }
1620 }
1621 }
1622
1623 // Check that references in class_data_item are to the right class.
1624 if (item->class_data_off_ != 0) {
Ian Rogers30fab402012-01-23 15:43:46 -08001625 const byte* data = begin_ + item->class_data_off_;
jeffhao10037c82012-01-23 15:06:23 -08001626 uint16_t data_definer = FindFirstClassDataDefiner(data);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001627 if (UNLIKELY((data_definer != item->class_idx_) && (data_definer != DexFile::kDexNoIndex16))) {
1628 ErrorStringPrintf("Invalid class_data_item");
jeffhao10037c82012-01-23 15:06:23 -08001629 return false;
1630 }
1631 }
1632
1633 // Check that references in annotations_directory_item are to right class.
1634 if (item->annotations_off_ != 0) {
Ian Rogers30fab402012-01-23 15:43:46 -08001635 const byte* data = begin_ + item->annotations_off_;
jeffhao10037c82012-01-23 15:06:23 -08001636 uint16_t annotations_definer = FindFirstAnnotationsDirectoryDefiner(data);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001637 if (UNLIKELY((annotations_definer != item->class_idx_) &&
1638 (annotations_definer != DexFile::kDexNoIndex16))) {
1639 ErrorStringPrintf("Invalid annotations_directory_item");
jeffhao10037c82012-01-23 15:06:23 -08001640 return false;
1641 }
1642 }
1643
1644 ptr_ += sizeof(DexFile::ClassDef);
1645 return true;
1646}
1647
1648bool DexFileVerifier::CheckInterAnnotationSetRefList() {
1649 const DexFile::AnnotationSetRefList* list =
1650 reinterpret_cast<const DexFile::AnnotationSetRefList*>(ptr_);
1651 const DexFile::AnnotationSetRefItem* item = list->list_;
1652 uint32_t count = list->size_;
1653
1654 while (count--) {
1655 if (item->annotations_off_ != 0 &&
1656 !CheckOffsetToTypeMap(item->annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
1657 return false;
1658 }
1659 item++;
1660 }
1661
1662 ptr_ = reinterpret_cast<const byte*>(item);
1663 return true;
1664}
1665
1666bool DexFileVerifier::CheckInterAnnotationSetItem() {
1667 const DexFile::AnnotationSetItem* set = reinterpret_cast<const DexFile::AnnotationSetItem*>(ptr_);
1668 const uint32_t* offsets = set->entries_;
1669 uint32_t count = set->size_;
1670 uint32_t last_idx = 0;
1671
1672 for (uint32_t i = 0; i < count; i++) {
1673 if (*offsets != 0 && !CheckOffsetToTypeMap(*offsets, DexFile::kDexTypeAnnotationItem)) {
1674 return false;
1675 }
1676
1677 // Get the annotation from the offset and the type index for the annotation.
1678 const DexFile::AnnotationItem* annotation =
Ian Rogers30fab402012-01-23 15:43:46 -08001679 reinterpret_cast<const DexFile::AnnotationItem*>(begin_ + *offsets);
jeffhao10037c82012-01-23 15:06:23 -08001680 const uint8_t* data = annotation->annotation_;
1681 uint32_t idx = DecodeUnsignedLeb128(&data);
1682
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001683 if (UNLIKELY(last_idx >= idx && i != 0)) {
1684 ErrorStringPrintf("Out-of-order entry types: %x then %x", last_idx, idx);
jeffhao10037c82012-01-23 15:06:23 -08001685 return false;
1686 }
1687
1688 last_idx = idx;
1689 offsets++;
1690 }
1691
1692 ptr_ = reinterpret_cast<const byte*>(offsets);
1693 return true;
1694}
1695
1696bool DexFileVerifier::CheckInterClassDataItem() {
1697 ClassDataItemIterator it(*dex_file_, ptr_);
1698 uint16_t defining_class = FindFirstClassDataDefiner(ptr_);
1699
1700 for (; it.HasNextStaticField() || it.HasNextInstanceField(); it.Next()) {
1701 const DexFile::FieldId& field = dex_file_->GetFieldId(it.GetMemberIndex());
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001702 if (UNLIKELY(field.class_idx_ != defining_class)) {
1703 ErrorStringPrintf("Mismatched defining class for class_data_item field");
jeffhao10037c82012-01-23 15:06:23 -08001704 return false;
1705 }
1706 }
1707 for (; it.HasNextDirectMethod() || it.HasNextVirtualMethod(); it.Next()) {
1708 uint32_t code_off = it.GetMethodCodeItemOffset();
1709 if (code_off != 0 && !CheckOffsetToTypeMap(code_off, DexFile::kDexTypeCodeItem)) {
1710 return false;
1711 }
1712 const DexFile::MethodId& method = dex_file_->GetMethodId(it.GetMemberIndex());
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001713 if (UNLIKELY(method.class_idx_ != defining_class)) {
1714 ErrorStringPrintf("Mismatched defining class for class_data_item method");
jeffhao10037c82012-01-23 15:06:23 -08001715 return false;
1716 }
1717 }
1718
1719 ptr_ = it.EndDataPointer();
1720 return true;
1721}
1722
1723bool DexFileVerifier::CheckInterAnnotationsDirectoryItem() {
1724 const DexFile::AnnotationsDirectoryItem* item =
1725 reinterpret_cast<const DexFile::AnnotationsDirectoryItem*>(ptr_);
1726 uint16_t defining_class = FindFirstAnnotationsDirectoryDefiner(ptr_);
1727
1728 if (item->class_annotations_off_ != 0 &&
1729 !CheckOffsetToTypeMap(item->class_annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
1730 return false;
1731 }
1732
1733 // Field annotations follow immediately after the annotations directory.
1734 const DexFile::FieldAnnotationsItem* field_item =
1735 reinterpret_cast<const DexFile::FieldAnnotationsItem*>(item + 1);
1736 uint32_t field_count = item->fields_size_;
1737 for (uint32_t i = 0; i < field_count; i++) {
1738 const DexFile::FieldId& field = dex_file_->GetFieldId(field_item->field_idx_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001739 if (UNLIKELY(field.class_idx_ != defining_class)) {
1740 ErrorStringPrintf("Mismatched defining class for field_annotation");
jeffhao10037c82012-01-23 15:06:23 -08001741 return false;
1742 }
1743 if (!CheckOffsetToTypeMap(field_item->annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
1744 return false;
1745 }
1746 field_item++;
1747 }
1748
1749 // Method annotations follow immediately after field annotations.
1750 const DexFile::MethodAnnotationsItem* method_item =
1751 reinterpret_cast<const DexFile::MethodAnnotationsItem*>(field_item);
1752 uint32_t method_count = item->methods_size_;
1753 for (uint32_t i = 0; i < method_count; i++) {
1754 const DexFile::MethodId& method = dex_file_->GetMethodId(method_item->method_idx_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001755 if (UNLIKELY(method.class_idx_ != defining_class)) {
1756 ErrorStringPrintf("Mismatched defining class for method_annotation");
jeffhao10037c82012-01-23 15:06:23 -08001757 return false;
1758 }
1759 if (!CheckOffsetToTypeMap(method_item->annotations_off_, DexFile::kDexTypeAnnotationSetItem)) {
1760 return false;
1761 }
1762 method_item++;
1763 }
1764
1765 // Parameter annotations follow immediately after method annotations.
1766 const DexFile::ParameterAnnotationsItem* parameter_item =
1767 reinterpret_cast<const DexFile::ParameterAnnotationsItem*>(method_item);
1768 uint32_t parameter_count = item->parameters_size_;
1769 for (uint32_t i = 0; i < parameter_count; i++) {
1770 const DexFile::MethodId& parameter_method = dex_file_->GetMethodId(parameter_item->method_idx_);
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001771 if (UNLIKELY(parameter_method.class_idx_ != defining_class)) {
1772 ErrorStringPrintf("Mismatched defining class for parameter_annotation");
jeffhao10037c82012-01-23 15:06:23 -08001773 return false;
1774 }
Dragos Sbirlea2b87ddf2013-05-28 14:14:12 -07001775 if (!CheckOffsetToTypeMap(parameter_item->annotations_off_,
1776 DexFile::kDexTypeAnnotationSetRefList)) {
jeffhao10037c82012-01-23 15:06:23 -08001777 return false;
1778 }
1779 parameter_item++;
1780 }
1781
1782 ptr_ = reinterpret_cast<const byte*>(parameter_item);
1783 return true;
1784}
1785
1786bool DexFileVerifier::CheckInterSectionIterate(uint32_t offset, uint32_t count, uint16_t type) {
1787 // Get the right alignment mask for the type of section.
1788 uint32_t alignment_mask;
1789 switch (type) {
1790 case DexFile::kDexTypeClassDataItem:
1791 alignment_mask = sizeof(uint8_t) - 1;
1792 break;
1793 default:
1794 alignment_mask = sizeof(uint32_t) - 1;
1795 break;
1796 }
1797
1798 // Iterate through the items in the section.
1799 previous_item_ = NULL;
1800 for (uint32_t i = 0; i < count; i++) {
1801 uint32_t new_offset = (offset + alignment_mask) & ~alignment_mask;
Ian Rogers30fab402012-01-23 15:43:46 -08001802 ptr_ = begin_ + new_offset;
jeffhao10037c82012-01-23 15:06:23 -08001803 const byte* prev_ptr = ptr_;
1804
1805 // Check depending on the section type.
1806 switch (type) {
1807 case DexFile::kDexTypeStringIdItem: {
1808 if (!CheckInterStringIdItem()) {
1809 return false;
1810 }
1811 break;
1812 }
1813 case DexFile::kDexTypeTypeIdItem: {
1814 if (!CheckInterTypeIdItem()) {
1815 return false;
1816 }
1817 break;
1818 }
1819 case DexFile::kDexTypeProtoIdItem: {
1820 if (!CheckInterProtoIdItem()) {
1821 return false;
1822 }
1823 break;
1824 }
1825 case DexFile::kDexTypeFieldIdItem: {
1826 if (!CheckInterFieldIdItem()) {
1827 return false;
1828 }
1829 break;
1830 }
1831 case DexFile::kDexTypeMethodIdItem: {
1832 if (!CheckInterMethodIdItem()) {
1833 return false;
1834 }
1835 break;
1836 }
1837 case DexFile::kDexTypeClassDefItem: {
1838 if (!CheckInterClassDefItem()) {
1839 return false;
1840 }
1841 break;
1842 }
1843 case DexFile::kDexTypeAnnotationSetRefList: {
1844 if (!CheckInterAnnotationSetRefList()) {
1845 return false;
1846 }
1847 break;
1848 }
1849 case DexFile::kDexTypeAnnotationSetItem: {
1850 if (!CheckInterAnnotationSetItem()) {
1851 return false;
1852 }
1853 break;
1854 }
1855 case DexFile::kDexTypeClassDataItem: {
1856 if (!CheckInterClassDataItem()) {
1857 return false;
1858 }
1859 break;
1860 }
1861 case DexFile::kDexTypeAnnotationsDirectoryItem: {
1862 if (!CheckInterAnnotationsDirectoryItem()) {
1863 return false;
1864 }
1865 break;
1866 }
1867 default:
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001868 ErrorStringPrintf("Unknown map item type %x", type);
jeffhao10037c82012-01-23 15:06:23 -08001869 return false;
1870 }
1871
1872 previous_item_ = prev_ptr;
Ian Rogers30fab402012-01-23 15:43:46 -08001873 offset = reinterpret_cast<uint32_t>(ptr_) - reinterpret_cast<uint32_t>(begin_);
jeffhao10037c82012-01-23 15:06:23 -08001874 }
1875
1876 return true;
1877}
1878
1879bool DexFileVerifier::CheckInterSection() {
Ian Rogers30fab402012-01-23 15:43:46 -08001880 const DexFile::MapList* map = reinterpret_cast<const DexFile::MapList*>(begin_ + header_->map_off_);
jeffhao10037c82012-01-23 15:06:23 -08001881 const DexFile::MapItem* item = map->list_;
1882 uint32_t count = map->size_;
1883
1884 // Cross check the items listed in the map.
1885 while (count--) {
1886 uint32_t section_offset = item->offset_;
1887 uint32_t section_count = item->size_;
1888 uint16_t type = item->type_;
1889
1890 switch (type) {
1891 case DexFile::kDexTypeHeaderItem:
1892 case DexFile::kDexTypeMapList:
1893 case DexFile::kDexTypeTypeList:
1894 case DexFile::kDexTypeCodeItem:
1895 case DexFile::kDexTypeStringDataItem:
1896 case DexFile::kDexTypeDebugInfoItem:
1897 case DexFile::kDexTypeAnnotationItem:
1898 case DexFile::kDexTypeEncodedArrayItem:
1899 break;
1900 case DexFile::kDexTypeStringIdItem:
1901 case DexFile::kDexTypeTypeIdItem:
1902 case DexFile::kDexTypeProtoIdItem:
1903 case DexFile::kDexTypeFieldIdItem:
1904 case DexFile::kDexTypeMethodIdItem:
1905 case DexFile::kDexTypeClassDefItem:
1906 case DexFile::kDexTypeAnnotationSetRefList:
1907 case DexFile::kDexTypeAnnotationSetItem:
1908 case DexFile::kDexTypeClassDataItem:
1909 case DexFile::kDexTypeAnnotationsDirectoryItem: {
1910 if (!CheckInterSectionIterate(section_offset, section_count, type)) {
1911 return false;
1912 }
1913 break;
1914 }
1915 default:
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001916 ErrorStringPrintf("Unknown map item type %x", type);
jeffhao10037c82012-01-23 15:06:23 -08001917 return false;
1918 }
1919
1920 item++;
1921 }
1922
1923 return true;
1924}
1925
1926bool DexFileVerifier::Verify() {
1927 // Check the header.
1928 if (!CheckHeader()) {
1929 return false;
1930 }
1931
1932 // Check the map section.
1933 if (!CheckMap()) {
1934 return false;
1935 }
1936
1937 // Check structure within remaining sections.
1938 if (!CheckIntraSection()) {
1939 return false;
1940 }
1941
1942 // Check references from one section to another.
1943 if (!CheckInterSection()) {
1944 return false;
1945 }
1946
1947 return true;
1948}
1949
Ian Rogers8d31bbd2013-10-13 10:44:14 -07001950void DexFileVerifier::ErrorStringPrintf(const char* fmt, ...) {
1951 va_list ap;
1952 va_start(ap, fmt);
1953 DCHECK(failure_reason_.empty()) << failure_reason_;
1954 failure_reason_ = StringPrintf("Failure to verify dex file '%s': ", location_);
1955 StringAppendV(&failure_reason_, fmt, ap);
1956 va_end(ap);
1957}
1958
jeffhao10037c82012-01-23 15:06:23 -08001959} // namespace art