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