blob: df9d7cb23102bd2d2777ab6955b0c62bbbd48487 [file] [log] [blame]
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07003#include "dex_verifier.h"
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07004
Elliott Hughes1f359b02011-07-17 14:27:17 -07005#include <iostream>
6
Brian Carlstrom1f870082011-08-23 16:02:11 -07007#include "class_linker.h"
8#include "dex_file.h"
9#include "dex_instruction.h"
10#include "dex_instruction_visitor.h"
jeffhaobdb76512011-09-07 11:43:16 -070011#include "dex_verifier.h"
Elliott Hughes1f359b02011-07-17 14:27:17 -070012#include "logging.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070013#include "runtime.h"
Elliott Hughes1f359b02011-07-17 14:27:17 -070014#include "stringpiece.h"
jeffhaobdb76512011-09-07 11:43:16 -070015#include "UniquePtr.h"
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070016
17namespace art {
18
jeffhaobdb76512011-09-07 11:43:16 -070019#define k_ kRegTypeUnknown
20#define kU kRegTypeUninit
21#define kX kRegTypeConflict
22#define k0 kRegTypeZero
23#define k1 kRegTypeOne
24#define kZ kRegTypeBoolean
25#define ky kRegTypeConstPosByte
26#define kY kRegTypeConstByte
27#define kh kRegTypeConstPosShort
28#define kH kRegTypeConstShort
29#define kc kRegTypeConstChar
30#define ki kRegTypeConstInteger
31#define kb kRegTypePosByte
32#define kB kRegTypeByte
33#define ks kRegTypePosShort
34#define kS kRegTypeShort
35#define kC kRegTypeChar
36#define kI kRegTypeInteger
37#define kF kRegTypeFloat
38#define kN kRegTypeConstLo
39#define kn kRegTypeConstHi
40#define kJ kRegTypeLongLo
41#define kj kRegTypeLongHi
42#define kD kRegTypeDoubleLo
43#define kd kRegTypeDoubleHi
44
45const char DexVerifier::merge_table_[kRegTypeMAX][kRegTypeMAX] =
46 {
47 /* chk: _ U X 0 1 Z y Y h H c i b B s S C I F N n J j D d */
48 { /*_*/ k_,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX },
49 { /*U*/ kX,kU,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX },
50 { /*X*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX },
51 { /*0*/ kX,kX,kX,k0,kZ,kZ,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
52 { /*1*/ kX,kX,kX,kZ,k1,kZ,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
53 { /*Z*/ kX,kX,kX,kZ,kZ,kZ,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
54 { /*y*/ kX,kX,kX,ky,ky,ky,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
55 { /*Y*/ kX,kX,kX,kY,kY,kY,kY,kY,kh,kH,kc,ki,kB,kB,kS,kS,kI,kI,kF,kX,kX,kX,kX,kX,kX },
56 { /*h*/ kX,kX,kX,kh,kh,kh,kh,kh,kh,kH,kc,ki,ks,kS,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
57 { /*H*/ kX,kX,kX,kH,kH,kH,kH,kH,kH,kH,kc,ki,kS,kS,kS,kS,kI,kI,kF,kX,kX,kX,kX,kX,kX },
58 { /*c*/ kX,kX,kX,kc,kc,kc,kc,kc,kc,kc,kc,ki,kC,kI,kC,kI,kC,kI,kF,kX,kX,kX,kX,kX,kX },
59 { /*i*/ kX,kX,kX,ki,ki,ki,ki,ki,ki,ki,ki,ki,kI,kI,kI,kI,kI,kI,kF,kX,kX,kX,kX,kX,kX },
60 { /*b*/ kX,kX,kX,kb,kb,kb,kb,kB,ks,kS,kC,kI,kb,kB,ks,kS,kC,kI,kX,kX,kX,kX,kX,kX,kX },
61 { /*B*/ kX,kX,kX,kB,kB,kB,kB,kB,kS,kS,kI,kI,kB,kB,kS,kS,kI,kI,kX,kX,kX,kX,kX,kX,kX },
62 { /*s*/ kX,kX,kX,ks,ks,ks,ks,kS,ks,kS,kC,kI,ks,kS,ks,kS,kC,kI,kX,kX,kX,kX,kX,kX,kX },
63 { /*S*/ kX,kX,kX,kS,kS,kS,kS,kS,kS,kS,kI,kI,kS,kS,kS,kS,kI,kI,kX,kX,kX,kX,kX,kX,kX },
64 { /*C*/ kX,kX,kX,kC,kC,kC,kC,kI,kC,kI,kC,kI,kC,kI,kC,kI,kC,kI,kX,kX,kX,kX,kX,kX,kX },
65 { /*I*/ kX,kX,kX,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kX,kX,kX,kX,kX,kX,kX },
66 { /*F*/ kX,kX,kX,kF,kF,kF,kF,kF,kF,kF,kF,kF,kX,kX,kX,kX,kX,kX,kF,kX,kX,kX,kX,kX,kX },
67 { /*N*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kN,kX,kJ,kX,kD,kX },
68 { /*n*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kn,kX,kj,kX,kd },
69 { /*J*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kJ,kX,kJ,kX,kX,kX },
70 { /*j*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kj,kX,kj,kX,kX },
71 { /*D*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kD,kX,kX,kX,kD,kX },
72 { /*d*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kd,kX,kX,kX,kd },
73 };
74
75#undef k_
76#undef kU
77#undef kX
78#undef k0
79#undef k1
80#undef kZ
81#undef ky
82#undef kY
83#undef kh
84#undef kH
85#undef kc
86#undef ki
87#undef kb
88#undef kB
89#undef ks
90#undef kS
91#undef kC
92#undef kI
93#undef kF
94#undef kN
95#undef kn
96#undef kJ
97#undef kj
98#undef kD
99#undef kd
100
101bool DexVerifier::VerifyClass(Class* klass) {
102 if (klass->IsVerified()) {
103 return true;
104 }
105 for (size_t i = 0; i < klass->NumDirectMethods(); ++i) {
106 Method* method = klass->GetDirectMethod(i);
107 if (!VerifyMethod(method)) {
108 LOG(ERROR) << "Verifier rejected class "
109 << klass->GetDescriptor()->ToModifiedUtf8();
110 return false;
111 }
112 }
113 for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
114 Method* method = klass->GetVirtualMethod(i);
115 if (!VerifyMethod(method)) {
116 LOG(ERROR) << "Verifier rejected class "
117 << klass->GetDescriptor()->ToModifiedUtf8();
118 return false;
119 }
120 }
121 return true;
jeffhaoba5ebb92011-08-25 17:24:37 -0700122}
123
jeffhaobdb76512011-09-07 11:43:16 -0700124bool DexVerifier::VerifyMethod(Method* method) {
125 const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
126 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
127 const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
128 const DexFile::CodeItem *code_item =
129 dex_file.GetCodeItem(method->GetCodeItemOffset());
130
131 /*
132 * Construct the verifier state container object.
133 */
134 VerifierData vdata(method, &dex_file, code_item);
135
136 /*
137 * If there aren't any instructions, make sure that's expected, then
138 * exit successfully.
139 */
140 if (code_item == NULL) {
141 if (!method->IsNative() && !method->IsAbstract()) {
142 LOG(ERROR) << "VFY: zero-length code in concrete non-native method";
143 return false;
144 }
145 return true;
146 }
147
148 /*
149 * Sanity-check the register counts. ins + locals = registers, so make
150 * sure that ins <= registers.
151 */
152 if (code_item->ins_size_ > code_item->registers_size_) {
153 LOG(ERROR) << "VFY: bad register counts (ins=" << code_item->ins_size_
154 << " regs=" << code_item->registers_size_;
155 return false;
156 }
157
158 /*
159 * Allocate and initialize an array to hold instruction data.
160 */
161 UniquePtr<InsnFlags> insn_flags(new InsnFlags[code_item->insns_size_]());
162 vdata.insn_flags_ = insn_flags.get();
163
164 /*
165 * Run through the instructions and see if the width checks out.
166 */
167 if (!ComputeWidthsAndCountOps(&vdata)) {
168 return false;
169 }
170
171 /*
172 * Flag instructions guarded by a "try" block and check exception handlers.
173 */
174 if (!ScanTryCatchBlocks(&vdata)) {
175 return false;
176 }
177
178 /*
179 * Perform static instruction verification.
180 */
181 if (!VerifyInstructions(&vdata)) {
182 return false;
183 }
184
185 /*
186 * Perform code flow analysis.
187 */
188 if (!VerifyCodeFlow(&vdata)) {
189 return false;
190 }
191
192 return true;
jeffhaoba5ebb92011-08-25 17:24:37 -0700193}
194
jeffhaobdb76512011-09-07 11:43:16 -0700195bool DexVerifier::VerifyInstructions(VerifierData* vdata) {
196 const DexFile::CodeItem* code_item = vdata->code_item_;
197 InsnFlags* insn_flags = vdata->insn_flags_;
198 const byte* ptr = reinterpret_cast<const byte*>(code_item->insns_);
199 const Instruction* inst = Instruction::At(ptr);
200
201 /* Flag the start of the method as a branch target. */
202 InsnSetBranchTarget(insn_flags, 0);
203
204 uint32_t width = 0;
205 uint32_t insns_size = code_item->insns_size_;
206
207 while (width < insns_size) {
208 if (!VerifyInstruction(vdata, inst, width)) {
209 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
210 << (int) inst->Opcode() << " at 0x" << width << std::dec;
211 return false;
212 }
213
214 /* Flag instructions that are garbage collection points */
215 if (inst->IsBranch() || inst->IsSwitch() || inst->IsThrow() ||
216 inst->IsReturn()) {
217 InsnSetGcPoint(insn_flags, width);
218 }
219
220 width += inst->Size();
221 inst = inst->Next();
222 }
223 return true;
jeffhaoba5ebb92011-08-25 17:24:37 -0700224}
225
jeffhaobdb76512011-09-07 11:43:16 -0700226bool DexVerifier::VerifyInstruction(VerifierData* vdata,
227 const Instruction* inst, uint32_t code_offset) {
228 const DexFile* dex_file = vdata->dex_file_;
229 const DexFile::CodeItem* code_item = vdata->code_item_;
230 InsnFlags* insn_flags = vdata->insn_flags_;
231 Instruction::DecodedInstruction dec_insn(inst);
232 bool result = true;
233
234 int argumentA = inst->GetVerifyTypeArgumentA();
235 int argumentB = inst->GetVerifyTypeArgumentB();
236 int argumentC = inst->GetVerifyTypeArgumentC();
237 int extra_flags = inst->GetVerifyExtraFlags();
238
239 switch (argumentA) {
240 case Instruction::kVerifyRegA:
241 result &= CheckRegisterIndex(code_item, dec_insn.vA_);
242 break;
243 case Instruction::kVerifyRegAWide:
244 result &= CheckWideRegisterIndex(code_item, dec_insn.vA_);
245 break;
246 }
247
248 switch (argumentB) {
249 case Instruction::kVerifyRegB:
250 result &= CheckRegisterIndex(code_item, dec_insn.vB_);
251 break;
252 case Instruction::kVerifyRegBField:
253 result &= CheckFieldIndex(dex_file, dec_insn.vB_);
254 break;
255 case Instruction::kVerifyRegBMethod:
256 result &= CheckMethodIndex(dex_file, dec_insn.vB_);
257 break;
258 case Instruction::kVerifyRegBNewInstance:
259 result &= CheckNewInstance(dex_file, dec_insn.vB_);
260 break;
261 case Instruction::kVerifyRegBString:
262 result &= CheckStringIndex(dex_file, dec_insn.vB_);
263 break;
264 case Instruction::kVerifyRegBType:
265 result &= CheckTypeIndex(dex_file, dec_insn.vB_);
266 break;
267 case Instruction::kVerifyRegBWide:
268 result &= CheckWideRegisterIndex(code_item, dec_insn.vB_);
269 break;
270 }
271
272 switch (argumentC) {
273 case Instruction::kVerifyRegC:
274 result &= CheckRegisterIndex(code_item, dec_insn.vC_);
275 break;
276 case Instruction::kVerifyRegCField:
277 result &= CheckFieldIndex(dex_file, dec_insn.vC_);
278 break;
279 case Instruction::kVerifyRegCNewArray:
280 result &= CheckNewArray(dex_file, dec_insn.vC_);
281 break;
282 case Instruction::kVerifyRegCType:
283 result &= CheckTypeIndex(dex_file, dec_insn.vC_);
284 break;
285 case Instruction::kVerifyRegCWide:
286 result &= CheckWideRegisterIndex(code_item, dec_insn.vC_);
287 break;
288 }
289
290 switch (extra_flags) {
291 case Instruction::kVerifyArrayData:
292 result &= CheckArrayData(code_item, code_offset);
293 break;
294 case Instruction::kVerifyBranchTarget:
295 result &= CheckBranchTarget(code_item, insn_flags, code_offset);
296 break;
297 case Instruction::kVerifySwitchTargets:
298 result &= CheckSwitchTargets(code_item, insn_flags, code_offset);
299 break;
300 case Instruction::kVerifyVarArg:
301 result &= CheckVarArgRegs(code_item, dec_insn.vA_, dec_insn.arg_);
302 break;
303 case Instruction::kVerifyVarArgRange:
304 result &= CheckVarArgRangeRegs(code_item, dec_insn.vA_, dec_insn.vC_);
305 break;
306 case Instruction::kVerifyError:
307 LOG(ERROR) << "VFY: unexpected opcode " << std::hex
308 << (int) dec_insn.opcode_ << std::dec;
309 result = false;
310 break;
311 }
312
313 return result;
jeffhaoba5ebb92011-08-25 17:24:37 -0700314}
315
jeffhaobdb76512011-09-07 11:43:16 -0700316bool DexVerifier::VerifyCodeFlow(VerifierData* vdata) {
317 Method* method = vdata->method_;
318 const DexFile::CodeItem* code_item = vdata->code_item_;
319 uint16_t registers_size = code_item->registers_size_;
320 uint32_t insns_size = code_item->insns_size_;
321 RegisterTable reg_table;
jeffhaoba5ebb92011-08-25 17:24:37 -0700322
jeffhaobdb76512011-09-07 11:43:16 -0700323 if (registers_size * insns_size > 4*1024*1024) {
324 LOG(ERROR) << "VFY: warning: method is huge (regs=" << registers_size
325 << " insns_size=" << insns_size << ")";
326 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700327
jeffhaobdb76512011-09-07 11:43:16 -0700328 /* Create and initialize register lists. */
329 if (!InitRegisterTable(vdata, &reg_table, kTrackRegsGcPoints)) {
330 return false;
331 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700332
jeffhaobdb76512011-09-07 11:43:16 -0700333 vdata->register_lines_ = reg_table.register_lines_;
334
335 /* Allocate a map to hold the classes of uninitialized instances. */
336 UniquePtr<UninitInstanceMap> uninit_map(CreateUninitInstanceMap(vdata));
337 vdata->uninit_map_ = uninit_map.get();
338
339 /* Initialize register types of method arguments. */
340 if (!SetTypesFromSignature(vdata, reg_table.register_lines_[0].reg_types_)) {
341 LOG(ERROR) << "VFY: bad signature '"
342 << method->GetSignature()->ToModifiedUtf8() << "' for "
343 << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
344 << "." << method->GetName()->ToModifiedUtf8();
345 return false;
346 }
347
348 /* Perform code flow verification. */
349 if (!CodeFlowVerifyMethod(vdata, &reg_table)) {
350 return false;
351 }
352
353 /* TODO: Generate a register map. */
jeffhaoba5ebb92011-08-25 17:24:37 -0700354
355
jeffhaobdb76512011-09-07 11:43:16 -0700356 return true;
357}
358
359bool DexVerifier::ComputeWidthsAndCountOps(VerifierData* vdata) {
360 const uint16_t* insns = vdata->code_item_->insns_;
361 uint32_t insns_size = vdata->code_item_->insns_size_;
362 InsnFlags* insn_flags = vdata->insn_flags_;
363 const byte* ptr = reinterpret_cast<const byte*>(insns);
364 const Instruction* inst = Instruction::At(ptr);
365 size_t new_instance_count = 0;
366 size_t monitor_enter_count = 0;
367 size_t width = 0;
368
369 while (width < insns_size) {
370 Instruction::Code opcode = inst->Opcode();
371 if (opcode == Instruction::NEW_INSTANCE) {
372 new_instance_count++;
373 } else if (opcode == Instruction::MONITOR_ENTER) {
374 monitor_enter_count++;
375 }
376
377 insn_flags[width] |= inst->Size();
378 width += inst->Size();
379 inst = inst->Next();
380 }
381
382 if (width != insns_size) {
383 LOG(ERROR) << "VFY: code did not end where expected (" << width << " vs. "
384 << insns_size << ")";
385 return false;
386 }
387
388 vdata->new_instance_count_ = new_instance_count;
389 vdata->monitor_enter_count_ = monitor_enter_count;
390 return true;
391}
392
393bool DexVerifier::ScanTryCatchBlocks(VerifierData* vdata) {
394 const DexFile::CodeItem* code_item = vdata->code_item_;
395 InsnFlags* insn_flags = vdata->insn_flags_;
396 uint32_t insns_size = code_item->insns_size_;
397 uint32_t tries_size = code_item->tries_size_;
398
399 if (tries_size == 0) {
400 return true;
401 }
402
403 const DexFile::TryItem* tries = DexFile::dexGetTryItems(*code_item, 0);
404
405 for (uint32_t idx = 0; idx < tries_size; idx++) {
406 const DexFile::TryItem* try_item = &tries[idx];
407 uint32_t start = try_item->start_addr_;
408 uint32_t end = start + try_item->insn_count_;
409
410 if ((start >= end) || (start >= insns_size) || (end > insns_size)) {
411 LOG(ERROR) << "VFY: bad exception entry: startAddr=" << start
412 << " endAddr=" << end << " (size=" << insns_size << ")";
413 return false;
414 }
415
416 if (InsnGetWidth(insn_flags, start) == 0) {
417 LOG(ERROR) << "VFY: 'try' block starts inside an instruction ("
418 << start << ")";
419 return false;
420 }
421
422 uint32_t addr;
423 for (addr = start; addr < end; addr += InsnGetWidth(insn_flags, addr)) {
424 InsnSetInTry(insn_flags, addr);
425 }
426 }
427
428 /* Iterate over each of the handlers to verify target addresses. */
429 const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item, 0);
430 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
431 for (uint32_t idx = 0; idx < handlers_size; idx++) {
432 DexFile::CatchHandlerIterator iterator(handlers_ptr);
433
434 for (; !iterator.HasNext(); iterator.Next()) {
435 uint32_t addr = iterator.Get().address_;
436 if (InsnGetWidth(insn_flags, addr) == 0) {
437 LOG(ERROR) << "VFY: exception handler starts at bad address ("
438 << addr << ")";
439 return false;
440 }
441
442 InsnSetBranchTarget(insn_flags, addr);
443 }
444
445 handlers_ptr = iterator.GetData();
446 }
447
448 return true;
449}
450
451bool DexVerifier::GetBranchOffset(const DexFile::CodeItem* code_item,
452 const InsnFlags insn_flags[], uint32_t cur_offset, int32_t* pOffset,
jeffhaoba5ebb92011-08-25 17:24:37 -0700453 bool* pConditional, bool* selfOkay) {
454 const uint16_t* insns = code_item->insns_ + cur_offset;
455
456 switch (*insns & 0xff) {
457 case Instruction::GOTO:
458 *pOffset = ((int16_t) *insns) >> 8;
459 *pConditional = false;
460 *selfOkay = false;
461 break;
462 case Instruction::GOTO_32:
463 *pOffset = insns[1] | (((uint32_t) insns[2]) << 16);
464 *pConditional = false;
465 *selfOkay = true;
466 break;
467 case Instruction::GOTO_16:
468 *pOffset = (int16_t) insns[1];
469 *pConditional = false;
470 *selfOkay = false;
471 break;
472 case Instruction::IF_EQ:
473 case Instruction::IF_NE:
474 case Instruction::IF_LT:
475 case Instruction::IF_GE:
476 case Instruction::IF_GT:
477 case Instruction::IF_LE:
478 case Instruction::IF_EQZ:
479 case Instruction::IF_NEZ:
480 case Instruction::IF_LTZ:
481 case Instruction::IF_GEZ:
482 case Instruction::IF_GTZ:
483 case Instruction::IF_LEZ:
484 *pOffset = (int16_t) insns[1];
485 *pConditional = true;
486 *selfOkay = false;
487 break;
488 default:
489 return false;
490 break;
491 }
492
493 return true;
494}
495
jeffhaobdb76512011-09-07 11:43:16 -0700496bool DexVerifier::CheckArrayData(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700497 uint32_t cur_offset) {
498 const uint32_t insn_count = code_item->insns_size_;
499 const uint16_t* insns = code_item->insns_ + cur_offset;
500 const uint16_t* array_data;
501 int32_t array_data_offset;
502
503 assert(cur_offset < insn_count);
504
505 /* make sure the start of the array data table is in range */
506 array_data_offset = insns[1] | (((int32_t) insns[2]) << 16);
507 if ((int32_t) cur_offset + array_data_offset < 0 ||
508 cur_offset + array_data_offset + 2 >= insn_count)
509 {
510 LOG(ERROR) << "VFY: invalid array data start: at " << cur_offset
511 << ", data offset " << array_data_offset << ", count "
512 << insn_count;
513 return false;
514 }
515
516 /* offset to array data table is a relative branch-style offset */
517 array_data = insns + array_data_offset;
518
519 /* make sure the table is 32-bit aligned */
520 if ((((uint32_t) array_data) & 0x03) != 0) {
521 LOG(ERROR) << "VFY: unaligned array data table: at " << cur_offset
522 << ", data offset " << array_data_offset;
523 return false;
524 }
525
526 uint32_t value_width = array_data[1];
527 uint32_t value_count = *(uint32_t*) (&array_data[2]);
528 uint32_t table_size = 4 + (value_width * value_count + 1) / 2;
529
530 /* make sure the end of the switch is in range */
531 if (cur_offset + array_data_offset + table_size > insn_count) {
532 LOG(ERROR) << "VFY: invalid array data end: at " << cur_offset
533 << ", data offset " << array_data_offset << ", end "
534 << cur_offset + array_data_offset + table_size << ", count "
535 << insn_count;
536 return false;
537 }
538
539 return true;
540}
541
jeffhaobdb76512011-09-07 11:43:16 -0700542bool DexVerifier::CheckNewInstance(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700543 if (idx >= dex_file->GetHeader().type_ids_size_) {
544 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
545 << dex_file->GetHeader().type_ids_size_ << ")";
546 return false;
547 }
548
549 const char* descriptor = dex_file->dexStringByTypeIdx(idx);
550 if (descriptor[0] != 'L') {
551 LOG(ERROR) << "VFY: can't call new-instance on type '"
552 << descriptor << "'";
553 return false;
554 }
555
556 return true;
557}
558
jeffhaobdb76512011-09-07 11:43:16 -0700559bool DexVerifier::CheckNewArray(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700560 if (idx >= dex_file->GetHeader().type_ids_size_) {
561 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
562 << dex_file->GetHeader().type_ids_size_ << ")";
563 return false;
564 }
565
566 int bracket_count = 0;
567 const char* descriptor = dex_file->dexStringByTypeIdx(idx);
568 const char* cp = descriptor;
569 while (*cp++ == '[')
570 bracket_count++;
571
572 if (bracket_count == 0) {
573 /* The given class must be an array type. */
574 LOG(ERROR) << "VFY: can't new-array class '" << descriptor
575 << "' (not an array)";
576 return false;
577 } else if (bracket_count > 255) {
578 /* It is illegal to create an array of more than 255 dimensions. */
579 LOG(ERROR) << "VFY: can't new-array class '" << descriptor
580 << "' (exceeds limit)";
581 return false;
582 }
583
584 return true;
585}
586
jeffhaobdb76512011-09-07 11:43:16 -0700587bool DexVerifier::CheckTypeIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700588 if (idx >= dex_file->GetHeader().type_ids_size_) {
589 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
590 << dex_file->GetHeader().type_ids_size_ << ")";
591 return false;
592 }
593 return true;
594}
595
jeffhaobdb76512011-09-07 11:43:16 -0700596bool DexVerifier::CheckFieldIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700597 if (idx >= dex_file->GetHeader().field_ids_size_) {
598 LOG(ERROR) << "VFY: bad field index " << idx << " (max "
599 << dex_file->GetHeader().field_ids_size_ << ")";
600 return false;
601 }
602 return true;
603}
604
jeffhaobdb76512011-09-07 11:43:16 -0700605bool DexVerifier::CheckMethodIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700606 if (idx >= dex_file->GetHeader().method_ids_size_) {
607 LOG(ERROR) << "VFY: bad method index " << idx << " (max "
608 << dex_file->GetHeader().method_ids_size_ << ")";
609 return false;
610 }
611 return true;
612}
613
jeffhaobdb76512011-09-07 11:43:16 -0700614bool DexVerifier::CheckStringIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700615 if (idx >= dex_file->GetHeader().string_ids_size_) {
616 LOG(ERROR) << "VFY: bad string index " << idx << " (max "
617 << dex_file->GetHeader().string_ids_size_ << ")";
618 return false;
619 }
620 return true;
621}
622
jeffhaobdb76512011-09-07 11:43:16 -0700623bool DexVerifier::CheckRegisterIndex(const DexFile::CodeItem* code_item,
624 uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700625 if (idx >= code_item->registers_size_) {
626 LOG(ERROR) << "VFY: register index out of range (" << idx << " >= "
627 << code_item->registers_size_ << ")";
628 return false;
629 }
630 return true;
631}
632
jeffhaobdb76512011-09-07 11:43:16 -0700633bool DexVerifier::CheckWideRegisterIndex(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700634 uint32_t idx) {
635 if (idx + 1 >= code_item->registers_size_) {
636 LOG(ERROR) << "VFY: wide register index out of range (" << idx
637 << "+1 >= " << code_item->registers_size_ << ")";
638 return false;
639 }
640 return true;
641}
642
jeffhaobdb76512011-09-07 11:43:16 -0700643bool DexVerifier::CheckVarArgRegs(const DexFile::CodeItem* code_item,
644 uint32_t vA, uint32_t arg[]) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700645 uint16_t registers_size = code_item->registers_size_;
646 uint32_t idx;
647
648 if (vA > 5) {
649 LOG(ERROR) << "VFY: invalid arg count (" << vA << ") in non-range invoke)";
650 return false;
651 }
652
653 for (idx = 0; idx < vA; idx++) {
654 if (arg[idx] > registers_size) {
655 LOG(ERROR) << "VFY: invalid reg index (" << arg[idx]
656 << ") in non-range invoke (> " << registers_size << ")";
657 return false;
658 }
659 }
660
661 return true;
662}
663
jeffhaobdb76512011-09-07 11:43:16 -0700664bool DexVerifier::CheckVarArgRangeRegs(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700665 uint32_t vA, uint32_t vC) {
666 uint16_t registers_size = code_item->registers_size_;
667
668 /*
669 * vA/vC are unsigned 8-bit/16-bit quantities for /range instructions,
670 * so there's no risk of integer overflow when adding them here.
671 */
672 if (vA + vC > registers_size) {
673 LOG(ERROR) << "VFY: invalid reg index " << vA << "+" << vC
674 << " in range invoke (> " << registers_size << ")";
675 return false;
676 }
677
678 return true;
679}
680
jeffhaobdb76512011-09-07 11:43:16 -0700681bool DexVerifier::CheckSwitchTargets(const DexFile::CodeItem* code_item,
682 InsnFlags insn_flags[], uint32_t cur_offset) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700683 const uint32_t insn_count = code_item->insns_size_;
684 const uint16_t* insns = code_item->insns_ + cur_offset;
685 const uint16_t* switch_insns;
686 uint16_t expected_signature;
687 uint32_t switch_count, table_size;
688 int32_t switch_offset, keys_offset, targets_offset;
689 int32_t offset, abs_offset;
690 uint32_t targ;
691
692 /* make sure the start of the switch is in range */
693 switch_offset = insns[1] | ((int32_t) insns[2]) << 16;
694 if ((int32_t) cur_offset + switch_offset < 0 ||
695 cur_offset + switch_offset + 2 >= insn_count) {
696 LOG(ERROR) << "VFY: invalid switch start: at " << cur_offset
697 << ", switch offset " << switch_offset << ", count "
698 << insn_count;
699 return false;
700 }
701
702 /* offset to switch table is a relative branch-style offset */
703 switch_insns = insns + switch_offset;
704
705 /* make sure the table is 32-bit aligned */
706 if ((((uint32_t) switch_insns) & 0x03) != 0) {
707 LOG(ERROR) << "VFY: unaligned switch table: at " << cur_offset
708 << ", switch offset " << switch_offset;
709 return false;
710 }
711
712 switch_count = switch_insns[1];
713
714 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
715 /* 0=sig, 1=count, 2/3=firstKey */
716 targets_offset = 4;
717 keys_offset = -1;
718 expected_signature = Instruction::kPackedSwitchSignature;
719 } else {
720 /* 0=sig, 1=count, 2..count*2 = keys */
721 keys_offset = 2;
722 targets_offset = 2 + 2 * switch_count;
723 expected_signature = Instruction::kSparseSwitchSignature;
724 }
725 table_size = targets_offset + switch_count * 2;
726
727 if (switch_insns[0] != expected_signature) {
jeffhaobdb76512011-09-07 11:43:16 -0700728 LOG(ERROR) << "VFY: wrong signature for switch table (0x" << std::hex
729 << switch_insns[0] << ", wanted 0x" << expected_signature << ")"
730 << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700731 return false;
732 }
733
734 /* make sure the end of the switch is in range */
735 if (cur_offset + switch_offset + table_size > (uint32_t) insn_count) {
736 LOG(ERROR) << "VFY: invalid switch end: at " << cur_offset
737 << ", switch offset " << switch_offset << ", end "
738 << cur_offset + switch_offset + table_size << ", count "
739 << insn_count;
740 return false;
741 }
742
743 /* for a sparse switch, verify the keys are in ascending order */
744 if (keys_offset > 0 && switch_count > 1) {
745 int32_t last_key;
746
747 last_key = switch_insns[keys_offset] |
748 (switch_insns[keys_offset + 1] << 16);
749 for (targ = 1; targ < switch_count; targ++) {
750 int32_t key = (int32_t) switch_insns[keys_offset + targ * 2] |
751 (int32_t) (switch_insns[keys_offset + targ * 2 + 1] << 16);
752 if (key <= last_key) {
753 LOG(ERROR) << "VFY: invalid packed switch: last key=" << last_key
754 << ", this=" << key;
755 return false;
756 }
757
758 last_key = key;
759 }
760 }
761
762 /* verify each switch target */
763 for (targ = 0; targ < switch_count; targ++) {
764 offset = (int32_t) switch_insns[targets_offset + targ * 2] |
765 (int32_t) (switch_insns[targets_offset + targ * 2 + 1] << 16);
766 abs_offset = cur_offset + offset;
767
768 if (abs_offset < 0 || abs_offset >= (int32_t) insn_count ||
769 !InsnIsOpcode(insn_flags, abs_offset)) {
770 LOG(ERROR) << "VFY: invalid switch target " << offset << " (-> "
jeffhaobdb76512011-09-07 11:43:16 -0700771 << std::hex << abs_offset << ") at " << cur_offset << std::dec
772 << "[" << targ << "]";
jeffhaoba5ebb92011-08-25 17:24:37 -0700773 return false;
774 }
jeffhaobdb76512011-09-07 11:43:16 -0700775 InsnSetBranchTarget(insn_flags, abs_offset);
jeffhaoba5ebb92011-08-25 17:24:37 -0700776 }
777
778 return true;
779}
780
jeffhaobdb76512011-09-07 11:43:16 -0700781bool DexVerifier::CheckBranchTarget(const DexFile::CodeItem* code_item,
782 InsnFlags insn_flags[], uint32_t cur_offset) {
783 const uint32_t insn_count = code_item->insns_size_;
jeffhaoba5ebb92011-08-25 17:24:37 -0700784 int32_t offset, abs_offset;
785 bool isConditional, selfOkay;
786
787 if (!GetBranchOffset(code_item, insn_flags, cur_offset, &offset,
788 &isConditional, &selfOkay))
789 return false;
790
791 if (!selfOkay && offset == 0) {
jeffhaobdb76512011-09-07 11:43:16 -0700792 LOG(ERROR) << "VFY: branch offset of zero not allowed at" << std::hex
793 << cur_offset << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700794 return false;
795 }
796
797 /*
798 * Check for 32-bit overflow. This isn't strictly necessary if we can
799 * depend on the VM to have identical "wrap-around" behavior, but
800 * it's unwise to depend on that.
801 */
802 if (((int64_t) cur_offset + (int64_t) offset) !=
jeffhaobdb76512011-09-07 11:43:16 -0700803 (int64_t) (cur_offset + offset)) {
804 LOG(ERROR) << "VFY: branch target overflow " << std::hex << cur_offset
805 << std::dec << " +" << offset;
jeffhaoba5ebb92011-08-25 17:24:37 -0700806 return false;
807 }
808 abs_offset = cur_offset + offset;
jeffhaobdb76512011-09-07 11:43:16 -0700809 if (abs_offset < 0 || (uint32_t) abs_offset >= insn_count ||
jeffhaoba5ebb92011-08-25 17:24:37 -0700810 !InsnIsOpcode(insn_flags, abs_offset))
811 {
812 LOG(ERROR) << "VFY: invalid branch target " << offset << " (-> "
jeffhaobdb76512011-09-07 11:43:16 -0700813 << std::hex << abs_offset << ") at " << cur_offset << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700814 return false;
815 }
jeffhaobdb76512011-09-07 11:43:16 -0700816 InsnSetBranchTarget(insn_flags, abs_offset);
jeffhaoba5ebb92011-08-25 17:24:37 -0700817
818 return true;
819}
820
jeffhaobdb76512011-09-07 11:43:16 -0700821bool DexVerifier::InitRegisterTable(VerifierData* vdata,
822 RegisterTable* reg_table, RegisterTrackingMode track_regs_for) {
823 const DexFile::CodeItem* code_item = vdata->code_item_;
824 InsnFlags* insn_flags = vdata->insn_flags_;
825 uint16_t registers_size = code_item->registers_size_;
826 uint32_t insns_size = code_item->insns_size_;
827 uint32_t i;
828
829 /*
830 * Every address gets a RegisterLine struct. This is wasteful, but
831 * not so much that it's worth chasing through an extra level of
832 * indirection.
833 */
834 reg_table->insn_reg_count_plus_ = registers_size + kExtraRegs;
835 reg_table->register_lines_ = new RegisterLine[insns_size]();
836
837 assert(insns_size > 0);
838
839 bool track_monitors;
840 //if (gDvm.monitorVerification) {
841 //track_monitors = (vdata->monitor_enter_count_ != 0);
842 //} else {
843 track_monitors = false;
844 //}
845
846 /*
847 * Allocate entries in the sparse register line table.
848 *
849 * There is a RegisterLine associated with every address, but not
850 * every RegisterLine has non-NULL pointers to storage for its fields.
851 */
852 for (i = 0; i < insns_size; i++) {
853 bool interesting;
854
855 switch (track_regs_for) {
856 case kTrackRegsAll:
857 interesting = InsnIsOpcode(insn_flags, i);
858 break;
859 case kTrackRegsGcPoints:
860 interesting = InsnIsGcPoint(insn_flags, i) ||
861 InsnIsBranchTarget(insn_flags, i);
862 break;
863 case kTrackRegsBranches:
864 interesting = InsnIsBranchTarget(insn_flags, i);
865 break;
866 default:
867 return false;
868 }
869
870 if (interesting) {
871 reg_table->register_lines_[i].Alloc(reg_table->insn_reg_count_plus_,
872 track_monitors);
873 }
874 }
875
876 /*
877 * Allocate space for our "temporary" register lines.
878 */
879 reg_table->work_line_.Alloc(reg_table->insn_reg_count_plus_, track_monitors);
880 reg_table->saved_line_.Alloc(reg_table->insn_reg_count_plus_, track_monitors);
881
882 return true;
883}
884
885DexVerifier::UninitInstanceMap* DexVerifier::CreateUninitInstanceMap(
886 VerifierData* vdata) {
887 Method* method = vdata->method_;
888 const DexFile::CodeItem* code_item = vdata->code_item_;
889 size_t new_instance_count = vdata->new_instance_count_;
890
891 if (IsInitMethod(method)) {
892 new_instance_count++;
893 }
894
895 /*
896 * Allocate the header and map as a single unit.
897 *
898 * TODO: consider having a static instance so we can avoid allocations.
899 * I don't think the verifier is guaranteed to be single-threaded when
900 * running in the VM (rather than dexopt), so that must be taken into
901 * account.
902 */
903 UninitInstanceMap* uninit_map = new UninitInstanceMap(new_instance_count);
904
905 size_t idx = 0;
906 if (IsInitMethod(method)) {
907 uninit_map->map_[idx++].addr_ = kUninitThisArgAddr;
908 }
909
910 /*
911 * Run through and find the new-instance instructions.
912 */
913 uint32_t addr = 0;
914 uint32_t insns_size = code_item->insns_size_;
915 const byte* ptr = reinterpret_cast<const byte*>(code_item->insns_);
jeffhaoba5ebb92011-08-25 17:24:37 -0700916 const Instruction* inst = Instruction::At(ptr);
jeffhaobdb76512011-09-07 11:43:16 -0700917 while (addr < insns_size) {
918 Instruction::Code opcode = inst->Opcode();
919 if (opcode == Instruction::NEW_INSTANCE) {
920 uninit_map->map_[idx++].addr_ = addr;
921 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700922
jeffhaobdb76512011-09-07 11:43:16 -0700923 addr += inst->Size();
jeffhaoba5ebb92011-08-25 17:24:37 -0700924 inst = inst->Next();
925 }
926
jeffhaobdb76512011-09-07 11:43:16 -0700927 assert(idx == new_instance_count);
928 return uninit_map;
929}
930
931bool DexVerifier::IsInitMethod(const Method* method) {
932 return (method->GetName()->Equals("<init>"));
933}
934
935Class* DexVerifier::LookupClassByDescriptor(const Method* method,
936 const char* descriptor, VerifyError* failure) {
937 /*
938 * The compiler occasionally puts references to nonexistent
939 * classes in signatures. For example, if you have a non-static
940 * inner class with no constructor, the compiler provides
941 * a private <init> for you. Constructing the class
942 * requires <init>(parent), but the outer class can't call
943 * that because the method is private. So the compiler
944 * generates a package-scope <init>(parent,bogus) method that
945 * just calls the regular <init> (the "bogus" part being necessary
946 * to distinguish the signature of the synthetic method).
947 * Treating the bogus class as an instance of java.lang.Object
948 * allows the verifier to process the class successfully.
949 */
950 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
951 const ClassLoader* class_loader =
952 method->GetDeclaringClass()->GetClassLoader();
953 Class* klass = class_linker->FindClass(descriptor, class_loader);
954
955 if (klass == NULL) {
956 Thread::Current()->ClearException();
957 if (strchr(descriptor, '$') != NULL) {
958 LOG(INFO) << "VFY: unable to find class referenced in signature ("
959 << descriptor << ")";
960 } else {
961 LOG(ERROR) << "VFY: unable to find class referenced in signature ("
962 << descriptor << ")";
963 }
964
965 /* Check if the descriptor is an array. */
966 if (descriptor[0] == '[') {
967 /*
968 * There should never be a problem loading primitive arrays.
969 */
970 if (descriptor[1] != 'L' && descriptor[1] != '[') {
971 LOG(ERROR) << "VFY: invalid char in signature in '" << descriptor
972 << "'";
973 *failure = VERIFY_ERROR_GENERIC;
974 }
975
976 /*
977 * Try to continue with base array type. This will let
978 * us pass basic stuff (e.g. get array len) that wouldn't
979 * fly with an Object. This is NOT correct if the
980 * missing type is a primitive array, but we should never
981 * have a problem loading those. (I'm not convinced this
982 * is correct or even useful. Just use Object here?)
983 */
984 klass = class_linker->FindClass("[Ljava/lang/Object;", class_loader);
985 } else if (descriptor[0] == 'L') {
986 /*
987 * We are looking at a non-array reference descriptor;
988 * try to continue with base reference type.
989 */
990 klass = class_linker->FindSystemClass("Ljava/lang/Object;");
991 } else {
992 /* We are looking at a primitive type. */
993 LOG(ERROR) << "VFY: invalid char in signature in '" << descriptor << "'";
994 *failure = VERIFY_ERROR_GENERIC;
995 }
996
997 if (klass == NULL) {
998 *failure = VERIFY_ERROR_GENERIC;
999 }
1000 }
1001
1002 if (klass->IsPrimitive()) {
1003 LOG(ERROR) << "VFY: invalid use of primitive type '" << descriptor << "'";
1004 *failure = VERIFY_ERROR_GENERIC;
1005 klass = NULL;
1006 }
1007
1008 return klass;
1009}
1010
1011Class* DexVerifier::LookupSignatureClass(const Method* method, std::string sig,
1012 VerifyError* failure) {
1013 assert(sig[0] == 'L');
1014 size_t end = sig.find(';');
1015
1016 if (end == std::string::npos) {
1017 LOG(ERROR) << "VFY: bad signature component '" << sig << "' (missing ';')";
1018 *failure = VERIFY_ERROR_GENERIC;
1019 return NULL;
1020 }
1021
1022 return LookupClassByDescriptor(method, sig.substr(0, end + 1).c_str(),
1023 failure);
1024}
1025
1026Class* DexVerifier::LookupSignatureArrayClass(const Method* method,
1027 std::string sig, VerifyError* failure) {
1028 assert(sig[0] == '[');
1029 size_t end = 0;
1030
1031 while (sig[end] == '[')
1032 end++;
1033
1034 if (sig[end] == 'L') {
1035 end = sig.find(';');
1036 if (end == std::string::npos) {
1037 LOG(ERROR) << "VFY: bad signature component '" << sig
1038 << "' (missing ';')";
1039 *failure = VERIFY_ERROR_GENERIC;
1040 return NULL;
1041 }
1042 }
1043
1044 return LookupClassByDescriptor(method, sig.substr(0, end + 1).c_str(),
1045 failure);
1046}
1047
1048bool DexVerifier::SetTypesFromSignature(VerifierData* vdata, RegType* reg_types)
1049{
1050 Method* method = vdata->method_;
1051 const DexFile* dex_file = vdata->dex_file_;
1052 const DexFile::CodeItem* code_item = vdata->code_item_;
1053 UninitInstanceMap* uninit_map = vdata->uninit_map_;
1054
1055 int arg_start = code_item->registers_size_ - code_item->ins_size_;
1056 int expected_args = code_item->ins_size_; /* long/double count as two */
1057 int actual_args = 0;
1058
1059 assert(arg_start >= 0); /* should have been verified earlier */
1060
1061 /*
1062 * Include the "this" pointer.
1063 */
1064 if (!method->IsStatic()) {
1065 /*
1066 * If this is a constructor for a class other than java.lang.Object,
1067 * mark the first ("this") argument as uninitialized. This restricts
1068 * field access until the superclass constructor is called.
1069 */
1070 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1071 Class* klass_object = class_linker->FindSystemClass("Ljava/lang/Object;");
1072 if (IsInitMethod(method) && method->GetDeclaringClass() != klass_object) {
1073 int idx = SetUninitInstance(uninit_map, kUninitThisArgAddr,
1074 method->GetDeclaringClass());
1075 assert(idx == 0);
1076 reg_types[arg_start + actual_args] = RegTypeFromUninitIndex(idx);
1077 } else {
1078 reg_types[arg_start + actual_args] =
1079 RegTypeFromClass(method->GetDeclaringClass());
1080 }
1081 actual_args++;
1082 }
1083
1084 const DexFile::ProtoId& proto_id =
1085 dex_file->GetProtoId(method->GetProtoIdx());
1086 DexFile::ParameterIterator iterator(*dex_file, proto_id);
1087 VerifyError failure = VERIFY_ERROR_NONE;
1088
1089 for (; iterator.HasNext(); iterator.Next()) {
1090 const char* descriptor = iterator.GetDescriptor();
1091
1092 if (descriptor == NULL) {
1093 break;
1094 }
1095
1096 if (actual_args >= expected_args) {
1097 LOG(ERROR) << "VFY: expected " << expected_args << " args, found more ("
1098 << descriptor << ")";
1099 return false;
1100 }
1101
1102 switch (*descriptor) {
1103 case 'L':
1104 case '[':
1105 /*
1106 * We assume that reference arguments are initialized. The
1107 * only way it could be otherwise (assuming the caller was
1108 * verified) is if the current method is <init>, but in that
1109 * case it's effectively considered initialized the instant
1110 * we reach here (in the sense that we can return without
1111 * doing anything or call virtual methods).
1112 */
1113 {
1114 Class* klass =
1115 LookupClassByDescriptor(method, descriptor, &failure);
1116 if (failure != VERIFY_ERROR_NONE)
1117 return false;
1118 reg_types[arg_start + actual_args] = RegTypeFromClass(klass);
1119 }
1120 actual_args++;
1121 break;
1122 case 'Z':
1123 reg_types[arg_start + actual_args] = kRegTypeBoolean;
1124 actual_args++;
1125 break;
1126 case 'C':
1127 reg_types[arg_start + actual_args] = kRegTypeChar;
1128 actual_args++;
1129 break;
1130 case 'B':
1131 reg_types[arg_start + actual_args] = kRegTypeByte;
1132 actual_args++;
1133 break;
1134 case 'I':
1135 reg_types[arg_start + actual_args] = kRegTypeInteger;
1136 actual_args++;
1137 break;
1138 case 'S':
1139 reg_types[arg_start + actual_args] = kRegTypeShort;
1140 actual_args++;
1141 break;
1142 case 'F':
1143 reg_types[arg_start + actual_args] = kRegTypeFloat;
1144 actual_args++;
1145 break;
1146 case 'D':
1147 reg_types[arg_start + actual_args] = kRegTypeDoubleLo;
1148 reg_types[arg_start + actual_args +1] = kRegTypeDoubleHi;
1149 actual_args += 2;
1150 break;
1151 case 'J':
1152 reg_types[arg_start + actual_args] = kRegTypeLongLo;
1153 reg_types[arg_start + actual_args +1] = kRegTypeLongHi;
1154 actual_args += 2;
1155 break;
1156 default:
1157 LOG(ERROR) << "VFY: unexpected signature type char '" << descriptor
1158 << "'";
1159 return false;
1160 }
1161 }
1162
1163 if (actual_args != expected_args) {
1164 LOG(ERROR) << "VFY: expected " << expected_args << " args, found "
1165 << actual_args;
jeffhaoba5ebb92011-08-25 17:24:37 -07001166 return false;
1167 }
1168
jeffhaobdb76512011-09-07 11:43:16 -07001169 const char* descriptor = dex_file->GetReturnTypeDescriptor(proto_id);
1170
1171 /*
1172 * Validate return type. We don't do the type lookup; just want to make
1173 * sure that it has the right format. Only major difference from the
1174 * method argument format is that 'V' is supported.
1175 */
1176 switch (*descriptor) {
1177 case 'I':
1178 case 'C':
1179 case 'S':
1180 case 'B':
1181 case 'Z':
1182 case 'V':
1183 case 'F':
1184 case 'D':
1185 case 'J':
1186 if (*(descriptor + 1) != '\0')
1187 return false;
1188 break;
1189 case '[':
1190 /* single/multi, object/primitive */
1191 while (*++descriptor == '[')
1192 ;
1193 if (*descriptor == 'L') {
1194 while (*++descriptor != ';' && *descriptor != '\0')
1195 ;
1196 if (*descriptor != ';')
1197 return false;
1198 } else {
1199 if (*(descriptor+1) != '\0')
1200 return false;
1201 }
1202 break;
1203 case 'L':
1204 /* could be more thorough here, but shouldn't be required */
1205 while (*++descriptor != ';' && *descriptor != '\0')
1206 ;
1207 if (*descriptor != ';')
1208 return false;
1209 break;
1210 default:
1211 return false;
1212 }
1213
jeffhaoba5ebb92011-08-25 17:24:37 -07001214 return true;
1215}
1216
jeffhaobdb76512011-09-07 11:43:16 -07001217int DexVerifier::SetUninitInstance(UninitInstanceMap* uninit_map, int addr,
1218 Class* klass) {
1219 int idx;
1220 assert(klass != NULL);
1221
1222 /* TODO: binary search when numEntries > 8 */
1223 for (idx = uninit_map->num_entries_ - 1; idx >= 0; idx--) {
1224 if (uninit_map->map_[idx].addr_ == addr) {
1225 if (uninit_map->map_[idx].klass_ != NULL &&
1226 uninit_map->map_[idx].klass_ != klass) {
1227 LOG(ERROR) << "VFY: addr " << addr << " already set to "
1228 << (int) uninit_map->map_[idx].klass_ << ", not setting to "
1229 << (int) klass;
1230 return -1; // already set to something else??
1231 }
1232 uninit_map->map_[idx].klass_ = klass;
1233 return idx;
1234 }
1235 }
1236
1237 LOG(ERROR) << "VFY: addr " << addr << " not found in uninit map";
1238 assert(false); // shouldn't happen
1239 return -1;
1240}
1241
1242bool DexVerifier::CodeFlowVerifyMethod(VerifierData* vdata,
1243 RegisterTable* reg_table) {
1244 const Method* method = vdata->method_;
1245 const DexFile::CodeItem* code_item = vdata->code_item_;
1246 InsnFlags* insn_flags = vdata->insn_flags_;
1247 const uint16_t* insns = code_item->insns_;
jeffhaoba5ebb92011-08-25 17:24:37 -07001248 uint32_t insns_size = code_item->insns_size_;
jeffhaobdb76512011-09-07 11:43:16 -07001249 size_t insn_idx, start_guess;
jeffhaoba5ebb92011-08-25 17:24:37 -07001250
jeffhaobdb76512011-09-07 11:43:16 -07001251 /* Begin by marking the first instruction as "changed". */
1252 InsnSetChanged(insn_flags, 0, true);
jeffhaoba5ebb92011-08-25 17:24:37 -07001253
jeffhaobdb76512011-09-07 11:43:16 -07001254 start_guess = 0;
jeffhaoba5ebb92011-08-25 17:24:37 -07001255
jeffhaobdb76512011-09-07 11:43:16 -07001256 /* Continue until no instructions are marked "changed". */
1257 while (true) {
1258 /*
1259 * Find the first marked one. Use "start_guess" as a way to find
1260 * one quickly.
1261 */
1262 for (insn_idx = start_guess; insn_idx < insns_size; insn_idx++) {
1263 if (InsnIsChanged(insn_flags, insn_idx))
1264 break;
1265 }
jeffhaoba5ebb92011-08-25 17:24:37 -07001266
jeffhaobdb76512011-09-07 11:43:16 -07001267 if (insn_idx == insns_size) {
1268 if (start_guess != 0) {
1269 /* try again, starting from the top */
1270 start_guess = 0;
1271 continue;
1272 } else {
1273 /* all flags are clear */
1274 break;
1275 }
1276 }
1277
1278 /*
1279 * We carry the working set of registers from instruction to
1280 * instruction. If this address can be the target of a branch
1281 * (or throw) instruction, or if we're skipping around chasing
1282 * "changed" flags, we need to load the set of registers from
1283 * the table.
1284 *
1285 * Because we always prefer to continue on to the next instruction,
1286 * we should never have a situation where we have a stray
1287 * "changed" flag set on an instruction that isn't a branch target.
1288 */
1289 if (InsnIsBranchTarget(insn_flags, insn_idx)) {
1290 RegisterLine* work_line = &reg_table->work_line_;
1291 CopyLineFromTable(work_line, reg_table, insn_idx);
1292 } else {
1293#ifndef NDEBUG
1294 /*
1295 * Sanity check: retrieve the stored register line (assuming
1296 * a full table) and make sure it actually matches.
1297 */
1298 RegisterLine* register_line = GetRegisterLine(reg_table, insn_idx);
1299 if (register_line->reg_types_ != NULL && CompareLineToTable(reg_table,
1300 insn_idx, &reg_table->work_line_) != 0) {
1301 Class* klass = method->GetDeclaringClass();
1302 LOG(ERROR) << "HUH? work_line diverged in "
1303 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1304 << method->GetName()->ToModifiedUtf8() << " "
1305 << method->GetSignature()->ToModifiedUtf8();
1306 }
1307#endif
1308 }
1309
1310 if (!CodeFlowVerifyInstruction(vdata, reg_table, insn_idx, &start_guess)) {
1311 Class* klass = method->GetDeclaringClass();
1312 LOG(ERROR) << "VFY: failure to verify "
1313 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1314 << method->GetName()->ToModifiedUtf8() << " "
1315 << method->GetSignature()->ToModifiedUtf8();
jeffhaoba5ebb92011-08-25 17:24:37 -07001316 return false;
1317 }
1318
jeffhaobdb76512011-09-07 11:43:16 -07001319 /* Clear "changed" and mark as visited. */
1320 InsnSetVisited(insn_flags, insn_idx, true);
1321 InsnSetChanged(insn_flags, insn_idx, false);
1322 }
jeffhaoba5ebb92011-08-25 17:24:37 -07001323
jeffhaobdb76512011-09-07 11:43:16 -07001324 if (DEAD_CODE_SCAN && ((method->GetAccessFlags() & kAccWritable) == 0)) {
1325 /*
1326 * Scan for dead code. There's nothing "evil" about dead code
1327 * (besides the wasted space), but it indicates a flaw somewhere
1328 * down the line, possibly in the verifier.
1329 *
1330 * If we've substituted "always throw" instructions into the stream,
1331 * we are almost certainly going to have some dead code.
1332 */
1333 int dead_start = -1;
1334 for (insn_idx = 0; insn_idx < insns_size;
1335 insn_idx += InsnGetWidth(insn_flags, insn_idx)) {
1336 /*
1337 * Switch-statement data doesn't get "visited" by scanner. It
1338 * may or may not be preceded by a padding NOP (for alignment).
1339 */
1340 if (insns[insn_idx] == Instruction::kPackedSwitchSignature ||
1341 insns[insn_idx] == Instruction::kSparseSwitchSignature ||
1342 insns[insn_idx] == Instruction::kArrayDataSignature ||
1343 (insns[insn_idx] == Instruction::NOP &&
1344 (insns[insn_idx + 1] == Instruction::kPackedSwitchSignature ||
1345 insns[insn_idx + 1] == Instruction::kSparseSwitchSignature ||
1346 insns[insn_idx + 1] == Instruction::kArrayDataSignature))) {
1347 InsnSetVisited(insn_flags, insn_idx, true);
1348 }
1349
1350 if (!InsnIsVisited(insn_flags, insn_idx)) {
1351 if (dead_start < 0)
1352 dead_start = insn_idx;
1353 } else if (dead_start >= 0) {
1354 Class* klass = method->GetDeclaringClass();
1355 LOG(INFO) << "VFY: dead code 0x" << std::hex << dead_start << "-"
1356 << insn_idx - 1 << std::dec << " in "
1357 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1358 << method->GetName()->ToModifiedUtf8() << " "
1359 << method->GetSignature()->ToModifiedUtf8();
1360 dead_start = -1;
1361 }
1362 }
1363 if (dead_start >= 0) {
1364 Class* klass = method->GetDeclaringClass();
1365 LOG(INFO) << "VFY: dead code 0x" << std::hex << dead_start << "-"
1366 << insn_idx - 1 << std::dec << " in "
1367 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1368 << method->GetName()->ToModifiedUtf8() << " "
1369 << method->GetSignature()->ToModifiedUtf8();
jeffhaoba5ebb92011-08-25 17:24:37 -07001370 }
1371 }
1372
jeffhaobdb76512011-09-07 11:43:16 -07001373 return true;
1374}
1375
1376bool DexVerifier::CodeFlowVerifyInstruction(VerifierData* vdata,
1377 RegisterTable* reg_table, uint32_t insn_idx, size_t* start_guess) {
1378 const Method* method = vdata->method_;
1379 Class* klass = method->GetDeclaringClass();
1380 const DexFile::CodeItem* code_item = vdata->code_item_;
1381 InsnFlags* insn_flags = vdata->insn_flags_;
1382 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1383 UninitInstanceMap* uninit_map = vdata->uninit_map_;
1384 const uint16_t* insns = code_item->insns_ + insn_idx;
1385 uint32_t insns_size = code_item->insns_size_;
1386 uint32_t registers_size = code_item->registers_size_;
1387
1388#ifdef VERIFIER_STATS
1389 if (InsnIsVisited(insn_flags, insn_idx)) {
1390 gDvm.verifierStats.instrsReexamined++;
1391 } else {
1392 gDvm.verifierStats.instrsExamined++;
1393 }
1394#endif
1395
1396 /*
1397 * Once we finish decoding the instruction, we need to figure out where
1398 * we can go from here. There are three possible ways to transfer
1399 * control to another statement:
1400 *
1401 * (1) Continue to the next instruction. Applies to all but
1402 * unconditional branches, method returns, and exception throws.
1403 * (2) Branch to one or more possible locations. Applies to branches
1404 * and switch statements.
1405 * (3) Exception handlers. Applies to any instruction that can
1406 * throw an exception that is handled by an encompassing "try"
1407 * block.
1408 *
1409 * We can also return, in which case there is no successor instruction
1410 * from this point.
1411 *
1412 * The behavior can be determined from the OpcodeFlags.
1413 */
1414 RegisterLine* work_line = &reg_table->work_line_;
1415 const DexFile* dex_file = vdata->dex_file_;
1416 const byte* ptr = reinterpret_cast<const byte*>(insns);
1417 const Instruction* inst = Instruction::At(ptr);
1418 Instruction::DecodedInstruction dec_insn(inst);
1419 int opcode_flag = inst->Flag();
1420
1421 Class* res_class;
1422 int32_t branch_target = 0;
1423 RegType tmp_type;
1424 bool just_set_result = false;
1425 VerifyError failure = VERIFY_ERROR_NONE;
1426
1427 /*
1428 * Make a copy of the previous register state. If the instruction
1429 * can throw an exception, we will copy/merge this into the "catch"
1430 * address rather than work_line, because we don't want the result
1431 * from the "successful" code path (e.g. a check-cast that "improves"
1432 * a type) to be visible to the exception handler.
1433 */
1434 if ((opcode_flag & Instruction::kThrow) != 0 &&
1435 InsnIsInTry(insn_flags, insn_idx)) {
1436 CopyRegisterLine(&reg_table->saved_line_, work_line,
1437 reg_table->insn_reg_count_plus_);
1438 } else {
1439#ifndef NDEBUG
1440 memset(reg_table->saved_line_.reg_types_, 0xdd,
1441 reg_table->insn_reg_count_plus_ * sizeof(RegType));
1442#endif
1443 }
1444
1445 switch (dec_insn.opcode_) {
1446 case Instruction::NOP:
1447 /*
1448 * A "pure" NOP has no effect on anything. Data tables start with
1449 * a signature that looks like a NOP; if we see one of these in
1450 * the course of executing code then we have a problem.
1451 */
1452 if (dec_insn.vA_ != 0) {
1453 LOG(ERROR) << "VFY: encountered data table in instruction stream";
1454 failure = VERIFY_ERROR_GENERIC;
1455 }
1456 break;
1457
1458 case Instruction::MOVE:
1459 case Instruction::MOVE_FROM16:
1460 case Instruction::MOVE_16:
1461 CopyRegister1(work_line, dec_insn.vA_, dec_insn.vB_, kTypeCategory1nr,
1462 &failure);
1463 break;
1464 case Instruction::MOVE_WIDE:
1465 case Instruction::MOVE_WIDE_FROM16:
1466 case Instruction::MOVE_WIDE_16:
1467 CopyRegister2(work_line, dec_insn.vA_, dec_insn.vB_, &failure);
1468 break;
1469 case Instruction::MOVE_OBJECT:
1470 case Instruction::MOVE_OBJECT_FROM16:
1471 case Instruction::MOVE_OBJECT_16:
1472 CopyRegister1(work_line, dec_insn.vA_, dec_insn.vB_, kTypeCategoryRef,
1473 &failure);
1474 break;
1475
1476 /*
1477 * The move-result instructions copy data out of a "pseudo-register"
1478 * with the results from the last method invocation. In practice we
1479 * might want to hold the result in an actual CPU register, so the
1480 * Dalvik spec requires that these only appear immediately after an
1481 * invoke or filled-new-array.
1482 *
1483 * These calls invalidate the "result" register. (This is now
1484 * redundant with the reset done below, but it can make the debug info
1485 * easier to read in some cases.)
1486 */
1487 case Instruction::MOVE_RESULT:
1488 CopyResultRegister1(work_line, registers_size, dec_insn.vA_,
1489 kTypeCategory1nr, &failure);
1490 break;
1491 case Instruction::MOVE_RESULT_WIDE:
1492 CopyResultRegister2(work_line, registers_size, dec_insn.vA_, &failure);
1493 break;
1494 case Instruction::MOVE_RESULT_OBJECT:
1495 CopyResultRegister1(work_line, registers_size, dec_insn.vA_,
1496 kTypeCategoryRef, &failure);
1497 break;
1498
1499 case Instruction::MOVE_EXCEPTION:
1500 /*
1501 * This statement can only appear as the first instruction in an
1502 * exception handler (though not all exception handlers need to
1503 * have one of these). We verify that as part of extracting the
1504 * exception type from the catch block list.
1505 *
1506 * "res_class" will hold the closest common superclass of all
1507 * exceptions that can be handled here.
1508 */
1509 res_class = GetCaughtExceptionType(vdata, insn_idx, &failure);
1510 if (res_class == NULL) {
1511 assert(failure != VERIFY_ERROR_NONE);
1512 } else {
1513 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1514 }
1515 break;
1516
1517 case Instruction::RETURN_VOID:
1518 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1519 failure = VERIFY_ERROR_GENERIC;
1520 } else if (GetMethodReturnType(dex_file, method) != kRegTypeUnknown) {
1521 LOG(ERROR) << "VFY: return-void not expected";
1522 failure = VERIFY_ERROR_GENERIC;
1523 }
1524 break;
1525 case Instruction::RETURN:
1526 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1527 failure = VERIFY_ERROR_GENERIC;
1528 } else {
1529 /* check the method signature */
1530 RegType return_type = GetMethodReturnType(dex_file, method);
1531 CheckTypeCategory(return_type, kTypeCategory1nr, &failure);
1532 if (failure != VERIFY_ERROR_NONE)
1533 LOG(ERROR) << "VFY: return-1nr not expected";
1534
1535 /*
1536 * compiler may generate synthetic functions that write byte
1537 * values into boolean fields. Also, it may use integer values
1538 * for boolean, byte, short, and character return types.
1539 */
1540 RegType src_type = GetRegisterType(work_line, dec_insn.vA_);
1541 if ((return_type == kRegTypeBoolean && src_type == kRegTypeByte) ||
1542 ((return_type == kRegTypeBoolean || return_type == kRegTypeByte ||
1543 return_type == kRegTypeShort || return_type == kRegTypeChar) &&
1544 src_type == kRegTypeInteger))
1545 return_type = src_type;
1546
1547 /* check the register contents */
1548 VerifyRegisterType(work_line, dec_insn.vA_, return_type, &failure);
1549 if (failure != VERIFY_ERROR_NONE) {
1550 LOG(ERROR) << "VFY: return-1nr on invalid register v" << dec_insn.vA_;
1551 }
1552 }
1553 break;
1554 case Instruction::RETURN_WIDE:
1555 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1556 failure = VERIFY_ERROR_GENERIC;
1557 } else {
1558 RegType return_type;
1559
1560 /* check the method signature */
1561 return_type = GetMethodReturnType(dex_file, method);
1562 CheckTypeCategory(return_type, kTypeCategory2, &failure);
1563 if (failure != VERIFY_ERROR_NONE)
1564 LOG(ERROR) << "VFY: return-wide not expected";
1565
1566 /* check the register contents */
1567 VerifyRegisterType(work_line, dec_insn.vA_, return_type, &failure);
1568 if (failure != VERIFY_ERROR_NONE) {
1569 LOG(ERROR) << "VFY: return-wide on invalid register pair v"
1570 << dec_insn.vA_;
1571 }
1572 }
1573 break;
1574 case Instruction::RETURN_OBJECT:
1575 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1576 failure = VERIFY_ERROR_GENERIC;
1577 } else {
1578 RegType return_type = GetMethodReturnType(dex_file, method);
1579 CheckTypeCategory(return_type, kTypeCategoryRef, &failure);
1580 if (failure != VERIFY_ERROR_NONE) {
1581 LOG(ERROR) << "VFY: return-object not expected";
1582 break;
1583 }
1584
1585 /* return_type is the *expected* return type, not register value */
1586 assert(return_type != kRegTypeZero);
1587 assert(!RegTypeIsUninitReference(return_type));
1588
1589 /*
1590 * Verify that the reference in vAA is an instance of the type
1591 * in "return_type". The Zero type is allowed here. If the
1592 * method is declared to return an interface, then any
1593 * initialized reference is acceptable.
1594 *
1595 * Note GetClassFromRegister fails if the register holds an
1596 * uninitialized reference, so we do not allow them to be
1597 * returned.
1598 */
1599 Class* decl_class = RegTypeInitializedReferenceToClass(return_type);
1600 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1601 if (failure != VERIFY_ERROR_NONE)
1602 break;
1603 if (res_class != NULL) {
1604 if (!decl_class->IsInterface() &&
1605 //!res_class->InstanceOf(decl_class)) {
1606 !decl_class->IsAssignableFrom(res_class)) {
1607 LOG(ERROR) << "VFY: returning " << std::hex
1608 << res_class->GetDescriptor()->ToModifiedUtf8()
1609 << " (cl=0x" << (int) res_class->GetClassLoader()
1610 << "), declared "
1611 << decl_class->GetDescriptor()->ToModifiedUtf8()
1612 << " (cl=0x" << (int) decl_class->GetClassLoader()
1613 << ")" << std::dec;
1614 failure = VERIFY_ERROR_GENERIC;
1615 break;
1616 }
1617 }
1618 }
1619 break;
1620
1621 case Instruction::CONST_4:
1622 case Instruction::CONST_16:
1623 case Instruction::CONST:
1624 /* could be boolean, int, float, or a null reference */
1625 SetRegisterType(work_line, dec_insn.vA_,
1626 DetermineCat1Const((int32_t) dec_insn.vB_));
1627 break;
1628 case Instruction::CONST_HIGH16:
1629 /* could be boolean, int, float, or a null reference */
1630 SetRegisterType(work_line, dec_insn.vA_,
1631 DetermineCat1Const((int32_t) dec_insn.vB_ << 16));
1632 break;
1633 case Instruction::CONST_WIDE_16:
1634 case Instruction::CONST_WIDE_32:
1635 case Instruction::CONST_WIDE:
1636 case Instruction::CONST_WIDE_HIGH16:
1637 /* could be long or double; resolved upon use */
1638 SetRegisterType(work_line, dec_insn.vA_, kRegTypeConstLo);
1639 break;
1640 case Instruction::CONST_STRING:
1641 case Instruction::CONST_STRING_JUMBO:
1642 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
1643 class_linker->FindSystemClass("Ljava/lang/String;")));
1644 break;
1645 case Instruction::CONST_CLASS:
1646 /* make sure we can resolve the class; access check is important */
1647 res_class = class_linker->ResolveType(*dex_file, dec_insn.vB_, klass);
1648 if (res_class == NULL) {
1649 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1650 LOG(ERROR) << "VFY: unable to resolve const-class " << dec_insn.vB_
1651 << " (" << bad_class_desc << ") in "
1652 << klass->GetDescriptor()->ToModifiedUtf8();
1653 assert(failure != VERIFY_ERROR_GENERIC);
1654 } else {
1655 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
1656 class_linker->FindSystemClass("Ljava/lang/Class;")));
1657 }
1658 break;
1659
1660 case Instruction::MONITOR_ENTER:
1661 HandleMonitorEnter(work_line, dec_insn.vA_, insn_idx, &failure);
1662 break;
1663 case Instruction::MONITOR_EXIT:
1664 /*
1665 * monitor-exit instructions are odd. They can throw exceptions,
1666 * but when they do they act as if they succeeded and the PC is
1667 * pointing to the following instruction. (This behavior goes back
1668 * to the need to handle asynchronous exceptions, a now-deprecated
1669 * feature that Dalvik doesn't support.)
1670 *
1671 * In practice we don't need to worry about this. The only
1672 * exceptions that can be thrown from monitor-exit are for a
1673 * null reference and -exit without a matching -enter. If the
1674 * structured locking checks are working, the former would have
1675 * failed on the -enter instruction, and the latter is impossible.
1676 *
1677 * This is fortunate, because issue 3221411 prevents us from
1678 * chasing the "can throw" path when monitor verification is
1679 * enabled. If we can fully verify the locking we can ignore
1680 * some catch blocks (which will show up as "dead" code when
1681 * we skip them here); if we can't, then the code path could be
1682 * "live" so we still need to check it.
1683 */
1684 if (work_line->monitor_entries_ != NULL)
1685 opcode_flag &= ~Instruction::kThrow;
1686 HandleMonitorExit(work_line, dec_insn.vA_, insn_idx, &failure);
1687 break;
1688
1689 case Instruction::CHECK_CAST:
1690 /*
1691 * If this instruction succeeds, we will promote register vA to
1692 * the type in vB. (This could be a demotion -- not expected, so
1693 * we don't try to address it.)
1694 *
1695 * If it fails, an exception is thrown, which we deal with later
1696 * by ignoring the update to dec_insn.vA_ when branching to a handler.
1697 */
1698 res_class = class_linker->ResolveType(*dex_file, dec_insn.vB_, klass);
1699 if (res_class == NULL) {
1700 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1701 LOG(ERROR) << "VFY: unable to resolve check-cast " << dec_insn.vB_
1702 << " (" << bad_class_desc << ") in "
1703 << klass->GetDescriptor()->ToModifiedUtf8();
1704 assert(failure != VERIFY_ERROR_GENERIC);
1705 } else {
1706 RegType orig_type;
1707
1708 orig_type = GetRegisterType(work_line, dec_insn.vA_);
1709 if (!RegTypeIsReference(orig_type)) {
1710 LOG(ERROR) << "VFY: check-cast on non-reference in v" << dec_insn.vA_;
1711 failure = VERIFY_ERROR_GENERIC;
1712 break;
1713 }
1714 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1715 }
1716 break;
1717 case Instruction::INSTANCE_OF:
1718 /* make sure we're checking a reference type */
1719 tmp_type = GetRegisterType(work_line, dec_insn.vB_);
1720 if (!RegTypeIsReference(tmp_type)) {
1721 LOG(ERROR) << "VFY: vB not a reference (" << tmp_type << ")";
1722 failure = VERIFY_ERROR_GENERIC;
1723 break;
1724 }
1725
1726 /* make sure we can resolve the class; access check is important */
1727 res_class = class_linker->ResolveType(*dex_file, dec_insn.vC_, klass);
1728 if (res_class == NULL) {
1729 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vC_);
1730 LOG(ERROR) << "VFY: unable to resolve instanceof " << dec_insn.vC_
1731 << " (" << bad_class_desc << ") in "
1732 << klass->GetDescriptor()->ToModifiedUtf8();
1733 assert(failure != VERIFY_ERROR_GENERIC);
1734 } else {
1735 /* result is boolean */
1736 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1737 }
1738 break;
1739
1740 case Instruction::ARRAY_LENGTH:
1741 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
1742 if (failure != VERIFY_ERROR_NONE)
1743 break;
1744 if (res_class != NULL && !res_class->IsArrayClass()) {
1745 LOG(ERROR) << "VFY: array-length on non-array";
1746 failure = VERIFY_ERROR_GENERIC;
1747 break;
1748 }
1749 SetRegisterType(work_line, dec_insn.vA_, kRegTypeInteger);
1750 break;
1751
1752 case Instruction::NEW_INSTANCE:
1753 res_class = class_linker->ResolveType(*dex_file, dec_insn.vB_, klass);
1754 if (res_class == NULL) {
1755 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1756 LOG(ERROR) << "VFY: unable to resolve new-instance " << dec_insn.vB_
1757 << " (" << bad_class_desc << ") in "
1758 << klass->GetDescriptor()->ToModifiedUtf8();
1759 assert(failure != VERIFY_ERROR_GENERIC);
1760 } else {
1761 RegType uninit_type;
1762
1763 /* can't create an instance of an interface or abstract class */
1764 if (res_class->IsAbstract() || res_class->IsInterface()) {
1765 LOG(ERROR) << "VFY: new-instance on interface or abstract class"
1766 << res_class->GetDescriptor()->ToModifiedUtf8();
1767 failure = VERIFY_ERROR_INSTANTIATION;
1768 break;
1769 }
1770
1771 /* add resolved class to uninit map if not already there */
1772 int uidx = SetUninitInstance(uninit_map, insn_idx, res_class);
1773 assert(uidx >= 0);
1774 uninit_type = RegTypeFromUninitIndex(uidx);
1775
1776 /*
1777 * Any registers holding previous allocations from this address
1778 * that have not yet been initialized must be marked invalid.
1779 */
1780 MarkUninitRefsAsInvalid(work_line, registers_size, uninit_map,
1781 uninit_type);
1782
1783 /* add the new uninitialized reference to the register ste */
1784 SetRegisterType(work_line, dec_insn.vA_, uninit_type);
1785 }
1786 break;
1787 case Instruction::NEW_ARRAY:
1788 res_class = class_linker->ResolveType(*dex_file, dec_insn.vC_, klass);
1789 if (res_class == NULL) {
1790 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vC_);
1791 LOG(ERROR) << "VFY: unable to resolve new-array " << dec_insn.vC_
1792 << " (" << bad_class_desc << ") in "
1793 << klass->GetDescriptor()->ToModifiedUtf8();
1794 assert(failure != VERIFY_ERROR_GENERIC);
1795 } else if (!res_class->IsArrayClass()) {
1796 LOG(ERROR) << "VFY: new-array on non-array class";
1797 failure = VERIFY_ERROR_GENERIC;
1798 } else {
1799 /* make sure "size" register is valid type */
1800 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeInteger, &failure);
1801 /* set register type to array class */
1802 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1803 }
1804 break;
1805 case Instruction::FILLED_NEW_ARRAY:
1806 case Instruction::FILLED_NEW_ARRAY_RANGE:
1807 res_class = class_linker->ResolveType(*dex_file, dec_insn.vB_, klass);
1808 if (res_class == NULL) {
1809 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1810 LOG(ERROR) << "VFY: unable to resolve filled-array " << dec_insn.vB_
1811 << " (" << bad_class_desc << ") in "
1812 << klass->GetDescriptor()->ToModifiedUtf8();
1813 assert(failure != VERIFY_ERROR_GENERIC);
1814 } else if (!res_class->IsArrayClass()) {
1815 LOG(ERROR) << "VFY: filled-new-array on non-array class";
1816 failure = VERIFY_ERROR_GENERIC;
1817 } else {
1818 bool is_range = (dec_insn.opcode_ ==
1819 Instruction::FILLED_NEW_ARRAY_RANGE);
1820
1821 /* check the arguments to the instruction */
1822 VerifyFilledNewArrayRegs(method, work_line, &dec_insn, res_class,
1823 is_range, &failure);
1824 /* filled-array result goes into "result" register */
1825 SetResultRegisterType(work_line, registers_size,
1826 RegTypeFromClass(res_class));
1827 just_set_result = true;
1828 }
1829 break;
1830
1831 case Instruction::CMPL_FLOAT:
1832 case Instruction::CMPG_FLOAT:
1833 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeFloat, &failure);
1834 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeFloat, &failure);
1835 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1836 break;
1837 case Instruction::CMPL_DOUBLE:
1838 case Instruction::CMPG_DOUBLE:
1839 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeDoubleLo, &failure);
1840 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeDoubleLo, &failure);
1841 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1842 break;
1843 case Instruction::CMP_LONG:
1844 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeLongLo, &failure);
1845 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeLongLo, &failure);
1846 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1847 break;
1848
1849 case Instruction::THROW:
1850 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1851 if (failure == VERIFY_ERROR_NONE && res_class != NULL) {
1852 Class* throwable_class =
1853 class_linker->FindSystemClass("Ljava/lang/Throwable;");
1854 if (!throwable_class->IsAssignableFrom(res_class)) {
1855 LOG(ERROR) << "VFY: thrown class "
1856 << res_class->GetDescriptor()->ToModifiedUtf8()
1857 << " not instanceof Throwable",
1858 failure = VERIFY_ERROR_GENERIC;
1859 }
1860 }
1861 break;
1862
1863 case Instruction::GOTO:
1864 case Instruction::GOTO_16:
1865 case Instruction::GOTO_32:
1866 /* no effect on or use of registers */
1867 break;
1868
1869 case Instruction::PACKED_SWITCH:
1870 case Instruction::SPARSE_SWITCH:
1871 /* verify that vAA is an integer, or can be converted to one */
1872 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeInteger, &failure);
1873 break;
1874
1875 case Instruction::FILL_ARRAY_DATA:
1876 {
1877 RegType value_type;
1878 const uint16_t *array_data;
1879 uint16_t elem_width;
1880
1881 /* Similar to the verification done for APUT */
1882 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1883 if (failure != VERIFY_ERROR_NONE)
1884 break;
1885
1886 /* res_class can be null if the reg type is Zero */
1887 if (res_class == NULL)
1888 break;
1889
1890 Class::PrimitiveType prim_type =
1891 res_class->GetComponentType()->GetPrimitiveType();
1892 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
1893 prim_type == Class::kPrimNot || prim_type == Class::kPrimVoid) {
1894 LOG(ERROR) << "VFY: invalid fill-array-data on " <<
1895 res_class->GetDescriptor()->ToModifiedUtf8();
1896 failure = VERIFY_ERROR_GENERIC;
1897 break;
1898 }
1899
1900 value_type = PrimitiveTypeToRegType(prim_type);
1901 assert(value_type != kRegTypeUnknown);
1902
1903 /*
1904 * Now verify if the element width in the table matches the element
1905 * width declared in the array
1906 */
1907 array_data = insns + (insns[1] | (((int32_t) insns[2]) << 16));
1908 if (array_data[0] != Instruction::kArrayDataSignature) {
1909 LOG(ERROR) << "VFY: invalid magic for array-data";
1910 failure = VERIFY_ERROR_GENERIC;
1911 break;
1912 }
1913
1914 switch (prim_type) {
1915 case Class::kPrimBoolean:
1916 case Class::kPrimByte:
1917 elem_width = 1;
1918 break;
1919 case Class::kPrimChar:
1920 case Class::kPrimShort:
1921 elem_width = 2;
1922 break;
1923 case Class::kPrimFloat:
1924 case Class::kPrimInt:
1925 elem_width = 4;
1926 break;
1927 case Class::kPrimDouble:
1928 case Class::kPrimLong:
1929 elem_width = 8;
1930 break;
1931 default:
1932 elem_width = 0;
1933 break;
1934 }
1935
1936 /*
1937 * Since we don't compress the data in Dex, expect to see equal
1938 * width of data stored in the table and expected from the array
1939 * class.
1940 */
1941 if (array_data[1] != elem_width) {
1942 LOG(ERROR) << "VFY: array-data size mismatch (" << array_data[1]
1943 << " vs " << elem_width << ")";
1944 failure = VERIFY_ERROR_GENERIC;
1945 }
1946 }
1947 break;
1948
1949 case Instruction::IF_EQ:
1950 case Instruction::IF_NE:
1951 {
1952 RegType type1, type2;
1953
1954 type1 = GetRegisterType(work_line, dec_insn.vA_);
1955 type2 = GetRegisterType(work_line, dec_insn.vB_);
1956
1957 /* both references? */
1958 if (RegTypeIsReference(type1) && RegTypeIsReference(type2))
1959 break;
1960
1961 /* both category-1nr? */
1962 CheckTypeCategory(type1, kTypeCategory1nr, &failure);
1963 CheckTypeCategory(type2, kTypeCategory1nr, &failure);
1964 if (failure != VERIFY_ERROR_NONE) {
1965 LOG(ERROR) << "VFY: args to if-eq/if-ne must both be refs or cat1";
1966 break;
1967 }
1968 }
1969 break;
1970 case Instruction::IF_LT:
1971 case Instruction::IF_GE:
1972 case Instruction::IF_GT:
1973 case Instruction::IF_LE:
1974 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
1975 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1976 if (failure != VERIFY_ERROR_NONE) {
1977 LOG(ERROR) << "VFY: args to 'if' must be cat-1nr";
1978 break;
1979 }
1980 tmp_type = GetRegisterType(work_line, dec_insn.vB_);
1981 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1982 if (failure != VERIFY_ERROR_NONE) {
1983 LOG(ERROR) << "VFY: args to 'if' must be cat-1nr";
1984 break;
1985 }
1986 break;
1987 case Instruction::IF_EQZ:
1988 case Instruction::IF_NEZ:
1989 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
1990 if (RegTypeIsReference(tmp_type))
1991 break;
1992 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1993 if (failure != VERIFY_ERROR_NONE)
1994 LOG(ERROR) << "VFY: expected cat-1 arg to if";
1995 break;
1996 case Instruction::IF_LTZ:
1997 case Instruction::IF_GEZ:
1998 case Instruction::IF_GTZ:
1999 case Instruction::IF_LEZ:
2000 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
2001 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
2002 if (failure != VERIFY_ERROR_NONE)
2003 LOG(ERROR) << "VFY: expected cat-1 arg to if";
2004 break;
2005
2006 case Instruction::AGET:
2007 tmp_type = kRegTypeConstInteger;
2008 goto aget_1nr_common;
2009 case Instruction::AGET_BOOLEAN:
2010 tmp_type = kRegTypeBoolean;
2011 goto aget_1nr_common;
2012 case Instruction::AGET_BYTE:
2013 tmp_type = kRegTypeByte;
2014 goto aget_1nr_common;
2015 case Instruction::AGET_CHAR:
2016 tmp_type = kRegTypeChar;
2017 goto aget_1nr_common;
2018 case Instruction::AGET_SHORT:
2019 tmp_type = kRegTypeShort;
2020 goto aget_1nr_common;
2021aget_1nr_common:
2022 {
2023 RegType src_type, index_type;
2024
2025 index_type = GetRegisterType(work_line, dec_insn.vC_);
2026 CheckArrayIndexType(method, index_type, &failure);
2027 if (failure != VERIFY_ERROR_NONE)
2028 break;
2029
2030 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2031 if (failure != VERIFY_ERROR_NONE)
2032 break;
2033 if (res_class != NULL) {
2034 /* verify the class */
2035 Class::PrimitiveType prim_type =
2036 res_class->GetComponentType()->GetPrimitiveType();
2037 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
2038 prim_type == Class::kPrimNot) {
2039 LOG(ERROR) << "VFY: invalid aget-1nr target "
2040 << res_class->GetDescriptor()->ToModifiedUtf8();
2041 failure = VERIFY_ERROR_GENERIC;
2042 break;
2043 }
2044
2045 /* make sure array type matches instruction */
2046 src_type = PrimitiveTypeToRegType(prim_type);
2047
2048 /* differentiate between float and int */
2049 if (src_type == kRegTypeFloat || src_type == kRegTypeInteger)
2050 tmp_type = src_type;
2051
2052 if (tmp_type != src_type) {
2053 LOG(ERROR) << "VFY: invalid aget-1nr, array type=" << src_type
2054 << " with inst type=" << tmp_type << " (on "
2055 << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
2056 failure = VERIFY_ERROR_GENERIC;
2057 break;
2058 }
2059
2060 }
2061 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2062 }
2063 break;
2064
2065 case Instruction::AGET_WIDE:
2066 {
2067 RegType dst_type, index_type;
2068
2069 index_type = GetRegisterType(work_line, dec_insn.vC_);
2070 CheckArrayIndexType(method, index_type, &failure);
2071 if (failure != VERIFY_ERROR_NONE)
2072 break;
2073
2074 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2075 if (failure != VERIFY_ERROR_NONE)
2076 break;
2077 if (res_class != NULL) {
2078 /* verify the class */
2079 Class::PrimitiveType prim_type =
2080 res_class->GetComponentType()->GetPrimitiveType();
2081 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
2082 prim_type == Class::kPrimNot) {
2083 LOG(ERROR) << "VFY: invalid aget-wide target "
2084 << res_class->GetDescriptor()->ToModifiedUtf8();
2085 failure = VERIFY_ERROR_GENERIC;
2086 break;
2087 }
2088
2089 /* try to refine "dst_type" */
2090 switch (prim_type) {
2091 case Class::kPrimLong:
2092 dst_type = kRegTypeLongLo;
2093 break;
2094 case Class::kPrimDouble:
2095 dst_type = kRegTypeDoubleLo;
2096 break;
2097 default:
2098 LOG(ERROR) << "VFY: invalid aget-wide on "
2099 << res_class->GetDescriptor()->ToModifiedUtf8();
2100 dst_type = kRegTypeUnknown;
2101 failure = VERIFY_ERROR_GENERIC;
2102 break;
2103 }
2104 } else {
2105 /*
2106 * Null array ref; this code path will fail at runtime. We
2107 * know this is either long or double, so label it const.
2108 */
2109 dst_type = kRegTypeConstLo;
2110 }
2111 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2112 }
2113 break;
2114
2115 case Instruction::AGET_OBJECT:
2116 {
2117 RegType dst_type, index_type;
2118
2119 index_type = GetRegisterType(work_line, dec_insn.vC_);
2120 CheckArrayIndexType(method, index_type, &failure);
2121 if (failure != VERIFY_ERROR_NONE)
2122 break;
2123
2124 /* get the class of the array we're pulling an object from */
2125 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2126 if (failure != VERIFY_ERROR_NONE)
2127 break;
2128 if (res_class != NULL) {
2129 Class* element_class;
2130
2131 assert(res_class != NULL);
2132 if (!res_class->IsArrayClass()) {
2133 LOG(ERROR) << "VFY: aget-object on non-array class";
2134 failure = VERIFY_ERROR_GENERIC;
2135 break;
2136 }
2137 assert(res_class->GetComponentType() != NULL);
2138
2139 /*
2140 * Find the element class. res_class->GetComponentType() indicates
2141 * the basic type, which won't be what we want for a
2142 * multi-dimensional array.
2143 */
2144 if (res_class->GetDescriptor()->CharAt(1) == '[') {
2145 assert(res_class->GetArrayRank() > 1);
2146 std::string descriptor =
2147 res_class->GetDescriptor()->ToModifiedUtf8();
2148 element_class = class_linker->FindClass(descriptor.c_str() + 1,
2149 res_class->GetClassLoader());
2150 } else if (res_class->GetDescriptor()->CharAt(1) == 'L') {
2151 assert(res_class->GetArrayRank() == 1);
2152 element_class = res_class->GetComponentType();
2153 } else {
2154 LOG(ERROR) << "VFY: aget-object on non-ref array class ("
2155 << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
2156 failure = VERIFY_ERROR_GENERIC;
2157 break;
2158 }
2159
2160 dst_type = RegTypeFromClass(element_class);
2161 } else {
2162 /*
2163 * The array reference is NULL, so the current code path will
2164 * throw an exception. For proper merging with later code
2165 * paths, and correct handling of "if-eqz" tests on the
2166 * result of the array get, we want to treat this as a null
2167 * reference.
2168 */
2169 dst_type = kRegTypeZero;
2170 }
2171 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2172 }
2173 break;
2174 case Instruction::APUT:
2175 tmp_type = kRegTypeInteger;
2176 goto aput_1nr_common;
2177 case Instruction::APUT_BOOLEAN:
2178 tmp_type = kRegTypeBoolean;
2179 goto aput_1nr_common;
2180 case Instruction::APUT_BYTE:
2181 tmp_type = kRegTypeByte;
2182 goto aput_1nr_common;
2183 case Instruction::APUT_CHAR:
2184 tmp_type = kRegTypeChar;
2185 goto aput_1nr_common;
2186 case Instruction::APUT_SHORT:
2187 tmp_type = kRegTypeShort;
2188 goto aput_1nr_common;
2189aput_1nr_common:
2190 {
2191 RegType src_type, dst_type, index_type;
2192
2193 index_type = GetRegisterType(work_line, dec_insn.vC_);
2194 CheckArrayIndexType(method, index_type, &failure);
2195 if (failure != VERIFY_ERROR_NONE)
2196 break;
2197
2198 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2199 if (failure != VERIFY_ERROR_NONE)
2200 break;
2201
2202 /* res_class can be null if the reg type is Zero */
2203 if (res_class == NULL)
2204 break;
2205
2206 Class::PrimitiveType prim_type =
2207 res_class->GetComponentType()->GetPrimitiveType();
2208 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
2209 prim_type == Class::kPrimNot) {
2210 LOG(ERROR) << "VFY: invalid aput-1nr on "
2211 << res_class->GetDescriptor()->ToModifiedUtf8();
2212 failure = VERIFY_ERROR_GENERIC;
2213 break;
2214 }
2215
2216 /* verify that instruction matches array */
2217 dst_type = PrimitiveTypeToRegType(prim_type);
2218
2219 /* correct if float */
2220 if (dst_type == kRegTypeFloat)
2221 tmp_type = kRegTypeFloat;
2222
2223 /* make sure the source register has the correct type */
2224 src_type = GetRegisterType(work_line, dec_insn.vA_);
2225 if (!CanConvertTo1nr(src_type, tmp_type)) {
2226 LOG(ERROR) << "VFY: invalid reg type " << src_type
2227 << " on aput instr (need " << tmp_type << ")";
2228 failure = VERIFY_ERROR_GENERIC;
2229 break;
2230 }
2231
2232 VerifyRegisterType(work_line, dec_insn.vA_, dst_type, &failure);
2233
2234 if (failure != VERIFY_ERROR_NONE || dst_type == kRegTypeUnknown ||
2235 tmp_type != dst_type) {
2236 LOG(ERROR) << "VFY: invalid aput-1nr on "
2237 << res_class->GetDescriptor()->ToModifiedUtf8()
2238 << " (inst=" << tmp_type << " dst=" << dst_type << ")";
2239 failure = VERIFY_ERROR_GENERIC;
2240 break;
2241 }
2242 }
2243 break;
2244 case Instruction::APUT_WIDE:
2245 tmp_type = GetRegisterType(work_line, dec_insn.vC_);
2246 CheckArrayIndexType(method, tmp_type, &failure);
2247 if (failure != VERIFY_ERROR_NONE)
2248 break;
2249
2250 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2251 if (failure != VERIFY_ERROR_NONE)
2252 break;
2253 if (res_class != NULL) {
2254 Class::PrimitiveType prim_type =
2255 res_class->GetComponentType()->GetPrimitiveType();
2256 /* verify the class and try to refine "dst_type" */
2257 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
2258 prim_type == Class::kPrimNot)
2259 {
2260 LOG(ERROR) << "VFY: invalid aput-wide on "
2261 << res_class->GetDescriptor()->ToModifiedUtf8();
2262 failure = VERIFY_ERROR_GENERIC;
2263 break;
2264 }
2265
2266 switch (prim_type) {
2267 case Class::kPrimLong:
2268 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo,
2269 &failure);
2270 break;
2271 case Class::kPrimDouble:
2272 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2273 &failure);
2274 break;
2275 default:
2276 LOG(ERROR) << "VFY: invalid aput-wide on "
2277 << res_class->GetDescriptor()->ToModifiedUtf8();
2278 failure = VERIFY_ERROR_GENERIC;
2279 break;
2280 }
2281 }
2282 break;
2283 case Instruction::APUT_OBJECT:
2284 tmp_type = GetRegisterType(work_line, dec_insn.vC_);
2285 CheckArrayIndexType(method, tmp_type, &failure);
2286 if (failure != VERIFY_ERROR_NONE)
2287 break;
2288
2289 /* get the ref we're storing; Zero is okay, Uninit is not */
2290 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
2291 if (failure != VERIFY_ERROR_NONE)
2292 break;
2293 if (res_class != NULL) {
2294 Class* array_class;
2295 Class* element_class;
2296
2297 /*
2298 * Get the array class. If the array ref is null, we won't
2299 * have type information (and we'll crash at runtime with a
2300 * null pointer exception).
2301 */
2302 array_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2303
2304 if (array_class != NULL) {
2305 /* see if the array holds a compatible type */
2306 if (!array_class->IsArrayClass()) {
2307 LOG(ERROR) << "VFY: invalid aput-object on "
2308 << array_class->GetDescriptor()->ToModifiedUtf8();
2309 failure = VERIFY_ERROR_GENERIC;
2310 break;
2311 }
2312
2313 /*
2314 * Find the element class. res_class->GetComponentType() indicates
2315 * the basic type, which won't be what we want for a
2316 * multi-dimensional array.
2317 *
2318 * All we want to check here is that the element type is a
2319 * reference class. We *don't* check instanceof here, because
2320 * you can still put a String into a String[] after the latter
2321 * has been cast to an Object[].
2322 */
2323 if (array_class->GetDescriptor()->CharAt(1) == '[') {
2324 assert(array_class->GetArrayRank() > 1);
2325 std::string descriptor =
2326 array_class->GetDescriptor()->ToModifiedUtf8();
2327 element_class = class_linker->FindClass(descriptor.c_str() + 1,
2328 array_class->GetClassLoader());
2329 } else {
2330 assert(array_class->GetArrayRank() == 1);
2331 element_class = array_class->GetComponentType();
2332 }
2333 if (element_class->GetPrimitiveType() != Class::kPrimNot) {
2334 LOG(ERROR) << "VFY: invalid aput-object of "
2335 << res_class->GetDescriptor()->ToModifiedUtf8()
2336 << " into "
2337 << array_class->GetDescriptor()->ToModifiedUtf8();
2338 failure = VERIFY_ERROR_GENERIC;
2339 break;
2340 }
2341 }
2342 }
2343 break;
2344
2345 case Instruction::IGET:
2346 tmp_type = kRegTypeInteger;
2347 goto iget_1nr_common;
2348 case Instruction::IGET_BOOLEAN:
2349 tmp_type = kRegTypeBoolean;
2350 goto iget_1nr_common;
2351 case Instruction::IGET_BYTE:
2352 tmp_type = kRegTypeByte;
2353 goto iget_1nr_common;
2354 case Instruction::IGET_CHAR:
2355 tmp_type = kRegTypeChar;
2356 goto iget_1nr_common;
2357 case Instruction::IGET_SHORT:
2358 tmp_type = kRegTypeShort;
2359 goto iget_1nr_common;
2360iget_1nr_common:
2361 {
2362 Field* inst_field;
2363 RegType obj_type, field_type;
2364
2365 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2366 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2367 if (failure != VERIFY_ERROR_NONE)
2368 break;
2369
2370 /* make sure the field's type is compatible with expectation */
2371 field_type =
2372 PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
2373
2374 /* correct if float */
2375 if (field_type == kRegTypeFloat)
2376 tmp_type = kRegTypeFloat;
2377
2378 if (field_type == kRegTypeUnknown || tmp_type != field_type) {
2379 Class* inst_field_class = inst_field->GetDeclaringClass();
2380 LOG(ERROR) << "VFY: invalid iget-1nr of "
2381 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2382 << "." << inst_field->GetName()->ToModifiedUtf8()
2383 << " (inst=" << tmp_type << " field=" << field_type << ")";
2384 failure = VERIFY_ERROR_GENERIC;
2385 break;
2386 }
2387
2388 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2389 }
2390 break;
2391 case Instruction::IGET_WIDE:
2392 {
2393 RegType dst_type;
2394 Field* inst_field;
2395 RegType obj_type;
2396
2397 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2398 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2399 Class* inst_field_class = inst_field->GetDeclaringClass();
2400 if (failure != VERIFY_ERROR_NONE)
2401 break;
2402 /* check the type, which should be prim */
2403 switch (inst_field->GetType()->GetPrimitiveType()) {
2404 case Class::kPrimDouble:
2405 dst_type = kRegTypeDoubleLo;
2406 break;
2407 case Class::kPrimLong:
2408 dst_type = kRegTypeLongLo;
2409 break;
2410 default:
2411 LOG(ERROR) << "VFY: invalid iget-wide of "
2412 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2413 << "." << inst_field->GetName()->ToModifiedUtf8();
2414 dst_type = kRegTypeUnknown;
2415 failure = VERIFY_ERROR_GENERIC;
2416 break;
2417 }
2418 if (failure == VERIFY_ERROR_NONE) {
2419 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2420 }
2421 }
2422 break;
2423 case Instruction::IGET_OBJECT:
2424 {
2425 Class* field_class;
2426 Field* inst_field;
2427 RegType obj_type;
2428
2429 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2430 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2431 if (failure != VERIFY_ERROR_NONE)
2432 break;
2433 field_class = inst_field->GetType();
2434 if (field_class == NULL) {
2435 /* class not found or primitive type */
2436 LOG(ERROR) << "VFY: unable to recover field class from "
2437 << inst_field->GetName()->ToModifiedUtf8();
2438 failure = VERIFY_ERROR_GENERIC;
2439 break;
2440 }
2441 if (failure == VERIFY_ERROR_NONE) {
2442 assert(!field_class->IsPrimitive());
2443 SetRegisterType(work_line, dec_insn.vA_,
2444 RegTypeFromClass(field_class));
2445 }
2446 }
2447 break;
2448 case Instruction::IPUT:
2449 tmp_type = kRegTypeInteger;
2450 goto iput_1nr_common;
2451 case Instruction::IPUT_BOOLEAN:
2452 tmp_type = kRegTypeBoolean;
2453 goto iput_1nr_common;
2454 case Instruction::IPUT_BYTE:
2455 tmp_type = kRegTypeByte;
2456 goto iput_1nr_common;
2457 case Instruction::IPUT_CHAR:
2458 tmp_type = kRegTypeChar;
2459 goto iput_1nr_common;
2460 case Instruction::IPUT_SHORT:
2461 tmp_type = kRegTypeShort;
2462 goto iput_1nr_common;
2463iput_1nr_common:
2464 {
2465 RegType src_type, field_type, obj_type;
2466 Field* inst_field;
2467
2468 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2469 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2470 if (failure != VERIFY_ERROR_NONE)
2471 break;
2472 CheckFinalFieldAccess(method, inst_field, &failure);
2473 if (failure != VERIFY_ERROR_NONE)
2474 break;
2475
2476 /* get type of field we're storing into */
2477 field_type =
2478 PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
2479 src_type = GetRegisterType(work_line, dec_insn.vA_);
2480
2481 /* correct if float */
2482 if (field_type == kRegTypeFloat)
2483 tmp_type = kRegTypeFloat;
2484
2485 /*
2486 * compiler can generate synthetic functions that write byte values
2487 * into boolean fields.
2488 */
2489 if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
2490 tmp_type = kRegTypeByte;
2491 if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
2492 field_type = kRegTypeByte;
2493
2494 /* make sure the source register has the correct type */
2495 if (!CanConvertTo1nr(src_type, tmp_type)) {
2496 LOG(ERROR) << "VFY: invalid reg type " << src_type
2497 << " on iput instr (need " << tmp_type << ")",
2498 failure = VERIFY_ERROR_GENERIC;
2499 break;
2500 }
2501
2502 VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);
2503
2504 if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
2505 tmp_type != field_type) {
2506 Class* inst_field_class = inst_field->GetDeclaringClass();
2507 LOG(ERROR) << "VFY: invalid iput-1nr of "
2508 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2509 << "." << inst_field->GetName()->ToModifiedUtf8()
2510 << " (inst=" << tmp_type << " field=" << field_type << ")";
2511 failure = VERIFY_ERROR_GENERIC;
2512 break;
2513 }
2514 }
2515 break;
2516 case Instruction::IPUT_WIDE:
2517 Field* inst_field;
2518 RegType obj_type;
2519
2520 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2521 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2522 if (failure != VERIFY_ERROR_NONE)
2523 break;
2524 CheckFinalFieldAccess(method, inst_field, &failure);
2525 if (failure != VERIFY_ERROR_NONE)
2526 break;
2527
2528 /* check the type, which should be prim */
2529 switch (inst_field->GetType()->GetPrimitiveType()) {
2530 case Class::kPrimDouble:
2531 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2532 &failure);
2533 break;
2534 case Class::kPrimLong:
2535 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
2536 break;
2537 default:
2538 LOG(ERROR) << "VFY: invalid iput-wide of "
2539 << inst_field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
2540 << "." << inst_field->GetName()->ToModifiedUtf8();
2541 failure = VERIFY_ERROR_GENERIC;
2542 break;
2543 }
2544 break;
2545 case Instruction::IPUT_OBJECT:
2546 {
2547 Class* field_class;
2548 Class* value_class;
2549 Field* inst_field;
2550 RegType obj_type, value_type;
2551
2552 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2553 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2554 if (failure != VERIFY_ERROR_NONE)
2555 break;
2556 CheckFinalFieldAccess(method, inst_field, &failure);
2557 if (failure != VERIFY_ERROR_NONE)
2558 break;
2559
2560 field_class = inst_field->GetType();
2561 if (field_class == NULL) {
2562 LOG(ERROR) << "VFY: unable to recover field class from '"
2563 << inst_field->GetName()->ToModifiedUtf8() << "'";
2564 failure = VERIFY_ERROR_GENERIC;
2565 break;
2566 }
2567
2568 value_type = GetRegisterType(work_line, dec_insn.vA_);
2569 if (!RegTypeIsReference(value_type)) {
2570 LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
2571 << " into ref field '"
2572 << inst_field->GetName()->ToModifiedUtf8() << "' ("
2573 << field_class->GetDescriptor()->ToModifiedUtf8() << ")";
2574 failure = VERIFY_ERROR_GENERIC;
2575 break;
2576 }
2577 if (value_type != kRegTypeZero) {
2578 value_class = RegTypeInitializedReferenceToClass(value_type);
2579 if (value_class == NULL) {
2580 LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
2581 << " into ref field";
2582 failure = VERIFY_ERROR_GENERIC;
2583 break;
2584 }
2585 /* allow if field is any interface or field is base class */
2586 if (!field_class->IsInterface() &&
2587 !field_class->IsAssignableFrom(value_class)) {
2588 Class* inst_field_class = inst_field->GetDeclaringClass();
2589 LOG(ERROR) << "VFY: storing type '"
2590 << value_class->GetDescriptor()->ToModifiedUtf8()
2591 << "' into field type '"
2592 << field_class->GetDescriptor()->ToModifiedUtf8()
2593 << "' ("
2594 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2595 << "." << inst_field->GetName()->ToModifiedUtf8() << ")";
2596 failure = VERIFY_ERROR_GENERIC;
2597 break;
2598 }
2599 }
2600 }
2601 break;
2602
2603 case Instruction::SGET:
2604 tmp_type = kRegTypeInteger;
2605 goto sget_1nr_common;
2606 case Instruction::SGET_BOOLEAN:
2607 tmp_type = kRegTypeBoolean;
2608 goto sget_1nr_common;
2609 case Instruction::SGET_BYTE:
2610 tmp_type = kRegTypeByte;
2611 goto sget_1nr_common;
2612 case Instruction::SGET_CHAR:
2613 tmp_type = kRegTypeChar;
2614 goto sget_1nr_common;
2615 case Instruction::SGET_SHORT:
2616 tmp_type = kRegTypeShort;
2617 goto sget_1nr_common;
2618sget_1nr_common:
2619 {
2620 Field* static_field;
2621 RegType field_type;
2622
2623 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2624 if (failure != VERIFY_ERROR_NONE)
2625 break;
2626
2627 /*
2628 * Make sure the field's type is compatible with expectation.
2629 * We can get ourselves into trouble if we mix & match loads
2630 * and stores with different widths, so rather than just checking
2631 * "CanConvertTo1nr" we require that the field types have equal
2632 * widths.
2633 */
2634 field_type =
2635 PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
2636
2637 /* correct if float */
2638 if (field_type == kRegTypeFloat)
2639 tmp_type = kRegTypeFloat;
2640
2641 if (tmp_type != field_type) {
2642 Class* static_field_class = static_field->GetDeclaringClass();
2643 LOG(ERROR) << "VFY: invalid sget-1nr of "
2644 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2645 << "." << static_field->GetName()->ToModifiedUtf8()
2646 << " (inst=" << tmp_type << " actual=" << field_type
2647 << ")";
2648 failure = VERIFY_ERROR_GENERIC;
2649 break;
2650 }
2651
2652 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2653 }
2654 break;
2655 case Instruction::SGET_WIDE:
2656 {
2657 Field* static_field;
2658 RegType dst_type;
2659
2660 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2661 Class* static_field_class = static_field->GetDeclaringClass();
2662 if (failure != VERIFY_ERROR_NONE)
2663 break;
2664 /* check the type, which should be prim */
2665 switch (static_field->GetType()->GetPrimitiveType()) {
2666 case Class::kPrimDouble:
2667 dst_type = kRegTypeDoubleLo;
2668 break;
2669 case Class::kPrimLong:
2670 dst_type = kRegTypeLongLo;
2671 break;
2672 default:
2673 LOG(ERROR) << "VFY: invalid sget-wide of "
2674 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2675 << "." << static_field->GetName()->ToModifiedUtf8();
2676 dst_type = kRegTypeUnknown;
2677 failure = VERIFY_ERROR_GENERIC;
2678 break;
2679 }
2680 if (failure == VERIFY_ERROR_NONE) {
2681 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2682 }
2683 }
2684 break;
2685 case Instruction::SGET_OBJECT:
2686 {
2687 Field* static_field;
2688 Class* field_class;
2689
2690 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2691 if (failure != VERIFY_ERROR_NONE)
2692 break;
2693 field_class = static_field->GetType();
2694 if (field_class == NULL) {
2695 LOG(ERROR) << "VFY: unable to recover field class from '"
2696 << static_field->GetName()->ToModifiedUtf8() << "'";
2697 failure = VERIFY_ERROR_GENERIC;
2698 break;
2699 }
2700 if (field_class->IsPrimitive()) {
2701 LOG(ERROR) << "VFY: attempt to get prim field with sget-object";
2702 failure = VERIFY_ERROR_GENERIC;
2703 break;
2704 }
2705 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(field_class));
2706 }
2707 break;
2708 case Instruction::SPUT:
2709 tmp_type = kRegTypeInteger;
2710 goto sput_1nr_common;
2711 case Instruction::SPUT_BOOLEAN:
2712 tmp_type = kRegTypeBoolean;
2713 goto sput_1nr_common;
2714 case Instruction::SPUT_BYTE:
2715 tmp_type = kRegTypeByte;
2716 goto sput_1nr_common;
2717 case Instruction::SPUT_CHAR:
2718 tmp_type = kRegTypeChar;
2719 goto sput_1nr_common;
2720 case Instruction::SPUT_SHORT:
2721 tmp_type = kRegTypeShort;
2722 goto sput_1nr_common;
2723sput_1nr_common:
2724 {
2725 RegType src_type, field_type;
2726 Field* static_field;
2727
2728 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2729 if (failure != VERIFY_ERROR_NONE)
2730 break;
2731 CheckFinalFieldAccess(method, static_field, &failure);
2732 if (failure != VERIFY_ERROR_NONE)
2733 break;
2734
2735 /*
2736 * Get type of field we're storing into. We know that the
2737 * contents of the register match the instruction, but we also
2738 * need to ensure that the instruction matches the field type.
2739 * Using e.g. sput-short to write into a 32-bit integer field
2740 * can lead to trouble if we do 16-bit writes.
2741 */
2742 field_type =
2743 PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
2744 src_type = GetRegisterType(work_line, dec_insn.vA_);
2745
2746 /* correct if float */
2747 if (field_type == kRegTypeFloat)
2748 tmp_type = kRegTypeFloat;
2749
2750 /*
2751 * compiler can generate synthetic functions that write byte values
2752 * into boolean fields.
2753 */
2754 if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
2755 tmp_type = kRegTypeByte;
2756 if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
2757 field_type = kRegTypeByte;
2758
2759 /* make sure the source register has the correct type */
2760 if (!CanConvertTo1nr(src_type, tmp_type)) {
2761 LOG(ERROR) << "VFY: invalid reg type " << src_type
2762 << " on sput instr (need " << tmp_type << ")";
2763 failure = VERIFY_ERROR_GENERIC;
2764 break;
2765 }
2766
2767 VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);
2768
2769 if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
2770 tmp_type != field_type) {
2771 Class* static_field_class = static_field->GetDeclaringClass();
2772 LOG(ERROR) << "VFY: invalid sput-1nr of "
2773 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2774 << "." << static_field->GetName()->ToModifiedUtf8()
2775 << " (inst=" << tmp_type << " actual=" << field_type
2776 << ")";
2777 failure = VERIFY_ERROR_GENERIC;
2778 break;
2779 }
2780 }
2781 break;
2782 case Instruction::SPUT_WIDE:
2783 Field* static_field;
2784
2785 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2786 if (failure != VERIFY_ERROR_NONE)
2787 break;
2788 CheckFinalFieldAccess(method, static_field, &failure);
2789 if (failure != VERIFY_ERROR_NONE)
2790 break;
2791
2792 /* check the type, which should be prim */
2793 switch (static_field->GetType()->GetPrimitiveType()) {
2794 case Class::kPrimDouble:
2795 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2796 &failure);
2797 break;
2798 case Class::kPrimLong:
2799 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
2800 break;
2801 default:
2802 LOG(ERROR) << "VFY: invalid sput-wide of "
2803 << static_field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
2804 << "." << static_field->GetName()->ToModifiedUtf8();
2805 failure = VERIFY_ERROR_GENERIC;
2806 break;
2807 }
2808 break;
2809 case Instruction::SPUT_OBJECT:
2810 {
2811 Class* field_class;
2812 Class* value_class;
2813 Field* static_field;
2814 RegType value_type;
2815
2816 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2817 if (failure != VERIFY_ERROR_NONE)
2818 break;
2819 CheckFinalFieldAccess(method, static_field, &failure);
2820 if (failure != VERIFY_ERROR_NONE)
2821 break;
2822
2823 field_class = static_field->GetType();
2824 if (field_class == NULL) {
2825 LOG(ERROR) << "VFY: unable to recover field class from '"
2826 << static_field->GetName()->ToModifiedUtf8() << "'";
2827 failure = VERIFY_ERROR_GENERIC;
2828 break;
2829 }
2830
2831 value_type = GetRegisterType(work_line, dec_insn.vA_);
2832 if (!RegTypeIsReference(value_type)) {
2833 LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
2834 << " into ref field '"
2835 << static_field->GetName()->ToModifiedUtf8() << "' ("
2836 << field_class->GetDescriptor()->ToModifiedUtf8() << ")",
2837 failure = VERIFY_ERROR_GENERIC;
2838 break;
2839 }
2840 if (value_type != kRegTypeZero) {
2841 value_class = RegTypeInitializedReferenceToClass(value_type);
2842 if (value_class == NULL) {
2843 LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
2844 << " into ref field";
2845 failure = VERIFY_ERROR_GENERIC;
2846 break;
2847 }
2848 /* allow if field is any interface or field is base class */
2849 if (!field_class->IsInterface() &&
2850 !field_class->IsAssignableFrom(value_class)) {
2851 Class* static_field_class = static_field->GetDeclaringClass();
2852 LOG(ERROR) << "VFY: storing type '"
2853 << value_class->GetDescriptor()->ToModifiedUtf8()
2854 << "' into field type '"
2855 << field_class->GetDescriptor()->ToModifiedUtf8()
2856 << "' ("
2857 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2858 << "." << static_field->GetName()->ToModifiedUtf8()
2859 << ")",
2860 failure = VERIFY_ERROR_GENERIC;
2861 break;
2862 }
2863 }
2864 }
2865 break;
2866
2867 case Instruction::INVOKE_VIRTUAL:
2868 case Instruction::INVOKE_VIRTUAL_RANGE:
2869 case Instruction::INVOKE_SUPER:
2870 case Instruction::INVOKE_SUPER_RANGE:
2871 {
2872 Method* called_method;
2873 RegType return_type;
2874 bool is_range;
2875 bool is_super;
2876
2877 is_range = (dec_insn.opcode_ == Instruction::INVOKE_VIRTUAL_RANGE ||
2878 dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
2879 is_super = (dec_insn.opcode_ == Instruction::INVOKE_SUPER ||
2880 dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
2881
2882 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2883 &dec_insn, METHOD_VIRTUAL, is_range, is_super, &failure);
2884 if (failure != VERIFY_ERROR_NONE)
2885 break;
2886 return_type = GetMethodReturnType(dex_file, called_method);
2887 SetResultRegisterType(work_line, registers_size, return_type);
2888 just_set_result = true;
2889 }
2890 break;
2891 case Instruction::INVOKE_DIRECT:
2892 case Instruction::INVOKE_DIRECT_RANGE:
2893 {
2894 RegType return_type;
2895 Method* called_method;
2896 bool is_range;
2897
2898 is_range = (dec_insn.opcode_ == Instruction::INVOKE_DIRECT_RANGE);
2899 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2900 &dec_insn, METHOD_DIRECT, is_range, false, &failure);
2901 if (failure != VERIFY_ERROR_NONE)
2902 break;
2903
2904 /*
2905 * Some additional checks when calling <init>. We know from
2906 * the invocation arg check that the "this" argument is an
2907 * instance of called_method->klass. Now we further restrict
2908 * that to require that called_method->klass is the same as
2909 * this->klass or this->super, allowing the latter only if
2910 * the "this" argument is the same as the "this" argument to
2911 * this method (which implies that we're in <init> ourselves).
2912 */
2913 if (IsInitMethod(called_method)) {
2914 RegType this_type;
2915 this_type = GetInvocationThis(work_line, &dec_insn, &failure);
2916 if (failure != VERIFY_ERROR_NONE)
2917 break;
2918
2919 /* no null refs allowed (?) */
2920 if (this_type == kRegTypeZero) {
2921 LOG(ERROR) << "VFY: unable to initialize null ref";
2922 failure = VERIFY_ERROR_GENERIC;
2923 break;
2924 }
2925
2926 Class* this_class;
2927
2928 this_class = RegTypeReferenceToClass(this_type, uninit_map);
2929 assert(this_class != NULL);
2930
2931 /* must be in same class or in superclass */
2932 if (called_method->GetDeclaringClass() == this_class->GetSuperClass())
2933 {
2934 if (this_class != method->GetDeclaringClass()) {
2935 LOG(ERROR) << "VFY: invoke-direct <init> on super only "
2936 << "allowed for 'this' in <init>";
2937 failure = VERIFY_ERROR_GENERIC;
2938 break;
2939 }
2940 } else if (called_method->GetDeclaringClass() != this_class) {
2941 LOG(ERROR) << "VFY: invoke-direct <init> must be on current "
2942 << "class or super";
2943 failure = VERIFY_ERROR_GENERIC;
2944 break;
2945 }
2946
2947 /* arg must be an uninitialized reference */
2948 if (!RegTypeIsUninitReference(this_type)) {
2949 LOG(ERROR) << "VFY: can only initialize the uninitialized";
2950 failure = VERIFY_ERROR_GENERIC;
2951 break;
2952 }
2953
2954 /*
2955 * Replace the uninitialized reference with an initialized
2956 * one, and clear the entry in the uninit map. We need to
2957 * do this for all registers that have the same object
2958 * instance in them, not just the "this" register.
2959 */
2960 MarkRefsAsInitialized(work_line, registers_size, uninit_map,
2961 this_type, &failure);
2962 if (failure != VERIFY_ERROR_NONE)
2963 break;
2964 }
2965 return_type = GetMethodReturnType(dex_file, called_method);
2966 SetResultRegisterType(work_line, registers_size, return_type);
2967 just_set_result = true;
2968 }
2969 break;
2970 case Instruction::INVOKE_STATIC:
2971 case Instruction::INVOKE_STATIC_RANGE:
2972 {
2973 RegType return_type;
2974 Method* called_method;
2975 bool is_range;
2976
2977 is_range = (dec_insn.opcode_ == Instruction::INVOKE_STATIC_RANGE);
2978 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2979 &dec_insn, METHOD_STATIC, is_range, false, &failure);
2980 if (failure != VERIFY_ERROR_NONE)
2981 break;
2982
2983 return_type = GetMethodReturnType(dex_file, called_method);
2984 SetResultRegisterType(work_line, registers_size, return_type);
2985 just_set_result = true;
2986 }
2987 break;
2988 case Instruction::INVOKE_INTERFACE:
2989 case Instruction::INVOKE_INTERFACE_RANGE:
2990 {
2991 RegType /*this_type,*/ return_type;
2992 Method* abs_method;
2993 bool is_range;
2994
2995 is_range = (dec_insn.opcode_ == Instruction::INVOKE_INTERFACE_RANGE);
2996 abs_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2997 &dec_insn, METHOD_INTERFACE, is_range, false, &failure);
2998 if (failure != VERIFY_ERROR_NONE)
2999 break;
3000
3001#if 0 /* can't do this here, fails on dalvik test 052-verifier-fun */
3002 /*
3003 * Get the type of the "this" arg, which should always be an
3004 * interface class. Because we don't do a full merge on
3005 * interface classes, this might have reduced to Object.
3006 */
3007 this_type = GetInvocationThis(work_line, &dec_insn, &failure);
3008 if (failure != VERIFY_ERROR_NONE)
3009 break;
3010
3011 if (this_type == kRegTypeZero) {
3012 /* null pointer always passes (and always fails at runtime) */
3013 } else {
3014 Class* this_class;
3015
3016 this_class = RegTypeInitializedReferenceToClass(this_type);
3017 if (this_class == NULL) {
3018 LOG(ERROR) << "VFY: interface call on uninitialized";
3019 failure = VERIFY_ERROR_GENERIC;
3020 break;
3021 }
3022
3023 /*
3024 * Either "this_class" needs to be the interface class that
3025 * defined abs_method, or abs_method's class needs to be one
3026 * of the interfaces implemented by "this_class". (Or, if
3027 * we couldn't complete the merge, this will be Object.)
3028 */
3029 if (this_class != abs_method->GetDeclaringClass() &&
3030 this_class != class_linker->FindSystemClass("Ljava/lang/Object;") &&
3031 !this_class->Implements(abs_method->GetDeclaringClass())) {
3032 LOG(ERROR) << "VFY: unable to match abs_method '"
3033 << abs_method->GetName()->ToModifiedUtf8() << "' with "
3034 << this_class->GetDescriptor()->ToModifiedUtf8()
3035 << " interfaces";
3036 failure = VERIFY_ERROR_GENERIC;
3037 break;
3038 }
3039 }
3040#endif
3041
3042 /*
3043 * We don't have an object instance, so we can't find the
3044 * concrete method. However, all of the type information is
3045 * in the abstract method, so we're good.
3046 */
3047 return_type = GetMethodReturnType(dex_file, abs_method);
3048 SetResultRegisterType(work_line, registers_size, return_type);
3049 just_set_result = true;
3050 }
3051 break;
3052
3053 case Instruction::NEG_INT:
3054 case Instruction::NOT_INT:
3055 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3056 &failure);
3057 break;
3058 case Instruction::NEG_LONG:
3059 case Instruction::NOT_LONG:
3060 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo, &failure);
3061 break;
3062 case Instruction::NEG_FLOAT:
3063 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat, &failure);
3064 break;
3065 case Instruction::NEG_DOUBLE:
3066 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3067 &failure);
3068 break;
3069 case Instruction::INT_TO_LONG:
3070 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeInteger,
3071 &failure);
3072 break;
3073 case Instruction::INT_TO_FLOAT:
3074 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeInteger, &failure);
3075 break;
3076 case Instruction::INT_TO_DOUBLE:
3077 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeInteger,
3078 &failure);
3079 break;
3080 case Instruction::LONG_TO_INT:
3081 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeLongLo,
3082 &failure);
3083 break;
3084 case Instruction::LONG_TO_FLOAT:
3085 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeLongLo, &failure);
3086 break;
3087 case Instruction::LONG_TO_DOUBLE:
3088 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeLongLo,
3089 &failure);
3090 break;
3091 case Instruction::FLOAT_TO_INT:
3092 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeFloat, &failure);
3093 break;
3094 case Instruction::FLOAT_TO_LONG:
3095 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeFloat, &failure);
3096 break;
3097 case Instruction::FLOAT_TO_DOUBLE:
3098 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeFloat,
3099 &failure);
3100 break;
3101 case Instruction::DOUBLE_TO_INT:
3102 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeDoubleLo,
3103 &failure);
3104 break;
3105 case Instruction::DOUBLE_TO_LONG:
3106 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeDoubleLo,
3107 &failure);
3108 break;
3109 case Instruction::DOUBLE_TO_FLOAT:
3110 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeDoubleLo,
3111 &failure);
3112 break;
3113 case Instruction::INT_TO_BYTE:
3114 CheckUnop(work_line, &dec_insn, kRegTypeByte, kRegTypeInteger, &failure);
3115 break;
3116 case Instruction::INT_TO_CHAR:
3117 CheckUnop(work_line, &dec_insn, kRegTypeChar, kRegTypeInteger, &failure);
3118 break;
3119 case Instruction::INT_TO_SHORT:
3120 CheckUnop(work_line, &dec_insn, kRegTypeShort, kRegTypeInteger, &failure);
3121 break;
3122
3123 case Instruction::ADD_INT:
3124 case Instruction::SUB_INT:
3125 case Instruction::MUL_INT:
3126 case Instruction::REM_INT:
3127 case Instruction::DIV_INT:
3128 case Instruction::SHL_INT:
3129 case Instruction::SHR_INT:
3130 case Instruction::USHR_INT:
3131 CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3132 kRegTypeInteger, false, &failure);
3133 break;
3134 case Instruction::AND_INT:
3135 case Instruction::OR_INT:
3136 case Instruction::XOR_INT:
3137 CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3138 kRegTypeInteger, true, &failure);
3139 break;
3140 case Instruction::ADD_LONG:
3141 case Instruction::SUB_LONG:
3142 case Instruction::MUL_LONG:
3143 case Instruction::DIV_LONG:
3144 case Instruction::REM_LONG:
3145 case Instruction::AND_LONG:
3146 case Instruction::OR_LONG:
3147 case Instruction::XOR_LONG:
3148 CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3149 kRegTypeLongLo, false, &failure);
3150 break;
3151 case Instruction::SHL_LONG:
3152 case Instruction::SHR_LONG:
3153 case Instruction::USHR_LONG:
3154 /* shift distance is Int, making these different from other binops */
3155 CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3156 kRegTypeInteger, false, &failure);
3157 break;
3158 case Instruction::ADD_FLOAT:
3159 case Instruction::SUB_FLOAT:
3160 case Instruction::MUL_FLOAT:
3161 case Instruction::DIV_FLOAT:
3162 case Instruction::REM_FLOAT:
3163 CheckBinop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
3164 kRegTypeFloat, false, &failure);
3165 break;
3166 case Instruction::ADD_DOUBLE:
3167 case Instruction::SUB_DOUBLE:
3168 case Instruction::MUL_DOUBLE:
3169 case Instruction::DIV_DOUBLE:
3170 case Instruction::REM_DOUBLE:
3171 CheckBinop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3172 kRegTypeDoubleLo, false, &failure);
3173 break;
3174 case Instruction::ADD_INT_2ADDR:
3175 case Instruction::SUB_INT_2ADDR:
3176 case Instruction::MUL_INT_2ADDR:
3177 case Instruction::REM_INT_2ADDR:
3178 case Instruction::SHL_INT_2ADDR:
3179 case Instruction::SHR_INT_2ADDR:
3180 case Instruction::USHR_INT_2ADDR:
3181 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3182 kRegTypeInteger, false, &failure);
3183 break;
3184 case Instruction::AND_INT_2ADDR:
3185 case Instruction::OR_INT_2ADDR:
3186 case Instruction::XOR_INT_2ADDR:
3187 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3188 kRegTypeInteger, true, &failure);
3189 break;
3190 case Instruction::DIV_INT_2ADDR:
3191 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3192 kRegTypeInteger, false, &failure);
3193 break;
3194 case Instruction::ADD_LONG_2ADDR:
3195 case Instruction::SUB_LONG_2ADDR:
3196 case Instruction::MUL_LONG_2ADDR:
3197 case Instruction::DIV_LONG_2ADDR:
3198 case Instruction::REM_LONG_2ADDR:
3199 case Instruction::AND_LONG_2ADDR:
3200 case Instruction::OR_LONG_2ADDR:
3201 case Instruction::XOR_LONG_2ADDR:
3202 CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3203 kRegTypeLongLo, false, &failure);
3204 break;
3205 case Instruction::SHL_LONG_2ADDR:
3206 case Instruction::SHR_LONG_2ADDR:
3207 case Instruction::USHR_LONG_2ADDR:
3208 CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3209 kRegTypeInteger, false, &failure);
3210 break;
3211 case Instruction::ADD_FLOAT_2ADDR:
3212 case Instruction::SUB_FLOAT_2ADDR:
3213 case Instruction::MUL_FLOAT_2ADDR:
3214 case Instruction::DIV_FLOAT_2ADDR:
3215 case Instruction::REM_FLOAT_2ADDR:
3216 CheckBinop2addr(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
3217 kRegTypeFloat, false, &failure);
3218 break;
3219 case Instruction::ADD_DOUBLE_2ADDR:
3220 case Instruction::SUB_DOUBLE_2ADDR:
3221 case Instruction::MUL_DOUBLE_2ADDR:
3222 case Instruction::DIV_DOUBLE_2ADDR:
3223 case Instruction::REM_DOUBLE_2ADDR:
3224 CheckBinop2addr(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3225 kRegTypeDoubleLo, false, &failure);
3226 break;
3227 case Instruction::ADD_INT_LIT16:
3228 case Instruction::RSUB_INT:
3229 case Instruction::MUL_INT_LIT16:
3230 case Instruction::DIV_INT_LIT16:
3231 case Instruction::REM_INT_LIT16:
3232 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
3233 &failure);
3234 break;
3235 case Instruction::AND_INT_LIT16:
3236 case Instruction::OR_INT_LIT16:
3237 case Instruction::XOR_INT_LIT16:
3238 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
3239 &failure);
3240 break;
3241 case Instruction::ADD_INT_LIT8:
3242 case Instruction::RSUB_INT_LIT8:
3243 case Instruction::MUL_INT_LIT8:
3244 case Instruction::DIV_INT_LIT8:
3245 case Instruction::REM_INT_LIT8:
3246 case Instruction::SHL_INT_LIT8:
3247 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
3248 &failure);
3249 break;
3250 case Instruction::SHR_INT_LIT8:
3251 tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
3252 false, &failure);
3253 CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
3254 &failure);
3255 break;
3256 case Instruction::USHR_INT_LIT8:
3257 tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
3258 true, &failure);
3259 CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
3260 &failure);
3261 break;
3262 case Instruction::AND_INT_LIT8:
3263 case Instruction::OR_INT_LIT8:
3264 case Instruction::XOR_INT_LIT8:
3265 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
3266 &failure);
3267 break;
3268
3269 /*
3270 * This falls into the general category of "optimized" instructions,
3271 * which don't generally appear during verification. Because it's
3272 * inserted in the course of verification, we can expect to see it here.
3273 */
3274 //case Instruction::THROW_VERIFICATION_ERROR:
3275 case Instruction::UNUSED_ED:
3276 break;
3277
3278 /*
3279 * Verifying "quickened" instructions is tricky, because we have
3280 * discarded the original field/method information. The byte offsets
3281 * and vtable indices only have meaning in the context of an object
3282 * instance.
3283 *
3284 * If a piece of code declares a local reference variable, assigns
3285 * null to it, and then issues a virtual method call on it, we
3286 * cannot evaluate the method call during verification. This situation
3287 * isn't hard to handle, since we know the call will always result in an
3288 * NPE, and the arguments and return value don't matter. Any code that
3289 * depends on the result of the method call is inaccessible, so the
3290 * fact that we can't fully verify anything that comes after the bad
3291 * call is not a problem.
3292 *
3293 * We must also consider the case of multiple code paths, only some of
3294 * which involve a null reference. We can completely verify the method
3295 * if we sidestep the results of executing with a null reference.
3296 * For example, if on the first pass through the code we try to do a
3297 * virtual method invocation through a null ref, we have to skip the
3298 * method checks and have the method return a "wildcard" type (which
3299 * merges with anything to become that other thing). The move-result
3300 * will tell us if it's a reference, single-word numeric, or double-word
3301 * value. We continue to perform the verification, and at the end of
3302 * the function any invocations that were never fully exercised are
3303 * marked as null-only.
3304 *
3305 * We would do something similar for the field accesses. The field's
3306 * type, once known, can be used to recover the width of short integers.
3307 * If the object reference was null, the field-get returns the "wildcard"
3308 * type, which is acceptable for any operation.
3309 */
3310 case Instruction::UNUSED_EE:
3311 case Instruction::UNUSED_EF:
3312 case Instruction::UNUSED_F2:
3313 case Instruction::UNUSED_F3:
3314 case Instruction::UNUSED_F4:
3315 case Instruction::UNUSED_F5:
3316 case Instruction::UNUSED_F6:
3317 case Instruction::UNUSED_F7:
3318 case Instruction::UNUSED_F8:
3319 case Instruction::UNUSED_F9:
3320 case Instruction::UNUSED_FA:
3321 case Instruction::UNUSED_FB:
3322 //case Instruction::EXECUTE_INLINE:
3323 //case Instruction::EXECUTE_INLINE_RANGE:
3324 //case Instruction::IGET_QUICK:
3325 //case Instruction::IGET_WIDE_QUICK:
3326 //case Instruction::IGET_OBJECT_QUICK:
3327 //case Instruction::IPUT_QUICK:
3328 //case Instruction::IPUT_WIDE_QUICK:
3329 //case Instruction::IPUT_OBJECT_QUICK:
3330 //case Instruction::INVOKE_VIRTUAL_QUICK:
3331 //case Instruction::INVOKE_VIRTUAL_QUICK_RANGE:
3332 //case Instruction::INVOKE_SUPER_QUICK:
3333 //case Instruction::INVOKE_SUPER_QUICK_RANGE:
3334 /* fall through to failure */
3335
3336 /*
3337 * These instructions are equivalent (from the verifier's point of view)
3338 * to the original form. The change was made for correctness rather
3339 * than improved performance (except for invoke-object-init, which
3340 * provides both). The substitution takes place after verification
3341 * completes, though, so we don't expect to see them here.
3342 */
3343 case Instruction::UNUSED_F0:
3344 case Instruction::UNUSED_F1:
3345 case Instruction::UNUSED_E3:
3346 case Instruction::UNUSED_E8:
3347 case Instruction::UNUSED_E7:
3348 case Instruction::UNUSED_E4:
3349 case Instruction::UNUSED_E9:
3350 case Instruction::UNUSED_FC:
3351 case Instruction::UNUSED_E5:
3352 case Instruction::UNUSED_EA:
3353 case Instruction::UNUSED_FD:
3354 case Instruction::UNUSED_E6:
3355 case Instruction::UNUSED_EB:
3356 case Instruction::UNUSED_FE:
3357 //case Instruction::INVOKE_OBJECT_INIT_RANGE:
3358 //case Instruction::RETURN_VOID_BARRIER:
3359 //case Instruction::IGET_VOLATILE:
3360 //case Instruction::IGET_WIDE_VOLATILE:
3361 //case Instruction::IGET_OBJECT_VOLATILE:
3362 //case Instruction::IPUT_VOLATILE:
3363 //case Instruction::IPUT_WIDE_VOLATILE:
3364 //case Instruction::IPUT_OBJECT_VOLATILE:
3365 //case Instruction::SGET_VOLATILE:
3366 //case Instruction::SGET_WIDE_VOLATILE:
3367 //case Instruction::SGET_OBJECT_VOLATILE:
3368 //case Instruction::SPUT_VOLATILE:
3369 //case Instruction::SPUT_WIDE_VOLATILE:
3370 //case Instruction::SPUT_OBJECT_VOLATILE:
3371 /* fall through to failure */
3372
3373 /* These should never appear during verification. */
3374 case Instruction::UNUSED_3E:
3375 case Instruction::UNUSED_3F:
3376 case Instruction::UNUSED_40:
3377 case Instruction::UNUSED_41:
3378 case Instruction::UNUSED_42:
3379 case Instruction::UNUSED_43:
3380 case Instruction::UNUSED_73:
3381 case Instruction::UNUSED_79:
3382 case Instruction::UNUSED_7A:
3383 case Instruction::UNUSED_EC:
3384 case Instruction::UNUSED_FF:
3385 //case Instruction::BREAKPOINT:
3386 //case Instruction::DISPATCH_FF:
3387 failure = VERIFY_ERROR_GENERIC;
3388 break;
3389
3390 /*
3391 * DO NOT add a "default" clause here. Without it the compiler will
3392 * complain if an instruction is missing (which is desirable).
3393 */
3394 }
3395
3396 if (failure != VERIFY_ERROR_NONE) {
3397 //if (failure == VERIFY_ERROR_GENERIC || gDvm.optimizing)
3398 if (failure == VERIFY_ERROR_GENERIC) {
3399 /* immediate failure, reject class */
3400 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
3401 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3402 return false;
3403 } else {
3404 /* replace opcode and continue on */
3405 LOG(ERROR) << "VFY: replacing opcode 0x" << std::hex
3406 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3407 if (!ReplaceFailingInstruction(code_item, insn_flags, insn_idx, failure))
3408 {
3409 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
3410 << (int) dec_insn.opcode_ << " at 0x" << insn_idx
3411 << std::dec;
3412 return false;
3413 }
3414 /* IMPORTANT: method->insns may have been changed */
3415 insns = code_item->insns_ + insn_idx;
3416
3417 /* continue on as if we just handled a throw-verification-error */
3418 failure = VERIFY_ERROR_NONE;
3419 opcode_flag = Instruction::kThrow;
3420 }
3421 }
3422
3423 /*
3424 * If we didn't just set the result register, clear it out. This
3425 * ensures that you can only use "move-result" immediately after the
3426 * result is set. (We could check this statically, but it's not
3427 * expensive and it makes our debugging output cleaner.)
3428 */
3429 if (!just_set_result) {
3430 int reg = RESULT_REGISTER(registers_size);
3431 SetRegisterType(work_line, reg, kRegTypeUnknown);
3432 SetRegisterType(work_line, reg + 1, kRegTypeUnknown);
3433 }
3434
3435 /*
3436 * Handle "continue". Tag the next consecutive instruction.
3437 */
3438 if ((opcode_flag & Instruction::kContinue) != 0) {
3439 size_t insn_width = InsnGetWidth(insn_flags, insn_idx);
3440 if (insn_idx + insn_width >= insns_size) {
3441 LOG(ERROR) << "VFY: execution can walk off end of code area (from 0x"
3442 << std::hex << insn_idx << std::dec << ")";
3443 return false;
3444 }
3445
3446 /*
3447 * The only way to get to a move-exception instruction is to get
3448 * thrown there. Make sure the next instruction isn't one.
3449 */
3450 if (!CheckMoveException(code_item->insns_, insn_idx + insn_width))
3451 return false;
3452
3453 if (GetRegisterLine(reg_table, insn_idx + insn_width)->reg_types_ != NULL) {
3454 /*
3455 * Merge registers into what we have for the next instruction,
3456 * and set the "changed" flag if needed.
3457 */
3458 if (!UpdateRegisters(insn_flags, reg_table, insn_idx + insn_width,
3459 work_line))
3460 return false;
3461 } else {
3462 /*
3463 * We're not recording register data for the next instruction,
3464 * so we don't know what the prior state was. We have to
3465 * assume that something has changed and re-evaluate it.
3466 */
3467 InsnSetChanged(insn_flags, insn_idx + insn_width, true);
3468 }
3469 }
3470
3471 /*
3472 * Handle "branch". Tag the branch target.
3473 *
3474 * NOTE: instructions like Instruction::EQZ provide information about the
3475 * state of the register when the branch is taken or not taken. For example,
3476 * somebody could get a reference field, check it for zero, and if the
3477 * branch is taken immediately store that register in a boolean field
3478 * since the value is known to be zero. We do not currently account for
3479 * that, and will reject the code.
3480 *
3481 * TODO: avoid re-fetching the branch target
3482 */
3483 if ((opcode_flag & Instruction::kBranch) != 0) {
3484 bool isConditional, selfOkay;
3485
3486 if (!GetBranchOffset(code_item, insn_flags, insn_idx, &branch_target,
3487 &isConditional, &selfOkay)) {
3488 /* should never happen after static verification */
3489 LOG(ERROR) << "VFY: bad branch at 0x" << std::hex << insn_idx << std::dec;
3490 return false;
3491 }
3492 assert(isConditional || (opcode_flag & Instruction::kContinue) == 0);
3493 assert(!isConditional || (opcode_flag & Instruction::kContinue) != 0);
3494
3495 if (!CheckMoveException(code_item->insns_, insn_idx + branch_target))
3496 return false;
3497
3498 /* update branch target, set "changed" if appropriate */
3499 if (!UpdateRegisters(insn_flags, reg_table, insn_idx + branch_target,
3500 work_line))
3501 return false;
3502 }
3503
3504 /*
3505 * Handle "switch". Tag all possible branch targets.
3506 *
3507 * We've already verified that the table is structurally sound, so we
3508 * just need to walk through and tag the targets.
3509 */
3510 if ((opcode_flag & Instruction::kSwitch) != 0) {
3511 int offset_to_switch = insns[1] | (((int32_t) insns[2]) << 16);
3512 const uint16_t* switch_insns = insns + offset_to_switch;
3513 int switch_count = switch_insns[1];
3514 int offset_to_targets, targ;
3515
3516 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
3517 /* 0 = sig, 1 = count, 2/3 = first key */
3518 offset_to_targets = 4;
3519 } else {
3520 /* 0 = sig, 1 = count, 2..count * 2 = keys */
3521 assert((*insns & 0xff) == Instruction::SPARSE_SWITCH);
3522 offset_to_targets = 2 + 2 * switch_count;
3523 }
3524
3525 /* verify each switch target */
3526 for (targ = 0; targ < switch_count; targ++) {
3527 int offset;
3528 uint32_t abs_offset;
3529
3530 /* offsets are 32-bit, and only partly endian-swapped */
3531 offset = switch_insns[offset_to_targets + targ * 2] |
3532 (((int32_t) switch_insns[offset_to_targets + targ * 2 + 1]) << 16);
3533 abs_offset = insn_idx + offset;
3534
3535 assert(abs_offset < insns_size);
3536
3537 if (!CheckMoveException(code_item->insns_, abs_offset))
3538 return false;
3539
3540 if (!UpdateRegisters(insn_flags, reg_table, abs_offset, work_line))
3541 return false;
3542 }
3543 }
3544
3545 /*
3546 * Handle instructions that can throw and that are sitting in a
3547 * "try" block. (If they're not in a "try" block when they throw,
3548 * control transfers out of the method.)
3549 */
3550 if ((opcode_flag & Instruction::kThrow) != 0 &&
3551 InsnIsInTry(insn_flags, insn_idx)) {
3552 bool has_catch_all = false;
3553 DexFile::CatchHandlerIterator iterator = DexFile::dexFindCatchHandler(
3554 *code_item, insn_idx);
3555
3556 for (; !iterator.HasNext(); iterator.Next()) {
3557 if (iterator.Get().type_idx_ == DexFile::kDexNoIndex)
3558 has_catch_all = true;
3559
3560 /*
3561 * Merge registers into the "catch" block. We want to
3562 * use the "savedRegs" rather than "work_regs", because
3563 * at runtime the exception will be thrown before the
3564 * instruction modifies any registers.
3565 */
3566 if (!UpdateRegisters(insn_flags, reg_table, iterator.Get().address_,
3567 &reg_table->saved_line_))
3568 return false;
3569 }
3570
3571 /*
3572 * If the monitor stack depth is nonzero, there must be a "catch all"
3573 * handler for this instruction. This does apply to monitor-exit
3574 * because of async exception handling.
3575 */
3576 if (work_line->monitor_stack_top_ != 0 && !has_catch_all) {
3577 /*
3578 * The state in work_line reflects the post-execution state.
3579 * If the current instruction is a monitor-enter and the monitor
3580 * stack was empty, we don't need a catch-all (if it throws,
3581 * it will do so before grabbing the lock).
3582 */
3583 if (!(dec_insn.opcode_ == Instruction::MONITOR_ENTER &&
3584 work_line->monitor_stack_top_ == 1))
3585 {
3586 LOG(ERROR) << "VFY: no catch-all for instruction at 0x" << std::hex
3587 << insn_idx << std::dec;
3588 return false;
3589 }
3590 }
3591 }
3592
3593 /*
3594 * If we're returning from the method, make sure our monitor stack is empty.
3595 */
3596 if ((opcode_flag & Instruction::kReturn) != 0 &&
3597 work_line->monitor_stack_top_ != 0) {
3598 LOG(ERROR) << "VFY: return with stack depth="
3599 << work_line->monitor_stack_top_ << " at 0x" << std::hex
3600 << insn_idx << std::dec;
3601 return false;
3602 }
3603
3604 /*
3605 * Update start_guess. Advance to the next instruction of that's
3606 * possible, otherwise use the branch target if one was found. If
3607 * neither of those exists we're in a return or throw; leave start_guess
3608 * alone and let the caller sort it out.
3609 */
3610 if ((opcode_flag & Instruction::kContinue) != 0) {
3611 *start_guess = insn_idx + InsnGetWidth(insn_flags, insn_idx);
3612 } else if ((opcode_flag & Instruction::kBranch) != 0) {
3613 /* we're still okay if branch_target is zero */
3614 *start_guess = insn_idx + branch_target;
3615 }
3616
3617 assert(*start_guess < insns_size &&
3618 InsnGetWidth(insn_flags, *start_guess) != 0);
3619
3620 return true;
3621}
3622
3623bool DexVerifier::ReplaceFailingInstruction(const DexFile::CodeItem* code_item,
3624 InsnFlags* insn_flags, int insn_idx, VerifyError failure) {
3625 const uint16_t* insns = code_item->insns_ + insn_idx;
3626 const byte* ptr = reinterpret_cast<const byte*>(insns);
3627 const Instruction* inst = Instruction::At(ptr);
3628 Instruction::Code opcode = inst->Opcode();
3629 VerifyErrorRefType ref_type;
3630
3631 /*
3632 * Generate the new instruction out of the old.
3633 *
3634 * First, make sure this is an instruction we're expecting to stomp on.
3635 */
3636 switch (opcode) {
3637 case Instruction::CONST_CLASS: // insn[1] == class ref, 2 bytes
3638 case Instruction::CHECK_CAST:
3639 case Instruction::INSTANCE_OF:
3640 case Instruction::NEW_INSTANCE:
3641 case Instruction::NEW_ARRAY:
3642 case Instruction::FILLED_NEW_ARRAY: // insn[1] == class ref, 3 bytes
3643 case Instruction::FILLED_NEW_ARRAY_RANGE:
3644 ref_type = VERIFY_ERROR_REF_CLASS;
3645 break;
3646
3647 case Instruction::IGET: // insn[1] == field ref, 2 bytes
3648 case Instruction::IGET_BOOLEAN:
3649 case Instruction::IGET_BYTE:
3650 case Instruction::IGET_CHAR:
3651 case Instruction::IGET_SHORT:
3652 case Instruction::IGET_WIDE:
3653 case Instruction::IGET_OBJECT:
3654 case Instruction::IPUT:
3655 case Instruction::IPUT_BOOLEAN:
3656 case Instruction::IPUT_BYTE:
3657 case Instruction::IPUT_CHAR:
3658 case Instruction::IPUT_SHORT:
3659 case Instruction::IPUT_WIDE:
3660 case Instruction::IPUT_OBJECT:
3661 case Instruction::SGET:
3662 case Instruction::SGET_BOOLEAN:
3663 case Instruction::SGET_BYTE:
3664 case Instruction::SGET_CHAR:
3665 case Instruction::SGET_SHORT:
3666 case Instruction::SGET_WIDE:
3667 case Instruction::SGET_OBJECT:
3668 case Instruction::SPUT:
3669 case Instruction::SPUT_BOOLEAN:
3670 case Instruction::SPUT_BYTE:
3671 case Instruction::SPUT_CHAR:
3672 case Instruction::SPUT_SHORT:
3673 case Instruction::SPUT_WIDE:
3674 case Instruction::SPUT_OBJECT:
3675 ref_type = VERIFY_ERROR_REF_FIELD;
3676 break;
3677
3678 case Instruction::INVOKE_VIRTUAL: // insn[1] == method ref, 3 bytes
3679 case Instruction::INVOKE_VIRTUAL_RANGE:
3680 case Instruction::INVOKE_SUPER:
3681 case Instruction::INVOKE_SUPER_RANGE:
3682 case Instruction::INVOKE_DIRECT:
3683 case Instruction::INVOKE_DIRECT_RANGE:
3684 case Instruction::INVOKE_STATIC:
3685 case Instruction::INVOKE_STATIC_RANGE:
3686 case Instruction::INVOKE_INTERFACE:
3687 case Instruction::INVOKE_INTERFACE_RANGE:
3688 ref_type = VERIFY_ERROR_REF_METHOD;
3689 break;
3690
3691 default:
3692 /* could handle this in a generic way, but this is probably safer */
3693 LOG(ERROR) << "GLITCH: verifier asked to replace opcode 0x" << std::hex
3694 << (int) opcode << std::dec;
3695 return false;
3696 }
3697
3698 assert(inst->IsThrow());
3699
3700 /* write a NOP over the third code unit, if necessary */
3701 int width = InsnGetWidth(insn_flags, insn_idx);
3702 switch (width) {
3703 case 2:
3704 /* nothing to do */
3705 break;
3706 case 3:
3707 // TODO: Add this functionality
3708 //UpdateCodeUnit(method, insns + 2, Instruction::NOP);
3709 break;
3710 default:
3711 /* whoops */
3712 LOG(FATAL) << "ERROR: stomped a " << width
3713 << "-unit instruction with a verifier error";
3714 }
3715
3716 /* encode the opcode, with the failure code in the high byte */
3717 // TODO: REPLACE FAILING OPCODES
3718 //assert(width == 2 || width == 3);
3719 //uint16_t new_val = Instruction::THROW_VERIFICATION_ERROR |
3720 //(failure << 8) | (ref_type << (8 + kVerifyErrorRefTypeShift));
3721 //UpdateCodeUnit(method, insns, new_val);
3722
3723 return true;
3724}
3725
3726/* Handle a monitor-enter instruction. */
3727void DexVerifier::HandleMonitorEnter(RegisterLine* work_line, uint32_t reg_idx,
3728 uint32_t insn_idx, VerifyError* failure) {
3729 if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
3730 LOG(ERROR) << "VFY: monitor-enter on non-object";
3731 *failure = VERIFY_ERROR_GENERIC;
3732 return;
3733 }
3734
3735 if (work_line->monitor_entries_ == NULL) {
3736 return;
3737 }
3738
3739 if (work_line->monitor_stack_top_ == kMaxMonitorStackDepth) {
3740 LOG(ERROR) << "VFY: monitor-enter stack overflow (" << kMaxMonitorStackDepth
3741 << ")";
3742 *failure = VERIFY_ERROR_GENERIC;
3743 return;
3744 }
3745
3746 /*
3747 * Push an entry on the stack, and set a bit in the register flags to
3748 * indicate that it's associated with this register.
3749 */
3750 work_line->monitor_entries_[reg_idx] |= 1 << work_line->monitor_stack_top_;
3751 work_line->monitor_stack_[work_line->monitor_stack_top_++] = insn_idx;
3752}
3753
3754/* Handle a monitor-exit instruction. */
3755void DexVerifier::HandleMonitorExit(RegisterLine* work_line, uint32_t reg_idx,
3756 uint32_t insn_idx, VerifyError* failure) {
3757 if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
3758 LOG(ERROR) << "VFY: monitor-exit on non-object";
3759 *failure = VERIFY_ERROR_GENERIC;
3760 return;
3761 }
3762
3763 if (work_line->monitor_entries_ == NULL) {
3764 return;
3765 }
3766
3767 if (work_line->monitor_stack_top_ == 0) {
3768 LOG(ERROR) << "VFY: monitor-exit stack underflow";
3769 *failure = VERIFY_ERROR_GENERIC;
3770 return;
3771 }
3772
3773 /*
3774 * Confirm that the entry at the top of the stack is associated with
3775 * the register. Pop the top entry off.
3776 */
3777 work_line->monitor_stack_top_--;
3778#ifdef BUG_3215458_FIXED
3779 /*
3780 * TODO: This code can safely be enabled if know we are working on
3781 * a dex file of format version 036 or later. (That is, we'll need to
3782 * add a check for the version number.)
3783 */
3784 if ((work_line->monitor_entries_[reg_idx] &
3785 (1 << work_line->monitor_stack_top_)) == 0) {
3786 LOG(ERROR) << "VFY: monitor-exit bit " << work_line->monitor_stack_top_
3787 << " not set: addr=0x" << std::hex << insn_idx << std::dec
3788 << " (bits[" << reg_idx << "]=" << std::hex
3789 << work_line->monitor_entries_[reg_idx] << std::dec << ")";
3790 *failure = VERIFY_ERROR_GENERIC;
3791 return;
3792 }
3793#endif
3794 work_line->monitor_stack_[work_line->monitor_stack_top_] = 0;
3795
3796 /* Clear the bit from the register flags. */
3797 work_line->monitor_entries_[reg_idx] &= ~(1 << work_line->monitor_stack_top_);
3798}
3799
3800Field* DexVerifier::GetInstField(VerifierData* vdata, RegType obj_type,
3801 int field_idx, VerifyError* failure) {
3802 Method* method = vdata->method_;
3803 const DexFile* dex_file = vdata->dex_file_;
3804 UninitInstanceMap* uninit_map = vdata->uninit_map_;
3805 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3806 DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
3807 const ClassLoader* class_loader =
3808 method->GetDeclaringClass()->GetClassLoader();
3809 Field* field = NULL;
3810 Class* obj_class;
3811 bool must_be_local = false;
3812
3813 if (!RegTypeIsReference(obj_type)) {
3814 LOG(ERROR) << "VFY: attempt to access field in non-reference type "
3815 << obj_type;
3816 *failure = VERIFY_ERROR_GENERIC;
3817 return field;
3818 }
3819
3820 field = class_linker->ResolveField(*dex_file, field_idx, dex_cache,
3821 class_loader, false);
3822 if (field == NULL) {
3823 LOG(ERROR) << "VFY: unable to resolve instance field " << field_idx;
3824 return field;
3825 }
3826
3827 if (obj_type == kRegTypeZero)
3828 return field;
3829
3830 /*
3831 * Access to fields in uninitialized objects is allowed if this is
3832 * the <init> method for the object and the field in question is
3833 * declared by this class.
3834 */
3835 obj_class = RegTypeReferenceToClass(obj_type, uninit_map);
3836 assert(obj_class != NULL);
3837 if (RegTypeIsUninitReference(obj_type)) {
3838 if (!IsInitMethod(method) || method->GetDeclaringClass() != obj_class) {
3839 LOG(ERROR) << "VFY: attempt to access field via uninitialized ref";
3840 *failure = VERIFY_ERROR_GENERIC;
3841 return field;
3842 }
3843 must_be_local = true;
3844 }
3845
3846 //if (!obj_class->InstanceOf(field->GetDeclaringClass())) {
3847 if (!field->GetDeclaringClass()->IsAssignableFrom(obj_class)) {
3848 LOG(ERROR) << "VFY: invalid field access (field "
3849 << field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
3850 << "." << field->GetName()->ToModifiedUtf8() << ", through "
3851 << obj_class->GetDescriptor()->ToModifiedUtf8() << " ref)";
3852 *failure = VERIFY_ERROR_NO_FIELD;
3853 return field;
3854 }
3855
3856 if (must_be_local) {
3857 bool found = false;
3858 /* for uninit ref, make sure it's defined by this class, not super */
3859 for (uint32_t i = 0; i < obj_class->NumInstanceFields(); i++) {
3860 found |= (field == obj_class->GetInstanceField(i));
3861 }
3862 if (!found) {
3863 LOG(ERROR) << "VFY: invalid constructor field access (field "
3864 << field->GetName()->ToModifiedUtf8() << " in "
3865 << obj_class->GetDescriptor()->ToModifiedUtf8() << ")";
3866 *failure = VERIFY_ERROR_GENERIC;
3867 return field;
3868 }
3869 }
3870
3871 return field;
3872}
3873
3874Field* DexVerifier::GetStaticField(VerifierData* vdata, int field_idx,
3875 VerifyError* failure) {
3876 Method* method = vdata->method_;
3877 const DexFile* dex_file = vdata->dex_file_;
3878 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3879 DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
3880 const ClassLoader* class_loader =
3881 method->GetDeclaringClass()->GetClassLoader();
3882 Field* field;
3883
3884 field = class_linker->ResolveField(*dex_file, field_idx, dex_cache,
3885 class_loader, true);
3886 if (field == NULL) {
3887 //const DexFile::FieldId field_id = dex_file->GetFieldId(field_idx);
3888
3889 //LOG(ERROR) << "VFY: unable to resolve static field " << field_idx << " ("
3890 //<< dex_file->GetFieldName(field_id) << ") in "
3891 //<< dex_file->GetFieldClassDescriptor(field_id);
3892 LOG(ERROR) << "VFY: unable to resolve static field";
3893 }
3894
3895 return field;
3896}
3897
3898Class* DexVerifier::GetCaughtExceptionType(VerifierData* vdata, int insn_idx,
3899 VerifyError* failure) {
3900 const DexFile* dex_file = vdata->dex_file_;
3901 const DexFile::CodeItem* code_item = vdata->code_item_;
3902 Method* method = vdata->method_;
3903 Class* common_super = NULL;
3904 uint32_t handlers_size;
jeffhaoba5ebb92011-08-25 17:24:37 -07003905 const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item, 0);
jeffhaobdb76512011-09-07 11:43:16 -07003906
3907 if (code_item->tries_size_ != 0) {
3908 handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
3909 } else {
3910 handlers_size = 0;
3911 }
3912
3913 for (uint32_t i = 0; i < handlers_size; i++) {
jeffhaoba5ebb92011-08-25 17:24:37 -07003914 DexFile::CatchHandlerIterator iterator(handlers_ptr);
3915
3916 for (; !iterator.HasNext(); iterator.Next()) {
jeffhaobdb76512011-09-07 11:43:16 -07003917 DexFile::CatchHandlerItem handler = iterator.Get();
3918 if (handler.address_ == (uint32_t) insn_idx) {
3919 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3920 Class* klass;
jeffhaoba5ebb92011-08-25 17:24:37 -07003921
jeffhaobdb76512011-09-07 11:43:16 -07003922 if (handler.type_idx_ == DexFile::kDexNoIndex) {
3923 klass = class_linker->FindSystemClass("Ljava/lang/Throwable;");
3924 } else {
3925 klass = class_linker->ResolveType(*dex_file, handler.type_idx_,
3926 method->GetDeclaringClass());
3927 }
3928
3929 if (klass == NULL) {
3930 LOG(ERROR) << "VFY: unable to resolve exception class "
3931 << handler.type_idx_ << " ("
3932 << dex_file->dexStringByTypeIdx(handler.type_idx_) << ")";
3933 /* TODO: do we want to keep going? If we don't fail
3934 * this we run the risk of having a non-Throwable
3935 * introduced at runtime. However, that won't pass
3936 * an instanceof test, so is essentially harmless.
3937 */
3938 } else {
3939 if (common_super == NULL)
3940 common_super = klass;
3941 else
3942 common_super = FindCommonSuperclass(klass, common_super);
3943 }
3944 }
jeffhaoba5ebb92011-08-25 17:24:37 -07003945 }
3946
3947 handlers_ptr = iterator.GetData();
3948 }
3949
jeffhaobdb76512011-09-07 11:43:16 -07003950 if (common_super == NULL) {
3951 /* no catch blocks, or no catches with classes we can find */
3952 LOG(ERROR) << "VFY: unable to find exception handler at addr 0x" << std::hex
3953 << insn_idx << std::dec;
3954 *failure = VERIFY_ERROR_GENERIC;
3955 }
3956
3957 return common_super;
jeffhaoba5ebb92011-08-25 17:24:37 -07003958}
3959
jeffhaobdb76512011-09-07 11:43:16 -07003960DexVerifier::RegType DexVerifier::GetMethodReturnType(const DexFile* dex_file,
3961 const Method* method) {
3962 Class* klass = method->GetReturnType();
3963 if (klass->IsPrimitive())
3964 return PrimitiveTypeToRegType(klass->GetPrimitiveType());
3965 else
3966 return RegTypeFromClass(klass);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07003967}
3968
jeffhaobdb76512011-09-07 11:43:16 -07003969Class* DexVerifier::GetClassFromRegister(const RegisterLine* register_line,
3970 uint32_t vsrc, VerifyError* failure) {
3971 /* get the element type of the array held in vsrc */
3972 RegType type = GetRegisterType(register_line, vsrc);
jeffhaoba5ebb92011-08-25 17:24:37 -07003973
jeffhaobdb76512011-09-07 11:43:16 -07003974 /* if "always zero", we allow it to fail at runtime */
3975 if (type == kRegTypeZero)
3976 return NULL;
3977
3978 if (!RegTypeIsReference(type)) {
3979 LOG(ERROR) << "VFY: tried to get class from non-ref register v" << vsrc
3980 << " (type=" << type << ")",
3981 *failure = VERIFY_ERROR_GENERIC;
3982 return NULL;
3983 }
3984 if (RegTypeIsUninitReference(type)) {
3985 LOG(ERROR) << "VFY: register " << vsrc << " holds uninitialized reference";
3986 *failure = VERIFY_ERROR_GENERIC;
3987 return NULL;
jeffhaoba5ebb92011-08-25 17:24:37 -07003988 }
3989
jeffhaobdb76512011-09-07 11:43:16 -07003990 return RegTypeInitializedReferenceToClass(type);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07003991}
3992
jeffhaobdb76512011-09-07 11:43:16 -07003993DexVerifier::RegType DexVerifier::GetInvocationThis(
3994 const RegisterLine* register_line,
3995 const Instruction::DecodedInstruction* dec_insn, VerifyError* failure) {
3996 if (dec_insn->vA_ < 1) {
3997 LOG(ERROR) << "VFY: invoke lacks 'this'";
3998 *failure = VERIFY_ERROR_GENERIC;
3999 return kRegTypeUnknown;
jeffhaoba5ebb92011-08-25 17:24:37 -07004000 }
jeffhaobdb76512011-09-07 11:43:16 -07004001
4002 /* get the element type of the array held in vsrc */
4003 RegType this_type = GetRegisterType(register_line, dec_insn->vC_);
4004 if (!RegTypeIsReference(this_type)) {
4005 LOG(ERROR) << "VFY: tried to get class from non-ref register v"
4006 << dec_insn->vC_ << " (type=" << this_type << ")";
4007 *failure = VERIFY_ERROR_GENERIC;
4008 return kRegTypeUnknown;
4009 }
4010
4011 return this_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07004012}
4013
jeffhaobdb76512011-09-07 11:43:16 -07004014void DexVerifier::SetRegisterType(RegisterLine* register_line, uint32_t vdst,
4015 RegType new_type) {
4016 RegType* insn_regs = register_line->reg_types_;
jeffhaoba5ebb92011-08-25 17:24:37 -07004017
jeffhaobdb76512011-09-07 11:43:16 -07004018 switch (new_type) {
4019 case kRegTypeUnknown:
4020 case kRegTypeBoolean:
4021 case kRegTypeOne:
4022 case kRegTypeConstByte:
4023 case kRegTypeConstPosByte:
4024 case kRegTypeConstShort:
4025 case kRegTypeConstPosShort:
4026 case kRegTypeConstChar:
4027 case kRegTypeConstInteger:
4028 case kRegTypeByte:
4029 case kRegTypePosByte:
4030 case kRegTypeShort:
4031 case kRegTypePosShort:
4032 case kRegTypeChar:
4033 case kRegTypeInteger:
4034 case kRegTypeFloat:
4035 case kRegTypeZero:
4036 case kRegTypeUninit:
4037 insn_regs[vdst] = new_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07004038 break;
jeffhaobdb76512011-09-07 11:43:16 -07004039 case kRegTypeConstLo:
4040 case kRegTypeLongLo:
4041 case kRegTypeDoubleLo:
4042 insn_regs[vdst] = new_type;
4043 insn_regs[vdst + 1] = new_type + 1;
4044 break;
4045 case kRegTypeConstHi:
4046 case kRegTypeLongHi:
4047 case kRegTypeDoubleHi:
4048 /* should never set these explicitly */
4049 LOG(FATAL) << "BUG: explicit set of high register type";
4050 break;
4051
4052 default:
4053 /* can't switch for ref types, so we check explicitly */
4054 if (RegTypeIsReference(new_type)) {
4055 insn_regs[vdst] = new_type;
4056
4057 /*
4058 * In most circumstances we won't see a reference to a primitive
4059 * class here (e.g. "D"), since that would mean the object in the
4060 * register is actually a primitive type. It can happen as the
4061 * result of an assumed-successful check-cast instruction in
4062 * which the second argument refers to a primitive class. (In
4063 * practice, such an instruction will always throw an exception.)
4064 *
4065 * This is not an issue for instructions like const-class, where
4066 * the object in the register is a java.lang.Class instance.
4067 */
4068 break;
4069 }
4070 /* bad type - fall through */
4071
4072 case kRegTypeConflict: // should only be set during a merge
4073 LOG(FATAL) << "BUG: set register to unknown type " << new_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07004074 break;
4075 }
4076
jeffhaobdb76512011-09-07 11:43:16 -07004077 /*
4078 * Clear the monitor entry bits for this register.
4079 */
4080 if (register_line->monitor_entries_ != NULL)
4081 register_line->monitor_entries_[vdst] = 0;
4082}
4083
4084void DexVerifier::VerifyRegisterType(RegisterLine* register_line, uint32_t vsrc,
4085 RegType check_type, VerifyError* failure) {
4086 const RegType* insn_regs = register_line->reg_types_;
4087 RegType src_type = insn_regs[vsrc];
4088
4089 switch (check_type) {
4090 case kRegTypeFloat:
4091 case kRegTypeBoolean:
4092 case kRegTypePosByte:
4093 case kRegTypeByte:
4094 case kRegTypePosShort:
4095 case kRegTypeShort:
4096 case kRegTypeChar:
4097 case kRegTypeInteger:
4098 if (!CanConvertTo1nr(src_type, check_type)) {
4099 LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
4100 << ", wanted " << check_type;
4101 *failure = VERIFY_ERROR_GENERIC;
4102 }
4103 /* Update type if result is float */
4104 if (check_type == kRegTypeFloat) {
4105 SetRegisterType(register_line, vsrc, check_type);
4106 } else {
4107 /* Update const type to actual type after use */
4108 SetRegisterType(register_line, vsrc, ConstTypeToRegType(src_type));
4109 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004110 break;
jeffhaobdb76512011-09-07 11:43:16 -07004111 case kRegTypeLongLo:
4112 case kRegTypeDoubleLo:
4113 if (insn_regs[vsrc + 1] != src_type + 1) {
4114 LOG(ERROR) << "VFY: register2 v" << vsrc << "-" << vsrc + 1
4115 << " values " << insn_regs[vsrc] << ","
4116 << insn_regs[vsrc + 1];
4117 *failure = VERIFY_ERROR_GENERIC;
4118 } else if (!CanConvertTo2(src_type, check_type)) {
4119 LOG(ERROR) << "VFY: register2 v" << vsrc << " type " << src_type
4120 << ", wanted " << check_type;
4121 *failure = VERIFY_ERROR_GENERIC;
4122 }
4123 /* Update type if source is from const */
4124 if (src_type == kRegTypeConstLo) {
4125 SetRegisterType(register_line, vsrc, check_type);
4126 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004127 break;
jeffhaobdb76512011-09-07 11:43:16 -07004128 case kRegTypeConstLo:
4129 case kRegTypeConstHi:
4130 case kRegTypeLongHi:
4131 case kRegTypeDoubleHi:
4132 case kRegTypeZero:
4133 case kRegTypeOne:
4134 case kRegTypeUnknown:
4135 case kRegTypeConflict:
4136 /* should never be checking for these explicitly */
4137 assert(false);
4138 *failure = VERIFY_ERROR_GENERIC;
4139 return;
4140 case kRegTypeUninit:
4141 default:
4142 /* make sure check_type is initialized reference */
4143 if (!RegTypeIsReference(check_type)) {
4144 LOG(ERROR) << "VFY: unexpected check type " << check_type;
4145 assert(false);
4146 *failure = VERIFY_ERROR_GENERIC;
4147 break;
4148 }
4149 if (RegTypeIsUninitReference(check_type)) {
4150 LOG(ERROR) << "VFY: uninitialized ref not expected as reg check";
4151 *failure = VERIFY_ERROR_GENERIC;
4152 break;
4153 }
4154 /* make sure src_type is initialized reference or always-NULL */
4155 if (!RegTypeIsReference(src_type)) {
4156 LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
4157 << ", wanted ref";
4158 *failure = VERIFY_ERROR_GENERIC;
4159 break;
4160 }
4161 if (RegTypeIsUninitReference(src_type)) {
4162 LOG(ERROR) << "VFY: register1 v" << vsrc << " holds uninitialized ref";
4163 *failure = VERIFY_ERROR_GENERIC;
4164 break;
4165 }
4166 /* if the register isn't Zero, make sure it's an instance of check */
4167 if (src_type != kRegTypeZero) {
4168 Class* src_class = RegTypeInitializedReferenceToClass(src_type);
4169 Class* check_class = RegTypeInitializedReferenceToClass(check_type);
4170 assert(src_class != NULL);
4171 assert(check_class != NULL);
4172
4173 if (!check_class->IsAssignableFrom(src_class)) {
4174 LOG(ERROR) << "VFY: " << src_class->GetDescriptor()->ToModifiedUtf8()
4175 << " is not instance of "
4176 << check_class->GetDescriptor()->ToModifiedUtf8();
4177 *failure = VERIFY_ERROR_GENERIC;
4178 }
4179 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004180 break;
4181 }
jeffhaobdb76512011-09-07 11:43:16 -07004182}
jeffhaoba5ebb92011-08-25 17:24:37 -07004183
jeffhaobdb76512011-09-07 11:43:16 -07004184void DexVerifier::SetResultRegisterType(RegisterLine* register_line,
4185 const int insn_reg_count, RegType new_type) {
4186 SetRegisterType(register_line, RESULT_REGISTER(insn_reg_count), new_type);
4187}
4188
4189void DexVerifier::MarkRefsAsInitialized(RegisterLine* register_line,
4190 int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type,
4191 VerifyError* failure) {
4192 RegType* insn_regs = register_line->reg_types_;
4193 Class* klass = GetUninitInstance(uninit_map,
4194 RegTypeToUninitIndex(uninit_type));
4195
4196 if (klass == NULL) {
4197 LOG(ERROR) << "VFY: unable to find type=" << std::hex << uninit_type
4198 << std::dec << " (idx=" << RegTypeToUninitIndex(uninit_type)
4199 << ")";
4200 *failure = VERIFY_ERROR_GENERIC;
4201 return;
jeffhaoba5ebb92011-08-25 17:24:37 -07004202 }
4203
jeffhaobdb76512011-09-07 11:43:16 -07004204 RegType init_type = RegTypeFromClass(klass);
4205 int changed = 0;
4206 for (int i = 0; i < insn_reg_count; i++) {
4207 if (insn_regs[i] == uninit_type) {
4208 insn_regs[i] = init_type;
4209 changed++;
4210 }
4211 }
4212 assert(changed > 0);
4213
4214 return;
4215}
4216
4217void DexVerifier::MarkUninitRefsAsInvalid(RegisterLine* register_line,
4218 int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type) {
4219 RegType* insn_regs = register_line->reg_types_;
4220
4221 for (int i = 0; i < insn_reg_count; i++) {
4222 if (insn_regs[i] == uninit_type) {
4223 insn_regs[i] = kRegTypeConflict;
4224 if (register_line->monitor_entries_ != NULL)
4225 register_line->monitor_entries_[i] = 0;
4226 }
4227 }
4228}
4229
4230void DexVerifier::CopyRegister1(RegisterLine* register_line, uint32_t vdst,
4231 uint32_t vsrc, TypeCategory cat, VerifyError* failure) {
4232 assert(cat == kTypeCategory1nr || cat == kTypeCategoryRef);
4233 RegType type = GetRegisterType(register_line, vsrc);
4234 CheckTypeCategory(type, cat, failure);
4235 if (*failure != VERIFY_ERROR_NONE) {
4236 LOG(ERROR) << "VFY: copy1 v" << vdst << "<-v" << vsrc << " type=" << type
4237 << " cat=" << (int) cat;
4238 } else {
4239 SetRegisterType(register_line, vdst, type);
4240 if (cat == kTypeCategoryRef && register_line->monitor_entries_ != NULL) {
4241 register_line->monitor_entries_[vdst] =
4242 register_line->monitor_entries_[vsrc];
4243 }
4244 }
4245}
4246
4247void DexVerifier::CopyRegister2(RegisterLine* register_line, uint32_t vdst,
4248 uint32_t vsrc, VerifyError* failure) {
4249 RegType type_l = GetRegisterType(register_line, vsrc);
4250 RegType type_h = GetRegisterType(register_line, vsrc + 1);
4251
4252 CheckTypeCategory(type_l, kTypeCategory2, failure);
4253 CheckWidePair(type_l, type_h, failure);
4254 if (*failure != VERIFY_ERROR_NONE) {
4255 LOG(ERROR) << "VFY: copy2 v" << vdst << "<-v" << vsrc << " type=" << type_l
4256 << "/" << type_h;
4257 } else {
4258 SetRegisterType(register_line, vdst, type_l);
4259 }
4260}
4261
4262void DexVerifier::CopyResultRegister1(RegisterLine* register_line,
4263 const int insn_reg_count, uint32_t vdst, TypeCategory cat,
4264 VerifyError* failure) {
4265 assert(vdst < (uint32_t) insn_reg_count);
4266
4267 uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
4268 RegType type = GetRegisterType(register_line, vsrc);
4269 CheckTypeCategory(type, cat, failure);
4270 if (*failure != VERIFY_ERROR_NONE) {
4271 LOG(ERROR) << "VFY: copyRes1 v" << vdst << "<-v" << vsrc << " cat="
4272 << (int) cat << " type=" << type;
4273 } else {
4274 SetRegisterType(register_line, vdst, type);
4275 SetRegisterType(register_line, vsrc, kRegTypeUnknown);
4276 }
4277}
4278
4279/*
4280 * Implement "move-result-wide". Copy the category-2 value from the result
4281 * register to another register, and reset the result register.
4282 */
4283void DexVerifier::CopyResultRegister2(RegisterLine* register_line,
4284 const int insn_reg_count, uint32_t vdst, VerifyError* failure) {
4285 assert(vdst < (uint32_t) insn_reg_count);
4286
4287 uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
4288 RegType type_l = GetRegisterType(register_line, vsrc);
4289 RegType type_h = GetRegisterType(register_line, vsrc + 1);
4290 CheckTypeCategory(type_l, kTypeCategory2, failure);
4291 CheckWidePair(type_l, type_h, failure);
4292 if (*failure != VERIFY_ERROR_NONE) {
4293 LOG(ERROR) << "VFY: copyRes2 v" << vdst << "<-v" << vsrc << " type="
4294 << type_l << "/" << type_h;
4295 } else {
4296 SetRegisterType(register_line, vdst, type_l);
4297 SetRegisterType(register_line, vsrc, kRegTypeUnknown);
4298 SetRegisterType(register_line, vsrc + 1, kRegTypeUnknown);
4299 }
4300}
4301
4302int DexVerifier::GetClassDepth(Class* klass) {
4303 int depth = 0;
4304 while (klass->GetSuperClass() != NULL) {
4305 klass = klass->GetSuperClass();
4306 depth++;
4307 }
4308 return depth;
4309}
4310
4311Class* DexVerifier::DigForSuperclass(Class* c1, Class* c2) {
4312 int depth1, depth2;
4313
4314 depth1 = GetClassDepth(c1);
4315 depth2 = GetClassDepth(c2);
4316
4317 /* pull the deepest one up */
4318 if (depth1 > depth2) {
4319 while (depth1 > depth2) {
4320 c1 = c1->GetSuperClass();
4321 depth1--;
4322 }
4323 } else {
4324 while (depth2 > depth1) {
4325 c2 = c2->GetSuperClass();
4326 depth2--;
4327 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004328 }
4329
jeffhaobdb76512011-09-07 11:43:16 -07004330 /* walk up in lock-step */
4331 while (c1 != c2) {
4332 c1 = c1->GetSuperClass();
4333 c2 = c2->GetSuperClass();
4334
4335 assert(c1 != NULL && c2 != NULL);
4336 }
4337
4338 return c1;
4339}
4340
4341Class* DexVerifier::FindCommonArraySuperclass(Class* c1, Class* c2) {
4342 Class* array_class = NULL;
4343 Class* common_elem;
4344 int array_dim1, array_dim2;
4345 int i, num_dims;
4346 bool has_primitive = false;
4347
4348 array_dim1 = c1->GetArrayRank();
4349 array_dim2 = c2->GetArrayRank();
4350 assert(c1->GetArrayRank() > 0);
4351 assert(c2->GetArrayRank() > 0);
4352
4353 if (c1->GetComponentType()->IsPrimitive()) {
4354 array_dim1--;
4355 has_primitive = true;
4356 }
4357 if (c2->GetComponentType()->IsPrimitive()) {
4358 array_dim2--;
4359 has_primitive = true;
4360 }
4361
4362 if (!has_primitive && array_dim1 == array_dim2) {
4363 /*
4364 * Two arrays of reference types with equal dimensions. Try to
4365 * find a good match.
4366 */
4367 common_elem = FindCommonSuperclass(c1->GetComponentType(),
4368 c2->GetComponentType());
4369 num_dims = array_dim1;
4370 } else {
4371 /*
4372 * Mismatched array depths and/or array(s) of primitives. We want
4373 * Object, or an Object array with appropriate dimensions.
4374 *
4375 * We initialize array_class to Object here, because it's possible
4376 * for us to set num_dims=0.
4377 */
4378 if (array_dim1 < array_dim2)
4379 num_dims = array_dim1;
4380 else
4381 num_dims = array_dim2;
4382 array_class = common_elem = c1->GetSuperClass(); // == java.lang.Object
4383 }
4384
4385 /*
4386 * Find an appropriately-dimensioned array class. This is easiest
4387 * to do iteratively, using the array class found by the current round
4388 * as the element type for the next round.
4389 */
4390 for (i = 0; i < num_dims; i++) {
4391 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4392 const ClassLoader* class_loader = c1->GetClassLoader();
4393 std::string descriptor = "[" +
4394 common_elem->GetDescriptor()->ToModifiedUtf8();
4395 array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
4396 common_elem = array_class;
4397 }
4398 assert(array_class != NULL);
4399
4400 return array_class;
4401}
4402
4403Class* DexVerifier::FindCommonSuperclass(Class* c1, Class* c2) {
4404 assert(!c1->IsPrimitive() && !c2->IsPrimitive());
4405
4406 if (c1 == c2)
4407 return c1;
4408
jeffhao5dbddee2011-09-07 16:38:26 -07004409 if (c1->IsInterface() && c1->IsAssignableFrom(c2)) {
jeffhaobdb76512011-09-07 11:43:16 -07004410 return c1;
4411 }
jeffhao5dbddee2011-09-07 16:38:26 -07004412 if (c2->IsInterface() && c2->IsAssignableFrom(c1)) {
jeffhaobdb76512011-09-07 11:43:16 -07004413 return c2;
4414 }
4415 if (c1->IsArrayClass() && c2->IsArrayClass()) {
4416 return FindCommonArraySuperclass(c1, c2);
4417 }
4418
4419 return DigForSuperclass(c1, c2);
4420}
4421
4422DexVerifier::RegType DexVerifier::MergeTypes(RegType type1, RegType type2,
4423 bool* changed) {
4424 RegType result;
4425
4426 /*
4427 * Check for trivial case so we don't have to hit memory.
4428 */
4429 if (type1 == type2)
4430 return type1;
4431
4432 /*
4433 * Use the table if we can, and reject any attempts to merge something
4434 * from the table with a reference type.
4435 *
4436 * Uninitialized references are composed of the enum ORed with an
4437 * index value. The uninitialized table entry at index zero *will*
4438 * show up as a simple kRegTypeUninit value. Since this cannot be
4439 * merged with anything but itself, the rules do the right thing.
4440 */
4441 if (type1 < kRegTypeMAX) {
4442 if (type2 < kRegTypeMAX) {
4443 result = merge_table_[type1][type2];
4444 } else {
4445 /* simple + reference == conflict, usually */
4446 if (type1 == kRegTypeZero)
4447 result = type2;
4448 else
4449 result = kRegTypeConflict;
4450 }
4451 } else {
4452 if (type2 < kRegTypeMAX) {
4453 /* reference + simple == conflict, usually */
4454 if (type2 == kRegTypeZero)
4455 result = type1;
4456 else
4457 result = kRegTypeConflict;
4458 } else {
4459 /* merging two references */
4460 if (RegTypeIsUninitReference(type1) ||
4461 RegTypeIsUninitReference(type2))
4462 {
4463 /* can't merge uninit with anything but self */
4464 result = kRegTypeConflict;
4465 } else {
4466 Class* klass1 = RegTypeInitializedReferenceToClass(type1);
4467 Class* klass2 = RegTypeInitializedReferenceToClass(type2);
4468 Class* merged_class = FindCommonSuperclass(klass1, klass2);
4469 assert(merged_class != NULL);
4470 result = RegTypeFromClass(merged_class);
4471 }
4472 }
4473 }
4474
4475 if (result != type1)
4476 *changed = true;
jeffhaoba5ebb92011-08-25 17:24:37 -07004477 return result;
jeffhaobdb76512011-09-07 11:43:16 -07004478}
4479
4480DexVerifier::MonitorEntries DexVerifier::MergeMonitorEntries(
4481 MonitorEntries ents1, MonitorEntries ents2, bool* changed) {
4482 MonitorEntries result = ents1 & ents2;
4483 if (result != ents1)
4484 *changed = true;
4485 return result;
4486}
4487
4488bool DexVerifier::UpdateRegisters(InsnFlags* insn_flags,
4489 RegisterTable* reg_table, int next_insn, const RegisterLine* work_line) {
4490 const size_t insn_reg_count_plus = reg_table->insn_reg_count_plus_;
4491 assert(work_line != NULL);
4492 const RegType* work_regs = work_line->reg_types_;
4493
4494 if (!InsnIsVisitedOrChanged(insn_flags, next_insn)) {
4495 /*
4496 * We haven't processed this instruction before, and we haven't
4497 * touched the registers here, so there's nothing to "merge". Copy
4498 * the registers over and mark it as changed. (This is the only
4499 * way a register can transition out of "unknown", so this is not
4500 * just an optimization.)
4501 */
4502 CopyLineToTable(reg_table, next_insn, work_line);
4503 InsnSetChanged(insn_flags, next_insn, true);
4504 } else {
4505 /* Merge registers, set Changed only if different */
4506 RegisterLine* target_line = GetRegisterLine(reg_table, next_insn);
4507 RegType* target_regs = target_line->reg_types_;
4508 MonitorEntries* work_mon_ents = work_line->monitor_entries_;
4509 MonitorEntries* target_mon_ents = target_line->monitor_entries_;
4510 bool changed = false;
4511 unsigned int idx;
4512
4513 assert(target_regs != NULL);
4514 if (target_mon_ents != NULL) {
4515 /* Monitor stacks must be identical. */
4516 if (target_line->monitor_stack_top_ != work_line->monitor_stack_top_) {
4517 LOG(ERROR) << "VFY: mismatched stack depth "
4518 << target_line->monitor_stack_top_ << " vs. "
4519 << work_line->monitor_stack_top_ << " at 0x"
4520 << std::hex << next_insn << std::dec;
4521 return false;
4522 }
4523 if (memcmp(target_line->monitor_stack_, work_line->monitor_stack_,
4524 target_line->monitor_stack_top_ * sizeof(uint32_t)) != 0) {
4525 LOG(ERROR) << "VFY: mismatched monitor stacks at 0x" << std::hex
4526 << next_insn << std::dec;
4527 return false;
4528 }
4529 }
4530
4531 for (idx = 0; idx < insn_reg_count_plus; idx++) {
4532 target_regs[idx] = MergeTypes(target_regs[idx], work_regs[idx], &changed);
4533
4534 if (target_mon_ents != NULL) {
4535 target_mon_ents[idx] = MergeMonitorEntries(target_mon_ents[idx],
4536 work_mon_ents[idx], &changed);
4537 }
4538 }
4539
4540 if (changed) {
4541 InsnSetChanged(insn_flags, next_insn, true);
4542 }
4543 }
4544
4545 return true;
4546}
4547
4548bool DexVerifier::CanConvertTo1nr(RegType src_type, RegType check_type) {
4549 static const char conv_tab[kRegType1nrEND - kRegType1nrSTART + 1]
4550 [kRegType1nrEND - kRegType1nrSTART + 1] =
4551 {
4552 /* chk: 0 1 Z y Y h H c i b B s S C I F */
4553 { /*0*/ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4554 { /*1*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4555 { /*Z*/ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
4556 { /*y*/ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4557 { /*Y*/ 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1 },
4558 { /*h*/ 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1 },
4559 { /*H*/ 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1 },
4560 { /*c*/ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1 },
4561 { /*i*/ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1 },
4562 { /*b*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0 },
4563 { /*B*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0 },
4564 { /*s*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 },
4565 { /*S*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 },
4566 { /*C*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 },
4567 { /*I*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },
4568 { /*F*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
4569 };
4570
4571 assert(check_type >= kRegType1nrSTART && check_type <= kRegType1nrEND);
4572
4573 if (src_type >= kRegType1nrSTART && src_type <= kRegType1nrEND)
4574 return (bool) conv_tab[src_type - kRegType1nrSTART]
4575 [check_type - kRegType1nrSTART];
4576
4577 return false;
4578}
4579
4580bool DexVerifier::CanConvertTo2(RegType src_type, RegType check_type) {
4581 return ((src_type == kRegTypeConstLo || src_type == check_type) &&
4582 (check_type == kRegTypeLongLo || check_type == kRegTypeDoubleLo));
4583}
4584
4585DexVerifier::RegType DexVerifier::PrimitiveTypeToRegType(
4586 Class::PrimitiveType prim_type) {
4587 switch (prim_type) {
4588 case Class::kPrimBoolean: return kRegTypeBoolean;
4589 case Class::kPrimByte: return kRegTypeByte;
4590 case Class::kPrimShort: return kRegTypeShort;
4591 case Class::kPrimChar: return kRegTypeChar;
4592 case Class::kPrimInt: return kRegTypeInteger;
4593 case Class::kPrimLong: return kRegTypeLongLo;
4594 case Class::kPrimFloat: return kRegTypeFloat;
4595 case Class::kPrimDouble: return kRegTypeDoubleLo;
4596 case Class::kPrimVoid:
4597 default: {
4598 return kRegTypeUnknown;
4599 }
4600 }
4601}
4602
4603DexVerifier::RegType DexVerifier::ConstTypeToRegType(RegType const_type) {
4604 switch (const_type) {
4605 case kRegTypeConstPosByte: return kRegTypePosByte;
4606 case kRegTypeConstByte: return kRegTypeByte;
4607 case kRegTypeConstPosShort: return kRegTypePosShort;
4608 case kRegTypeConstShort: return kRegTypeShort;
4609 case kRegTypeConstChar: return kRegTypeChar;
4610 case kRegTypeConstInteger: return kRegTypeInteger;
4611 default: {
4612 return const_type;
4613 }
4614 }
4615}
4616
4617char DexVerifier::DetermineCat1Const(int32_t value) {
4618 if (value < -32768)
4619 return kRegTypeConstInteger;
4620 else if (value < -128)
4621 return kRegTypeConstShort;
4622 else if (value < 0)
4623 return kRegTypeConstByte;
4624 else if (value == 0)
4625 return kRegTypeZero;
4626 else if (value == 1)
4627 return kRegTypeOne;
4628 else if (value < 128)
4629 return kRegTypeConstPosByte;
4630 else if (value < 32768)
4631 return kRegTypeConstPosShort;
4632 else if (value < 65536)
4633 return kRegTypeConstChar;
4634 else
4635 return kRegTypeConstInteger;
4636}
4637
4638void DexVerifier::CheckFinalFieldAccess(const Method* method,
4639 const Field* field, VerifyError* failure) {
4640 if (!field->IsFinal())
4641 return;
4642
4643 /* make sure we're in the same class */
4644 if (method->GetDeclaringClass() != field->GetDeclaringClass()) {
4645 LOG(ERROR) << "VFY: can't modify final field "
4646 << field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
4647 << "." << field->GetName()->ToModifiedUtf8();
4648 *failure = VERIFY_ERROR_ACCESS_FIELD;
4649 return;
4650 }
4651}
4652
4653void DexVerifier::CheckArrayIndexType(const Method* method, RegType reg_type,
4654 VerifyError* failure) {
4655 if (*failure == VERIFY_ERROR_NONE) {
4656 /*
4657 * The 1nr types are interchangeable at this level. We could
4658 * do something special if we can definitively identify it as a
4659 * float, but there's no real value in doing so.
4660 */
4661 CheckTypeCategory(reg_type, kTypeCategory1nr, failure);
4662 if (*failure != VERIFY_ERROR_NONE) {
4663 LOG(ERROR) << "Invalid reg type for array index (" << reg_type << ")";
4664 }
4665 }
4666}
4667
4668bool DexVerifier::CheckConstructorReturn(const Method* method,
4669 const RegisterLine* register_line, const int insn_reg_count) {
4670 const RegType* insn_regs = register_line->reg_types_;
4671
4672 if (!IsInitMethod(method))
4673 return true;
4674
4675 RegType uninit_this = RegTypeFromUninitIndex(kUninitThisArgSlot);
4676
4677 for (int i = 0; i < insn_reg_count; i++) {
4678 if (insn_regs[i] == uninit_this) {
4679 LOG(ERROR) << "VFY: <init> returning without calling superclass init";
4680 return false;
4681 }
4682 }
4683 return true;
4684}
4685
4686bool DexVerifier::CheckMoveException(const uint16_t* insns, int insn_idx) {
4687 if ((insns[insn_idx] & 0xff) == Instruction::MOVE_EXCEPTION) {
4688 LOG(ERROR) << "VFY: invalid use of move-exception";
4689 return false;
4690 }
4691 return true;
4692}
4693
4694void DexVerifier::CheckTypeCategory(RegType type, TypeCategory cat,
4695 VerifyError* failure) {
4696 switch (cat) {
4697 case kTypeCategory1nr:
4698 switch (type) {
4699 case kRegTypeZero:
4700 case kRegTypeOne:
4701 case kRegTypeBoolean:
4702 case kRegTypeConstPosByte:
4703 case kRegTypeConstByte:
4704 case kRegTypeConstPosShort:
4705 case kRegTypeConstShort:
4706 case kRegTypeConstChar:
4707 case kRegTypeConstInteger:
4708 case kRegTypePosByte:
4709 case kRegTypeByte:
4710 case kRegTypePosShort:
4711 case kRegTypeShort:
4712 case kRegTypeChar:
4713 case kRegTypeInteger:
4714 case kRegTypeFloat:
4715 break;
4716 default:
4717 *failure = VERIFY_ERROR_GENERIC;
4718 break;
4719 }
4720 break;
4721 case kTypeCategory2:
4722 switch (type) {
4723 case kRegTypeConstLo:
4724 case kRegTypeLongLo:
4725 case kRegTypeDoubleLo:
4726 break;
4727 default:
4728 *failure = VERIFY_ERROR_GENERIC;
4729 break;
4730 }
4731 break;
4732 case kTypeCategoryRef:
4733 if (type != kRegTypeZero && !RegTypeIsReference(type))
4734 *failure = VERIFY_ERROR_GENERIC;
4735 break;
4736 default:
4737 assert(false);
4738 *failure = VERIFY_ERROR_GENERIC;
4739 break;
4740 }
4741}
4742
4743void DexVerifier::CheckWidePair(RegType type_l, RegType type_h,
4744 VerifyError* failure) {
4745 if ((type_h != type_l + 1))
4746 *failure = VERIFY_ERROR_GENERIC;
4747}
4748
4749void DexVerifier::CheckUnop(RegisterLine* register_line,
4750 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4751 RegType src_type, VerifyError* failure) {
4752 VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
4753 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4754}
4755
4756bool DexVerifier::UpcastBooleanOp(RegisterLine* register_line, uint32_t reg1,
4757 uint32_t reg2) {
4758 RegType type1, type2;
4759
4760 type1 = GetRegisterType(register_line, reg1);
4761 type2 = GetRegisterType(register_line, reg2);
4762
4763 if ((type1 == kRegTypeBoolean || type1 == kRegTypeZero || type1 == kRegTypeOne) &&
4764 (type2 == kRegTypeBoolean || type2 == kRegTypeZero || type2 == kRegTypeOne)) {
4765 return true;
4766 }
4767 return false;
4768}
4769
4770void DexVerifier::CheckLitop(RegisterLine* register_line,
4771 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4772 RegType src_type, bool check_boolean_op, VerifyError* failure) {
4773 VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
4774
4775 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
4776 assert(dst_type == kRegTypeInteger);
4777
4778 /* check vB with the call, then check the constant manually */
4779 if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vB_)
4780 && (dec_insn->vC_ == 0 || dec_insn->vC_ == 1)) {
4781 dst_type = kRegTypeBoolean;
4782 }
4783 }
4784
4785 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4786}
4787
4788void DexVerifier::CheckBinop(RegisterLine* register_line,
4789 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4790 RegType src_type1, RegType src_type2, bool check_boolean_op,
4791 VerifyError* failure) {
4792 VerifyRegisterType(register_line, dec_insn->vB_, src_type1, failure);
4793 VerifyRegisterType(register_line, dec_insn->vC_, src_type2, failure);
4794
4795 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
4796 assert(dst_type == kRegTypeInteger);
4797 if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vC_))
4798 dst_type = kRegTypeBoolean;
4799 }
4800
4801 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4802}
4803
4804void DexVerifier::CheckBinop2addr(RegisterLine* register_line,
4805 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4806 RegType src_type1, RegType src_type2, bool check_boolean_op,
4807 VerifyError* failure) {
4808 VerifyRegisterType(register_line, dec_insn->vA_, src_type1, failure);
4809 VerifyRegisterType(register_line, dec_insn->vB_, src_type2, failure);
4810
4811 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
4812 assert(dst_type == kRegTypeInteger);
4813 if (UpcastBooleanOp(register_line, dec_insn->vA_, dec_insn->vB_))
4814 dst_type = kRegTypeBoolean;
4815 }
4816
4817 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4818}
4819
4820DexVerifier::RegType DexVerifier::AdjustForRightShift(
4821 RegisterLine* register_line, int reg, unsigned int shift_count,
4822 bool is_unsigned_shift, VerifyError* failure) {
4823 RegType src_type = GetRegisterType(register_line, reg);
4824 RegType new_type;
4825
4826 /* convert const derived types to their actual types */
4827 src_type = ConstTypeToRegType(src_type);
4828
4829 /* no-op */
4830 if (shift_count == 0)
4831 return src_type;
4832
4833 /* safe defaults */
4834 if (is_unsigned_shift)
4835 new_type = kRegTypeInteger;
4836 else
4837 new_type = src_type;
4838
4839 if (shift_count >= 32) {
4840 LOG(ERROR) << "Got unexpectedly large shift count " << shift_count;
4841 /* fail? */
4842 return new_type;
4843 }
4844
4845 switch (src_type) {
4846 case kRegTypeInteger: /* 32-bit signed value */
4847 if (is_unsigned_shift) {
4848 if (shift_count > 24)
4849 new_type = kRegTypePosByte;
4850 else if (shift_count >= 16)
4851 new_type = kRegTypeChar;
4852 } else {
4853 if (shift_count >= 24)
4854 new_type = kRegTypeByte;
4855 else if (shift_count >= 16)
4856 new_type = kRegTypeShort;
4857 }
4858 break;
4859 case kRegTypeShort: /* 16-bit signed value */
4860 if (is_unsigned_shift) {
4861 /* default (kRegTypeInteger) is correct */
4862 } else {
4863 if (shift_count >= 8)
4864 new_type = kRegTypeByte;
4865 }
4866 break;
4867 case kRegTypePosShort: /* 15-bit unsigned value */
4868 if (shift_count >= 8)
4869 new_type = kRegTypePosByte;
4870 break;
4871 case kRegTypeChar: /* 16-bit unsigned value */
4872 if (shift_count > 8)
4873 new_type = kRegTypePosByte;
4874 break;
4875 case kRegTypeByte: /* 8-bit signed value */
4876 /* defaults (u=kRegTypeInteger / s=src_type) are correct */
4877 break;
4878 case kRegTypePosByte: /* 7-bit unsigned value */
4879 /* always use new_type=src_type */
4880 new_type = src_type;
4881 break;
4882 case kRegTypeZero: /* 1-bit unsigned value */
4883 case kRegTypeOne:
4884 case kRegTypeBoolean:
4885 /* unnecessary? */
4886 new_type = kRegTypeZero;
4887 break;
4888 default:
4889 /* long, double, references; shouldn't be here! */
4890 assert(false);
4891 break;
4892 }
4893
4894 return new_type;
4895}
4896
4897void DexVerifier::VerifyFilledNewArrayRegs(const Method* method,
4898 RegisterLine* register_line,
4899 const Instruction::DecodedInstruction* dec_insn, Class* res_class,
4900 bool is_range, VerifyError* failure) {
4901 uint32_t arg_count = dec_insn->vA_;
4902 RegType expected_type;
4903 Class::PrimitiveType elem_type;
4904 unsigned int ui;
4905
4906 assert(res_class->IsArrayClass());
4907 elem_type = res_class->GetComponentType()->GetPrimitiveType();
4908 if (elem_type == Class::kPrimNot) {
4909 expected_type = RegTypeFromClass(res_class->GetComponentType());
4910 } else {
4911 expected_type = PrimitiveTypeToRegType(elem_type);
4912 }
4913
4914 /*
4915 * Verify each register. If "arg_count" is bad, VerifyRegisterType()
4916 * will run off the end of the list and fail. It's legal, if silly,
4917 * for arg_count to be zero.
4918 */
4919 for (ui = 0; ui < arg_count; ui++) {
4920 uint32_t get_reg;
4921
4922 if (is_range)
4923 get_reg = dec_insn->vC_ + ui;
4924 else
4925 get_reg = dec_insn->arg_[ui];
4926
4927 VerifyRegisterType(register_line, get_reg, expected_type, failure);
4928 if (*failure != VERIFY_ERROR_NONE) {
4929 LOG(ERROR) << "VFY: filled-new-array arg " << ui << "(" << get_reg
4930 << ") not valid";
4931 return;
4932 }
4933 }
4934}
4935
4936bool DexVerifier::IsCorrectInvokeKind(MethodType method_type,
4937 Method* res_method) {
4938 switch (method_type) {
4939 case METHOD_DIRECT:
4940 return res_method->IsDirect();
4941 case METHOD_STATIC:
4942 return res_method->IsStatic();
4943 case METHOD_VIRTUAL:
4944 case METHOD_INTERFACE:
4945 return !res_method->IsDirect();
4946 default:
4947 return false;
4948 }
4949}
4950
4951Method* DexVerifier::VerifyInvocationArgs(VerifierData* vdata,
4952 RegisterLine* register_line, const int insn_reg_count,
4953 const Instruction::DecodedInstruction* dec_insn, MethodType method_type,
4954 bool is_range, bool is_super, VerifyError* failure) {
4955 Method* method = vdata->method_;
4956 const DexFile* dex_file = vdata->dex_file_;
4957 const DexFile::CodeItem* code_item = vdata->code_item_;
4958 UninitInstanceMap* uninit_map = vdata->uninit_map_;
4959 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4960 DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
4961 const ClassLoader* class_loader =
4962 method->GetDeclaringClass()->GetClassLoader();
4963
4964 Method* res_method;
4965 std::string sig;
4966 size_t sig_offset;
4967 int expected_args;
4968 int actual_args;
4969
4970 /*
4971 * Resolve the method. This could be an abstract or concrete method
4972 * depending on what sort of call we're making.
4973 */
4974 res_method = class_linker->ResolveMethod(*dex_file, dec_insn->vB_, dex_cache,
4975 class_loader, (method_type == METHOD_DIRECT || method_type == METHOD_STATIC));
4976
4977 /* Scan all implemented interfaces for the method */
4978 if (method_type == METHOD_INTERFACE && res_method == NULL) {
4979
4980 }
4981
4982 if (res_method == NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07004983 LOG(ERROR) << "VFY: unable to resolve called method";
4984 *failure = VERIFY_ERROR_NO_METHOD;
4985 return NULL;
4986 }
4987 Class* res_class = res_method->GetDeclaringClass();
4988
4989 /*
4990 * Only time you can explicitly call a method starting with '<' is when
4991 * making a "direct" invocation on "<init>". There are additional
4992 * restrictions but we don't enforce them here.
4993 */
4994 if (res_method->GetName()->Equals("<init>")) {
4995 if (method_type != METHOD_DIRECT || !IsInitMethod(res_method)) {
4996 LOG(ERROR) << "VFY: invalid call to "
4997 << res_class->GetDescriptor()->ToModifiedUtf8()
4998 << "." << res_method->GetName();
4999 goto bad_sig;
5000 }
5001 }
5002
5003 /*
5004 * See if the method type implied by the invoke instruction matches the
5005 * access flags for the target method.
5006 */
5007 if (!IsCorrectInvokeKind(method_type, res_method)) {
5008 LOG(ERROR) << "VFY: invoke type does not match method type of "
5009 << res_class->GetDescriptor()->ToModifiedUtf8()
5010 << "." << res_method->GetName()->ToModifiedUtf8();
5011
5012 *failure = VERIFY_ERROR_GENERIC;
5013 return NULL;
5014 }
5015
5016 /*
5017 * If we're using invoke-super(method), make sure that the executing
5018 * method's class' superclass has a vtable entry for the target method.
5019 */
5020 if (is_super) {
5021 assert(method_type == METHOD_VIRTUAL);
5022 Class* super = method->GetDeclaringClass()->GetSuperClass();
5023 if (super == NULL || res_method->GetMethodIndex() > super->GetVTable()->GetLength()) {
5024 if (super == NULL) {
5025 LOG(ERROR) << "VFY: invalid invoke-super from "
5026 << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5027 << "." << method->GetName()->ToModifiedUtf8() << " to super -."
5028 << res_method->GetName()->ToModifiedUtf8()
5029 << " " << res_method->GetSignature()->ToModifiedUtf8();
5030 } else {
5031 LOG(ERROR) << "VFY: invalid invoke-super from "
5032 << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5033 << "." << method->GetName()->ToModifiedUtf8() << " to super "
5034 << super->GetDescriptor()->ToModifiedUtf8()
5035 << "." << res_method->GetName()->ToModifiedUtf8()
5036 << " " << res_method->GetSignature()->ToModifiedUtf8();
5037 }
5038 *failure = VERIFY_ERROR_NO_METHOD;
5039 return NULL;
5040 }
5041 }
5042
5043 /*
5044 * We use vAA as our expected arg count, rather than res_method->insSize,
5045 * because we need to match the call to the signature. Also, we might
5046 * might be calling through an abstract method definition (which doesn't
5047 * have register count values).
5048 */
5049 expected_args = dec_insn->vA_;
5050 actual_args = 0;
5051
5052 /* caught by static verifier */
5053 assert(is_range || expected_args <= 5);
5054
5055 if (expected_args > code_item->outs_size_) {
5056 LOG(ERROR) << "VFY: invalid arg count (" << expected_args
5057 << ") exceeds outsSize (" << code_item->outs_size_ << ")";
5058 *failure = VERIFY_ERROR_GENERIC;
5059 return NULL;
5060 }
5061
5062 sig = res_method->GetSignature()->ToModifiedUtf8();
5063 if (sig[0] != '(') {
5064 LOG(ERROR) << "VFY: descriptor doesn't start with '(': " << sig;
5065 goto bad_sig;
5066 }
5067
5068 /*
5069 * Check the "this" argument, which must be an instance of the class
5070 * that declared the method. For an interface class, we don't do the
5071 * full interface merge, so we can't do a rigorous check here (which
5072 * is okay since we have to do it at runtime).
5073 */
5074 if (!res_method->IsStatic()) {
5075 Class* actual_this_ref;
5076 RegType actual_arg_type;
5077
5078 actual_arg_type = GetInvocationThis(register_line, dec_insn, failure);
5079 if (*failure != VERIFY_ERROR_NONE)
5080 return NULL;
5081
5082 if (RegTypeIsUninitReference(actual_arg_type) &&
5083 !res_method->GetName()->Equals("<init>")) {
5084 LOG(ERROR) << "VFY: 'this' arg must be initialized";
5085 *failure = VERIFY_ERROR_GENERIC;
5086 return NULL;
5087 }
5088 if (method_type != METHOD_INTERFACE && actual_arg_type != kRegTypeZero) {
5089 actual_this_ref = RegTypeReferenceToClass(actual_arg_type, uninit_map);
5090 if (!res_method->GetDeclaringClass()->IsAssignableFrom(actual_this_ref)) {
5091 LOG(ERROR) << "VFY: 'this' arg '"
5092 << actual_this_ref->GetDescriptor()->ToModifiedUtf8()
5093 << "' not instance of '"
5094 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5095 << "'";
5096 *failure = VERIFY_ERROR_GENERIC;
5097 return NULL;
5098 }
5099 }
5100 actual_args++;
5101 }
5102
5103 /*
5104 * Process the target method's signature. This signature may or may not
5105 * have been verified, so we can't assume it's properly formed.
5106 */
5107 for (sig_offset = 1; sig_offset < sig.size(); sig_offset++) {
jeffhaobdb76512011-09-07 11:43:16 -07005108 if (sig[sig_offset] == ')')
5109 break;
5110
5111 if (actual_args >= expected_args) {
5112 LOG(ERROR) << "VFY: expected " << expected_args << " args, found more ("
5113 << sig.substr(sig_offset) << ")";
5114 goto bad_sig;
5115 }
5116
5117 uint32_t get_reg;
5118 if (is_range)
5119 get_reg = dec_insn->vC_ + actual_args;
5120 else
5121 get_reg = dec_insn->arg_[actual_args];
5122
5123 switch (sig[sig_offset]) {
5124 case 'L':
5125 {
5126 Class* klass = LookupSignatureClass(method, sig.substr(sig_offset),
5127 failure);
5128 if (*failure != VERIFY_ERROR_NONE)
5129 goto bad_sig;
5130 VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
5131 failure);
5132 if (*failure != VERIFY_ERROR_NONE) {
5133 LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
5134 << klass->GetDescriptor()->ToModifiedUtf8() << ")";
5135 goto bad_sig;
5136 }
5137 sig_offset += sig.substr(sig_offset).find(';');
5138 }
5139 actual_args++;
5140 break;
5141 case '[':
5142 {
5143 Class* klass = LookupSignatureArrayClass(method,
5144 sig.substr(sig_offset), failure);
5145 if (*failure != VERIFY_ERROR_NONE)
5146 goto bad_sig;
5147 VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
5148 failure);
5149 if (*failure != VERIFY_ERROR_NONE) {
5150 LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
5151 << klass->GetDescriptor()->ToModifiedUtf8() << ")";
5152 goto bad_sig;
5153 }
5154 while (sig[sig_offset] == '[')
5155 sig_offset++;
5156 if (sig[sig_offset] == 'L')
5157 sig_offset += sig.substr(sig_offset).find(';');
5158 }
5159 actual_args++;
5160 break;
5161 case 'Z':
5162 VerifyRegisterType(register_line, get_reg, kRegTypeBoolean, failure);
5163 actual_args++;
5164 break;
5165 case 'C':
5166 VerifyRegisterType(register_line, get_reg, kRegTypeChar, failure);
5167 actual_args++;
5168 break;
5169 case 'B':
5170 VerifyRegisterType(register_line, get_reg, kRegTypeByte, failure);
5171 actual_args++;
5172 break;
5173 case 'I':
5174 VerifyRegisterType(register_line, get_reg, kRegTypeInteger, failure);
5175 actual_args++;
5176 break;
5177 case 'S':
5178 VerifyRegisterType(register_line, get_reg, kRegTypeShort, failure);
5179 actual_args++;
5180 break;
5181 case 'F':
5182 VerifyRegisterType(register_line, get_reg, kRegTypeFloat, failure);
5183 actual_args++;
5184 break;
5185 case 'D':
5186 VerifyRegisterType(register_line, get_reg, kRegTypeDoubleLo, failure);
5187 actual_args += 2;
5188 break;
5189 case 'J':
5190 VerifyRegisterType(register_line, get_reg, kRegTypeLongLo, failure);
5191 actual_args += 2;
5192 break;
5193 default:
5194 LOG(ERROR) << "VFY: invocation target: bad signature type char '"
5195 << sig << "'";
5196 goto bad_sig;
5197 }
5198 }
5199 if (sig[sig_offset] != ')') {
5200 LOG(ERROR) << "VFY: invocation target: bad signature '"
5201 << res_method->GetSignature()->ToModifiedUtf8() << "'";
5202 goto bad_sig;
5203 }
5204
5205 if (actual_args != expected_args) {
5206 LOG(ERROR) << "VFY: expected " << expected_args << " args, found "
5207 << actual_args;
5208 goto bad_sig;
5209 }
5210
5211 return res_method;
5212
5213bad_sig:
5214 if (res_method != NULL) {
5215 LOG(ERROR) << "VFY: rejecting call to "
5216 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5217 << "." << res_method->GetName()->ToModifiedUtf8() << " "
5218 << res_method->GetSignature()->ToModifiedUtf8();
5219 }
5220
5221 if (*failure == VERIFY_ERROR_NONE)
5222 *failure = VERIFY_ERROR_GENERIC;
5223 return NULL;
5224}
jeffhaoba5ebb92011-08-25 17:24:37 -07005225
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07005226} // namespace art