blob: 5d622f95dc23c22ca891fbe0906fe18d9dffecbd [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)) {
jeffhao98eacac2011-09-14 16:11:53 -0700107 LOG(ERROR) << "Verifier rejected class "
108 << klass->GetDescriptor()->ToModifiedUtf8();
jeffhaobdb76512011-09-07 11:43:16 -0700109 return false;
110 }
111 }
112 for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
113 Method* method = klass->GetVirtualMethod(i);
114 if (!VerifyMethod(method)) {
jeffhao98eacac2011-09-14 16:11:53 -0700115 LOG(ERROR) << "Verifier rejected class "
116 << klass->GetDescriptor()->ToModifiedUtf8();
jeffhaobdb76512011-09-07 11:43:16 -0700117 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 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700148 * Sanity-check the register counts. ins + locals = registers, so make
jeffhaobdb76512011-09-07 11:43:16 -0700149 * 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)) {
jeffhaod1f0fde2011-09-08 17:25:33 -0700207 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
jeffhaobdb76512011-09-07 11:43:16 -0700208 << (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_;
jeffhaod1f0fde2011-09-08 17:25:33 -0700319 bool generate_register_map = true;
jeffhaobdb76512011-09-07 11:43:16 -0700320 RegisterTable reg_table;
jeffhaoba5ebb92011-08-25 17:24:37 -0700321
jeffhaobdb76512011-09-07 11:43:16 -0700322 if (registers_size * insns_size > 4*1024*1024) {
323 LOG(ERROR) << "VFY: warning: method is huge (regs=" << registers_size
324 << " insns_size=" << insns_size << ")";
325 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700326
jeffhaobdb76512011-09-07 11:43:16 -0700327 /* Create and initialize register lists. */
jeffhaod1f0fde2011-09-08 17:25:33 -0700328 if (!InitRegisterTable(vdata, &reg_table,
329 generate_register_map ? kTrackRegsGcPoints : kTrackRegsBranches)) {
jeffhaobdb76512011-09-07 11:43:16 -0700330 return false;
331 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700332
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700333 vdata->register_lines_ = reg_table.register_lines_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700334
335 /* Allocate a map to hold the classes of uninitialized instances. */
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700336 vdata->uninit_map_.reset(CreateUninitInstanceMap(vdata));
jeffhaobdb76512011-09-07 11:43:16 -0700337
338 /* Initialize register types of method arguments. */
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700339 if (!SetTypesFromSignature(vdata, reg_table.register_lines_[0].reg_types_.get())) {
jeffhaobdb76512011-09-07 11:43:16 -0700340 LOG(ERROR) << "VFY: bad signature '"
341 << method->GetSignature()->ToModifiedUtf8() << "' for "
342 << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
343 << "." << method->GetName()->ToModifiedUtf8();
344 return false;
345 }
346
347 /* Perform code flow verification. */
348 if (!CodeFlowVerifyMethod(vdata, &reg_table)) {
349 return false;
350 }
351
jeffhaod1f0fde2011-09-08 17:25:33 -0700352 /* Generate a register map. */
353 if (generate_register_map) {
354 RegisterMap* map = GenerateRegisterMapV(vdata);
355 /*
356 * Tuck the map into the Method. It will either get used directly or, if
357 * we're in dexopt, will be packed up and appended to the DEX file.
358 */
359 // TODO: Put the map somewhere...
360 delete map;
361 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700362
jeffhaobdb76512011-09-07 11:43:16 -0700363 return true;
364}
365
366bool DexVerifier::ComputeWidthsAndCountOps(VerifierData* vdata) {
367 const uint16_t* insns = vdata->code_item_->insns_;
368 uint32_t insns_size = vdata->code_item_->insns_size_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700369 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700370 const byte* ptr = reinterpret_cast<const byte*>(insns);
371 const Instruction* inst = Instruction::At(ptr);
372 size_t new_instance_count = 0;
373 size_t monitor_enter_count = 0;
374 size_t width = 0;
375
376 while (width < insns_size) {
377 Instruction::Code opcode = inst->Opcode();
378 if (opcode == Instruction::NEW_INSTANCE) {
379 new_instance_count++;
380 } else if (opcode == Instruction::MONITOR_ENTER) {
381 monitor_enter_count++;
382 }
383
384 insn_flags[width] |= inst->Size();
385 width += inst->Size();
386 inst = inst->Next();
387 }
388
389 if (width != insns_size) {
390 LOG(ERROR) << "VFY: code did not end where expected (" << width << " vs. "
391 << insns_size << ")";
392 return false;
393 }
394
395 vdata->new_instance_count_ = new_instance_count;
396 vdata->monitor_enter_count_ = monitor_enter_count;
397 return true;
398}
399
400bool DexVerifier::ScanTryCatchBlocks(VerifierData* vdata) {
401 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700402 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700403 uint32_t insns_size = code_item->insns_size_;
404 uint32_t tries_size = code_item->tries_size_;
405
406 if (tries_size == 0) {
407 return true;
408 }
409
410 const DexFile::TryItem* tries = DexFile::dexGetTryItems(*code_item, 0);
411
412 for (uint32_t idx = 0; idx < tries_size; idx++) {
413 const DexFile::TryItem* try_item = &tries[idx];
414 uint32_t start = try_item->start_addr_;
415 uint32_t end = start + try_item->insn_count_;
416
417 if ((start >= end) || (start >= insns_size) || (end > insns_size)) {
418 LOG(ERROR) << "VFY: bad exception entry: startAddr=" << start
419 << " endAddr=" << end << " (size=" << insns_size << ")";
420 return false;
421 }
422
423 if (InsnGetWidth(insn_flags, start) == 0) {
424 LOG(ERROR) << "VFY: 'try' block starts inside an instruction ("
425 << start << ")";
426 return false;
427 }
428
429 uint32_t addr;
430 for (addr = start; addr < end; addr += InsnGetWidth(insn_flags, addr)) {
431 InsnSetInTry(insn_flags, addr);
432 }
433 }
434
435 /* Iterate over each of the handlers to verify target addresses. */
436 const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item, 0);
437 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
438 for (uint32_t idx = 0; idx < handlers_size; idx++) {
439 DexFile::CatchHandlerIterator iterator(handlers_ptr);
440
441 for (; !iterator.HasNext(); iterator.Next()) {
442 uint32_t addr = iterator.Get().address_;
443 if (InsnGetWidth(insn_flags, addr) == 0) {
444 LOG(ERROR) << "VFY: exception handler starts at bad address ("
445 << addr << ")";
446 return false;
447 }
448
449 InsnSetBranchTarget(insn_flags, addr);
450 }
451
452 handlers_ptr = iterator.GetData();
453 }
454
455 return true;
456}
457
458bool DexVerifier::GetBranchOffset(const DexFile::CodeItem* code_item,
459 const InsnFlags insn_flags[], uint32_t cur_offset, int32_t* pOffset,
jeffhaoba5ebb92011-08-25 17:24:37 -0700460 bool* pConditional, bool* selfOkay) {
461 const uint16_t* insns = code_item->insns_ + cur_offset;
462
463 switch (*insns & 0xff) {
464 case Instruction::GOTO:
465 *pOffset = ((int16_t) *insns) >> 8;
466 *pConditional = false;
467 *selfOkay = false;
468 break;
469 case Instruction::GOTO_32:
470 *pOffset = insns[1] | (((uint32_t) insns[2]) << 16);
471 *pConditional = false;
472 *selfOkay = true;
473 break;
474 case Instruction::GOTO_16:
475 *pOffset = (int16_t) insns[1];
476 *pConditional = false;
477 *selfOkay = false;
478 break;
479 case Instruction::IF_EQ:
480 case Instruction::IF_NE:
481 case Instruction::IF_LT:
482 case Instruction::IF_GE:
483 case Instruction::IF_GT:
484 case Instruction::IF_LE:
485 case Instruction::IF_EQZ:
486 case Instruction::IF_NEZ:
487 case Instruction::IF_LTZ:
488 case Instruction::IF_GEZ:
489 case Instruction::IF_GTZ:
490 case Instruction::IF_LEZ:
491 *pOffset = (int16_t) insns[1];
492 *pConditional = true;
493 *selfOkay = false;
494 break;
495 default:
496 return false;
497 break;
498 }
499
500 return true;
501}
502
jeffhaobdb76512011-09-07 11:43:16 -0700503bool DexVerifier::CheckArrayData(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700504 uint32_t cur_offset) {
505 const uint32_t insn_count = code_item->insns_size_;
506 const uint16_t* insns = code_item->insns_ + cur_offset;
507 const uint16_t* array_data;
508 int32_t array_data_offset;
509
510 assert(cur_offset < insn_count);
511
512 /* make sure the start of the array data table is in range */
513 array_data_offset = insns[1] | (((int32_t) insns[2]) << 16);
514 if ((int32_t) cur_offset + array_data_offset < 0 ||
515 cur_offset + array_data_offset + 2 >= insn_count)
516 {
517 LOG(ERROR) << "VFY: invalid array data start: at " << cur_offset
518 << ", data offset " << array_data_offset << ", count "
519 << insn_count;
520 return false;
521 }
522
523 /* offset to array data table is a relative branch-style offset */
524 array_data = insns + array_data_offset;
525
526 /* make sure the table is 32-bit aligned */
527 if ((((uint32_t) array_data) & 0x03) != 0) {
528 LOG(ERROR) << "VFY: unaligned array data table: at " << cur_offset
529 << ", data offset " << array_data_offset;
530 return false;
531 }
532
533 uint32_t value_width = array_data[1];
534 uint32_t value_count = *(uint32_t*) (&array_data[2]);
535 uint32_t table_size = 4 + (value_width * value_count + 1) / 2;
536
537 /* make sure the end of the switch is in range */
538 if (cur_offset + array_data_offset + table_size > insn_count) {
539 LOG(ERROR) << "VFY: invalid array data end: at " << cur_offset
540 << ", data offset " << array_data_offset << ", end "
541 << cur_offset + array_data_offset + table_size << ", count "
542 << insn_count;
543 return false;
544 }
545
546 return true;
547}
548
jeffhaobdb76512011-09-07 11:43:16 -0700549bool DexVerifier::CheckNewInstance(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700550 if (idx >= dex_file->GetHeader().type_ids_size_) {
551 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
552 << dex_file->GetHeader().type_ids_size_ << ")";
553 return false;
554 }
555
556 const char* descriptor = dex_file->dexStringByTypeIdx(idx);
557 if (descriptor[0] != 'L') {
558 LOG(ERROR) << "VFY: can't call new-instance on type '"
559 << descriptor << "'";
560 return false;
561 }
562
563 return true;
564}
565
jeffhaobdb76512011-09-07 11:43:16 -0700566bool DexVerifier::CheckNewArray(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700567 if (idx >= dex_file->GetHeader().type_ids_size_) {
568 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
569 << dex_file->GetHeader().type_ids_size_ << ")";
570 return false;
571 }
572
573 int bracket_count = 0;
574 const char* descriptor = dex_file->dexStringByTypeIdx(idx);
575 const char* cp = descriptor;
576 while (*cp++ == '[')
577 bracket_count++;
578
579 if (bracket_count == 0) {
580 /* The given class must be an array type. */
581 LOG(ERROR) << "VFY: can't new-array class '" << descriptor
582 << "' (not an array)";
583 return false;
584 } else if (bracket_count > 255) {
585 /* It is illegal to create an array of more than 255 dimensions. */
586 LOG(ERROR) << "VFY: can't new-array class '" << descriptor
587 << "' (exceeds limit)";
588 return false;
589 }
590
591 return true;
592}
593
jeffhaobdb76512011-09-07 11:43:16 -0700594bool DexVerifier::CheckTypeIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700595 if (idx >= dex_file->GetHeader().type_ids_size_) {
596 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
597 << dex_file->GetHeader().type_ids_size_ << ")";
598 return false;
599 }
600 return true;
601}
602
jeffhaobdb76512011-09-07 11:43:16 -0700603bool DexVerifier::CheckFieldIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700604 if (idx >= dex_file->GetHeader().field_ids_size_) {
605 LOG(ERROR) << "VFY: bad field index " << idx << " (max "
606 << dex_file->GetHeader().field_ids_size_ << ")";
607 return false;
608 }
609 return true;
610}
611
jeffhaobdb76512011-09-07 11:43:16 -0700612bool DexVerifier::CheckMethodIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700613 if (idx >= dex_file->GetHeader().method_ids_size_) {
614 LOG(ERROR) << "VFY: bad method index " << idx << " (max "
615 << dex_file->GetHeader().method_ids_size_ << ")";
616 return false;
617 }
618 return true;
619}
620
jeffhaobdb76512011-09-07 11:43:16 -0700621bool DexVerifier::CheckStringIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700622 if (idx >= dex_file->GetHeader().string_ids_size_) {
623 LOG(ERROR) << "VFY: bad string index " << idx << " (max "
624 << dex_file->GetHeader().string_ids_size_ << ")";
625 return false;
626 }
627 return true;
628}
629
jeffhaobdb76512011-09-07 11:43:16 -0700630bool DexVerifier::CheckRegisterIndex(const DexFile::CodeItem* code_item,
631 uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700632 if (idx >= code_item->registers_size_) {
633 LOG(ERROR) << "VFY: register index out of range (" << idx << " >= "
634 << code_item->registers_size_ << ")";
635 return false;
636 }
637 return true;
638}
639
jeffhaobdb76512011-09-07 11:43:16 -0700640bool DexVerifier::CheckWideRegisterIndex(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700641 uint32_t idx) {
642 if (idx + 1 >= code_item->registers_size_) {
643 LOG(ERROR) << "VFY: wide register index out of range (" << idx
644 << "+1 >= " << code_item->registers_size_ << ")";
645 return false;
646 }
647 return true;
648}
649
jeffhaobdb76512011-09-07 11:43:16 -0700650bool DexVerifier::CheckVarArgRegs(const DexFile::CodeItem* code_item,
651 uint32_t vA, uint32_t arg[]) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700652 uint16_t registers_size = code_item->registers_size_;
653 uint32_t idx;
654
655 if (vA > 5) {
656 LOG(ERROR) << "VFY: invalid arg count (" << vA << ") in non-range invoke)";
657 return false;
658 }
659
660 for (idx = 0; idx < vA; idx++) {
661 if (arg[idx] > registers_size) {
662 LOG(ERROR) << "VFY: invalid reg index (" << arg[idx]
663 << ") in non-range invoke (> " << registers_size << ")";
664 return false;
665 }
666 }
667
668 return true;
669}
670
jeffhaobdb76512011-09-07 11:43:16 -0700671bool DexVerifier::CheckVarArgRangeRegs(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700672 uint32_t vA, uint32_t vC) {
673 uint16_t registers_size = code_item->registers_size_;
674
675 /*
676 * vA/vC are unsigned 8-bit/16-bit quantities for /range instructions,
677 * so there's no risk of integer overflow when adding them here.
678 */
679 if (vA + vC > registers_size) {
680 LOG(ERROR) << "VFY: invalid reg index " << vA << "+" << vC
681 << " in range invoke (> " << registers_size << ")";
682 return false;
683 }
684
685 return true;
686}
687
jeffhaobdb76512011-09-07 11:43:16 -0700688bool DexVerifier::CheckSwitchTargets(const DexFile::CodeItem* code_item,
689 InsnFlags insn_flags[], uint32_t cur_offset) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700690 const uint32_t insn_count = code_item->insns_size_;
691 const uint16_t* insns = code_item->insns_ + cur_offset;
692 const uint16_t* switch_insns;
693 uint16_t expected_signature;
694 uint32_t switch_count, table_size;
695 int32_t switch_offset, keys_offset, targets_offset;
696 int32_t offset, abs_offset;
697 uint32_t targ;
698
699 /* make sure the start of the switch is in range */
700 switch_offset = insns[1] | ((int32_t) insns[2]) << 16;
701 if ((int32_t) cur_offset + switch_offset < 0 ||
702 cur_offset + switch_offset + 2 >= insn_count) {
703 LOG(ERROR) << "VFY: invalid switch start: at " << cur_offset
704 << ", switch offset " << switch_offset << ", count "
705 << insn_count;
706 return false;
707 }
708
709 /* offset to switch table is a relative branch-style offset */
710 switch_insns = insns + switch_offset;
711
712 /* make sure the table is 32-bit aligned */
713 if ((((uint32_t) switch_insns) & 0x03) != 0) {
714 LOG(ERROR) << "VFY: unaligned switch table: at " << cur_offset
715 << ", switch offset " << switch_offset;
716 return false;
717 }
718
719 switch_count = switch_insns[1];
720
721 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
722 /* 0=sig, 1=count, 2/3=firstKey */
723 targets_offset = 4;
724 keys_offset = -1;
725 expected_signature = Instruction::kPackedSwitchSignature;
726 } else {
727 /* 0=sig, 1=count, 2..count*2 = keys */
728 keys_offset = 2;
729 targets_offset = 2 + 2 * switch_count;
730 expected_signature = Instruction::kSparseSwitchSignature;
731 }
732 table_size = targets_offset + switch_count * 2;
733
734 if (switch_insns[0] != expected_signature) {
jeffhaobdb76512011-09-07 11:43:16 -0700735 LOG(ERROR) << "VFY: wrong signature for switch table (0x" << std::hex
736 << switch_insns[0] << ", wanted 0x" << expected_signature << ")"
737 << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700738 return false;
739 }
740
741 /* make sure the end of the switch is in range */
742 if (cur_offset + switch_offset + table_size > (uint32_t) insn_count) {
743 LOG(ERROR) << "VFY: invalid switch end: at " << cur_offset
744 << ", switch offset " << switch_offset << ", end "
745 << cur_offset + switch_offset + table_size << ", count "
746 << insn_count;
747 return false;
748 }
749
750 /* for a sparse switch, verify the keys are in ascending order */
751 if (keys_offset > 0 && switch_count > 1) {
752 int32_t last_key;
753
754 last_key = switch_insns[keys_offset] |
755 (switch_insns[keys_offset + 1] << 16);
756 for (targ = 1; targ < switch_count; targ++) {
757 int32_t key = (int32_t) switch_insns[keys_offset + targ * 2] |
758 (int32_t) (switch_insns[keys_offset + targ * 2 + 1] << 16);
759 if (key <= last_key) {
760 LOG(ERROR) << "VFY: invalid packed switch: last key=" << last_key
761 << ", this=" << key;
762 return false;
763 }
764
765 last_key = key;
766 }
767 }
768
769 /* verify each switch target */
770 for (targ = 0; targ < switch_count; targ++) {
771 offset = (int32_t) switch_insns[targets_offset + targ * 2] |
772 (int32_t) (switch_insns[targets_offset + targ * 2 + 1] << 16);
773 abs_offset = cur_offset + offset;
774
775 if (abs_offset < 0 || abs_offset >= (int32_t) insn_count ||
776 !InsnIsOpcode(insn_flags, abs_offset)) {
777 LOG(ERROR) << "VFY: invalid switch target " << offset << " (-> "
jeffhaobdb76512011-09-07 11:43:16 -0700778 << std::hex << abs_offset << ") at " << cur_offset << std::dec
779 << "[" << targ << "]";
jeffhaoba5ebb92011-08-25 17:24:37 -0700780 return false;
781 }
jeffhaobdb76512011-09-07 11:43:16 -0700782 InsnSetBranchTarget(insn_flags, abs_offset);
jeffhaoba5ebb92011-08-25 17:24:37 -0700783 }
784
785 return true;
786}
787
jeffhaobdb76512011-09-07 11:43:16 -0700788bool DexVerifier::CheckBranchTarget(const DexFile::CodeItem* code_item,
789 InsnFlags insn_flags[], uint32_t cur_offset) {
790 const uint32_t insn_count = code_item->insns_size_;
jeffhaoba5ebb92011-08-25 17:24:37 -0700791 int32_t offset, abs_offset;
792 bool isConditional, selfOkay;
793
794 if (!GetBranchOffset(code_item, insn_flags, cur_offset, &offset,
795 &isConditional, &selfOkay))
796 return false;
797
798 if (!selfOkay && offset == 0) {
jeffhaobdb76512011-09-07 11:43:16 -0700799 LOG(ERROR) << "VFY: branch offset of zero not allowed at" << std::hex
800 << cur_offset << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700801 return false;
802 }
803
804 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700805 * Check for 32-bit overflow. This isn't strictly necessary if we can
jeffhaoba5ebb92011-08-25 17:24:37 -0700806 * depend on the VM to have identical "wrap-around" behavior, but
807 * it's unwise to depend on that.
808 */
809 if (((int64_t) cur_offset + (int64_t) offset) !=
jeffhaobdb76512011-09-07 11:43:16 -0700810 (int64_t) (cur_offset + offset)) {
811 LOG(ERROR) << "VFY: branch target overflow " << std::hex << cur_offset
812 << std::dec << " +" << offset;
jeffhaoba5ebb92011-08-25 17:24:37 -0700813 return false;
814 }
815 abs_offset = cur_offset + offset;
jeffhaobdb76512011-09-07 11:43:16 -0700816 if (abs_offset < 0 || (uint32_t) abs_offset >= insn_count ||
jeffhaoba5ebb92011-08-25 17:24:37 -0700817 !InsnIsOpcode(insn_flags, abs_offset))
818 {
819 LOG(ERROR) << "VFY: invalid branch target " << offset << " (-> "
jeffhaobdb76512011-09-07 11:43:16 -0700820 << std::hex << abs_offset << ") at " << cur_offset << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700821 return false;
822 }
jeffhaobdb76512011-09-07 11:43:16 -0700823 InsnSetBranchTarget(insn_flags, abs_offset);
jeffhaoba5ebb92011-08-25 17:24:37 -0700824
825 return true;
826}
827
jeffhaobdb76512011-09-07 11:43:16 -0700828bool DexVerifier::InitRegisterTable(VerifierData* vdata,
829 RegisterTable* reg_table, RegisterTrackingMode track_regs_for) {
830 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700831 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700832 uint16_t registers_size = code_item->registers_size_;
833 uint32_t insns_size = code_item->insns_size_;
834 uint32_t i;
835
836 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700837 * Every address gets a RegisterLine struct. This is wasteful, but
jeffhaobdb76512011-09-07 11:43:16 -0700838 * not so much that it's worth chasing through an extra level of
839 * indirection.
840 */
841 reg_table->insn_reg_count_plus_ = registers_size + kExtraRegs;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700842 reg_table->register_lines_.reset(new RegisterLine[insns_size]());
jeffhaobdb76512011-09-07 11:43:16 -0700843
844 assert(insns_size > 0);
845
846 bool track_monitors;
847 //if (gDvm.monitorVerification) {
848 //track_monitors = (vdata->monitor_enter_count_ != 0);
849 //} else {
850 track_monitors = false;
851 //}
852
853 /*
854 * Allocate entries in the sparse register line table.
855 *
856 * There is a RegisterLine associated with every address, but not
857 * every RegisterLine has non-NULL pointers to storage for its fields.
858 */
859 for (i = 0; i < insns_size; i++) {
860 bool interesting;
861
862 switch (track_regs_for) {
863 case kTrackRegsAll:
864 interesting = InsnIsOpcode(insn_flags, i);
865 break;
866 case kTrackRegsGcPoints:
867 interesting = InsnIsGcPoint(insn_flags, i) ||
868 InsnIsBranchTarget(insn_flags, i);
869 break;
870 case kTrackRegsBranches:
871 interesting = InsnIsBranchTarget(insn_flags, i);
872 break;
873 default:
874 return false;
875 }
876
877 if (interesting) {
878 reg_table->register_lines_[i].Alloc(reg_table->insn_reg_count_plus_,
879 track_monitors);
880 }
881 }
882
883 /*
884 * Allocate space for our "temporary" register lines.
885 */
886 reg_table->work_line_.Alloc(reg_table->insn_reg_count_plus_, track_monitors);
887 reg_table->saved_line_.Alloc(reg_table->insn_reg_count_plus_, track_monitors);
888
889 return true;
890}
891
892DexVerifier::UninitInstanceMap* DexVerifier::CreateUninitInstanceMap(
893 VerifierData* vdata) {
894 Method* method = vdata->method_;
895 const DexFile::CodeItem* code_item = vdata->code_item_;
896 size_t new_instance_count = vdata->new_instance_count_;
897
898 if (IsInitMethod(method)) {
899 new_instance_count++;
900 }
901
902 /*
903 * Allocate the header and map as a single unit.
904 *
905 * TODO: consider having a static instance so we can avoid allocations.
906 * I don't think the verifier is guaranteed to be single-threaded when
907 * running in the VM (rather than dexopt), so that must be taken into
908 * account.
909 */
910 UninitInstanceMap* uninit_map = new UninitInstanceMap(new_instance_count);
911
912 size_t idx = 0;
913 if (IsInitMethod(method)) {
914 uninit_map->map_[idx++].addr_ = kUninitThisArgAddr;
915 }
916
917 /*
918 * Run through and find the new-instance instructions.
919 */
920 uint32_t addr = 0;
921 uint32_t insns_size = code_item->insns_size_;
922 const byte* ptr = reinterpret_cast<const byte*>(code_item->insns_);
jeffhaoba5ebb92011-08-25 17:24:37 -0700923 const Instruction* inst = Instruction::At(ptr);
jeffhaobdb76512011-09-07 11:43:16 -0700924 while (addr < insns_size) {
925 Instruction::Code opcode = inst->Opcode();
926 if (opcode == Instruction::NEW_INSTANCE) {
927 uninit_map->map_[idx++].addr_ = addr;
928 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700929
jeffhaobdb76512011-09-07 11:43:16 -0700930 addr += inst->Size();
jeffhaoba5ebb92011-08-25 17:24:37 -0700931 inst = inst->Next();
932 }
933
jeffhaobdb76512011-09-07 11:43:16 -0700934 assert(idx == new_instance_count);
935 return uninit_map;
936}
937
938bool DexVerifier::IsInitMethod(const Method* method) {
939 return (method->GetName()->Equals("<init>"));
940}
941
942Class* DexVerifier::LookupClassByDescriptor(const Method* method,
943 const char* descriptor, VerifyError* failure) {
944 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700945 * The compiler occasionally puts references to nonexistent classes in
946 * signatures. For example, if you have a non-static inner class with no
947 * constructor, the compiler provides a private <init> for you.
948 * Constructing the class requires <init>(parent), but the outer class can't
949 * call that because the method is private. So the compiler generates a
950 * package-scope <init>(parent,bogus) method that just calls the regular
951 * <init> (the "bogus" part being necessary to distinguish the signature of
952 * the synthetic method). Treating the bogus class as an instance of
953 * java.lang.Object allows the verifier to process the class successfully.
jeffhaobdb76512011-09-07 11:43:16 -0700954 */
955 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
956 const ClassLoader* class_loader =
957 method->GetDeclaringClass()->GetClassLoader();
958 Class* klass = class_linker->FindClass(descriptor, class_loader);
959
960 if (klass == NULL) {
961 Thread::Current()->ClearException();
962 if (strchr(descriptor, '$') != NULL) {
963 LOG(INFO) << "VFY: unable to find class referenced in signature ("
964 << descriptor << ")";
965 } else {
966 LOG(ERROR) << "VFY: unable to find class referenced in signature ("
967 << descriptor << ")";
968 }
969
970 /* Check if the descriptor is an array. */
971 if (descriptor[0] == '[') {
972 /*
973 * There should never be a problem loading primitive arrays.
974 */
975 if (descriptor[1] != 'L' && descriptor[1] != '[') {
976 LOG(ERROR) << "VFY: invalid char in signature in '" << descriptor
977 << "'";
978 *failure = VERIFY_ERROR_GENERIC;
979 }
980
981 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700982 * Try to continue with base array type. This will let us pass basic
983 * stuff (e.g. get array len) that wouldn't fly with an Object. This
984 * is NOT correct if the missing type is a primitive array, but we
985 * should never have a problem loading those. (I'm not convinced this
986 * is correct or even useful. Just use Object here?)
jeffhaobdb76512011-09-07 11:43:16 -0700987 */
988 klass = class_linker->FindClass("[Ljava/lang/Object;", class_loader);
989 } else if (descriptor[0] == 'L') {
990 /*
991 * We are looking at a non-array reference descriptor;
992 * try to continue with base reference type.
993 */
994 klass = class_linker->FindSystemClass("Ljava/lang/Object;");
995 } else {
996 /* We are looking at a primitive type. */
997 LOG(ERROR) << "VFY: invalid char in signature in '" << descriptor << "'";
998 *failure = VERIFY_ERROR_GENERIC;
999 }
1000
1001 if (klass == NULL) {
1002 *failure = VERIFY_ERROR_GENERIC;
1003 }
1004 }
1005
1006 if (klass->IsPrimitive()) {
1007 LOG(ERROR) << "VFY: invalid use of primitive type '" << descriptor << "'";
1008 *failure = VERIFY_ERROR_GENERIC;
1009 klass = NULL;
1010 }
1011
1012 return klass;
1013}
1014
1015Class* DexVerifier::LookupSignatureClass(const Method* method, std::string sig,
1016 VerifyError* failure) {
1017 assert(sig[0] == 'L');
1018 size_t end = sig.find(';');
1019
1020 if (end == std::string::npos) {
1021 LOG(ERROR) << "VFY: bad signature component '" << sig << "' (missing ';')";
1022 *failure = VERIFY_ERROR_GENERIC;
1023 return NULL;
1024 }
1025
1026 return LookupClassByDescriptor(method, sig.substr(0, end + 1).c_str(),
1027 failure);
1028}
1029
1030Class* DexVerifier::LookupSignatureArrayClass(const Method* method,
1031 std::string sig, VerifyError* failure) {
1032 assert(sig[0] == '[');
1033 size_t end = 0;
1034
1035 while (sig[end] == '[')
1036 end++;
1037
1038 if (sig[end] == 'L') {
1039 end = sig.find(';');
1040 if (end == std::string::npos) {
1041 LOG(ERROR) << "VFY: bad signature component '" << sig
1042 << "' (missing ';')";
1043 *failure = VERIFY_ERROR_GENERIC;
1044 return NULL;
1045 }
1046 }
1047
1048 return LookupClassByDescriptor(method, sig.substr(0, end + 1).c_str(),
1049 failure);
1050}
1051
1052bool DexVerifier::SetTypesFromSignature(VerifierData* vdata, RegType* reg_types)
1053{
1054 Method* method = vdata->method_;
1055 const DexFile* dex_file = vdata->dex_file_;
1056 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001057 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001058
1059 int arg_start = code_item->registers_size_ - code_item->ins_size_;
1060 int expected_args = code_item->ins_size_; /* long/double count as two */
1061 int actual_args = 0;
1062
1063 assert(arg_start >= 0); /* should have been verified earlier */
1064
1065 /*
1066 * Include the "this" pointer.
1067 */
1068 if (!method->IsStatic()) {
1069 /*
1070 * If this is a constructor for a class other than java.lang.Object,
jeffhaod1f0fde2011-09-08 17:25:33 -07001071 * mark the first ("this") argument as uninitialized. This restricts
jeffhaobdb76512011-09-07 11:43:16 -07001072 * field access until the superclass constructor is called.
1073 */
1074 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1075 Class* klass_object = class_linker->FindSystemClass("Ljava/lang/Object;");
1076 if (IsInitMethod(method) && method->GetDeclaringClass() != klass_object) {
1077 int idx = SetUninitInstance(uninit_map, kUninitThisArgAddr,
1078 method->GetDeclaringClass());
1079 assert(idx == 0);
1080 reg_types[arg_start + actual_args] = RegTypeFromUninitIndex(idx);
1081 } else {
1082 reg_types[arg_start + actual_args] =
1083 RegTypeFromClass(method->GetDeclaringClass());
1084 }
1085 actual_args++;
1086 }
1087
1088 const DexFile::ProtoId& proto_id =
1089 dex_file->GetProtoId(method->GetProtoIdx());
1090 DexFile::ParameterIterator iterator(*dex_file, proto_id);
1091 VerifyError failure = VERIFY_ERROR_NONE;
1092
1093 for (; iterator.HasNext(); iterator.Next()) {
1094 const char* descriptor = iterator.GetDescriptor();
1095
1096 if (descriptor == NULL) {
1097 break;
1098 }
1099
1100 if (actual_args >= expected_args) {
1101 LOG(ERROR) << "VFY: expected " << expected_args << " args, found more ("
1102 << descriptor << ")";
1103 return false;
1104 }
1105
1106 switch (*descriptor) {
1107 case 'L':
1108 case '[':
1109 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001110 * We assume that reference arguments are initialized. The only way
1111 * it could be otherwise (assuming the caller was verified) is if
1112 * the current method is <init>, but in that case it's effectively
1113 * considered initialized the instant we reach here (in the sense
1114 * that we can return without doing anything or call virtual methods).
jeffhaobdb76512011-09-07 11:43:16 -07001115 */
1116 {
1117 Class* klass =
1118 LookupClassByDescriptor(method, descriptor, &failure);
1119 if (failure != VERIFY_ERROR_NONE)
1120 return false;
1121 reg_types[arg_start + actual_args] = RegTypeFromClass(klass);
1122 }
1123 actual_args++;
1124 break;
1125 case 'Z':
1126 reg_types[arg_start + actual_args] = kRegTypeBoolean;
1127 actual_args++;
1128 break;
1129 case 'C':
1130 reg_types[arg_start + actual_args] = kRegTypeChar;
1131 actual_args++;
1132 break;
1133 case 'B':
1134 reg_types[arg_start + actual_args] = kRegTypeByte;
1135 actual_args++;
1136 break;
1137 case 'I':
1138 reg_types[arg_start + actual_args] = kRegTypeInteger;
1139 actual_args++;
1140 break;
1141 case 'S':
1142 reg_types[arg_start + actual_args] = kRegTypeShort;
1143 actual_args++;
1144 break;
1145 case 'F':
1146 reg_types[arg_start + actual_args] = kRegTypeFloat;
1147 actual_args++;
1148 break;
1149 case 'D':
1150 reg_types[arg_start + actual_args] = kRegTypeDoubleLo;
1151 reg_types[arg_start + actual_args +1] = kRegTypeDoubleHi;
1152 actual_args += 2;
1153 break;
1154 case 'J':
1155 reg_types[arg_start + actual_args] = kRegTypeLongLo;
1156 reg_types[arg_start + actual_args +1] = kRegTypeLongHi;
1157 actual_args += 2;
1158 break;
1159 default:
1160 LOG(ERROR) << "VFY: unexpected signature type char '" << descriptor
1161 << "'";
1162 return false;
1163 }
1164 }
1165
1166 if (actual_args != expected_args) {
1167 LOG(ERROR) << "VFY: expected " << expected_args << " args, found "
1168 << actual_args;
jeffhaoba5ebb92011-08-25 17:24:37 -07001169 return false;
1170 }
1171
jeffhaobdb76512011-09-07 11:43:16 -07001172 const char* descriptor = dex_file->GetReturnTypeDescriptor(proto_id);
1173
1174 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001175 * Validate return type. We don't do the type lookup; just want to make
1176 * sure that it has the right format. Only major difference from the
jeffhaobdb76512011-09-07 11:43:16 -07001177 * method argument format is that 'V' is supported.
1178 */
1179 switch (*descriptor) {
1180 case 'I':
1181 case 'C':
1182 case 'S':
1183 case 'B':
1184 case 'Z':
1185 case 'V':
1186 case 'F':
1187 case 'D':
1188 case 'J':
1189 if (*(descriptor + 1) != '\0')
1190 return false;
1191 break;
1192 case '[':
1193 /* single/multi, object/primitive */
1194 while (*++descriptor == '[')
1195 ;
1196 if (*descriptor == 'L') {
1197 while (*++descriptor != ';' && *descriptor != '\0')
1198 ;
1199 if (*descriptor != ';')
1200 return false;
1201 } else {
1202 if (*(descriptor+1) != '\0')
1203 return false;
1204 }
1205 break;
1206 case 'L':
1207 /* could be more thorough here, but shouldn't be required */
1208 while (*++descriptor != ';' && *descriptor != '\0')
1209 ;
1210 if (*descriptor != ';')
1211 return false;
1212 break;
1213 default:
1214 return false;
1215 }
1216
jeffhaoba5ebb92011-08-25 17:24:37 -07001217 return true;
1218}
1219
jeffhaobdb76512011-09-07 11:43:16 -07001220int DexVerifier::SetUninitInstance(UninitInstanceMap* uninit_map, int addr,
1221 Class* klass) {
1222 int idx;
1223 assert(klass != NULL);
1224
jeffhaod1f0fde2011-09-08 17:25:33 -07001225 /* TODO: binary search when num_entries > 8 */
jeffhaobdb76512011-09-07 11:43:16 -07001226 for (idx = uninit_map->num_entries_ - 1; idx >= 0; idx--) {
1227 if (uninit_map->map_[idx].addr_ == addr) {
1228 if (uninit_map->map_[idx].klass_ != NULL &&
1229 uninit_map->map_[idx].klass_ != klass) {
1230 LOG(ERROR) << "VFY: addr " << addr << " already set to "
1231 << (int) uninit_map->map_[idx].klass_ << ", not setting to "
1232 << (int) klass;
1233 return -1; // already set to something else??
1234 }
1235 uninit_map->map_[idx].klass_ = klass;
1236 return idx;
1237 }
1238 }
1239
1240 LOG(ERROR) << "VFY: addr " << addr << " not found in uninit map";
1241 assert(false); // shouldn't happen
1242 return -1;
1243}
1244
1245bool DexVerifier::CodeFlowVerifyMethod(VerifierData* vdata,
1246 RegisterTable* reg_table) {
1247 const Method* method = vdata->method_;
1248 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001249 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001250 const uint16_t* insns = code_item->insns_;
jeffhaoba5ebb92011-08-25 17:24:37 -07001251 uint32_t insns_size = code_item->insns_size_;
jeffhaobdb76512011-09-07 11:43:16 -07001252 size_t insn_idx, start_guess;
jeffhaoba5ebb92011-08-25 17:24:37 -07001253
jeffhaobdb76512011-09-07 11:43:16 -07001254 /* Begin by marking the first instruction as "changed". */
1255 InsnSetChanged(insn_flags, 0, true);
jeffhaoba5ebb92011-08-25 17:24:37 -07001256
jeffhaobdb76512011-09-07 11:43:16 -07001257 start_guess = 0;
jeffhaoba5ebb92011-08-25 17:24:37 -07001258
jeffhaobdb76512011-09-07 11:43:16 -07001259 /* Continue until no instructions are marked "changed". */
1260 while (true) {
1261 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001262 * Find the first marked one. Use "start_guess" as a way to find
jeffhaobdb76512011-09-07 11:43:16 -07001263 * one quickly.
1264 */
1265 for (insn_idx = start_guess; insn_idx < insns_size; insn_idx++) {
1266 if (InsnIsChanged(insn_flags, insn_idx))
1267 break;
1268 }
jeffhaoba5ebb92011-08-25 17:24:37 -07001269
jeffhaobdb76512011-09-07 11:43:16 -07001270 if (insn_idx == insns_size) {
1271 if (start_guess != 0) {
1272 /* try again, starting from the top */
1273 start_guess = 0;
1274 continue;
1275 } else {
1276 /* all flags are clear */
1277 break;
1278 }
1279 }
1280
1281 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001282 * We carry the working set of registers from instruction to instruction.
1283 * If this address can be the target of a branch (or throw) instruction,
1284 * or if we're skipping around chasing "changed" flags, we need to load
1285 * the set of registers from the table.
jeffhaobdb76512011-09-07 11:43:16 -07001286 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001287 * Because we always prefer to continue on to the next instruction, we
1288 * should never have a situation where we have a stray "changed" flag set
1289 * on an instruction that isn't a branch target.
jeffhaobdb76512011-09-07 11:43:16 -07001290 */
1291 if (InsnIsBranchTarget(insn_flags, insn_idx)) {
1292 RegisterLine* work_line = &reg_table->work_line_;
1293 CopyLineFromTable(work_line, reg_table, insn_idx);
1294 } else {
1295#ifndef NDEBUG
1296 /*
1297 * Sanity check: retrieve the stored register line (assuming
1298 * a full table) and make sure it actually matches.
1299 */
1300 RegisterLine* register_line = GetRegisterLine(reg_table, insn_idx);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001301 if (register_line->reg_types_.get() != NULL && CompareLineToTable(reg_table,
jeffhaobdb76512011-09-07 11:43:16 -07001302 insn_idx, &reg_table->work_line_) != 0) {
1303 Class* klass = method->GetDeclaringClass();
1304 LOG(ERROR) << "HUH? work_line diverged in "
1305 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1306 << method->GetName()->ToModifiedUtf8() << " "
1307 << method->GetSignature()->ToModifiedUtf8();
1308 }
1309#endif
1310 }
1311
1312 if (!CodeFlowVerifyInstruction(vdata, reg_table, insn_idx, &start_guess)) {
1313 Class* klass = method->GetDeclaringClass();
1314 LOG(ERROR) << "VFY: failure to verify "
1315 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1316 << method->GetName()->ToModifiedUtf8() << " "
1317 << method->GetSignature()->ToModifiedUtf8();
jeffhaoba5ebb92011-08-25 17:24:37 -07001318 return false;
1319 }
1320
jeffhaobdb76512011-09-07 11:43:16 -07001321 /* Clear "changed" and mark as visited. */
1322 InsnSetVisited(insn_flags, insn_idx, true);
1323 InsnSetChanged(insn_flags, insn_idx, false);
1324 }
jeffhaoba5ebb92011-08-25 17:24:37 -07001325
jeffhaobdb76512011-09-07 11:43:16 -07001326 if (DEAD_CODE_SCAN && ((method->GetAccessFlags() & kAccWritable) == 0)) {
1327 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001328 * Scan for dead code. There's nothing "evil" about dead code
jeffhaobdb76512011-09-07 11:43:16 -07001329 * (besides the wasted space), but it indicates a flaw somewhere
1330 * down the line, possibly in the verifier.
1331 *
1332 * If we've substituted "always throw" instructions into the stream,
1333 * we are almost certainly going to have some dead code.
1334 */
1335 int dead_start = -1;
1336 for (insn_idx = 0; insn_idx < insns_size;
1337 insn_idx += InsnGetWidth(insn_flags, insn_idx)) {
1338 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001339 * Switch-statement data doesn't get "visited" by scanner. It
jeffhaobdb76512011-09-07 11:43:16 -07001340 * may or may not be preceded by a padding NOP (for alignment).
1341 */
1342 if (insns[insn_idx] == Instruction::kPackedSwitchSignature ||
1343 insns[insn_idx] == Instruction::kSparseSwitchSignature ||
1344 insns[insn_idx] == Instruction::kArrayDataSignature ||
1345 (insns[insn_idx] == Instruction::NOP &&
1346 (insns[insn_idx + 1] == Instruction::kPackedSwitchSignature ||
1347 insns[insn_idx + 1] == Instruction::kSparseSwitchSignature ||
1348 insns[insn_idx + 1] == Instruction::kArrayDataSignature))) {
1349 InsnSetVisited(insn_flags, insn_idx, true);
1350 }
1351
1352 if (!InsnIsVisited(insn_flags, insn_idx)) {
1353 if (dead_start < 0)
1354 dead_start = insn_idx;
1355 } else if (dead_start >= 0) {
1356 Class* klass = method->GetDeclaringClass();
1357 LOG(INFO) << "VFY: dead code 0x" << std::hex << dead_start << "-"
1358 << insn_idx - 1 << std::dec << " in "
1359 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1360 << method->GetName()->ToModifiedUtf8() << " "
1361 << method->GetSignature()->ToModifiedUtf8();
1362 dead_start = -1;
1363 }
1364 }
1365 if (dead_start >= 0) {
1366 Class* klass = method->GetDeclaringClass();
1367 LOG(INFO) << "VFY: dead code 0x" << std::hex << dead_start << "-"
1368 << insn_idx - 1 << std::dec << " in "
1369 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1370 << method->GetName()->ToModifiedUtf8() << " "
1371 << method->GetSignature()->ToModifiedUtf8();
jeffhaoba5ebb92011-08-25 17:24:37 -07001372 }
1373 }
1374
jeffhaobdb76512011-09-07 11:43:16 -07001375 return true;
1376}
1377
1378bool DexVerifier::CodeFlowVerifyInstruction(VerifierData* vdata,
1379 RegisterTable* reg_table, uint32_t insn_idx, size_t* start_guess) {
1380 const Method* method = vdata->method_;
1381 Class* klass = method->GetDeclaringClass();
1382 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001383 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001384 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001385 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001386 const uint16_t* insns = code_item->insns_ + insn_idx;
1387 uint32_t insns_size = code_item->insns_size_;
1388 uint32_t registers_size = code_item->registers_size_;
1389
1390#ifdef VERIFIER_STATS
1391 if (InsnIsVisited(insn_flags, insn_idx)) {
1392 gDvm.verifierStats.instrsReexamined++;
1393 } else {
1394 gDvm.verifierStats.instrsExamined++;
1395 }
1396#endif
1397
1398 /*
1399 * Once we finish decoding the instruction, we need to figure out where
jeffhaod1f0fde2011-09-08 17:25:33 -07001400 * we can go from here. There are three possible ways to transfer
jeffhaobdb76512011-09-07 11:43:16 -07001401 * control to another statement:
1402 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001403 * (1) Continue to the next instruction. Applies to all but
jeffhaobdb76512011-09-07 11:43:16 -07001404 * unconditional branches, method returns, and exception throws.
jeffhaod1f0fde2011-09-08 17:25:33 -07001405 * (2) Branch to one or more possible locations. Applies to branches
jeffhaobdb76512011-09-07 11:43:16 -07001406 * and switch statements.
jeffhaod1f0fde2011-09-08 17:25:33 -07001407 * (3) Exception handlers. Applies to any instruction that can
jeffhaobdb76512011-09-07 11:43:16 -07001408 * throw an exception that is handled by an encompassing "try"
1409 * block.
1410 *
1411 * We can also return, in which case there is no successor instruction
1412 * from this point.
1413 *
1414 * The behavior can be determined from the OpcodeFlags.
1415 */
1416 RegisterLine* work_line = &reg_table->work_line_;
1417 const DexFile* dex_file = vdata->dex_file_;
1418 const byte* ptr = reinterpret_cast<const byte*>(insns);
1419 const Instruction* inst = Instruction::At(ptr);
1420 Instruction::DecodedInstruction dec_insn(inst);
1421 int opcode_flag = inst->Flag();
1422
1423 Class* res_class;
1424 int32_t branch_target = 0;
1425 RegType tmp_type;
1426 bool just_set_result = false;
1427 VerifyError failure = VERIFY_ERROR_NONE;
1428
1429 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001430 * Make a copy of the previous register state. If the instruction
jeffhaobdb76512011-09-07 11:43:16 -07001431 * can throw an exception, we will copy/merge this into the "catch"
1432 * address rather than work_line, because we don't want the result
1433 * from the "successful" code path (e.g. a check-cast that "improves"
1434 * a type) to be visible to the exception handler.
1435 */
1436 if ((opcode_flag & Instruction::kThrow) != 0 &&
1437 InsnIsInTry(insn_flags, insn_idx)) {
1438 CopyRegisterLine(&reg_table->saved_line_, work_line,
1439 reg_table->insn_reg_count_plus_);
1440 } else {
1441#ifndef NDEBUG
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001442 memset(reg_table->saved_line_.reg_types_.get(), 0xdd,
jeffhaobdb76512011-09-07 11:43:16 -07001443 reg_table->insn_reg_count_plus_ * sizeof(RegType));
1444#endif
1445 }
1446
1447 switch (dec_insn.opcode_) {
1448 case Instruction::NOP:
1449 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001450 * A "pure" NOP has no effect on anything. Data tables start with
jeffhaobdb76512011-09-07 11:43:16 -07001451 * a signature that looks like a NOP; if we see one of these in
1452 * the course of executing code then we have a problem.
1453 */
1454 if (dec_insn.vA_ != 0) {
1455 LOG(ERROR) << "VFY: encountered data table in instruction stream";
1456 failure = VERIFY_ERROR_GENERIC;
1457 }
1458 break;
1459
1460 case Instruction::MOVE:
1461 case Instruction::MOVE_FROM16:
1462 case Instruction::MOVE_16:
1463 CopyRegister1(work_line, dec_insn.vA_, dec_insn.vB_, kTypeCategory1nr,
1464 &failure);
1465 break;
1466 case Instruction::MOVE_WIDE:
1467 case Instruction::MOVE_WIDE_FROM16:
1468 case Instruction::MOVE_WIDE_16:
1469 CopyRegister2(work_line, dec_insn.vA_, dec_insn.vB_, &failure);
1470 break;
1471 case Instruction::MOVE_OBJECT:
1472 case Instruction::MOVE_OBJECT_FROM16:
1473 case Instruction::MOVE_OBJECT_16:
1474 CopyRegister1(work_line, dec_insn.vA_, dec_insn.vB_, kTypeCategoryRef,
1475 &failure);
1476 break;
1477
1478 /*
1479 * The move-result instructions copy data out of a "pseudo-register"
jeffhaod1f0fde2011-09-08 17:25:33 -07001480 * with the results from the last method invocation. In practice we
jeffhaobdb76512011-09-07 11:43:16 -07001481 * might want to hold the result in an actual CPU register, so the
1482 * Dalvik spec requires that these only appear immediately after an
1483 * invoke or filled-new-array.
1484 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001485 * These calls invalidate the "result" register. (This is now
jeffhaobdb76512011-09-07 11:43:16 -07001486 * redundant with the reset done below, but it can make the debug info
1487 * easier to read in some cases.)
1488 */
1489 case Instruction::MOVE_RESULT:
1490 CopyResultRegister1(work_line, registers_size, dec_insn.vA_,
1491 kTypeCategory1nr, &failure);
1492 break;
1493 case Instruction::MOVE_RESULT_WIDE:
1494 CopyResultRegister2(work_line, registers_size, dec_insn.vA_, &failure);
1495 break;
1496 case Instruction::MOVE_RESULT_OBJECT:
1497 CopyResultRegister1(work_line, registers_size, dec_insn.vA_,
1498 kTypeCategoryRef, &failure);
1499 break;
1500
1501 case Instruction::MOVE_EXCEPTION:
1502 /*
1503 * This statement can only appear as the first instruction in an
1504 * exception handler (though not all exception handlers need to
jeffhaod1f0fde2011-09-08 17:25:33 -07001505 * have one of these). We verify that as part of extracting the
jeffhaobdb76512011-09-07 11:43:16 -07001506 * exception type from the catch block list.
1507 *
1508 * "res_class" will hold the closest common superclass of all
1509 * exceptions that can be handled here.
1510 */
1511 res_class = GetCaughtExceptionType(vdata, insn_idx, &failure);
1512 if (res_class == NULL) {
1513 assert(failure != VERIFY_ERROR_NONE);
1514 } else {
1515 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1516 }
1517 break;
1518
1519 case Instruction::RETURN_VOID:
1520 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1521 failure = VERIFY_ERROR_GENERIC;
1522 } else if (GetMethodReturnType(dex_file, method) != kRegTypeUnknown) {
1523 LOG(ERROR) << "VFY: return-void not expected";
1524 failure = VERIFY_ERROR_GENERIC;
1525 }
1526 break;
1527 case Instruction::RETURN:
1528 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1529 failure = VERIFY_ERROR_GENERIC;
1530 } else {
1531 /* check the method signature */
1532 RegType return_type = GetMethodReturnType(dex_file, method);
1533 CheckTypeCategory(return_type, kTypeCategory1nr, &failure);
1534 if (failure != VERIFY_ERROR_NONE)
1535 LOG(ERROR) << "VFY: return-1nr not expected";
1536
1537 /*
1538 * compiler may generate synthetic functions that write byte
1539 * values into boolean fields. Also, it may use integer values
1540 * for boolean, byte, short, and character return types.
1541 */
1542 RegType src_type = GetRegisterType(work_line, dec_insn.vA_);
1543 if ((return_type == kRegTypeBoolean && src_type == kRegTypeByte) ||
1544 ((return_type == kRegTypeBoolean || return_type == kRegTypeByte ||
1545 return_type == kRegTypeShort || return_type == kRegTypeChar) &&
1546 src_type == kRegTypeInteger))
1547 return_type = src_type;
1548
1549 /* check the register contents */
1550 VerifyRegisterType(work_line, dec_insn.vA_, return_type, &failure);
1551 if (failure != VERIFY_ERROR_NONE) {
1552 LOG(ERROR) << "VFY: return-1nr on invalid register v" << dec_insn.vA_;
1553 }
1554 }
1555 break;
1556 case Instruction::RETURN_WIDE:
1557 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1558 failure = VERIFY_ERROR_GENERIC;
1559 } else {
1560 RegType return_type;
1561
1562 /* check the method signature */
1563 return_type = GetMethodReturnType(dex_file, method);
1564 CheckTypeCategory(return_type, kTypeCategory2, &failure);
1565 if (failure != VERIFY_ERROR_NONE)
1566 LOG(ERROR) << "VFY: return-wide not expected";
1567
1568 /* check the register contents */
1569 VerifyRegisterType(work_line, dec_insn.vA_, return_type, &failure);
1570 if (failure != VERIFY_ERROR_NONE) {
1571 LOG(ERROR) << "VFY: return-wide on invalid register pair v"
1572 << dec_insn.vA_;
1573 }
1574 }
1575 break;
1576 case Instruction::RETURN_OBJECT:
1577 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1578 failure = VERIFY_ERROR_GENERIC;
1579 } else {
1580 RegType return_type = GetMethodReturnType(dex_file, method);
1581 CheckTypeCategory(return_type, kTypeCategoryRef, &failure);
1582 if (failure != VERIFY_ERROR_NONE) {
1583 LOG(ERROR) << "VFY: return-object not expected";
1584 break;
1585 }
1586
1587 /* return_type is the *expected* return type, not register value */
1588 assert(return_type != kRegTypeZero);
1589 assert(!RegTypeIsUninitReference(return_type));
1590
1591 /*
1592 * Verify that the reference in vAA is an instance of the type
jeffhaod1f0fde2011-09-08 17:25:33 -07001593 * in "return_type". The Zero type is allowed here. If the
jeffhaobdb76512011-09-07 11:43:16 -07001594 * method is declared to return an interface, then any
1595 * initialized reference is acceptable.
1596 *
1597 * Note GetClassFromRegister fails if the register holds an
1598 * uninitialized reference, so we do not allow them to be
1599 * returned.
1600 */
1601 Class* decl_class = RegTypeInitializedReferenceToClass(return_type);
1602 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1603 if (failure != VERIFY_ERROR_NONE)
1604 break;
1605 if (res_class != NULL) {
1606 if (!decl_class->IsInterface() &&
1607 //!res_class->InstanceOf(decl_class)) {
1608 !decl_class->IsAssignableFrom(res_class)) {
1609 LOG(ERROR) << "VFY: returning " << std::hex
1610 << res_class->GetDescriptor()->ToModifiedUtf8()
1611 << " (cl=0x" << (int) res_class->GetClassLoader()
1612 << "), declared "
1613 << decl_class->GetDescriptor()->ToModifiedUtf8()
1614 << " (cl=0x" << (int) decl_class->GetClassLoader()
1615 << ")" << std::dec;
1616 failure = VERIFY_ERROR_GENERIC;
1617 break;
1618 }
1619 }
1620 }
1621 break;
1622
1623 case Instruction::CONST_4:
1624 case Instruction::CONST_16:
1625 case Instruction::CONST:
1626 /* could be boolean, int, float, or a null reference */
1627 SetRegisterType(work_line, dec_insn.vA_,
1628 DetermineCat1Const((int32_t) dec_insn.vB_));
1629 break;
1630 case Instruction::CONST_HIGH16:
1631 /* could be boolean, int, float, or a null reference */
1632 SetRegisterType(work_line, dec_insn.vA_,
1633 DetermineCat1Const((int32_t) dec_insn.vB_ << 16));
1634 break;
1635 case Instruction::CONST_WIDE_16:
1636 case Instruction::CONST_WIDE_32:
1637 case Instruction::CONST_WIDE:
1638 case Instruction::CONST_WIDE_HIGH16:
1639 /* could be long or double; resolved upon use */
1640 SetRegisterType(work_line, dec_insn.vA_, kRegTypeConstLo);
1641 break;
1642 case Instruction::CONST_STRING:
1643 case Instruction::CONST_STRING_JUMBO:
1644 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
1645 class_linker->FindSystemClass("Ljava/lang/String;")));
1646 break;
1647 case Instruction::CONST_CLASS:
1648 /* make sure we can resolve the class; access check is important */
jeffhao98eacac2011-09-14 16:11:53 -07001649 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001650 if (res_class == NULL) {
1651 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1652 LOG(ERROR) << "VFY: unable to resolve const-class " << dec_insn.vB_
1653 << " (" << bad_class_desc << ") in "
1654 << klass->GetDescriptor()->ToModifiedUtf8();
1655 assert(failure != VERIFY_ERROR_GENERIC);
1656 } else {
1657 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
1658 class_linker->FindSystemClass("Ljava/lang/Class;")));
1659 }
1660 break;
1661
1662 case Instruction::MONITOR_ENTER:
1663 HandleMonitorEnter(work_line, dec_insn.vA_, insn_idx, &failure);
1664 break;
1665 case Instruction::MONITOR_EXIT:
1666 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001667 * monitor-exit instructions are odd. They can throw exceptions,
jeffhaobdb76512011-09-07 11:43:16 -07001668 * but when they do they act as if they succeeded and the PC is
jeffhaod1f0fde2011-09-08 17:25:33 -07001669 * pointing to the following instruction. (This behavior goes back
jeffhaobdb76512011-09-07 11:43:16 -07001670 * to the need to handle asynchronous exceptions, a now-deprecated
1671 * feature that Dalvik doesn't support.)
1672 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001673 * In practice we don't need to worry about this. The only
jeffhaobdb76512011-09-07 11:43:16 -07001674 * exceptions that can be thrown from monitor-exit are for a
jeffhaod1f0fde2011-09-08 17:25:33 -07001675 * null reference and -exit without a matching -enter. If the
jeffhaobdb76512011-09-07 11:43:16 -07001676 * structured locking checks are working, the former would have
1677 * failed on the -enter instruction, and the latter is impossible.
1678 *
1679 * This is fortunate, because issue 3221411 prevents us from
1680 * chasing the "can throw" path when monitor verification is
jeffhaod1f0fde2011-09-08 17:25:33 -07001681 * enabled. If we can fully verify the locking we can ignore
jeffhaobdb76512011-09-07 11:43:16 -07001682 * some catch blocks (which will show up as "dead" code when
1683 * we skip them here); if we can't, then the code path could be
1684 * "live" so we still need to check it.
1685 */
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001686 if (work_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07001687 opcode_flag &= ~Instruction::kThrow;
1688 HandleMonitorExit(work_line, dec_insn.vA_, insn_idx, &failure);
1689 break;
1690
1691 case Instruction::CHECK_CAST:
1692 /*
1693 * If this instruction succeeds, we will promote register vA to
jeffhaod1f0fde2011-09-08 17:25:33 -07001694 * the type in vB. (This could be a demotion -- not expected, so
jeffhaobdb76512011-09-07 11:43:16 -07001695 * we don't try to address it.)
1696 *
1697 * If it fails, an exception is thrown, which we deal with later
1698 * by ignoring the update to dec_insn.vA_ when branching to a handler.
1699 */
jeffhao98eacac2011-09-14 16:11:53 -07001700 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001701 if (res_class == NULL) {
1702 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1703 LOG(ERROR) << "VFY: unable to resolve check-cast " << dec_insn.vB_
1704 << " (" << bad_class_desc << ") in "
1705 << klass->GetDescriptor()->ToModifiedUtf8();
1706 assert(failure != VERIFY_ERROR_GENERIC);
1707 } else {
1708 RegType orig_type;
1709
1710 orig_type = GetRegisterType(work_line, dec_insn.vA_);
1711 if (!RegTypeIsReference(orig_type)) {
1712 LOG(ERROR) << "VFY: check-cast on non-reference in v" << dec_insn.vA_;
1713 failure = VERIFY_ERROR_GENERIC;
1714 break;
1715 }
1716 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1717 }
1718 break;
1719 case Instruction::INSTANCE_OF:
1720 /* make sure we're checking a reference type */
1721 tmp_type = GetRegisterType(work_line, dec_insn.vB_);
1722 if (!RegTypeIsReference(tmp_type)) {
1723 LOG(ERROR) << "VFY: vB not a reference (" << tmp_type << ")";
1724 failure = VERIFY_ERROR_GENERIC;
1725 break;
1726 }
1727
1728 /* make sure we can resolve the class; access check is important */
jeffhao98eacac2011-09-14 16:11:53 -07001729 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vC_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001730 if (res_class == NULL) {
1731 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vC_);
1732 LOG(ERROR) << "VFY: unable to resolve instanceof " << dec_insn.vC_
1733 << " (" << bad_class_desc << ") in "
1734 << klass->GetDescriptor()->ToModifiedUtf8();
1735 assert(failure != VERIFY_ERROR_GENERIC);
1736 } else {
1737 /* result is boolean */
1738 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1739 }
1740 break;
1741
1742 case Instruction::ARRAY_LENGTH:
1743 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
1744 if (failure != VERIFY_ERROR_NONE)
1745 break;
1746 if (res_class != NULL && !res_class->IsArrayClass()) {
1747 LOG(ERROR) << "VFY: array-length on non-array";
1748 failure = VERIFY_ERROR_GENERIC;
1749 break;
1750 }
1751 SetRegisterType(work_line, dec_insn.vA_, kRegTypeInteger);
1752 break;
1753
1754 case Instruction::NEW_INSTANCE:
jeffhao98eacac2011-09-14 16:11:53 -07001755 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001756 if (res_class == NULL) {
1757 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1758 LOG(ERROR) << "VFY: unable to resolve new-instance " << dec_insn.vB_
1759 << " (" << bad_class_desc << ") in "
1760 << klass->GetDescriptor()->ToModifiedUtf8();
1761 assert(failure != VERIFY_ERROR_GENERIC);
1762 } else {
1763 RegType uninit_type;
1764
1765 /* can't create an instance of an interface or abstract class */
1766 if (res_class->IsAbstract() || res_class->IsInterface()) {
1767 LOG(ERROR) << "VFY: new-instance on interface or abstract class"
1768 << res_class->GetDescriptor()->ToModifiedUtf8();
1769 failure = VERIFY_ERROR_INSTANTIATION;
1770 break;
1771 }
1772
1773 /* add resolved class to uninit map if not already there */
1774 int uidx = SetUninitInstance(uninit_map, insn_idx, res_class);
1775 assert(uidx >= 0);
1776 uninit_type = RegTypeFromUninitIndex(uidx);
1777
1778 /*
1779 * Any registers holding previous allocations from this address
1780 * that have not yet been initialized must be marked invalid.
1781 */
1782 MarkUninitRefsAsInvalid(work_line, registers_size, uninit_map,
1783 uninit_type);
1784
1785 /* add the new uninitialized reference to the register ste */
1786 SetRegisterType(work_line, dec_insn.vA_, uninit_type);
1787 }
1788 break;
1789 case Instruction::NEW_ARRAY:
jeffhao98eacac2011-09-14 16:11:53 -07001790 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vC_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001791 if (res_class == NULL) {
1792 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vC_);
1793 LOG(ERROR) << "VFY: unable to resolve new-array " << dec_insn.vC_
1794 << " (" << bad_class_desc << ") in "
1795 << klass->GetDescriptor()->ToModifiedUtf8();
1796 assert(failure != VERIFY_ERROR_GENERIC);
1797 } else if (!res_class->IsArrayClass()) {
1798 LOG(ERROR) << "VFY: new-array on non-array class";
1799 failure = VERIFY_ERROR_GENERIC;
1800 } else {
1801 /* make sure "size" register is valid type */
1802 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeInteger, &failure);
1803 /* set register type to array class */
1804 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1805 }
1806 break;
1807 case Instruction::FILLED_NEW_ARRAY:
1808 case Instruction::FILLED_NEW_ARRAY_RANGE:
jeffhao98eacac2011-09-14 16:11:53 -07001809 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001810 if (res_class == NULL) {
1811 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1812 LOG(ERROR) << "VFY: unable to resolve filled-array " << dec_insn.vB_
1813 << " (" << bad_class_desc << ") in "
1814 << klass->GetDescriptor()->ToModifiedUtf8();
1815 assert(failure != VERIFY_ERROR_GENERIC);
1816 } else if (!res_class->IsArrayClass()) {
1817 LOG(ERROR) << "VFY: filled-new-array on non-array class";
1818 failure = VERIFY_ERROR_GENERIC;
1819 } else {
1820 bool is_range = (dec_insn.opcode_ ==
1821 Instruction::FILLED_NEW_ARRAY_RANGE);
1822
1823 /* check the arguments to the instruction */
1824 VerifyFilledNewArrayRegs(method, work_line, &dec_insn, res_class,
1825 is_range, &failure);
1826 /* filled-array result goes into "result" register */
1827 SetResultRegisterType(work_line, registers_size,
1828 RegTypeFromClass(res_class));
1829 just_set_result = true;
1830 }
1831 break;
1832
1833 case Instruction::CMPL_FLOAT:
1834 case Instruction::CMPG_FLOAT:
1835 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeFloat, &failure);
1836 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeFloat, &failure);
1837 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1838 break;
1839 case Instruction::CMPL_DOUBLE:
1840 case Instruction::CMPG_DOUBLE:
1841 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeDoubleLo, &failure);
1842 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeDoubleLo, &failure);
1843 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1844 break;
1845 case Instruction::CMP_LONG:
1846 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeLongLo, &failure);
1847 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeLongLo, &failure);
1848 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1849 break;
1850
1851 case Instruction::THROW:
1852 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1853 if (failure == VERIFY_ERROR_NONE && res_class != NULL) {
1854 Class* throwable_class =
1855 class_linker->FindSystemClass("Ljava/lang/Throwable;");
1856 if (!throwable_class->IsAssignableFrom(res_class)) {
1857 LOG(ERROR) << "VFY: thrown class "
1858 << res_class->GetDescriptor()->ToModifiedUtf8()
1859 << " not instanceof Throwable",
1860 failure = VERIFY_ERROR_GENERIC;
1861 }
1862 }
1863 break;
1864
1865 case Instruction::GOTO:
1866 case Instruction::GOTO_16:
1867 case Instruction::GOTO_32:
1868 /* no effect on or use of registers */
1869 break;
1870
1871 case Instruction::PACKED_SWITCH:
1872 case Instruction::SPARSE_SWITCH:
1873 /* verify that vAA is an integer, or can be converted to one */
1874 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeInteger, &failure);
1875 break;
1876
1877 case Instruction::FILL_ARRAY_DATA:
1878 {
1879 RegType value_type;
1880 const uint16_t *array_data;
1881 uint16_t elem_width;
1882
1883 /* Similar to the verification done for APUT */
1884 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1885 if (failure != VERIFY_ERROR_NONE)
1886 break;
1887
1888 /* res_class can be null if the reg type is Zero */
1889 if (res_class == NULL)
1890 break;
1891
1892 Class::PrimitiveType prim_type =
1893 res_class->GetComponentType()->GetPrimitiveType();
1894 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
1895 prim_type == Class::kPrimNot || prim_type == Class::kPrimVoid) {
1896 LOG(ERROR) << "VFY: invalid fill-array-data on " <<
1897 res_class->GetDescriptor()->ToModifiedUtf8();
1898 failure = VERIFY_ERROR_GENERIC;
1899 break;
1900 }
1901
1902 value_type = PrimitiveTypeToRegType(prim_type);
1903 assert(value_type != kRegTypeUnknown);
1904
1905 /*
1906 * Now verify if the element width in the table matches the element
1907 * width declared in the array
1908 */
1909 array_data = insns + (insns[1] | (((int32_t) insns[2]) << 16));
1910 if (array_data[0] != Instruction::kArrayDataSignature) {
1911 LOG(ERROR) << "VFY: invalid magic for array-data";
1912 failure = VERIFY_ERROR_GENERIC;
1913 break;
1914 }
1915
1916 switch (prim_type) {
1917 case Class::kPrimBoolean:
1918 case Class::kPrimByte:
1919 elem_width = 1;
1920 break;
1921 case Class::kPrimChar:
1922 case Class::kPrimShort:
1923 elem_width = 2;
1924 break;
1925 case Class::kPrimFloat:
1926 case Class::kPrimInt:
1927 elem_width = 4;
1928 break;
1929 case Class::kPrimDouble:
1930 case Class::kPrimLong:
1931 elem_width = 8;
1932 break;
1933 default:
1934 elem_width = 0;
1935 break;
1936 }
1937
1938 /*
1939 * Since we don't compress the data in Dex, expect to see equal
1940 * width of data stored in the table and expected from the array
1941 * class.
1942 */
1943 if (array_data[1] != elem_width) {
1944 LOG(ERROR) << "VFY: array-data size mismatch (" << array_data[1]
1945 << " vs " << elem_width << ")";
1946 failure = VERIFY_ERROR_GENERIC;
1947 }
1948 }
1949 break;
1950
1951 case Instruction::IF_EQ:
1952 case Instruction::IF_NE:
1953 {
1954 RegType type1, type2;
1955
1956 type1 = GetRegisterType(work_line, dec_insn.vA_);
1957 type2 = GetRegisterType(work_line, dec_insn.vB_);
1958
1959 /* both references? */
1960 if (RegTypeIsReference(type1) && RegTypeIsReference(type2))
1961 break;
1962
1963 /* both category-1nr? */
1964 CheckTypeCategory(type1, kTypeCategory1nr, &failure);
1965 CheckTypeCategory(type2, kTypeCategory1nr, &failure);
1966 if (failure != VERIFY_ERROR_NONE) {
1967 LOG(ERROR) << "VFY: args to if-eq/if-ne must both be refs or cat1";
1968 break;
1969 }
1970 }
1971 break;
1972 case Instruction::IF_LT:
1973 case Instruction::IF_GE:
1974 case Instruction::IF_GT:
1975 case Instruction::IF_LE:
1976 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
1977 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1978 if (failure != VERIFY_ERROR_NONE) {
1979 LOG(ERROR) << "VFY: args to 'if' must be cat-1nr";
1980 break;
1981 }
1982 tmp_type = GetRegisterType(work_line, dec_insn.vB_);
1983 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1984 if (failure != VERIFY_ERROR_NONE) {
1985 LOG(ERROR) << "VFY: args to 'if' must be cat-1nr";
1986 break;
1987 }
1988 break;
1989 case Instruction::IF_EQZ:
1990 case Instruction::IF_NEZ:
1991 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
1992 if (RegTypeIsReference(tmp_type))
1993 break;
1994 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1995 if (failure != VERIFY_ERROR_NONE)
1996 LOG(ERROR) << "VFY: expected cat-1 arg to if";
1997 break;
1998 case Instruction::IF_LTZ:
1999 case Instruction::IF_GEZ:
2000 case Instruction::IF_GTZ:
2001 case Instruction::IF_LEZ:
2002 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
2003 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
2004 if (failure != VERIFY_ERROR_NONE)
2005 LOG(ERROR) << "VFY: expected cat-1 arg to if";
2006 break;
2007
2008 case Instruction::AGET:
2009 tmp_type = kRegTypeConstInteger;
2010 goto aget_1nr_common;
2011 case Instruction::AGET_BOOLEAN:
2012 tmp_type = kRegTypeBoolean;
2013 goto aget_1nr_common;
2014 case Instruction::AGET_BYTE:
2015 tmp_type = kRegTypeByte;
2016 goto aget_1nr_common;
2017 case Instruction::AGET_CHAR:
2018 tmp_type = kRegTypeChar;
2019 goto aget_1nr_common;
2020 case Instruction::AGET_SHORT:
2021 tmp_type = kRegTypeShort;
2022 goto aget_1nr_common;
2023aget_1nr_common:
2024 {
2025 RegType src_type, index_type;
2026
2027 index_type = GetRegisterType(work_line, dec_insn.vC_);
2028 CheckArrayIndexType(method, index_type, &failure);
2029 if (failure != VERIFY_ERROR_NONE)
2030 break;
2031
2032 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2033 if (failure != VERIFY_ERROR_NONE)
2034 break;
2035 if (res_class != NULL) {
2036 /* verify the class */
2037 Class::PrimitiveType prim_type =
2038 res_class->GetComponentType()->GetPrimitiveType();
2039 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
2040 prim_type == Class::kPrimNot) {
2041 LOG(ERROR) << "VFY: invalid aget-1nr target "
2042 << res_class->GetDescriptor()->ToModifiedUtf8();
2043 failure = VERIFY_ERROR_GENERIC;
2044 break;
2045 }
2046
2047 /* make sure array type matches instruction */
2048 src_type = PrimitiveTypeToRegType(prim_type);
2049
2050 /* differentiate between float and int */
2051 if (src_type == kRegTypeFloat || src_type == kRegTypeInteger)
2052 tmp_type = src_type;
2053
2054 if (tmp_type != src_type) {
2055 LOG(ERROR) << "VFY: invalid aget-1nr, array type=" << src_type
2056 << " with inst type=" << tmp_type << " (on "
2057 << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
2058 failure = VERIFY_ERROR_GENERIC;
2059 break;
2060 }
2061
2062 }
2063 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2064 }
2065 break;
2066
2067 case Instruction::AGET_WIDE:
2068 {
2069 RegType dst_type, index_type;
2070
2071 index_type = GetRegisterType(work_line, dec_insn.vC_);
2072 CheckArrayIndexType(method, index_type, &failure);
2073 if (failure != VERIFY_ERROR_NONE)
2074 break;
2075
2076 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2077 if (failure != VERIFY_ERROR_NONE)
2078 break;
2079 if (res_class != NULL) {
2080 /* verify the class */
2081 Class::PrimitiveType prim_type =
2082 res_class->GetComponentType()->GetPrimitiveType();
2083 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
2084 prim_type == Class::kPrimNot) {
2085 LOG(ERROR) << "VFY: invalid aget-wide target "
2086 << res_class->GetDescriptor()->ToModifiedUtf8();
2087 failure = VERIFY_ERROR_GENERIC;
2088 break;
2089 }
2090
2091 /* try to refine "dst_type" */
2092 switch (prim_type) {
2093 case Class::kPrimLong:
2094 dst_type = kRegTypeLongLo;
2095 break;
2096 case Class::kPrimDouble:
2097 dst_type = kRegTypeDoubleLo;
2098 break;
2099 default:
2100 LOG(ERROR) << "VFY: invalid aget-wide on "
2101 << res_class->GetDescriptor()->ToModifiedUtf8();
2102 dst_type = kRegTypeUnknown;
2103 failure = VERIFY_ERROR_GENERIC;
2104 break;
2105 }
2106 } else {
2107 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002108 * Null array ref; this code path will fail at runtime. We
jeffhaobdb76512011-09-07 11:43:16 -07002109 * know this is either long or double, so label it const.
2110 */
2111 dst_type = kRegTypeConstLo;
2112 }
2113 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2114 }
2115 break;
2116
2117 case Instruction::AGET_OBJECT:
2118 {
2119 RegType dst_type, index_type;
2120
2121 index_type = GetRegisterType(work_line, dec_insn.vC_);
2122 CheckArrayIndexType(method, index_type, &failure);
2123 if (failure != VERIFY_ERROR_NONE)
2124 break;
2125
2126 /* get the class of the array we're pulling an object from */
2127 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2128 if (failure != VERIFY_ERROR_NONE)
2129 break;
2130 if (res_class != NULL) {
2131 Class* element_class;
2132
2133 assert(res_class != NULL);
2134 if (!res_class->IsArrayClass()) {
2135 LOG(ERROR) << "VFY: aget-object on non-array class";
2136 failure = VERIFY_ERROR_GENERIC;
2137 break;
2138 }
2139 assert(res_class->GetComponentType() != NULL);
2140
2141 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002142 * Find the element class. res_class->GetComponentType() indicates
jeffhaobdb76512011-09-07 11:43:16 -07002143 * the basic type, which won't be what we want for a
2144 * multi-dimensional array.
2145 */
2146 if (res_class->GetDescriptor()->CharAt(1) == '[') {
2147 assert(res_class->GetArrayRank() > 1);
2148 std::string descriptor =
2149 res_class->GetDescriptor()->ToModifiedUtf8();
2150 element_class = class_linker->FindClass(descriptor.c_str() + 1,
2151 res_class->GetClassLoader());
2152 } else if (res_class->GetDescriptor()->CharAt(1) == 'L') {
2153 assert(res_class->GetArrayRank() == 1);
2154 element_class = res_class->GetComponentType();
2155 } else {
2156 LOG(ERROR) << "VFY: aget-object on non-ref array class ("
2157 << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
2158 failure = VERIFY_ERROR_GENERIC;
2159 break;
2160 }
2161
2162 dst_type = RegTypeFromClass(element_class);
2163 } else {
2164 /*
2165 * The array reference is NULL, so the current code path will
jeffhaod1f0fde2011-09-08 17:25:33 -07002166 * throw an exception. For proper merging with later code
jeffhaobdb76512011-09-07 11:43:16 -07002167 * paths, and correct handling of "if-eqz" tests on the
2168 * result of the array get, we want to treat this as a null
2169 * reference.
2170 */
2171 dst_type = kRegTypeZero;
2172 }
2173 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2174 }
2175 break;
2176 case Instruction::APUT:
2177 tmp_type = kRegTypeInteger;
2178 goto aput_1nr_common;
2179 case Instruction::APUT_BOOLEAN:
2180 tmp_type = kRegTypeBoolean;
2181 goto aput_1nr_common;
2182 case Instruction::APUT_BYTE:
2183 tmp_type = kRegTypeByte;
2184 goto aput_1nr_common;
2185 case Instruction::APUT_CHAR:
2186 tmp_type = kRegTypeChar;
2187 goto aput_1nr_common;
2188 case Instruction::APUT_SHORT:
2189 tmp_type = kRegTypeShort;
2190 goto aput_1nr_common;
2191aput_1nr_common:
2192 {
2193 RegType src_type, dst_type, index_type;
2194
2195 index_type = GetRegisterType(work_line, dec_insn.vC_);
2196 CheckArrayIndexType(method, index_type, &failure);
2197 if (failure != VERIFY_ERROR_NONE)
2198 break;
2199
2200 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2201 if (failure != VERIFY_ERROR_NONE)
2202 break;
2203
2204 /* res_class can be null if the reg type is Zero */
2205 if (res_class == NULL)
2206 break;
2207
2208 Class::PrimitiveType prim_type =
2209 res_class->GetComponentType()->GetPrimitiveType();
2210 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
2211 prim_type == Class::kPrimNot) {
2212 LOG(ERROR) << "VFY: invalid aput-1nr on "
2213 << res_class->GetDescriptor()->ToModifiedUtf8();
2214 failure = VERIFY_ERROR_GENERIC;
2215 break;
2216 }
2217
2218 /* verify that instruction matches array */
2219 dst_type = PrimitiveTypeToRegType(prim_type);
2220
2221 /* correct if float */
2222 if (dst_type == kRegTypeFloat)
2223 tmp_type = kRegTypeFloat;
2224
2225 /* make sure the source register has the correct type */
2226 src_type = GetRegisterType(work_line, dec_insn.vA_);
2227 if (!CanConvertTo1nr(src_type, tmp_type)) {
2228 LOG(ERROR) << "VFY: invalid reg type " << src_type
2229 << " on aput instr (need " << tmp_type << ")";
2230 failure = VERIFY_ERROR_GENERIC;
2231 break;
2232 }
2233
2234 VerifyRegisterType(work_line, dec_insn.vA_, dst_type, &failure);
2235
2236 if (failure != VERIFY_ERROR_NONE || dst_type == kRegTypeUnknown ||
2237 tmp_type != dst_type) {
2238 LOG(ERROR) << "VFY: invalid aput-1nr on "
2239 << res_class->GetDescriptor()->ToModifiedUtf8()
2240 << " (inst=" << tmp_type << " dst=" << dst_type << ")";
2241 failure = VERIFY_ERROR_GENERIC;
2242 break;
2243 }
2244 }
2245 break;
2246 case Instruction::APUT_WIDE:
2247 tmp_type = GetRegisterType(work_line, dec_insn.vC_);
2248 CheckArrayIndexType(method, tmp_type, &failure);
2249 if (failure != VERIFY_ERROR_NONE)
2250 break;
2251
2252 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2253 if (failure != VERIFY_ERROR_NONE)
2254 break;
2255 if (res_class != NULL) {
2256 Class::PrimitiveType prim_type =
2257 res_class->GetComponentType()->GetPrimitiveType();
2258 /* verify the class and try to refine "dst_type" */
2259 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
2260 prim_type == Class::kPrimNot)
2261 {
2262 LOG(ERROR) << "VFY: invalid aput-wide on "
2263 << res_class->GetDescriptor()->ToModifiedUtf8();
2264 failure = VERIFY_ERROR_GENERIC;
2265 break;
2266 }
2267
2268 switch (prim_type) {
2269 case Class::kPrimLong:
2270 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo,
2271 &failure);
2272 break;
2273 case Class::kPrimDouble:
2274 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2275 &failure);
2276 break;
2277 default:
2278 LOG(ERROR) << "VFY: invalid aput-wide on "
2279 << res_class->GetDescriptor()->ToModifiedUtf8();
2280 failure = VERIFY_ERROR_GENERIC;
2281 break;
2282 }
2283 }
2284 break;
2285 case Instruction::APUT_OBJECT:
2286 tmp_type = GetRegisterType(work_line, dec_insn.vC_);
2287 CheckArrayIndexType(method, tmp_type, &failure);
2288 if (failure != VERIFY_ERROR_NONE)
2289 break;
2290
2291 /* get the ref we're storing; Zero is okay, Uninit is not */
2292 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
2293 if (failure != VERIFY_ERROR_NONE)
2294 break;
2295 if (res_class != NULL) {
2296 Class* array_class;
2297 Class* element_class;
2298
2299 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002300 * Get the array class. If the array ref is null, we won't
jeffhaobdb76512011-09-07 11:43:16 -07002301 * have type information (and we'll crash at runtime with a
2302 * null pointer exception).
2303 */
2304 array_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2305
2306 if (array_class != NULL) {
2307 /* see if the array holds a compatible type */
2308 if (!array_class->IsArrayClass()) {
2309 LOG(ERROR) << "VFY: invalid aput-object on "
2310 << array_class->GetDescriptor()->ToModifiedUtf8();
2311 failure = VERIFY_ERROR_GENERIC;
2312 break;
2313 }
2314
2315 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002316 * Find the element class. res_class->GetComponentType() indicates
jeffhaobdb76512011-09-07 11:43:16 -07002317 * the basic type, which won't be what we want for a
2318 * multi-dimensional array.
2319 *
2320 * All we want to check here is that the element type is a
jeffhaod1f0fde2011-09-08 17:25:33 -07002321 * reference class. We *don't* check instanceof here, because
jeffhaobdb76512011-09-07 11:43:16 -07002322 * you can still put a String into a String[] after the latter
2323 * has been cast to an Object[].
2324 */
2325 if (array_class->GetDescriptor()->CharAt(1) == '[') {
2326 assert(array_class->GetArrayRank() > 1);
2327 std::string descriptor =
2328 array_class->GetDescriptor()->ToModifiedUtf8();
2329 element_class = class_linker->FindClass(descriptor.c_str() + 1,
2330 array_class->GetClassLoader());
2331 } else {
2332 assert(array_class->GetArrayRank() == 1);
2333 element_class = array_class->GetComponentType();
2334 }
2335 if (element_class->GetPrimitiveType() != Class::kPrimNot) {
2336 LOG(ERROR) << "VFY: invalid aput-object of "
2337 << res_class->GetDescriptor()->ToModifiedUtf8()
2338 << " into "
2339 << array_class->GetDescriptor()->ToModifiedUtf8();
2340 failure = VERIFY_ERROR_GENERIC;
2341 break;
2342 }
2343 }
2344 }
2345 break;
2346
2347 case Instruction::IGET:
2348 tmp_type = kRegTypeInteger;
2349 goto iget_1nr_common;
2350 case Instruction::IGET_BOOLEAN:
2351 tmp_type = kRegTypeBoolean;
2352 goto iget_1nr_common;
2353 case Instruction::IGET_BYTE:
2354 tmp_type = kRegTypeByte;
2355 goto iget_1nr_common;
2356 case Instruction::IGET_CHAR:
2357 tmp_type = kRegTypeChar;
2358 goto iget_1nr_common;
2359 case Instruction::IGET_SHORT:
2360 tmp_type = kRegTypeShort;
2361 goto iget_1nr_common;
2362iget_1nr_common:
2363 {
2364 Field* inst_field;
2365 RegType obj_type, field_type;
2366
2367 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2368 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2369 if (failure != VERIFY_ERROR_NONE)
2370 break;
2371
2372 /* make sure the field's type is compatible with expectation */
2373 field_type =
2374 PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
2375
2376 /* correct if float */
2377 if (field_type == kRegTypeFloat)
2378 tmp_type = kRegTypeFloat;
2379
2380 if (field_type == kRegTypeUnknown || tmp_type != field_type) {
2381 Class* inst_field_class = inst_field->GetDeclaringClass();
2382 LOG(ERROR) << "VFY: invalid iget-1nr of "
2383 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2384 << "." << inst_field->GetName()->ToModifiedUtf8()
2385 << " (inst=" << tmp_type << " field=" << field_type << ")";
2386 failure = VERIFY_ERROR_GENERIC;
2387 break;
2388 }
2389
2390 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2391 }
2392 break;
2393 case Instruction::IGET_WIDE:
2394 {
2395 RegType dst_type;
2396 Field* inst_field;
2397 RegType obj_type;
2398
2399 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2400 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2401 Class* inst_field_class = inst_field->GetDeclaringClass();
2402 if (failure != VERIFY_ERROR_NONE)
2403 break;
2404 /* check the type, which should be prim */
2405 switch (inst_field->GetType()->GetPrimitiveType()) {
2406 case Class::kPrimDouble:
2407 dst_type = kRegTypeDoubleLo;
2408 break;
2409 case Class::kPrimLong:
2410 dst_type = kRegTypeLongLo;
2411 break;
2412 default:
2413 LOG(ERROR) << "VFY: invalid iget-wide of "
2414 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2415 << "." << inst_field->GetName()->ToModifiedUtf8();
2416 dst_type = kRegTypeUnknown;
2417 failure = VERIFY_ERROR_GENERIC;
2418 break;
2419 }
2420 if (failure == VERIFY_ERROR_NONE) {
2421 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2422 }
2423 }
2424 break;
2425 case Instruction::IGET_OBJECT:
2426 {
2427 Class* field_class;
2428 Field* inst_field;
2429 RegType obj_type;
2430
2431 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2432 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2433 if (failure != VERIFY_ERROR_NONE)
2434 break;
2435 field_class = inst_field->GetType();
2436 if (field_class == NULL) {
2437 /* class not found or primitive type */
2438 LOG(ERROR) << "VFY: unable to recover field class from "
2439 << inst_field->GetName()->ToModifiedUtf8();
2440 failure = VERIFY_ERROR_GENERIC;
2441 break;
2442 }
2443 if (failure == VERIFY_ERROR_NONE) {
2444 assert(!field_class->IsPrimitive());
2445 SetRegisterType(work_line, dec_insn.vA_,
2446 RegTypeFromClass(field_class));
2447 }
2448 }
2449 break;
2450 case Instruction::IPUT:
2451 tmp_type = kRegTypeInteger;
2452 goto iput_1nr_common;
2453 case Instruction::IPUT_BOOLEAN:
2454 tmp_type = kRegTypeBoolean;
2455 goto iput_1nr_common;
2456 case Instruction::IPUT_BYTE:
2457 tmp_type = kRegTypeByte;
2458 goto iput_1nr_common;
2459 case Instruction::IPUT_CHAR:
2460 tmp_type = kRegTypeChar;
2461 goto iput_1nr_common;
2462 case Instruction::IPUT_SHORT:
2463 tmp_type = kRegTypeShort;
2464 goto iput_1nr_common;
2465iput_1nr_common:
2466 {
2467 RegType src_type, field_type, obj_type;
2468 Field* inst_field;
2469
2470 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2471 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2472 if (failure != VERIFY_ERROR_NONE)
2473 break;
2474 CheckFinalFieldAccess(method, inst_field, &failure);
2475 if (failure != VERIFY_ERROR_NONE)
2476 break;
2477
2478 /* get type of field we're storing into */
2479 field_type =
2480 PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
2481 src_type = GetRegisterType(work_line, dec_insn.vA_);
2482
2483 /* correct if float */
2484 if (field_type == kRegTypeFloat)
2485 tmp_type = kRegTypeFloat;
2486
2487 /*
2488 * compiler can generate synthetic functions that write byte values
2489 * into boolean fields.
2490 */
2491 if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
2492 tmp_type = kRegTypeByte;
2493 if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
2494 field_type = kRegTypeByte;
2495
2496 /* make sure the source register has the correct type */
2497 if (!CanConvertTo1nr(src_type, tmp_type)) {
2498 LOG(ERROR) << "VFY: invalid reg type " << src_type
2499 << " on iput instr (need " << tmp_type << ")",
2500 failure = VERIFY_ERROR_GENERIC;
2501 break;
2502 }
2503
2504 VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);
2505
2506 if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
2507 tmp_type != field_type) {
2508 Class* inst_field_class = inst_field->GetDeclaringClass();
2509 LOG(ERROR) << "VFY: invalid iput-1nr of "
2510 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2511 << "." << inst_field->GetName()->ToModifiedUtf8()
2512 << " (inst=" << tmp_type << " field=" << field_type << ")";
2513 failure = VERIFY_ERROR_GENERIC;
2514 break;
2515 }
2516 }
2517 break;
2518 case Instruction::IPUT_WIDE:
2519 Field* inst_field;
2520 RegType obj_type;
2521
2522 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2523 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2524 if (failure != VERIFY_ERROR_NONE)
2525 break;
2526 CheckFinalFieldAccess(method, inst_field, &failure);
2527 if (failure != VERIFY_ERROR_NONE)
2528 break;
2529
2530 /* check the type, which should be prim */
2531 switch (inst_field->GetType()->GetPrimitiveType()) {
2532 case Class::kPrimDouble:
2533 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2534 &failure);
2535 break;
2536 case Class::kPrimLong:
2537 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
2538 break;
2539 default:
2540 LOG(ERROR) << "VFY: invalid iput-wide of "
2541 << inst_field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
2542 << "." << inst_field->GetName()->ToModifiedUtf8();
2543 failure = VERIFY_ERROR_GENERIC;
2544 break;
2545 }
2546 break;
2547 case Instruction::IPUT_OBJECT:
2548 {
2549 Class* field_class;
2550 Class* value_class;
2551 Field* inst_field;
2552 RegType obj_type, value_type;
2553
2554 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2555 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2556 if (failure != VERIFY_ERROR_NONE)
2557 break;
2558 CheckFinalFieldAccess(method, inst_field, &failure);
2559 if (failure != VERIFY_ERROR_NONE)
2560 break;
2561
2562 field_class = inst_field->GetType();
2563 if (field_class == NULL) {
2564 LOG(ERROR) << "VFY: unable to recover field class from '"
2565 << inst_field->GetName()->ToModifiedUtf8() << "'";
2566 failure = VERIFY_ERROR_GENERIC;
2567 break;
2568 }
2569
2570 value_type = GetRegisterType(work_line, dec_insn.vA_);
2571 if (!RegTypeIsReference(value_type)) {
2572 LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
2573 << " into ref field '"
2574 << inst_field->GetName()->ToModifiedUtf8() << "' ("
2575 << field_class->GetDescriptor()->ToModifiedUtf8() << ")";
2576 failure = VERIFY_ERROR_GENERIC;
2577 break;
2578 }
2579 if (value_type != kRegTypeZero) {
2580 value_class = RegTypeInitializedReferenceToClass(value_type);
2581 if (value_class == NULL) {
2582 LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
2583 << " into ref field";
2584 failure = VERIFY_ERROR_GENERIC;
2585 break;
2586 }
2587 /* allow if field is any interface or field is base class */
2588 if (!field_class->IsInterface() &&
2589 !field_class->IsAssignableFrom(value_class)) {
2590 Class* inst_field_class = inst_field->GetDeclaringClass();
2591 LOG(ERROR) << "VFY: storing type '"
2592 << value_class->GetDescriptor()->ToModifiedUtf8()
2593 << "' into field type '"
2594 << field_class->GetDescriptor()->ToModifiedUtf8()
2595 << "' ("
2596 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2597 << "." << inst_field->GetName()->ToModifiedUtf8() << ")";
2598 failure = VERIFY_ERROR_GENERIC;
2599 break;
2600 }
2601 }
2602 }
2603 break;
2604
2605 case Instruction::SGET:
2606 tmp_type = kRegTypeInteger;
2607 goto sget_1nr_common;
2608 case Instruction::SGET_BOOLEAN:
2609 tmp_type = kRegTypeBoolean;
2610 goto sget_1nr_common;
2611 case Instruction::SGET_BYTE:
2612 tmp_type = kRegTypeByte;
2613 goto sget_1nr_common;
2614 case Instruction::SGET_CHAR:
2615 tmp_type = kRegTypeChar;
2616 goto sget_1nr_common;
2617 case Instruction::SGET_SHORT:
2618 tmp_type = kRegTypeShort;
2619 goto sget_1nr_common;
2620sget_1nr_common:
2621 {
2622 Field* static_field;
2623 RegType field_type;
2624
2625 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2626 if (failure != VERIFY_ERROR_NONE)
2627 break;
2628
2629 /*
2630 * Make sure the field's type is compatible with expectation.
2631 * We can get ourselves into trouble if we mix & match loads
2632 * and stores with different widths, so rather than just checking
2633 * "CanConvertTo1nr" we require that the field types have equal
2634 * widths.
2635 */
2636 field_type =
2637 PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
2638
2639 /* correct if float */
2640 if (field_type == kRegTypeFloat)
2641 tmp_type = kRegTypeFloat;
2642
2643 if (tmp_type != field_type) {
2644 Class* static_field_class = static_field->GetDeclaringClass();
2645 LOG(ERROR) << "VFY: invalid sget-1nr of "
2646 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2647 << "." << static_field->GetName()->ToModifiedUtf8()
2648 << " (inst=" << tmp_type << " actual=" << field_type
2649 << ")";
2650 failure = VERIFY_ERROR_GENERIC;
2651 break;
2652 }
2653
2654 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2655 }
2656 break;
2657 case Instruction::SGET_WIDE:
2658 {
2659 Field* static_field;
2660 RegType dst_type;
2661
2662 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2663 Class* static_field_class = static_field->GetDeclaringClass();
2664 if (failure != VERIFY_ERROR_NONE)
2665 break;
2666 /* check the type, which should be prim */
2667 switch (static_field->GetType()->GetPrimitiveType()) {
2668 case Class::kPrimDouble:
2669 dst_type = kRegTypeDoubleLo;
2670 break;
2671 case Class::kPrimLong:
2672 dst_type = kRegTypeLongLo;
2673 break;
2674 default:
2675 LOG(ERROR) << "VFY: invalid sget-wide of "
2676 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2677 << "." << static_field->GetName()->ToModifiedUtf8();
2678 dst_type = kRegTypeUnknown;
2679 failure = VERIFY_ERROR_GENERIC;
2680 break;
2681 }
2682 if (failure == VERIFY_ERROR_NONE) {
2683 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2684 }
2685 }
2686 break;
2687 case Instruction::SGET_OBJECT:
2688 {
2689 Field* static_field;
2690 Class* field_class;
2691
2692 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2693 if (failure != VERIFY_ERROR_NONE)
2694 break;
2695 field_class = static_field->GetType();
2696 if (field_class == NULL) {
2697 LOG(ERROR) << "VFY: unable to recover field class from '"
2698 << static_field->GetName()->ToModifiedUtf8() << "'";
2699 failure = VERIFY_ERROR_GENERIC;
2700 break;
2701 }
2702 if (field_class->IsPrimitive()) {
2703 LOG(ERROR) << "VFY: attempt to get prim field with sget-object";
2704 failure = VERIFY_ERROR_GENERIC;
2705 break;
2706 }
2707 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(field_class));
2708 }
2709 break;
2710 case Instruction::SPUT:
2711 tmp_type = kRegTypeInteger;
2712 goto sput_1nr_common;
2713 case Instruction::SPUT_BOOLEAN:
2714 tmp_type = kRegTypeBoolean;
2715 goto sput_1nr_common;
2716 case Instruction::SPUT_BYTE:
2717 tmp_type = kRegTypeByte;
2718 goto sput_1nr_common;
2719 case Instruction::SPUT_CHAR:
2720 tmp_type = kRegTypeChar;
2721 goto sput_1nr_common;
2722 case Instruction::SPUT_SHORT:
2723 tmp_type = kRegTypeShort;
2724 goto sput_1nr_common;
2725sput_1nr_common:
2726 {
2727 RegType src_type, field_type;
2728 Field* static_field;
2729
2730 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2731 if (failure != VERIFY_ERROR_NONE)
2732 break;
2733 CheckFinalFieldAccess(method, static_field, &failure);
2734 if (failure != VERIFY_ERROR_NONE)
2735 break;
2736
2737 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002738 * Get type of field we're storing into. We know that the
jeffhaobdb76512011-09-07 11:43:16 -07002739 * contents of the register match the instruction, but we also
2740 * need to ensure that the instruction matches the field type.
2741 * Using e.g. sput-short to write into a 32-bit integer field
2742 * can lead to trouble if we do 16-bit writes.
2743 */
2744 field_type =
2745 PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
2746 src_type = GetRegisterType(work_line, dec_insn.vA_);
2747
2748 /* correct if float */
2749 if (field_type == kRegTypeFloat)
2750 tmp_type = kRegTypeFloat;
2751
2752 /*
2753 * compiler can generate synthetic functions that write byte values
2754 * into boolean fields.
2755 */
2756 if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
2757 tmp_type = kRegTypeByte;
2758 if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
2759 field_type = kRegTypeByte;
2760
2761 /* make sure the source register has the correct type */
2762 if (!CanConvertTo1nr(src_type, tmp_type)) {
2763 LOG(ERROR) << "VFY: invalid reg type " << src_type
2764 << " on sput instr (need " << tmp_type << ")";
2765 failure = VERIFY_ERROR_GENERIC;
2766 break;
2767 }
2768
2769 VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);
2770
2771 if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
2772 tmp_type != field_type) {
2773 Class* static_field_class = static_field->GetDeclaringClass();
2774 LOG(ERROR) << "VFY: invalid sput-1nr of "
2775 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2776 << "." << static_field->GetName()->ToModifiedUtf8()
2777 << " (inst=" << tmp_type << " actual=" << field_type
2778 << ")";
2779 failure = VERIFY_ERROR_GENERIC;
2780 break;
2781 }
2782 }
2783 break;
2784 case Instruction::SPUT_WIDE:
2785 Field* static_field;
2786
2787 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2788 if (failure != VERIFY_ERROR_NONE)
2789 break;
2790 CheckFinalFieldAccess(method, static_field, &failure);
2791 if (failure != VERIFY_ERROR_NONE)
2792 break;
2793
2794 /* check the type, which should be prim */
2795 switch (static_field->GetType()->GetPrimitiveType()) {
2796 case Class::kPrimDouble:
2797 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2798 &failure);
2799 break;
2800 case Class::kPrimLong:
2801 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
2802 break;
2803 default:
2804 LOG(ERROR) << "VFY: invalid sput-wide of "
2805 << static_field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
2806 << "." << static_field->GetName()->ToModifiedUtf8();
2807 failure = VERIFY_ERROR_GENERIC;
2808 break;
2809 }
2810 break;
2811 case Instruction::SPUT_OBJECT:
2812 {
2813 Class* field_class;
2814 Class* value_class;
2815 Field* static_field;
2816 RegType value_type;
2817
2818 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2819 if (failure != VERIFY_ERROR_NONE)
2820 break;
2821 CheckFinalFieldAccess(method, static_field, &failure);
2822 if (failure != VERIFY_ERROR_NONE)
2823 break;
2824
2825 field_class = static_field->GetType();
2826 if (field_class == NULL) {
2827 LOG(ERROR) << "VFY: unable to recover field class from '"
2828 << static_field->GetName()->ToModifiedUtf8() << "'";
2829 failure = VERIFY_ERROR_GENERIC;
2830 break;
2831 }
2832
2833 value_type = GetRegisterType(work_line, dec_insn.vA_);
2834 if (!RegTypeIsReference(value_type)) {
2835 LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
2836 << " into ref field '"
2837 << static_field->GetName()->ToModifiedUtf8() << "' ("
2838 << field_class->GetDescriptor()->ToModifiedUtf8() << ")",
2839 failure = VERIFY_ERROR_GENERIC;
2840 break;
2841 }
2842 if (value_type != kRegTypeZero) {
2843 value_class = RegTypeInitializedReferenceToClass(value_type);
2844 if (value_class == NULL) {
2845 LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
2846 << " into ref field";
2847 failure = VERIFY_ERROR_GENERIC;
2848 break;
2849 }
2850 /* allow if field is any interface or field is base class */
2851 if (!field_class->IsInterface() &&
2852 !field_class->IsAssignableFrom(value_class)) {
2853 Class* static_field_class = static_field->GetDeclaringClass();
2854 LOG(ERROR) << "VFY: storing type '"
2855 << value_class->GetDescriptor()->ToModifiedUtf8()
2856 << "' into field type '"
2857 << field_class->GetDescriptor()->ToModifiedUtf8()
2858 << "' ("
2859 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2860 << "." << static_field->GetName()->ToModifiedUtf8()
2861 << ")",
2862 failure = VERIFY_ERROR_GENERIC;
2863 break;
2864 }
2865 }
2866 }
2867 break;
2868
2869 case Instruction::INVOKE_VIRTUAL:
2870 case Instruction::INVOKE_VIRTUAL_RANGE:
2871 case Instruction::INVOKE_SUPER:
2872 case Instruction::INVOKE_SUPER_RANGE:
2873 {
2874 Method* called_method;
2875 RegType return_type;
2876 bool is_range;
2877 bool is_super;
2878
2879 is_range = (dec_insn.opcode_ == Instruction::INVOKE_VIRTUAL_RANGE ||
2880 dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
2881 is_super = (dec_insn.opcode_ == Instruction::INVOKE_SUPER ||
2882 dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
2883
2884 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2885 &dec_insn, METHOD_VIRTUAL, is_range, is_super, &failure);
2886 if (failure != VERIFY_ERROR_NONE)
2887 break;
2888 return_type = GetMethodReturnType(dex_file, called_method);
2889 SetResultRegisterType(work_line, registers_size, return_type);
2890 just_set_result = true;
2891 }
2892 break;
2893 case Instruction::INVOKE_DIRECT:
2894 case Instruction::INVOKE_DIRECT_RANGE:
2895 {
2896 RegType return_type;
2897 Method* called_method;
2898 bool is_range;
2899
2900 is_range = (dec_insn.opcode_ == Instruction::INVOKE_DIRECT_RANGE);
2901 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2902 &dec_insn, METHOD_DIRECT, is_range, false, &failure);
2903 if (failure != VERIFY_ERROR_NONE)
2904 break;
2905
2906 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002907 * Some additional checks when calling <init>. We know from
jeffhaobdb76512011-09-07 11:43:16 -07002908 * the invocation arg check that the "this" argument is an
jeffhaod1f0fde2011-09-08 17:25:33 -07002909 * instance of called_method->klass. Now we further restrict
jeffhaobdb76512011-09-07 11:43:16 -07002910 * that to require that called_method->klass is the same as
2911 * this->klass or this->super, allowing the latter only if
2912 * the "this" argument is the same as the "this" argument to
2913 * this method (which implies that we're in <init> ourselves).
2914 */
2915 if (IsInitMethod(called_method)) {
2916 RegType this_type;
2917 this_type = GetInvocationThis(work_line, &dec_insn, &failure);
2918 if (failure != VERIFY_ERROR_NONE)
2919 break;
2920
2921 /* no null refs allowed (?) */
2922 if (this_type == kRegTypeZero) {
2923 LOG(ERROR) << "VFY: unable to initialize null ref";
2924 failure = VERIFY_ERROR_GENERIC;
2925 break;
2926 }
2927
2928 Class* this_class;
2929
2930 this_class = RegTypeReferenceToClass(this_type, uninit_map);
2931 assert(this_class != NULL);
2932
2933 /* must be in same class or in superclass */
2934 if (called_method->GetDeclaringClass() == this_class->GetSuperClass())
2935 {
2936 if (this_class != method->GetDeclaringClass()) {
2937 LOG(ERROR) << "VFY: invoke-direct <init> on super only "
2938 << "allowed for 'this' in <init>";
2939 failure = VERIFY_ERROR_GENERIC;
2940 break;
2941 }
2942 } else if (called_method->GetDeclaringClass() != this_class) {
2943 LOG(ERROR) << "VFY: invoke-direct <init> must be on current "
2944 << "class or super";
2945 failure = VERIFY_ERROR_GENERIC;
2946 break;
2947 }
2948
2949 /* arg must be an uninitialized reference */
2950 if (!RegTypeIsUninitReference(this_type)) {
2951 LOG(ERROR) << "VFY: can only initialize the uninitialized";
2952 failure = VERIFY_ERROR_GENERIC;
2953 break;
2954 }
2955
2956 /*
2957 * Replace the uninitialized reference with an initialized
jeffhaod1f0fde2011-09-08 17:25:33 -07002958 * one, and clear the entry in the uninit map. We need to
jeffhaobdb76512011-09-07 11:43:16 -07002959 * do this for all registers that have the same object
2960 * instance in them, not just the "this" register.
2961 */
2962 MarkRefsAsInitialized(work_line, registers_size, uninit_map,
2963 this_type, &failure);
2964 if (failure != VERIFY_ERROR_NONE)
2965 break;
2966 }
2967 return_type = GetMethodReturnType(dex_file, called_method);
2968 SetResultRegisterType(work_line, registers_size, return_type);
2969 just_set_result = true;
2970 }
2971 break;
2972 case Instruction::INVOKE_STATIC:
2973 case Instruction::INVOKE_STATIC_RANGE:
2974 {
2975 RegType return_type;
2976 Method* called_method;
2977 bool is_range;
2978
2979 is_range = (dec_insn.opcode_ == Instruction::INVOKE_STATIC_RANGE);
2980 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2981 &dec_insn, METHOD_STATIC, is_range, false, &failure);
2982 if (failure != VERIFY_ERROR_NONE)
2983 break;
2984
2985 return_type = GetMethodReturnType(dex_file, called_method);
2986 SetResultRegisterType(work_line, registers_size, return_type);
2987 just_set_result = true;
2988 }
2989 break;
2990 case Instruction::INVOKE_INTERFACE:
2991 case Instruction::INVOKE_INTERFACE_RANGE:
2992 {
2993 RegType /*this_type,*/ return_type;
2994 Method* abs_method;
2995 bool is_range;
2996
2997 is_range = (dec_insn.opcode_ == Instruction::INVOKE_INTERFACE_RANGE);
2998 abs_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2999 &dec_insn, METHOD_INTERFACE, is_range, false, &failure);
3000 if (failure != VERIFY_ERROR_NONE)
3001 break;
3002
3003#if 0 /* can't do this here, fails on dalvik test 052-verifier-fun */
3004 /*
3005 * Get the type of the "this" arg, which should always be an
jeffhaod1f0fde2011-09-08 17:25:33 -07003006 * interface class. Because we don't do a full merge on
jeffhaobdb76512011-09-07 11:43:16 -07003007 * interface classes, this might have reduced to Object.
3008 */
3009 this_type = GetInvocationThis(work_line, &dec_insn, &failure);
3010 if (failure != VERIFY_ERROR_NONE)
3011 break;
3012
3013 if (this_type == kRegTypeZero) {
3014 /* null pointer always passes (and always fails at runtime) */
3015 } else {
3016 Class* this_class;
3017
3018 this_class = RegTypeInitializedReferenceToClass(this_type);
3019 if (this_class == NULL) {
3020 LOG(ERROR) << "VFY: interface call on uninitialized";
3021 failure = VERIFY_ERROR_GENERIC;
3022 break;
3023 }
3024
3025 /*
3026 * Either "this_class" needs to be the interface class that
3027 * defined abs_method, or abs_method's class needs to be one
jeffhaod1f0fde2011-09-08 17:25:33 -07003028 * of the interfaces implemented by "this_class". (Or, if
jeffhaobdb76512011-09-07 11:43:16 -07003029 * we couldn't complete the merge, this will be Object.)
3030 */
3031 if (this_class != abs_method->GetDeclaringClass() &&
3032 this_class != class_linker->FindSystemClass("Ljava/lang/Object;") &&
3033 !this_class->Implements(abs_method->GetDeclaringClass())) {
3034 LOG(ERROR) << "VFY: unable to match abs_method '"
3035 << abs_method->GetName()->ToModifiedUtf8() << "' with "
3036 << this_class->GetDescriptor()->ToModifiedUtf8()
3037 << " interfaces";
3038 failure = VERIFY_ERROR_GENERIC;
3039 break;
3040 }
3041 }
3042#endif
3043
3044 /*
3045 * We don't have an object instance, so we can't find the
jeffhaod1f0fde2011-09-08 17:25:33 -07003046 * concrete method. However, all of the type information is
jeffhaobdb76512011-09-07 11:43:16 -07003047 * in the abstract method, so we're good.
3048 */
3049 return_type = GetMethodReturnType(dex_file, abs_method);
3050 SetResultRegisterType(work_line, registers_size, return_type);
3051 just_set_result = true;
3052 }
3053 break;
3054
3055 case Instruction::NEG_INT:
3056 case Instruction::NOT_INT:
3057 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3058 &failure);
3059 break;
3060 case Instruction::NEG_LONG:
3061 case Instruction::NOT_LONG:
3062 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo, &failure);
3063 break;
3064 case Instruction::NEG_FLOAT:
3065 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat, &failure);
3066 break;
3067 case Instruction::NEG_DOUBLE:
3068 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3069 &failure);
3070 break;
3071 case Instruction::INT_TO_LONG:
3072 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeInteger,
3073 &failure);
3074 break;
3075 case Instruction::INT_TO_FLOAT:
3076 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeInteger, &failure);
3077 break;
3078 case Instruction::INT_TO_DOUBLE:
3079 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeInteger,
3080 &failure);
3081 break;
3082 case Instruction::LONG_TO_INT:
3083 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeLongLo,
3084 &failure);
3085 break;
3086 case Instruction::LONG_TO_FLOAT:
3087 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeLongLo, &failure);
3088 break;
3089 case Instruction::LONG_TO_DOUBLE:
3090 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeLongLo,
3091 &failure);
3092 break;
3093 case Instruction::FLOAT_TO_INT:
3094 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeFloat, &failure);
3095 break;
3096 case Instruction::FLOAT_TO_LONG:
3097 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeFloat, &failure);
3098 break;
3099 case Instruction::FLOAT_TO_DOUBLE:
3100 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeFloat,
3101 &failure);
3102 break;
3103 case Instruction::DOUBLE_TO_INT:
3104 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeDoubleLo,
3105 &failure);
3106 break;
3107 case Instruction::DOUBLE_TO_LONG:
3108 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeDoubleLo,
3109 &failure);
3110 break;
3111 case Instruction::DOUBLE_TO_FLOAT:
3112 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeDoubleLo,
3113 &failure);
3114 break;
3115 case Instruction::INT_TO_BYTE:
3116 CheckUnop(work_line, &dec_insn, kRegTypeByte, kRegTypeInteger, &failure);
3117 break;
3118 case Instruction::INT_TO_CHAR:
3119 CheckUnop(work_line, &dec_insn, kRegTypeChar, kRegTypeInteger, &failure);
3120 break;
3121 case Instruction::INT_TO_SHORT:
3122 CheckUnop(work_line, &dec_insn, kRegTypeShort, kRegTypeInteger, &failure);
3123 break;
3124
3125 case Instruction::ADD_INT:
3126 case Instruction::SUB_INT:
3127 case Instruction::MUL_INT:
3128 case Instruction::REM_INT:
3129 case Instruction::DIV_INT:
3130 case Instruction::SHL_INT:
3131 case Instruction::SHR_INT:
3132 case Instruction::USHR_INT:
3133 CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3134 kRegTypeInteger, false, &failure);
3135 break;
3136 case Instruction::AND_INT:
3137 case Instruction::OR_INT:
3138 case Instruction::XOR_INT:
3139 CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3140 kRegTypeInteger, true, &failure);
3141 break;
3142 case Instruction::ADD_LONG:
3143 case Instruction::SUB_LONG:
3144 case Instruction::MUL_LONG:
3145 case Instruction::DIV_LONG:
3146 case Instruction::REM_LONG:
3147 case Instruction::AND_LONG:
3148 case Instruction::OR_LONG:
3149 case Instruction::XOR_LONG:
3150 CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3151 kRegTypeLongLo, false, &failure);
3152 break;
3153 case Instruction::SHL_LONG:
3154 case Instruction::SHR_LONG:
3155 case Instruction::USHR_LONG:
3156 /* shift distance is Int, making these different from other binops */
3157 CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3158 kRegTypeInteger, false, &failure);
3159 break;
3160 case Instruction::ADD_FLOAT:
3161 case Instruction::SUB_FLOAT:
3162 case Instruction::MUL_FLOAT:
3163 case Instruction::DIV_FLOAT:
3164 case Instruction::REM_FLOAT:
3165 CheckBinop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
3166 kRegTypeFloat, false, &failure);
3167 break;
3168 case Instruction::ADD_DOUBLE:
3169 case Instruction::SUB_DOUBLE:
3170 case Instruction::MUL_DOUBLE:
3171 case Instruction::DIV_DOUBLE:
3172 case Instruction::REM_DOUBLE:
3173 CheckBinop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3174 kRegTypeDoubleLo, false, &failure);
3175 break;
3176 case Instruction::ADD_INT_2ADDR:
3177 case Instruction::SUB_INT_2ADDR:
3178 case Instruction::MUL_INT_2ADDR:
3179 case Instruction::REM_INT_2ADDR:
3180 case Instruction::SHL_INT_2ADDR:
3181 case Instruction::SHR_INT_2ADDR:
3182 case Instruction::USHR_INT_2ADDR:
3183 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3184 kRegTypeInteger, false, &failure);
3185 break;
3186 case Instruction::AND_INT_2ADDR:
3187 case Instruction::OR_INT_2ADDR:
3188 case Instruction::XOR_INT_2ADDR:
3189 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3190 kRegTypeInteger, true, &failure);
3191 break;
3192 case Instruction::DIV_INT_2ADDR:
3193 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3194 kRegTypeInteger, false, &failure);
3195 break;
3196 case Instruction::ADD_LONG_2ADDR:
3197 case Instruction::SUB_LONG_2ADDR:
3198 case Instruction::MUL_LONG_2ADDR:
3199 case Instruction::DIV_LONG_2ADDR:
3200 case Instruction::REM_LONG_2ADDR:
3201 case Instruction::AND_LONG_2ADDR:
3202 case Instruction::OR_LONG_2ADDR:
3203 case Instruction::XOR_LONG_2ADDR:
3204 CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3205 kRegTypeLongLo, false, &failure);
3206 break;
3207 case Instruction::SHL_LONG_2ADDR:
3208 case Instruction::SHR_LONG_2ADDR:
3209 case Instruction::USHR_LONG_2ADDR:
3210 CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3211 kRegTypeInteger, false, &failure);
3212 break;
3213 case Instruction::ADD_FLOAT_2ADDR:
3214 case Instruction::SUB_FLOAT_2ADDR:
3215 case Instruction::MUL_FLOAT_2ADDR:
3216 case Instruction::DIV_FLOAT_2ADDR:
3217 case Instruction::REM_FLOAT_2ADDR:
3218 CheckBinop2addr(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
3219 kRegTypeFloat, false, &failure);
3220 break;
3221 case Instruction::ADD_DOUBLE_2ADDR:
3222 case Instruction::SUB_DOUBLE_2ADDR:
3223 case Instruction::MUL_DOUBLE_2ADDR:
3224 case Instruction::DIV_DOUBLE_2ADDR:
3225 case Instruction::REM_DOUBLE_2ADDR:
3226 CheckBinop2addr(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3227 kRegTypeDoubleLo, false, &failure);
3228 break;
3229 case Instruction::ADD_INT_LIT16:
3230 case Instruction::RSUB_INT:
3231 case Instruction::MUL_INT_LIT16:
3232 case Instruction::DIV_INT_LIT16:
3233 case Instruction::REM_INT_LIT16:
3234 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
3235 &failure);
3236 break;
3237 case Instruction::AND_INT_LIT16:
3238 case Instruction::OR_INT_LIT16:
3239 case Instruction::XOR_INT_LIT16:
3240 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
3241 &failure);
3242 break;
3243 case Instruction::ADD_INT_LIT8:
3244 case Instruction::RSUB_INT_LIT8:
3245 case Instruction::MUL_INT_LIT8:
3246 case Instruction::DIV_INT_LIT8:
3247 case Instruction::REM_INT_LIT8:
3248 case Instruction::SHL_INT_LIT8:
3249 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
3250 &failure);
3251 break;
3252 case Instruction::SHR_INT_LIT8:
3253 tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
3254 false, &failure);
3255 CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
3256 &failure);
3257 break;
3258 case Instruction::USHR_INT_LIT8:
3259 tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
3260 true, &failure);
3261 CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
3262 &failure);
3263 break;
3264 case Instruction::AND_INT_LIT8:
3265 case Instruction::OR_INT_LIT8:
3266 case Instruction::XOR_INT_LIT8:
3267 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
3268 &failure);
3269 break;
3270
3271 /*
3272 * This falls into the general category of "optimized" instructions,
jeffhaod1f0fde2011-09-08 17:25:33 -07003273 * which don't generally appear during verification. Because it's
jeffhaobdb76512011-09-07 11:43:16 -07003274 * inserted in the course of verification, we can expect to see it here.
3275 */
3276 //case Instruction::THROW_VERIFICATION_ERROR:
3277 case Instruction::UNUSED_ED:
3278 break;
3279
3280 /*
3281 * Verifying "quickened" instructions is tricky, because we have
jeffhaod1f0fde2011-09-08 17:25:33 -07003282 * discarded the original field/method information. The byte offsets
jeffhaobdb76512011-09-07 11:43:16 -07003283 * and vtable indices only have meaning in the context of an object
3284 * instance.
3285 *
3286 * If a piece of code declares a local reference variable, assigns
3287 * null to it, and then issues a virtual method call on it, we
jeffhaod1f0fde2011-09-08 17:25:33 -07003288 * cannot evaluate the method call during verification. This situation
jeffhaobdb76512011-09-07 11:43:16 -07003289 * isn't hard to handle, since we know the call will always result in an
jeffhaod1f0fde2011-09-08 17:25:33 -07003290 * NPE, and the arguments and return value don't matter. Any code that
jeffhaobdb76512011-09-07 11:43:16 -07003291 * depends on the result of the method call is inaccessible, so the
3292 * fact that we can't fully verify anything that comes after the bad
3293 * call is not a problem.
3294 *
3295 * We must also consider the case of multiple code paths, only some of
jeffhaod1f0fde2011-09-08 17:25:33 -07003296 * which involve a null reference. We can completely verify the method
jeffhaobdb76512011-09-07 11:43:16 -07003297 * if we sidestep the results of executing with a null reference.
3298 * For example, if on the first pass through the code we try to do a
3299 * virtual method invocation through a null ref, we have to skip the
3300 * method checks and have the method return a "wildcard" type (which
jeffhaod1f0fde2011-09-08 17:25:33 -07003301 * merges with anything to become that other thing). The move-result
jeffhaobdb76512011-09-07 11:43:16 -07003302 * will tell us if it's a reference, single-word numeric, or double-word
jeffhaod1f0fde2011-09-08 17:25:33 -07003303 * value. We continue to perform the verification, and at the end of
jeffhaobdb76512011-09-07 11:43:16 -07003304 * the function any invocations that were never fully exercised are
3305 * marked as null-only.
3306 *
jeffhaod1f0fde2011-09-08 17:25:33 -07003307 * We would do something similar for the field accesses. The field's
jeffhaobdb76512011-09-07 11:43:16 -07003308 * type, once known, can be used to recover the width of short integers.
3309 * If the object reference was null, the field-get returns the "wildcard"
3310 * type, which is acceptable for any operation.
3311 */
3312 case Instruction::UNUSED_EE:
3313 case Instruction::UNUSED_EF:
3314 case Instruction::UNUSED_F2:
3315 case Instruction::UNUSED_F3:
3316 case Instruction::UNUSED_F4:
3317 case Instruction::UNUSED_F5:
3318 case Instruction::UNUSED_F6:
3319 case Instruction::UNUSED_F7:
3320 case Instruction::UNUSED_F8:
3321 case Instruction::UNUSED_F9:
3322 case Instruction::UNUSED_FA:
3323 case Instruction::UNUSED_FB:
3324 //case Instruction::EXECUTE_INLINE:
3325 //case Instruction::EXECUTE_INLINE_RANGE:
3326 //case Instruction::IGET_QUICK:
3327 //case Instruction::IGET_WIDE_QUICK:
3328 //case Instruction::IGET_OBJECT_QUICK:
3329 //case Instruction::IPUT_QUICK:
3330 //case Instruction::IPUT_WIDE_QUICK:
3331 //case Instruction::IPUT_OBJECT_QUICK:
3332 //case Instruction::INVOKE_VIRTUAL_QUICK:
3333 //case Instruction::INVOKE_VIRTUAL_QUICK_RANGE:
3334 //case Instruction::INVOKE_SUPER_QUICK:
3335 //case Instruction::INVOKE_SUPER_QUICK_RANGE:
3336 /* fall through to failure */
3337
3338 /*
3339 * These instructions are equivalent (from the verifier's point of view)
jeffhaod1f0fde2011-09-08 17:25:33 -07003340 * to the original form. The change was made for correctness rather
jeffhaobdb76512011-09-07 11:43:16 -07003341 * than improved performance (except for invoke-object-init, which
jeffhaod1f0fde2011-09-08 17:25:33 -07003342 * provides both). The substitution takes place after verification
jeffhaobdb76512011-09-07 11:43:16 -07003343 * completes, though, so we don't expect to see them here.
3344 */
3345 case Instruction::UNUSED_F0:
3346 case Instruction::UNUSED_F1:
3347 case Instruction::UNUSED_E3:
3348 case Instruction::UNUSED_E8:
3349 case Instruction::UNUSED_E7:
3350 case Instruction::UNUSED_E4:
3351 case Instruction::UNUSED_E9:
3352 case Instruction::UNUSED_FC:
3353 case Instruction::UNUSED_E5:
3354 case Instruction::UNUSED_EA:
3355 case Instruction::UNUSED_FD:
3356 case Instruction::UNUSED_E6:
3357 case Instruction::UNUSED_EB:
3358 case Instruction::UNUSED_FE:
3359 //case Instruction::INVOKE_OBJECT_INIT_RANGE:
3360 //case Instruction::RETURN_VOID_BARRIER:
3361 //case Instruction::IGET_VOLATILE:
3362 //case Instruction::IGET_WIDE_VOLATILE:
3363 //case Instruction::IGET_OBJECT_VOLATILE:
3364 //case Instruction::IPUT_VOLATILE:
3365 //case Instruction::IPUT_WIDE_VOLATILE:
3366 //case Instruction::IPUT_OBJECT_VOLATILE:
3367 //case Instruction::SGET_VOLATILE:
3368 //case Instruction::SGET_WIDE_VOLATILE:
3369 //case Instruction::SGET_OBJECT_VOLATILE:
3370 //case Instruction::SPUT_VOLATILE:
3371 //case Instruction::SPUT_WIDE_VOLATILE:
3372 //case Instruction::SPUT_OBJECT_VOLATILE:
3373 /* fall through to failure */
3374
3375 /* These should never appear during verification. */
3376 case Instruction::UNUSED_3E:
3377 case Instruction::UNUSED_3F:
3378 case Instruction::UNUSED_40:
3379 case Instruction::UNUSED_41:
3380 case Instruction::UNUSED_42:
3381 case Instruction::UNUSED_43:
3382 case Instruction::UNUSED_73:
3383 case Instruction::UNUSED_79:
3384 case Instruction::UNUSED_7A:
3385 case Instruction::UNUSED_EC:
3386 case Instruction::UNUSED_FF:
3387 //case Instruction::BREAKPOINT:
3388 //case Instruction::DISPATCH_FF:
3389 failure = VERIFY_ERROR_GENERIC;
3390 break;
3391
3392 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003393 * DO NOT add a "default" clause here. Without it the compiler will
jeffhaobdb76512011-09-07 11:43:16 -07003394 * complain if an instruction is missing (which is desirable).
3395 */
3396 }
3397
3398 if (failure != VERIFY_ERROR_NONE) {
jeffhaobdb76512011-09-07 11:43:16 -07003399 if (failure == VERIFY_ERROR_GENERIC) {
3400 /* immediate failure, reject class */
3401 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
3402 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3403 return false;
3404 } else {
jeffhao98eacac2011-09-14 16:11:53 -07003405 // TODO: CHECK IF THIS WILL WORK!
3406 /* ignore the failure and move on */
3407 LOG(ERROR) << "VFY: failing opcode 0x" << std::hex
3408 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3409 failure = VERIFY_ERROR_NONE;
3410#if 0
jeffhaobdb76512011-09-07 11:43:16 -07003411 /* replace opcode and continue on */
3412 LOG(ERROR) << "VFY: replacing opcode 0x" << std::hex
3413 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3414 if (!ReplaceFailingInstruction(code_item, insn_flags, insn_idx, failure))
3415 {
3416 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
3417 << (int) dec_insn.opcode_ << " at 0x" << insn_idx
3418 << std::dec;
3419 return false;
3420 }
3421 /* IMPORTANT: method->insns may have been changed */
3422 insns = code_item->insns_ + insn_idx;
3423
3424 /* continue on as if we just handled a throw-verification-error */
3425 failure = VERIFY_ERROR_NONE;
3426 opcode_flag = Instruction::kThrow;
jeffhao98eacac2011-09-14 16:11:53 -07003427#endif
jeffhaobdb76512011-09-07 11:43:16 -07003428 }
3429 }
3430
3431 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003432 * If we didn't just set the result register, clear it out. This
jeffhaobdb76512011-09-07 11:43:16 -07003433 * ensures that you can only use "move-result" immediately after the
jeffhaod1f0fde2011-09-08 17:25:33 -07003434 * result is set. (We could check this statically, but it's not
jeffhaobdb76512011-09-07 11:43:16 -07003435 * expensive and it makes our debugging output cleaner.)
3436 */
3437 if (!just_set_result) {
3438 int reg = RESULT_REGISTER(registers_size);
3439 SetRegisterType(work_line, reg, kRegTypeUnknown);
3440 SetRegisterType(work_line, reg + 1, kRegTypeUnknown);
3441 }
3442
3443 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003444 * Handle "continue". Tag the next consecutive instruction.
jeffhaobdb76512011-09-07 11:43:16 -07003445 */
3446 if ((opcode_flag & Instruction::kContinue) != 0) {
3447 size_t insn_width = InsnGetWidth(insn_flags, insn_idx);
3448 if (insn_idx + insn_width >= insns_size) {
3449 LOG(ERROR) << "VFY: execution can walk off end of code area (from 0x"
3450 << std::hex << insn_idx << std::dec << ")";
3451 return false;
3452 }
3453
3454 /*
3455 * The only way to get to a move-exception instruction is to get
jeffhaod1f0fde2011-09-08 17:25:33 -07003456 * thrown there. Make sure the next instruction isn't one.
jeffhaobdb76512011-09-07 11:43:16 -07003457 */
3458 if (!CheckMoveException(code_item->insns_, insn_idx + insn_width))
3459 return false;
3460
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003461 if (GetRegisterLine(reg_table, insn_idx + insn_width)->reg_types_.get() != NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003462 /*
3463 * Merge registers into what we have for the next instruction,
3464 * and set the "changed" flag if needed.
3465 */
3466 if (!UpdateRegisters(insn_flags, reg_table, insn_idx + insn_width,
3467 work_line))
3468 return false;
3469 } else {
3470 /*
3471 * We're not recording register data for the next instruction,
jeffhaod1f0fde2011-09-08 17:25:33 -07003472 * so we don't know what the prior state was. We have to
jeffhaobdb76512011-09-07 11:43:16 -07003473 * assume that something has changed and re-evaluate it.
3474 */
3475 InsnSetChanged(insn_flags, insn_idx + insn_width, true);
3476 }
3477 }
3478
3479 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003480 * Handle "branch". Tag the branch target.
jeffhaobdb76512011-09-07 11:43:16 -07003481 *
3482 * NOTE: instructions like Instruction::EQZ provide information about the
jeffhaod1f0fde2011-09-08 17:25:33 -07003483 * state of the register when the branch is taken or not taken. For example,
jeffhaobdb76512011-09-07 11:43:16 -07003484 * somebody could get a reference field, check it for zero, and if the
3485 * branch is taken immediately store that register in a boolean field
jeffhaod1f0fde2011-09-08 17:25:33 -07003486 * since the value is known to be zero. We do not currently account for
jeffhaobdb76512011-09-07 11:43:16 -07003487 * that, and will reject the code.
3488 *
3489 * TODO: avoid re-fetching the branch target
3490 */
3491 if ((opcode_flag & Instruction::kBranch) != 0) {
3492 bool isConditional, selfOkay;
3493
3494 if (!GetBranchOffset(code_item, insn_flags, insn_idx, &branch_target,
3495 &isConditional, &selfOkay)) {
3496 /* should never happen after static verification */
3497 LOG(ERROR) << "VFY: bad branch at 0x" << std::hex << insn_idx << std::dec;
3498 return false;
3499 }
3500 assert(isConditional || (opcode_flag & Instruction::kContinue) == 0);
3501 assert(!isConditional || (opcode_flag & Instruction::kContinue) != 0);
3502
3503 if (!CheckMoveException(code_item->insns_, insn_idx + branch_target))
3504 return false;
3505
3506 /* update branch target, set "changed" if appropriate */
3507 if (!UpdateRegisters(insn_flags, reg_table, insn_idx + branch_target,
3508 work_line))
3509 return false;
3510 }
3511
3512 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003513 * Handle "switch". Tag all possible branch targets.
jeffhaobdb76512011-09-07 11:43:16 -07003514 *
3515 * We've already verified that the table is structurally sound, so we
3516 * just need to walk through and tag the targets.
3517 */
3518 if ((opcode_flag & Instruction::kSwitch) != 0) {
3519 int offset_to_switch = insns[1] | (((int32_t) insns[2]) << 16);
3520 const uint16_t* switch_insns = insns + offset_to_switch;
3521 int switch_count = switch_insns[1];
3522 int offset_to_targets, targ;
3523
3524 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
3525 /* 0 = sig, 1 = count, 2/3 = first key */
3526 offset_to_targets = 4;
3527 } else {
3528 /* 0 = sig, 1 = count, 2..count * 2 = keys */
3529 assert((*insns & 0xff) == Instruction::SPARSE_SWITCH);
3530 offset_to_targets = 2 + 2 * switch_count;
3531 }
3532
3533 /* verify each switch target */
3534 for (targ = 0; targ < switch_count; targ++) {
3535 int offset;
3536 uint32_t abs_offset;
3537
3538 /* offsets are 32-bit, and only partly endian-swapped */
3539 offset = switch_insns[offset_to_targets + targ * 2] |
3540 (((int32_t) switch_insns[offset_to_targets + targ * 2 + 1]) << 16);
3541 abs_offset = insn_idx + offset;
3542
3543 assert(abs_offset < insns_size);
3544
3545 if (!CheckMoveException(code_item->insns_, abs_offset))
3546 return false;
3547
3548 if (!UpdateRegisters(insn_flags, reg_table, abs_offset, work_line))
3549 return false;
3550 }
3551 }
3552
3553 /*
3554 * Handle instructions that can throw and that are sitting in a
jeffhaod1f0fde2011-09-08 17:25:33 -07003555 * "try" block. (If they're not in a "try" block when they throw,
jeffhaobdb76512011-09-07 11:43:16 -07003556 * control transfers out of the method.)
3557 */
3558 if ((opcode_flag & Instruction::kThrow) != 0 &&
3559 InsnIsInTry(insn_flags, insn_idx)) {
3560 bool has_catch_all = false;
3561 DexFile::CatchHandlerIterator iterator = DexFile::dexFindCatchHandler(
3562 *code_item, insn_idx);
3563
3564 for (; !iterator.HasNext(); iterator.Next()) {
3565 if (iterator.Get().type_idx_ == DexFile::kDexNoIndex)
3566 has_catch_all = true;
3567
3568 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003569 * Merge registers into the "catch" block. We want to use the
3570 * "savedRegs" rather than "work_regs", because at runtime the
3571 * exception will be thrown before the instruction modifies any
3572 * registers.
jeffhaobdb76512011-09-07 11:43:16 -07003573 */
3574 if (!UpdateRegisters(insn_flags, reg_table, iterator.Get().address_,
3575 &reg_table->saved_line_))
3576 return false;
3577 }
3578
3579 /*
3580 * If the monitor stack depth is nonzero, there must be a "catch all"
jeffhaod1f0fde2011-09-08 17:25:33 -07003581 * handler for this instruction. This does apply to monitor-exit
jeffhaobdb76512011-09-07 11:43:16 -07003582 * because of async exception handling.
3583 */
3584 if (work_line->monitor_stack_top_ != 0 && !has_catch_all) {
3585 /*
3586 * The state in work_line reflects the post-execution state.
3587 * If the current instruction is a monitor-enter and the monitor
3588 * stack was empty, we don't need a catch-all (if it throws,
3589 * it will do so before grabbing the lock).
3590 */
3591 if (!(dec_insn.opcode_ == Instruction::MONITOR_ENTER &&
3592 work_line->monitor_stack_top_ == 1))
3593 {
3594 LOG(ERROR) << "VFY: no catch-all for instruction at 0x" << std::hex
3595 << insn_idx << std::dec;
3596 return false;
3597 }
3598 }
3599 }
3600
jeffhaod1f0fde2011-09-08 17:25:33 -07003601 /* If we're returning from the method, make sure monitor stack is empty. */
jeffhaobdb76512011-09-07 11:43:16 -07003602 if ((opcode_flag & Instruction::kReturn) != 0 &&
3603 work_line->monitor_stack_top_ != 0) {
3604 LOG(ERROR) << "VFY: return with stack depth="
3605 << work_line->monitor_stack_top_ << " at 0x" << std::hex
3606 << insn_idx << std::dec;
3607 return false;
3608 }
3609
3610 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003611 * Update start_guess. Advance to the next instruction of that's
3612 * possible, otherwise use the branch target if one was found. If
jeffhaobdb76512011-09-07 11:43:16 -07003613 * neither of those exists we're in a return or throw; leave start_guess
3614 * alone and let the caller sort it out.
3615 */
3616 if ((opcode_flag & Instruction::kContinue) != 0) {
3617 *start_guess = insn_idx + InsnGetWidth(insn_flags, insn_idx);
3618 } else if ((opcode_flag & Instruction::kBranch) != 0) {
3619 /* we're still okay if branch_target is zero */
3620 *start_guess = insn_idx + branch_target;
3621 }
3622
3623 assert(*start_guess < insns_size &&
3624 InsnGetWidth(insn_flags, *start_guess) != 0);
3625
3626 return true;
3627}
3628
3629bool DexVerifier::ReplaceFailingInstruction(const DexFile::CodeItem* code_item,
3630 InsnFlags* insn_flags, int insn_idx, VerifyError failure) {
3631 const uint16_t* insns = code_item->insns_ + insn_idx;
3632 const byte* ptr = reinterpret_cast<const byte*>(insns);
3633 const Instruction* inst = Instruction::At(ptr);
3634 Instruction::Code opcode = inst->Opcode();
3635 VerifyErrorRefType ref_type;
3636
3637 /*
3638 * Generate the new instruction out of the old.
3639 *
3640 * First, make sure this is an instruction we're expecting to stomp on.
3641 */
3642 switch (opcode) {
3643 case Instruction::CONST_CLASS: // insn[1] == class ref, 2 bytes
3644 case Instruction::CHECK_CAST:
3645 case Instruction::INSTANCE_OF:
3646 case Instruction::NEW_INSTANCE:
3647 case Instruction::NEW_ARRAY:
3648 case Instruction::FILLED_NEW_ARRAY: // insn[1] == class ref, 3 bytes
3649 case Instruction::FILLED_NEW_ARRAY_RANGE:
3650 ref_type = VERIFY_ERROR_REF_CLASS;
3651 break;
3652
3653 case Instruction::IGET: // insn[1] == field ref, 2 bytes
3654 case Instruction::IGET_BOOLEAN:
3655 case Instruction::IGET_BYTE:
3656 case Instruction::IGET_CHAR:
3657 case Instruction::IGET_SHORT:
3658 case Instruction::IGET_WIDE:
3659 case Instruction::IGET_OBJECT:
3660 case Instruction::IPUT:
3661 case Instruction::IPUT_BOOLEAN:
3662 case Instruction::IPUT_BYTE:
3663 case Instruction::IPUT_CHAR:
3664 case Instruction::IPUT_SHORT:
3665 case Instruction::IPUT_WIDE:
3666 case Instruction::IPUT_OBJECT:
3667 case Instruction::SGET:
3668 case Instruction::SGET_BOOLEAN:
3669 case Instruction::SGET_BYTE:
3670 case Instruction::SGET_CHAR:
3671 case Instruction::SGET_SHORT:
3672 case Instruction::SGET_WIDE:
3673 case Instruction::SGET_OBJECT:
3674 case Instruction::SPUT:
3675 case Instruction::SPUT_BOOLEAN:
3676 case Instruction::SPUT_BYTE:
3677 case Instruction::SPUT_CHAR:
3678 case Instruction::SPUT_SHORT:
3679 case Instruction::SPUT_WIDE:
3680 case Instruction::SPUT_OBJECT:
3681 ref_type = VERIFY_ERROR_REF_FIELD;
3682 break;
3683
3684 case Instruction::INVOKE_VIRTUAL: // insn[1] == method ref, 3 bytes
3685 case Instruction::INVOKE_VIRTUAL_RANGE:
3686 case Instruction::INVOKE_SUPER:
3687 case Instruction::INVOKE_SUPER_RANGE:
3688 case Instruction::INVOKE_DIRECT:
3689 case Instruction::INVOKE_DIRECT_RANGE:
3690 case Instruction::INVOKE_STATIC:
3691 case Instruction::INVOKE_STATIC_RANGE:
3692 case Instruction::INVOKE_INTERFACE:
3693 case Instruction::INVOKE_INTERFACE_RANGE:
3694 ref_type = VERIFY_ERROR_REF_METHOD;
3695 break;
3696
3697 default:
3698 /* could handle this in a generic way, but this is probably safer */
3699 LOG(ERROR) << "GLITCH: verifier asked to replace opcode 0x" << std::hex
3700 << (int) opcode << std::dec;
3701 return false;
3702 }
3703
3704 assert(inst->IsThrow());
3705
3706 /* write a NOP over the third code unit, if necessary */
3707 int width = InsnGetWidth(insn_flags, insn_idx);
3708 switch (width) {
3709 case 2:
3710 /* nothing to do */
3711 break;
3712 case 3:
3713 // TODO: Add this functionality
3714 //UpdateCodeUnit(method, insns + 2, Instruction::NOP);
3715 break;
3716 default:
3717 /* whoops */
3718 LOG(FATAL) << "ERROR: stomped a " << width
3719 << "-unit instruction with a verifier error";
3720 }
3721
3722 /* encode the opcode, with the failure code in the high byte */
3723 // TODO: REPLACE FAILING OPCODES
3724 //assert(width == 2 || width == 3);
3725 //uint16_t new_val = Instruction::THROW_VERIFICATION_ERROR |
jeffhao98eacac2011-09-14 16:11:53 -07003726 //uint16_t new_val = Instruction::UNUSED_ED |
jeffhaobdb76512011-09-07 11:43:16 -07003727 //(failure << 8) | (ref_type << (8 + kVerifyErrorRefTypeShift));
3728 //UpdateCodeUnit(method, insns, new_val);
3729
3730 return true;
3731}
3732
3733/* Handle a monitor-enter instruction. */
3734void DexVerifier::HandleMonitorEnter(RegisterLine* work_line, uint32_t reg_idx,
3735 uint32_t insn_idx, VerifyError* failure) {
3736 if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
3737 LOG(ERROR) << "VFY: monitor-enter on non-object";
3738 *failure = VERIFY_ERROR_GENERIC;
3739 return;
3740 }
3741
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003742 if (work_line->monitor_entries_.get() == NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003743 return;
3744 }
3745
3746 if (work_line->monitor_stack_top_ == kMaxMonitorStackDepth) {
3747 LOG(ERROR) << "VFY: monitor-enter stack overflow (" << kMaxMonitorStackDepth
3748 << ")";
3749 *failure = VERIFY_ERROR_GENERIC;
3750 return;
3751 }
3752
3753 /*
3754 * Push an entry on the stack, and set a bit in the register flags to
3755 * indicate that it's associated with this register.
3756 */
3757 work_line->monitor_entries_[reg_idx] |= 1 << work_line->monitor_stack_top_;
3758 work_line->monitor_stack_[work_line->monitor_stack_top_++] = insn_idx;
3759}
3760
3761/* Handle a monitor-exit instruction. */
3762void DexVerifier::HandleMonitorExit(RegisterLine* work_line, uint32_t reg_idx,
3763 uint32_t insn_idx, VerifyError* failure) {
3764 if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
3765 LOG(ERROR) << "VFY: monitor-exit on non-object";
3766 *failure = VERIFY_ERROR_GENERIC;
3767 return;
3768 }
3769
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003770 if (work_line->monitor_entries_.get() == NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003771 return;
3772 }
3773
3774 if (work_line->monitor_stack_top_ == 0) {
3775 LOG(ERROR) << "VFY: monitor-exit stack underflow";
3776 *failure = VERIFY_ERROR_GENERIC;
3777 return;
3778 }
3779
3780 /*
3781 * Confirm that the entry at the top of the stack is associated with
jeffhaod1f0fde2011-09-08 17:25:33 -07003782 * the register. Pop the top entry off.
jeffhaobdb76512011-09-07 11:43:16 -07003783 */
3784 work_line->monitor_stack_top_--;
3785#ifdef BUG_3215458_FIXED
3786 /*
3787 * TODO: This code can safely be enabled if know we are working on
3788 * a dex file of format version 036 or later. (That is, we'll need to
3789 * add a check for the version number.)
3790 */
3791 if ((work_line->monitor_entries_[reg_idx] &
3792 (1 << work_line->monitor_stack_top_)) == 0) {
3793 LOG(ERROR) << "VFY: monitor-exit bit " << work_line->monitor_stack_top_
3794 << " not set: addr=0x" << std::hex << insn_idx << std::dec
3795 << " (bits[" << reg_idx << "]=" << std::hex
3796 << work_line->monitor_entries_[reg_idx] << std::dec << ")";
3797 *failure = VERIFY_ERROR_GENERIC;
3798 return;
3799 }
3800#endif
3801 work_line->monitor_stack_[work_line->monitor_stack_top_] = 0;
3802
3803 /* Clear the bit from the register flags. */
3804 work_line->monitor_entries_[reg_idx] &= ~(1 << work_line->monitor_stack_top_);
3805}
3806
3807Field* DexVerifier::GetInstField(VerifierData* vdata, RegType obj_type,
3808 int field_idx, VerifyError* failure) {
3809 Method* method = vdata->method_;
3810 const DexFile* dex_file = vdata->dex_file_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003811 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07003812 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3813 DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
3814 const ClassLoader* class_loader =
3815 method->GetDeclaringClass()->GetClassLoader();
3816 Field* field = NULL;
3817 Class* obj_class;
3818 bool must_be_local = false;
3819
3820 if (!RegTypeIsReference(obj_type)) {
3821 LOG(ERROR) << "VFY: attempt to access field in non-reference type "
3822 << obj_type;
3823 *failure = VERIFY_ERROR_GENERIC;
3824 return field;
3825 }
3826
3827 field = class_linker->ResolveField(*dex_file, field_idx, dex_cache,
3828 class_loader, false);
3829 if (field == NULL) {
3830 LOG(ERROR) << "VFY: unable to resolve instance field " << field_idx;
3831 return field;
3832 }
3833
3834 if (obj_type == kRegTypeZero)
3835 return field;
3836
3837 /*
3838 * Access to fields in uninitialized objects is allowed if this is
3839 * the <init> method for the object and the field in question is
3840 * declared by this class.
3841 */
3842 obj_class = RegTypeReferenceToClass(obj_type, uninit_map);
3843 assert(obj_class != NULL);
3844 if (RegTypeIsUninitReference(obj_type)) {
3845 if (!IsInitMethod(method) || method->GetDeclaringClass() != obj_class) {
3846 LOG(ERROR) << "VFY: attempt to access field via uninitialized ref";
3847 *failure = VERIFY_ERROR_GENERIC;
3848 return field;
3849 }
3850 must_be_local = true;
3851 }
3852
jeffhaobdb76512011-09-07 11:43:16 -07003853 if (!field->GetDeclaringClass()->IsAssignableFrom(obj_class)) {
3854 LOG(ERROR) << "VFY: invalid field access (field "
3855 << field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
3856 << "." << field->GetName()->ToModifiedUtf8() << ", through "
3857 << obj_class->GetDescriptor()->ToModifiedUtf8() << " ref)";
3858 *failure = VERIFY_ERROR_NO_FIELD;
3859 return field;
3860 }
3861
3862 if (must_be_local) {
3863 bool found = false;
3864 /* for uninit ref, make sure it's defined by this class, not super */
3865 for (uint32_t i = 0; i < obj_class->NumInstanceFields(); i++) {
3866 found |= (field == obj_class->GetInstanceField(i));
3867 }
3868 if (!found) {
3869 LOG(ERROR) << "VFY: invalid constructor field access (field "
3870 << field->GetName()->ToModifiedUtf8() << " in "
3871 << obj_class->GetDescriptor()->ToModifiedUtf8() << ")";
3872 *failure = VERIFY_ERROR_GENERIC;
3873 return field;
3874 }
3875 }
3876
3877 return field;
3878}
3879
3880Field* DexVerifier::GetStaticField(VerifierData* vdata, int field_idx,
3881 VerifyError* failure) {
3882 Method* method = vdata->method_;
3883 const DexFile* dex_file = vdata->dex_file_;
3884 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3885 DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
3886 const ClassLoader* class_loader =
3887 method->GetDeclaringClass()->GetClassLoader();
3888 Field* field;
3889
3890 field = class_linker->ResolveField(*dex_file, field_idx, dex_cache,
3891 class_loader, true);
3892 if (field == NULL) {
3893 //const DexFile::FieldId field_id = dex_file->GetFieldId(field_idx);
3894
3895 //LOG(ERROR) << "VFY: unable to resolve static field " << field_idx << " ("
3896 //<< dex_file->GetFieldName(field_id) << ") in "
3897 //<< dex_file->GetFieldClassDescriptor(field_id);
3898 LOG(ERROR) << "VFY: unable to resolve static field";
3899 }
3900
3901 return field;
3902}
3903
3904Class* DexVerifier::GetCaughtExceptionType(VerifierData* vdata, int insn_idx,
3905 VerifyError* failure) {
3906 const DexFile* dex_file = vdata->dex_file_;
3907 const DexFile::CodeItem* code_item = vdata->code_item_;
3908 Method* method = vdata->method_;
3909 Class* common_super = NULL;
3910 uint32_t handlers_size;
jeffhaoba5ebb92011-08-25 17:24:37 -07003911 const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item, 0);
jeffhaobdb76512011-09-07 11:43:16 -07003912
3913 if (code_item->tries_size_ != 0) {
3914 handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
3915 } else {
3916 handlers_size = 0;
3917 }
3918
3919 for (uint32_t i = 0; i < handlers_size; i++) {
jeffhaoba5ebb92011-08-25 17:24:37 -07003920 DexFile::CatchHandlerIterator iterator(handlers_ptr);
3921
3922 for (; !iterator.HasNext(); iterator.Next()) {
jeffhaobdb76512011-09-07 11:43:16 -07003923 DexFile::CatchHandlerItem handler = iterator.Get();
3924 if (handler.address_ == (uint32_t) insn_idx) {
3925 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3926 Class* klass;
jeffhaoba5ebb92011-08-25 17:24:37 -07003927
jeffhaobdb76512011-09-07 11:43:16 -07003928 if (handler.type_idx_ == DexFile::kDexNoIndex) {
3929 klass = class_linker->FindSystemClass("Ljava/lang/Throwable;");
3930 } else {
jeffhao98eacac2011-09-14 16:11:53 -07003931 klass = ResolveClassAndCheckAccess(dex_file, handler.type_idx_,
3932 method->GetDeclaringClass(), failure);
jeffhaobdb76512011-09-07 11:43:16 -07003933 }
3934
3935 if (klass == NULL) {
3936 LOG(ERROR) << "VFY: unable to resolve exception class "
3937 << handler.type_idx_ << " ("
3938 << dex_file->dexStringByTypeIdx(handler.type_idx_) << ")";
jeffhaod1f0fde2011-09-08 17:25:33 -07003939 /* TODO: do we want to keep going? If we don't fail this we run
3940 * the risk of having a non-Throwable introduced at runtime.
3941 * However, that won't pass an instanceof test, so is essentially
3942 * harmless.
jeffhaobdb76512011-09-07 11:43:16 -07003943 */
3944 } else {
3945 if (common_super == NULL)
3946 common_super = klass;
3947 else
3948 common_super = FindCommonSuperclass(klass, common_super);
3949 }
3950 }
jeffhaoba5ebb92011-08-25 17:24:37 -07003951 }
3952
3953 handlers_ptr = iterator.GetData();
3954 }
3955
jeffhaobdb76512011-09-07 11:43:16 -07003956 if (common_super == NULL) {
3957 /* no catch blocks, or no catches with classes we can find */
3958 LOG(ERROR) << "VFY: unable to find exception handler at addr 0x" << std::hex
3959 << insn_idx << std::dec;
3960 *failure = VERIFY_ERROR_GENERIC;
3961 }
3962
3963 return common_super;
jeffhaoba5ebb92011-08-25 17:24:37 -07003964}
3965
jeffhaobdb76512011-09-07 11:43:16 -07003966DexVerifier::RegType DexVerifier::GetMethodReturnType(const DexFile* dex_file,
3967 const Method* method) {
3968 Class* klass = method->GetReturnType();
3969 if (klass->IsPrimitive())
3970 return PrimitiveTypeToRegType(klass->GetPrimitiveType());
3971 else
3972 return RegTypeFromClass(klass);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07003973}
3974
jeffhaobdb76512011-09-07 11:43:16 -07003975Class* DexVerifier::GetClassFromRegister(const RegisterLine* register_line,
3976 uint32_t vsrc, VerifyError* failure) {
3977 /* get the element type of the array held in vsrc */
3978 RegType type = GetRegisterType(register_line, vsrc);
jeffhaoba5ebb92011-08-25 17:24:37 -07003979
jeffhaobdb76512011-09-07 11:43:16 -07003980 /* if "always zero", we allow it to fail at runtime */
3981 if (type == kRegTypeZero)
3982 return NULL;
3983
3984 if (!RegTypeIsReference(type)) {
3985 LOG(ERROR) << "VFY: tried to get class from non-ref register v" << vsrc
3986 << " (type=" << type << ")",
3987 *failure = VERIFY_ERROR_GENERIC;
3988 return NULL;
3989 }
3990 if (RegTypeIsUninitReference(type)) {
3991 LOG(ERROR) << "VFY: register " << vsrc << " holds uninitialized reference";
3992 *failure = VERIFY_ERROR_GENERIC;
3993 return NULL;
jeffhaoba5ebb92011-08-25 17:24:37 -07003994 }
3995
jeffhaobdb76512011-09-07 11:43:16 -07003996 return RegTypeInitializedReferenceToClass(type);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07003997}
3998
jeffhaobdb76512011-09-07 11:43:16 -07003999DexVerifier::RegType DexVerifier::GetInvocationThis(
4000 const RegisterLine* register_line,
4001 const Instruction::DecodedInstruction* dec_insn, VerifyError* failure) {
4002 if (dec_insn->vA_ < 1) {
4003 LOG(ERROR) << "VFY: invoke lacks 'this'";
4004 *failure = VERIFY_ERROR_GENERIC;
4005 return kRegTypeUnknown;
jeffhaoba5ebb92011-08-25 17:24:37 -07004006 }
jeffhaobdb76512011-09-07 11:43:16 -07004007
4008 /* get the element type of the array held in vsrc */
4009 RegType this_type = GetRegisterType(register_line, dec_insn->vC_);
4010 if (!RegTypeIsReference(this_type)) {
4011 LOG(ERROR) << "VFY: tried to get class from non-ref register v"
4012 << dec_insn->vC_ << " (type=" << this_type << ")";
4013 *failure = VERIFY_ERROR_GENERIC;
4014 return kRegTypeUnknown;
4015 }
4016
4017 return this_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07004018}
4019
jeffhaobdb76512011-09-07 11:43:16 -07004020void DexVerifier::SetRegisterType(RegisterLine* register_line, uint32_t vdst,
4021 RegType new_type) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004022 RegType* insn_regs = register_line->reg_types_.get();
jeffhaoba5ebb92011-08-25 17:24:37 -07004023
jeffhaobdb76512011-09-07 11:43:16 -07004024 switch (new_type) {
4025 case kRegTypeUnknown:
4026 case kRegTypeBoolean:
4027 case kRegTypeOne:
4028 case kRegTypeConstByte:
4029 case kRegTypeConstPosByte:
4030 case kRegTypeConstShort:
4031 case kRegTypeConstPosShort:
4032 case kRegTypeConstChar:
4033 case kRegTypeConstInteger:
4034 case kRegTypeByte:
4035 case kRegTypePosByte:
4036 case kRegTypeShort:
4037 case kRegTypePosShort:
4038 case kRegTypeChar:
4039 case kRegTypeInteger:
4040 case kRegTypeFloat:
4041 case kRegTypeZero:
4042 case kRegTypeUninit:
4043 insn_regs[vdst] = new_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07004044 break;
jeffhaobdb76512011-09-07 11:43:16 -07004045 case kRegTypeConstLo:
4046 case kRegTypeLongLo:
4047 case kRegTypeDoubleLo:
4048 insn_regs[vdst] = new_type;
4049 insn_regs[vdst + 1] = new_type + 1;
4050 break;
4051 case kRegTypeConstHi:
4052 case kRegTypeLongHi:
4053 case kRegTypeDoubleHi:
4054 /* should never set these explicitly */
4055 LOG(FATAL) << "BUG: explicit set of high register type";
4056 break;
4057
4058 default:
4059 /* can't switch for ref types, so we check explicitly */
4060 if (RegTypeIsReference(new_type)) {
4061 insn_regs[vdst] = new_type;
4062
4063 /*
4064 * In most circumstances we won't see a reference to a primitive
4065 * class here (e.g. "D"), since that would mean the object in the
jeffhaod1f0fde2011-09-08 17:25:33 -07004066 * register is actually a primitive type. It can happen as the
jeffhaobdb76512011-09-07 11:43:16 -07004067 * result of an assumed-successful check-cast instruction in
jeffhaod1f0fde2011-09-08 17:25:33 -07004068 * which the second argument refers to a primitive class. (In
jeffhaobdb76512011-09-07 11:43:16 -07004069 * practice, such an instruction will always throw an exception.)
4070 *
4071 * This is not an issue for instructions like const-class, where
4072 * the object in the register is a java.lang.Class instance.
4073 */
4074 break;
4075 }
4076 /* bad type - fall through */
4077
4078 case kRegTypeConflict: // should only be set during a merge
4079 LOG(FATAL) << "BUG: set register to unknown type " << new_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07004080 break;
4081 }
4082
jeffhaobdb76512011-09-07 11:43:16 -07004083 /*
4084 * Clear the monitor entry bits for this register.
4085 */
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004086 if (register_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07004087 register_line->monitor_entries_[vdst] = 0;
4088}
4089
4090void DexVerifier::VerifyRegisterType(RegisterLine* register_line, uint32_t vsrc,
4091 RegType check_type, VerifyError* failure) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004092 const RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004093 RegType src_type = insn_regs[vsrc];
4094
4095 switch (check_type) {
4096 case kRegTypeFloat:
4097 case kRegTypeBoolean:
4098 case kRegTypePosByte:
4099 case kRegTypeByte:
4100 case kRegTypePosShort:
4101 case kRegTypeShort:
4102 case kRegTypeChar:
4103 case kRegTypeInteger:
4104 if (!CanConvertTo1nr(src_type, check_type)) {
4105 LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
4106 << ", wanted " << check_type;
4107 *failure = VERIFY_ERROR_GENERIC;
4108 }
4109 /* Update type if result is float */
4110 if (check_type == kRegTypeFloat) {
4111 SetRegisterType(register_line, vsrc, check_type);
4112 } else {
4113 /* Update const type to actual type after use */
4114 SetRegisterType(register_line, vsrc, ConstTypeToRegType(src_type));
4115 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004116 break;
jeffhaobdb76512011-09-07 11:43:16 -07004117 case kRegTypeLongLo:
4118 case kRegTypeDoubleLo:
4119 if (insn_regs[vsrc + 1] != src_type + 1) {
4120 LOG(ERROR) << "VFY: register2 v" << vsrc << "-" << vsrc + 1
4121 << " values " << insn_regs[vsrc] << ","
4122 << insn_regs[vsrc + 1];
4123 *failure = VERIFY_ERROR_GENERIC;
4124 } else if (!CanConvertTo2(src_type, check_type)) {
4125 LOG(ERROR) << "VFY: register2 v" << vsrc << " type " << src_type
4126 << ", wanted " << check_type;
4127 *failure = VERIFY_ERROR_GENERIC;
4128 }
4129 /* Update type if source is from const */
4130 if (src_type == kRegTypeConstLo) {
4131 SetRegisterType(register_line, vsrc, check_type);
4132 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004133 break;
jeffhaobdb76512011-09-07 11:43:16 -07004134 case kRegTypeConstLo:
4135 case kRegTypeConstHi:
4136 case kRegTypeLongHi:
4137 case kRegTypeDoubleHi:
4138 case kRegTypeZero:
4139 case kRegTypeOne:
4140 case kRegTypeUnknown:
4141 case kRegTypeConflict:
4142 /* should never be checking for these explicitly */
4143 assert(false);
4144 *failure = VERIFY_ERROR_GENERIC;
4145 return;
4146 case kRegTypeUninit:
4147 default:
4148 /* make sure check_type is initialized reference */
4149 if (!RegTypeIsReference(check_type)) {
4150 LOG(ERROR) << "VFY: unexpected check type " << check_type;
4151 assert(false);
4152 *failure = VERIFY_ERROR_GENERIC;
4153 break;
4154 }
4155 if (RegTypeIsUninitReference(check_type)) {
4156 LOG(ERROR) << "VFY: uninitialized ref not expected as reg check";
4157 *failure = VERIFY_ERROR_GENERIC;
4158 break;
4159 }
4160 /* make sure src_type is initialized reference or always-NULL */
4161 if (!RegTypeIsReference(src_type)) {
4162 LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
4163 << ", wanted ref";
4164 *failure = VERIFY_ERROR_GENERIC;
4165 break;
4166 }
4167 if (RegTypeIsUninitReference(src_type)) {
4168 LOG(ERROR) << "VFY: register1 v" << vsrc << " holds uninitialized ref";
4169 *failure = VERIFY_ERROR_GENERIC;
4170 break;
4171 }
4172 /* if the register isn't Zero, make sure it's an instance of check */
4173 if (src_type != kRegTypeZero) {
4174 Class* src_class = RegTypeInitializedReferenceToClass(src_type);
4175 Class* check_class = RegTypeInitializedReferenceToClass(check_type);
4176 assert(src_class != NULL);
4177 assert(check_class != NULL);
4178
4179 if (!check_class->IsAssignableFrom(src_class)) {
4180 LOG(ERROR) << "VFY: " << src_class->GetDescriptor()->ToModifiedUtf8()
4181 << " is not instance of "
4182 << check_class->GetDescriptor()->ToModifiedUtf8();
4183 *failure = VERIFY_ERROR_GENERIC;
4184 }
4185 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004186 break;
4187 }
jeffhaobdb76512011-09-07 11:43:16 -07004188}
jeffhaoba5ebb92011-08-25 17:24:37 -07004189
jeffhaobdb76512011-09-07 11:43:16 -07004190void DexVerifier::SetResultRegisterType(RegisterLine* register_line,
4191 const int insn_reg_count, RegType new_type) {
4192 SetRegisterType(register_line, RESULT_REGISTER(insn_reg_count), new_type);
4193}
4194
4195void DexVerifier::MarkRefsAsInitialized(RegisterLine* register_line,
4196 int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type,
4197 VerifyError* failure) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004198 RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004199 Class* klass = GetUninitInstance(uninit_map,
4200 RegTypeToUninitIndex(uninit_type));
4201
4202 if (klass == NULL) {
4203 LOG(ERROR) << "VFY: unable to find type=" << std::hex << uninit_type
4204 << std::dec << " (idx=" << RegTypeToUninitIndex(uninit_type)
4205 << ")";
4206 *failure = VERIFY_ERROR_GENERIC;
4207 return;
jeffhaoba5ebb92011-08-25 17:24:37 -07004208 }
4209
jeffhaobdb76512011-09-07 11:43:16 -07004210 RegType init_type = RegTypeFromClass(klass);
4211 int changed = 0;
4212 for (int i = 0; i < insn_reg_count; i++) {
4213 if (insn_regs[i] == uninit_type) {
4214 insn_regs[i] = init_type;
4215 changed++;
4216 }
4217 }
4218 assert(changed > 0);
4219
4220 return;
4221}
4222
4223void DexVerifier::MarkUninitRefsAsInvalid(RegisterLine* register_line,
4224 int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004225 RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004226
4227 for (int i = 0; i < insn_reg_count; i++) {
4228 if (insn_regs[i] == uninit_type) {
4229 insn_regs[i] = kRegTypeConflict;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004230 if (register_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07004231 register_line->monitor_entries_[i] = 0;
4232 }
4233 }
4234}
4235
4236void DexVerifier::CopyRegister1(RegisterLine* register_line, uint32_t vdst,
4237 uint32_t vsrc, TypeCategory cat, VerifyError* failure) {
4238 assert(cat == kTypeCategory1nr || cat == kTypeCategoryRef);
4239 RegType type = GetRegisterType(register_line, vsrc);
4240 CheckTypeCategory(type, cat, failure);
4241 if (*failure != VERIFY_ERROR_NONE) {
4242 LOG(ERROR) << "VFY: copy1 v" << vdst << "<-v" << vsrc << " type=" << type
4243 << " cat=" << (int) cat;
4244 } else {
4245 SetRegisterType(register_line, vdst, type);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004246 if (cat == kTypeCategoryRef && register_line->monitor_entries_.get() != NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07004247 register_line->monitor_entries_[vdst] =
4248 register_line->monitor_entries_[vsrc];
4249 }
4250 }
4251}
4252
4253void DexVerifier::CopyRegister2(RegisterLine* register_line, uint32_t vdst,
4254 uint32_t vsrc, VerifyError* failure) {
4255 RegType type_l = GetRegisterType(register_line, vsrc);
4256 RegType type_h = GetRegisterType(register_line, vsrc + 1);
4257
4258 CheckTypeCategory(type_l, kTypeCategory2, failure);
4259 CheckWidePair(type_l, type_h, failure);
4260 if (*failure != VERIFY_ERROR_NONE) {
4261 LOG(ERROR) << "VFY: copy2 v" << vdst << "<-v" << vsrc << " type=" << type_l
4262 << "/" << type_h;
4263 } else {
4264 SetRegisterType(register_line, vdst, type_l);
4265 }
4266}
4267
4268void DexVerifier::CopyResultRegister1(RegisterLine* register_line,
4269 const int insn_reg_count, uint32_t vdst, TypeCategory cat,
4270 VerifyError* failure) {
4271 assert(vdst < (uint32_t) insn_reg_count);
4272
4273 uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
4274 RegType type = GetRegisterType(register_line, vsrc);
4275 CheckTypeCategory(type, cat, failure);
4276 if (*failure != VERIFY_ERROR_NONE) {
4277 LOG(ERROR) << "VFY: copyRes1 v" << vdst << "<-v" << vsrc << " cat="
4278 << (int) cat << " type=" << type;
4279 } else {
4280 SetRegisterType(register_line, vdst, type);
4281 SetRegisterType(register_line, vsrc, kRegTypeUnknown);
4282 }
4283}
4284
4285/*
jeffhaod1f0fde2011-09-08 17:25:33 -07004286 * Implement "move-result-wide". Copy the category-2 value from the result
jeffhaobdb76512011-09-07 11:43:16 -07004287 * register to another register, and reset the result register.
4288 */
4289void DexVerifier::CopyResultRegister2(RegisterLine* register_line,
4290 const int insn_reg_count, uint32_t vdst, VerifyError* failure) {
4291 assert(vdst < (uint32_t) insn_reg_count);
4292
4293 uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
4294 RegType type_l = GetRegisterType(register_line, vsrc);
4295 RegType type_h = GetRegisterType(register_line, vsrc + 1);
4296 CheckTypeCategory(type_l, kTypeCategory2, failure);
4297 CheckWidePair(type_l, type_h, failure);
4298 if (*failure != VERIFY_ERROR_NONE) {
4299 LOG(ERROR) << "VFY: copyRes2 v" << vdst << "<-v" << vsrc << " type="
4300 << type_l << "/" << type_h;
4301 } else {
4302 SetRegisterType(register_line, vdst, type_l);
4303 SetRegisterType(register_line, vsrc, kRegTypeUnknown);
4304 SetRegisterType(register_line, vsrc + 1, kRegTypeUnknown);
4305 }
4306}
4307
4308int DexVerifier::GetClassDepth(Class* klass) {
4309 int depth = 0;
4310 while (klass->GetSuperClass() != NULL) {
4311 klass = klass->GetSuperClass();
4312 depth++;
4313 }
4314 return depth;
4315}
4316
4317Class* DexVerifier::DigForSuperclass(Class* c1, Class* c2) {
4318 int depth1, depth2;
4319
4320 depth1 = GetClassDepth(c1);
4321 depth2 = GetClassDepth(c2);
4322
4323 /* pull the deepest one up */
4324 if (depth1 > depth2) {
4325 while (depth1 > depth2) {
4326 c1 = c1->GetSuperClass();
4327 depth1--;
4328 }
4329 } else {
4330 while (depth2 > depth1) {
4331 c2 = c2->GetSuperClass();
4332 depth2--;
4333 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004334 }
4335
jeffhaobdb76512011-09-07 11:43:16 -07004336 /* walk up in lock-step */
4337 while (c1 != c2) {
4338 c1 = c1->GetSuperClass();
4339 c2 = c2->GetSuperClass();
4340
4341 assert(c1 != NULL && c2 != NULL);
4342 }
4343
4344 return c1;
4345}
4346
4347Class* DexVerifier::FindCommonArraySuperclass(Class* c1, Class* c2) {
4348 Class* array_class = NULL;
4349 Class* common_elem;
4350 int array_dim1, array_dim2;
4351 int i, num_dims;
4352 bool has_primitive = false;
4353
4354 array_dim1 = c1->GetArrayRank();
4355 array_dim2 = c2->GetArrayRank();
4356 assert(c1->GetArrayRank() > 0);
4357 assert(c2->GetArrayRank() > 0);
4358
4359 if (c1->GetComponentType()->IsPrimitive()) {
4360 array_dim1--;
4361 has_primitive = true;
4362 }
4363 if (c2->GetComponentType()->IsPrimitive()) {
4364 array_dim2--;
4365 has_primitive = true;
4366 }
4367
4368 if (!has_primitive && array_dim1 == array_dim2) {
4369 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004370 * Two arrays of reference types with equal dimensions. Try to
jeffhaobdb76512011-09-07 11:43:16 -07004371 * find a good match.
4372 */
4373 common_elem = FindCommonSuperclass(c1->GetComponentType(),
4374 c2->GetComponentType());
4375 num_dims = array_dim1;
4376 } else {
4377 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004378 * Mismatched array depths and/or array(s) of primitives. We want
jeffhaobdb76512011-09-07 11:43:16 -07004379 * Object, or an Object array with appropriate dimensions.
4380 *
4381 * We initialize array_class to Object here, because it's possible
4382 * for us to set num_dims=0.
4383 */
4384 if (array_dim1 < array_dim2)
4385 num_dims = array_dim1;
4386 else
4387 num_dims = array_dim2;
4388 array_class = common_elem = c1->GetSuperClass(); // == java.lang.Object
4389 }
4390
4391 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004392 * Find an appropriately-dimensioned array class. This is easiest
jeffhaobdb76512011-09-07 11:43:16 -07004393 * to do iteratively, using the array class found by the current round
4394 * as the element type for the next round.
4395 */
4396 for (i = 0; i < num_dims; i++) {
4397 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4398 const ClassLoader* class_loader = c1->GetClassLoader();
4399 std::string descriptor = "[" +
4400 common_elem->GetDescriptor()->ToModifiedUtf8();
4401 array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
4402 common_elem = array_class;
4403 }
4404 assert(array_class != NULL);
4405
4406 return array_class;
4407}
4408
4409Class* DexVerifier::FindCommonSuperclass(Class* c1, Class* c2) {
4410 assert(!c1->IsPrimitive() && !c2->IsPrimitive());
4411
4412 if (c1 == c2)
4413 return c1;
4414
jeffhao5dbddee2011-09-07 16:38:26 -07004415 if (c1->IsInterface() && c1->IsAssignableFrom(c2)) {
jeffhaobdb76512011-09-07 11:43:16 -07004416 return c1;
4417 }
jeffhao5dbddee2011-09-07 16:38:26 -07004418 if (c2->IsInterface() && c2->IsAssignableFrom(c1)) {
jeffhaobdb76512011-09-07 11:43:16 -07004419 return c2;
4420 }
4421 if (c1->IsArrayClass() && c2->IsArrayClass()) {
4422 return FindCommonArraySuperclass(c1, c2);
4423 }
4424
4425 return DigForSuperclass(c1, c2);
4426}
4427
jeffhao98eacac2011-09-14 16:11:53 -07004428Class* DexVerifier::ResolveClassAndCheckAccess(const DexFile* dex_file,
4429 uint32_t class_idx, const Class* referrer, VerifyError* failure) {
4430 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4431 Class* res_class = class_linker->ResolveType(*dex_file, class_idx, referrer);
4432
4433 if (res_class == NULL) {
4434 *failure = VERIFY_ERROR_NO_CLASS;
4435 return NULL;
4436 }
4437
4438 /* Check if access is allowed. */
4439 if (!referrer->CanAccess(res_class)) {
4440 LOG(ERROR) << "VFY: illegal class access: "
4441 << referrer->GetDescriptor()->ToModifiedUtf8() << " -> "
4442 << res_class->GetDescriptor()->ToModifiedUtf8();
4443 *failure = VERIFY_ERROR_ACCESS_CLASS;
4444 return NULL;
4445 }
4446
4447 return res_class;
4448}
4449
jeffhaobdb76512011-09-07 11:43:16 -07004450DexVerifier::RegType DexVerifier::MergeTypes(RegType type1, RegType type2,
4451 bool* changed) {
4452 RegType result;
4453
jeffhao98eacac2011-09-14 16:11:53 -07004454 /* Check for trivial case so we don't have to hit memory. */
jeffhaobdb76512011-09-07 11:43:16 -07004455 if (type1 == type2)
4456 return type1;
4457
4458 /*
4459 * Use the table if we can, and reject any attempts to merge something
4460 * from the table with a reference type.
4461 *
4462 * Uninitialized references are composed of the enum ORed with an
jeffhaod1f0fde2011-09-08 17:25:33 -07004463 * index value. The uninitialized table entry at index zero *will*
4464 * show up as a simple kRegTypeUninit value. Since this cannot be
jeffhaobdb76512011-09-07 11:43:16 -07004465 * merged with anything but itself, the rules do the right thing.
4466 */
4467 if (type1 < kRegTypeMAX) {
4468 if (type2 < kRegTypeMAX) {
4469 result = merge_table_[type1][type2];
4470 } else {
4471 /* simple + reference == conflict, usually */
4472 if (type1 == kRegTypeZero)
4473 result = type2;
4474 else
4475 result = kRegTypeConflict;
4476 }
4477 } else {
4478 if (type2 < kRegTypeMAX) {
4479 /* reference + simple == conflict, usually */
4480 if (type2 == kRegTypeZero)
4481 result = type1;
4482 else
4483 result = kRegTypeConflict;
4484 } else {
4485 /* merging two references */
4486 if (RegTypeIsUninitReference(type1) ||
4487 RegTypeIsUninitReference(type2))
4488 {
4489 /* can't merge uninit with anything but self */
4490 result = kRegTypeConflict;
4491 } else {
4492 Class* klass1 = RegTypeInitializedReferenceToClass(type1);
4493 Class* klass2 = RegTypeInitializedReferenceToClass(type2);
4494 Class* merged_class = FindCommonSuperclass(klass1, klass2);
4495 assert(merged_class != NULL);
4496 result = RegTypeFromClass(merged_class);
4497 }
4498 }
4499 }
4500
4501 if (result != type1)
4502 *changed = true;
jeffhaoba5ebb92011-08-25 17:24:37 -07004503 return result;
jeffhaobdb76512011-09-07 11:43:16 -07004504}
4505
4506DexVerifier::MonitorEntries DexVerifier::MergeMonitorEntries(
4507 MonitorEntries ents1, MonitorEntries ents2, bool* changed) {
4508 MonitorEntries result = ents1 & ents2;
4509 if (result != ents1)
4510 *changed = true;
4511 return result;
4512}
4513
4514bool DexVerifier::UpdateRegisters(InsnFlags* insn_flags,
4515 RegisterTable* reg_table, int next_insn, const RegisterLine* work_line) {
4516 const size_t insn_reg_count_plus = reg_table->insn_reg_count_plus_;
4517 assert(work_line != NULL);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004518 const RegType* work_regs = work_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004519
4520 if (!InsnIsVisitedOrChanged(insn_flags, next_insn)) {
4521 /*
4522 * We haven't processed this instruction before, and we haven't
jeffhaod1f0fde2011-09-08 17:25:33 -07004523 * touched the registers here, so there's nothing to "merge". Copy
4524 * the registers over and mark it as changed. (This is the only
jeffhaobdb76512011-09-07 11:43:16 -07004525 * way a register can transition out of "unknown", so this is not
4526 * just an optimization.)
4527 */
4528 CopyLineToTable(reg_table, next_insn, work_line);
4529 InsnSetChanged(insn_flags, next_insn, true);
4530 } else {
4531 /* Merge registers, set Changed only if different */
4532 RegisterLine* target_line = GetRegisterLine(reg_table, next_insn);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004533 RegType* target_regs = target_line->reg_types_.get();
4534 MonitorEntries* work_mon_ents = work_line->monitor_entries_.get();
4535 MonitorEntries* target_mon_ents = target_line->monitor_entries_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004536 bool changed = false;
4537 unsigned int idx;
4538
4539 assert(target_regs != NULL);
4540 if (target_mon_ents != NULL) {
4541 /* Monitor stacks must be identical. */
4542 if (target_line->monitor_stack_top_ != work_line->monitor_stack_top_) {
4543 LOG(ERROR) << "VFY: mismatched stack depth "
4544 << target_line->monitor_stack_top_ << " vs. "
4545 << work_line->monitor_stack_top_ << " at 0x"
4546 << std::hex << next_insn << std::dec;
4547 return false;
4548 }
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004549 if (memcmp(target_line->monitor_stack_.get(), work_line->monitor_stack_.get(),
jeffhaobdb76512011-09-07 11:43:16 -07004550 target_line->monitor_stack_top_ * sizeof(uint32_t)) != 0) {
4551 LOG(ERROR) << "VFY: mismatched monitor stacks at 0x" << std::hex
4552 << next_insn << std::dec;
4553 return false;
4554 }
4555 }
4556
4557 for (idx = 0; idx < insn_reg_count_plus; idx++) {
4558 target_regs[idx] = MergeTypes(target_regs[idx], work_regs[idx], &changed);
4559
4560 if (target_mon_ents != NULL) {
4561 target_mon_ents[idx] = MergeMonitorEntries(target_mon_ents[idx],
4562 work_mon_ents[idx], &changed);
4563 }
4564 }
4565
4566 if (changed) {
4567 InsnSetChanged(insn_flags, next_insn, true);
4568 }
4569 }
4570
4571 return true;
4572}
4573
4574bool DexVerifier::CanConvertTo1nr(RegType src_type, RegType check_type) {
4575 static const char conv_tab[kRegType1nrEND - kRegType1nrSTART + 1]
4576 [kRegType1nrEND - kRegType1nrSTART + 1] =
4577 {
4578 /* chk: 0 1 Z y Y h H c i b B s S C I F */
4579 { /*0*/ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4580 { /*1*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4581 { /*Z*/ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
4582 { /*y*/ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4583 { /*Y*/ 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1 },
4584 { /*h*/ 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1 },
4585 { /*H*/ 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1 },
4586 { /*c*/ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1 },
4587 { /*i*/ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1 },
4588 { /*b*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0 },
4589 { /*B*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0 },
4590 { /*s*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 },
4591 { /*S*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 },
4592 { /*C*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 },
4593 { /*I*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },
4594 { /*F*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
4595 };
4596
4597 assert(check_type >= kRegType1nrSTART && check_type <= kRegType1nrEND);
4598
4599 if (src_type >= kRegType1nrSTART && src_type <= kRegType1nrEND)
4600 return (bool) conv_tab[src_type - kRegType1nrSTART]
4601 [check_type - kRegType1nrSTART];
4602
4603 return false;
4604}
4605
4606bool DexVerifier::CanConvertTo2(RegType src_type, RegType check_type) {
4607 return ((src_type == kRegTypeConstLo || src_type == check_type) &&
4608 (check_type == kRegTypeLongLo || check_type == kRegTypeDoubleLo));
4609}
4610
4611DexVerifier::RegType DexVerifier::PrimitiveTypeToRegType(
4612 Class::PrimitiveType prim_type) {
4613 switch (prim_type) {
4614 case Class::kPrimBoolean: return kRegTypeBoolean;
4615 case Class::kPrimByte: return kRegTypeByte;
4616 case Class::kPrimShort: return kRegTypeShort;
4617 case Class::kPrimChar: return kRegTypeChar;
4618 case Class::kPrimInt: return kRegTypeInteger;
4619 case Class::kPrimLong: return kRegTypeLongLo;
4620 case Class::kPrimFloat: return kRegTypeFloat;
4621 case Class::kPrimDouble: return kRegTypeDoubleLo;
4622 case Class::kPrimVoid:
4623 default: {
4624 return kRegTypeUnknown;
4625 }
4626 }
4627}
4628
4629DexVerifier::RegType DexVerifier::ConstTypeToRegType(RegType const_type) {
4630 switch (const_type) {
4631 case kRegTypeConstPosByte: return kRegTypePosByte;
4632 case kRegTypeConstByte: return kRegTypeByte;
4633 case kRegTypeConstPosShort: return kRegTypePosShort;
4634 case kRegTypeConstShort: return kRegTypeShort;
4635 case kRegTypeConstChar: return kRegTypeChar;
4636 case kRegTypeConstInteger: return kRegTypeInteger;
4637 default: {
4638 return const_type;
4639 }
4640 }
4641}
4642
4643char DexVerifier::DetermineCat1Const(int32_t value) {
4644 if (value < -32768)
4645 return kRegTypeConstInteger;
4646 else if (value < -128)
4647 return kRegTypeConstShort;
4648 else if (value < 0)
4649 return kRegTypeConstByte;
4650 else if (value == 0)
4651 return kRegTypeZero;
4652 else if (value == 1)
4653 return kRegTypeOne;
4654 else if (value < 128)
4655 return kRegTypeConstPosByte;
4656 else if (value < 32768)
4657 return kRegTypeConstPosShort;
4658 else if (value < 65536)
4659 return kRegTypeConstChar;
4660 else
4661 return kRegTypeConstInteger;
4662}
4663
4664void DexVerifier::CheckFinalFieldAccess(const Method* method,
4665 const Field* field, VerifyError* failure) {
4666 if (!field->IsFinal())
4667 return;
4668
4669 /* make sure we're in the same class */
4670 if (method->GetDeclaringClass() != field->GetDeclaringClass()) {
4671 LOG(ERROR) << "VFY: can't modify final field "
4672 << field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
4673 << "." << field->GetName()->ToModifiedUtf8();
4674 *failure = VERIFY_ERROR_ACCESS_FIELD;
4675 return;
4676 }
4677}
4678
4679void DexVerifier::CheckArrayIndexType(const Method* method, RegType reg_type,
4680 VerifyError* failure) {
4681 if (*failure == VERIFY_ERROR_NONE) {
4682 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004683 * The 1nr types are interchangeable at this level. We could
jeffhaobdb76512011-09-07 11:43:16 -07004684 * do something special if we can definitively identify it as a
4685 * float, but there's no real value in doing so.
4686 */
4687 CheckTypeCategory(reg_type, kTypeCategory1nr, failure);
4688 if (*failure != VERIFY_ERROR_NONE) {
4689 LOG(ERROR) << "Invalid reg type for array index (" << reg_type << ")";
4690 }
4691 }
4692}
4693
4694bool DexVerifier::CheckConstructorReturn(const Method* method,
4695 const RegisterLine* register_line, const int insn_reg_count) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004696 const RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004697
4698 if (!IsInitMethod(method))
4699 return true;
4700
4701 RegType uninit_this = RegTypeFromUninitIndex(kUninitThisArgSlot);
4702
4703 for (int i = 0; i < insn_reg_count; i++) {
4704 if (insn_regs[i] == uninit_this) {
4705 LOG(ERROR) << "VFY: <init> returning without calling superclass init";
4706 return false;
4707 }
4708 }
4709 return true;
4710}
4711
4712bool DexVerifier::CheckMoveException(const uint16_t* insns, int insn_idx) {
4713 if ((insns[insn_idx] & 0xff) == Instruction::MOVE_EXCEPTION) {
4714 LOG(ERROR) << "VFY: invalid use of move-exception";
4715 return false;
4716 }
4717 return true;
4718}
4719
4720void DexVerifier::CheckTypeCategory(RegType type, TypeCategory cat,
4721 VerifyError* failure) {
4722 switch (cat) {
4723 case kTypeCategory1nr:
4724 switch (type) {
4725 case kRegTypeZero:
4726 case kRegTypeOne:
4727 case kRegTypeBoolean:
4728 case kRegTypeConstPosByte:
4729 case kRegTypeConstByte:
4730 case kRegTypeConstPosShort:
4731 case kRegTypeConstShort:
4732 case kRegTypeConstChar:
4733 case kRegTypeConstInteger:
4734 case kRegTypePosByte:
4735 case kRegTypeByte:
4736 case kRegTypePosShort:
4737 case kRegTypeShort:
4738 case kRegTypeChar:
4739 case kRegTypeInteger:
4740 case kRegTypeFloat:
4741 break;
4742 default:
4743 *failure = VERIFY_ERROR_GENERIC;
4744 break;
4745 }
4746 break;
4747 case kTypeCategory2:
4748 switch (type) {
4749 case kRegTypeConstLo:
4750 case kRegTypeLongLo:
4751 case kRegTypeDoubleLo:
4752 break;
4753 default:
4754 *failure = VERIFY_ERROR_GENERIC;
4755 break;
4756 }
4757 break;
4758 case kTypeCategoryRef:
4759 if (type != kRegTypeZero && !RegTypeIsReference(type))
4760 *failure = VERIFY_ERROR_GENERIC;
4761 break;
4762 default:
4763 assert(false);
4764 *failure = VERIFY_ERROR_GENERIC;
4765 break;
4766 }
4767}
4768
4769void DexVerifier::CheckWidePair(RegType type_l, RegType type_h,
4770 VerifyError* failure) {
4771 if ((type_h != type_l + 1))
4772 *failure = VERIFY_ERROR_GENERIC;
4773}
4774
4775void DexVerifier::CheckUnop(RegisterLine* register_line,
4776 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4777 RegType src_type, VerifyError* failure) {
4778 VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
4779 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4780}
4781
4782bool DexVerifier::UpcastBooleanOp(RegisterLine* register_line, uint32_t reg1,
4783 uint32_t reg2) {
4784 RegType type1, type2;
4785
4786 type1 = GetRegisterType(register_line, reg1);
4787 type2 = GetRegisterType(register_line, reg2);
4788
4789 if ((type1 == kRegTypeBoolean || type1 == kRegTypeZero || type1 == kRegTypeOne) &&
4790 (type2 == kRegTypeBoolean || type2 == kRegTypeZero || type2 == kRegTypeOne)) {
4791 return true;
4792 }
4793 return false;
4794}
4795
4796void DexVerifier::CheckLitop(RegisterLine* register_line,
4797 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4798 RegType src_type, bool check_boolean_op, VerifyError* failure) {
4799 VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
4800
4801 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
4802 assert(dst_type == kRegTypeInteger);
4803
4804 /* check vB with the call, then check the constant manually */
4805 if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vB_)
4806 && (dec_insn->vC_ == 0 || dec_insn->vC_ == 1)) {
4807 dst_type = kRegTypeBoolean;
4808 }
4809 }
4810
4811 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4812}
4813
4814void DexVerifier::CheckBinop(RegisterLine* register_line,
4815 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4816 RegType src_type1, RegType src_type2, bool check_boolean_op,
4817 VerifyError* failure) {
4818 VerifyRegisterType(register_line, dec_insn->vB_, src_type1, failure);
4819 VerifyRegisterType(register_line, dec_insn->vC_, src_type2, failure);
4820
4821 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
4822 assert(dst_type == kRegTypeInteger);
4823 if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vC_))
4824 dst_type = kRegTypeBoolean;
4825 }
4826
4827 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4828}
4829
4830void DexVerifier::CheckBinop2addr(RegisterLine* register_line,
4831 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4832 RegType src_type1, RegType src_type2, bool check_boolean_op,
4833 VerifyError* failure) {
4834 VerifyRegisterType(register_line, dec_insn->vA_, src_type1, failure);
4835 VerifyRegisterType(register_line, dec_insn->vB_, src_type2, failure);
4836
4837 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
4838 assert(dst_type == kRegTypeInteger);
4839 if (UpcastBooleanOp(register_line, dec_insn->vA_, dec_insn->vB_))
4840 dst_type = kRegTypeBoolean;
4841 }
4842
4843 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4844}
4845
4846DexVerifier::RegType DexVerifier::AdjustForRightShift(
4847 RegisterLine* register_line, int reg, unsigned int shift_count,
4848 bool is_unsigned_shift, VerifyError* failure) {
4849 RegType src_type = GetRegisterType(register_line, reg);
4850 RegType new_type;
4851
4852 /* convert const derived types to their actual types */
4853 src_type = ConstTypeToRegType(src_type);
4854
4855 /* no-op */
4856 if (shift_count == 0)
4857 return src_type;
4858
4859 /* safe defaults */
4860 if (is_unsigned_shift)
4861 new_type = kRegTypeInteger;
4862 else
4863 new_type = src_type;
4864
4865 if (shift_count >= 32) {
4866 LOG(ERROR) << "Got unexpectedly large shift count " << shift_count;
4867 /* fail? */
4868 return new_type;
4869 }
4870
4871 switch (src_type) {
4872 case kRegTypeInteger: /* 32-bit signed value */
4873 if (is_unsigned_shift) {
4874 if (shift_count > 24)
4875 new_type = kRegTypePosByte;
4876 else if (shift_count >= 16)
4877 new_type = kRegTypeChar;
4878 } else {
4879 if (shift_count >= 24)
4880 new_type = kRegTypeByte;
4881 else if (shift_count >= 16)
4882 new_type = kRegTypeShort;
4883 }
4884 break;
4885 case kRegTypeShort: /* 16-bit signed value */
4886 if (is_unsigned_shift) {
4887 /* default (kRegTypeInteger) is correct */
4888 } else {
4889 if (shift_count >= 8)
4890 new_type = kRegTypeByte;
4891 }
4892 break;
4893 case kRegTypePosShort: /* 15-bit unsigned value */
4894 if (shift_count >= 8)
4895 new_type = kRegTypePosByte;
4896 break;
4897 case kRegTypeChar: /* 16-bit unsigned value */
4898 if (shift_count > 8)
4899 new_type = kRegTypePosByte;
4900 break;
4901 case kRegTypeByte: /* 8-bit signed value */
4902 /* defaults (u=kRegTypeInteger / s=src_type) are correct */
4903 break;
4904 case kRegTypePosByte: /* 7-bit unsigned value */
4905 /* always use new_type=src_type */
4906 new_type = src_type;
4907 break;
4908 case kRegTypeZero: /* 1-bit unsigned value */
4909 case kRegTypeOne:
4910 case kRegTypeBoolean:
4911 /* unnecessary? */
4912 new_type = kRegTypeZero;
4913 break;
4914 default:
4915 /* long, double, references; shouldn't be here! */
4916 assert(false);
4917 break;
4918 }
4919
4920 return new_type;
4921}
4922
4923void DexVerifier::VerifyFilledNewArrayRegs(const Method* method,
4924 RegisterLine* register_line,
4925 const Instruction::DecodedInstruction* dec_insn, Class* res_class,
4926 bool is_range, VerifyError* failure) {
4927 uint32_t arg_count = dec_insn->vA_;
4928 RegType expected_type;
4929 Class::PrimitiveType elem_type;
4930 unsigned int ui;
4931
4932 assert(res_class->IsArrayClass());
4933 elem_type = res_class->GetComponentType()->GetPrimitiveType();
4934 if (elem_type == Class::kPrimNot) {
4935 expected_type = RegTypeFromClass(res_class->GetComponentType());
4936 } else {
4937 expected_type = PrimitiveTypeToRegType(elem_type);
4938 }
4939
4940 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004941 * Verify each register. If "arg_count" is bad, VerifyRegisterType()
4942 * will run off the end of the list and fail. It's legal, if silly,
jeffhaobdb76512011-09-07 11:43:16 -07004943 * for arg_count to be zero.
4944 */
4945 for (ui = 0; ui < arg_count; ui++) {
4946 uint32_t get_reg;
4947
4948 if (is_range)
4949 get_reg = dec_insn->vC_ + ui;
4950 else
4951 get_reg = dec_insn->arg_[ui];
4952
4953 VerifyRegisterType(register_line, get_reg, expected_type, failure);
4954 if (*failure != VERIFY_ERROR_NONE) {
4955 LOG(ERROR) << "VFY: filled-new-array arg " << ui << "(" << get_reg
4956 << ") not valid";
4957 return;
4958 }
4959 }
4960}
4961
4962bool DexVerifier::IsCorrectInvokeKind(MethodType method_type,
4963 Method* res_method) {
4964 switch (method_type) {
4965 case METHOD_DIRECT:
4966 return res_method->IsDirect();
4967 case METHOD_STATIC:
4968 return res_method->IsStatic();
4969 case METHOD_VIRTUAL:
4970 case METHOD_INTERFACE:
4971 return !res_method->IsDirect();
4972 default:
4973 return false;
4974 }
4975}
4976
4977Method* DexVerifier::VerifyInvocationArgs(VerifierData* vdata,
4978 RegisterLine* register_line, const int insn_reg_count,
4979 const Instruction::DecodedInstruction* dec_insn, MethodType method_type,
4980 bool is_range, bool is_super, VerifyError* failure) {
4981 Method* method = vdata->method_;
4982 const DexFile* dex_file = vdata->dex_file_;
4983 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004984 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004985 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4986 DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
4987 const ClassLoader* class_loader =
4988 method->GetDeclaringClass()->GetClassLoader();
4989
4990 Method* res_method;
4991 std::string sig;
4992 size_t sig_offset;
4993 int expected_args;
4994 int actual_args;
4995
4996 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004997 * Resolve the method. This could be an abstract or concrete method
jeffhaobdb76512011-09-07 11:43:16 -07004998 * depending on what sort of call we're making.
4999 */
5000 res_method = class_linker->ResolveMethod(*dex_file, dec_insn->vB_, dex_cache,
5001 class_loader, (method_type == METHOD_DIRECT || method_type == METHOD_STATIC));
5002
jeffhaobdb76512011-09-07 11:43:16 -07005003 if (res_method == NULL) {
jeffhao98eacac2011-09-14 16:11:53 -07005004 const DexFile::MethodId& method_id = dex_file->GetMethodId(dec_insn->vB_);
5005 const char* method_name = dex_file->GetMethodName(method_id);
5006 const char* method_proto = dex_file->GetMethodPrototype(method_id);
5007 const char* class_descriptor = dex_file->GetMethodClassDescriptor(method_id);
5008
5009 LOG(ERROR) << "VFY: unable to resolve method " << dec_insn->vB_ << ": "
5010 << class_descriptor << "." << method_name << " " << method_proto;
jeffhaobdb76512011-09-07 11:43:16 -07005011 *failure = VERIFY_ERROR_NO_METHOD;
5012 return NULL;
5013 }
jeffhaobdb76512011-09-07 11:43:16 -07005014
5015 /*
5016 * Only time you can explicitly call a method starting with '<' is when
jeffhaod1f0fde2011-09-08 17:25:33 -07005017 * making a "direct" invocation on "<init>". There are additional
jeffhaobdb76512011-09-07 11:43:16 -07005018 * restrictions but we don't enforce them here.
5019 */
5020 if (res_method->GetName()->Equals("<init>")) {
5021 if (method_type != METHOD_DIRECT || !IsInitMethod(res_method)) {
5022 LOG(ERROR) << "VFY: invalid call to "
jeffhao98eacac2011-09-14 16:11:53 -07005023 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
jeffhaobdb76512011-09-07 11:43:16 -07005024 << "." << res_method->GetName();
5025 goto bad_sig;
5026 }
5027 }
5028
5029 /*
5030 * See if the method type implied by the invoke instruction matches the
5031 * access flags for the target method.
5032 */
5033 if (!IsCorrectInvokeKind(method_type, res_method)) {
5034 LOG(ERROR) << "VFY: invoke type does not match method type of "
jeffhao98eacac2011-09-14 16:11:53 -07005035 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
jeffhaobdb76512011-09-07 11:43:16 -07005036 << "." << res_method->GetName()->ToModifiedUtf8();
5037
5038 *failure = VERIFY_ERROR_GENERIC;
5039 return NULL;
5040 }
5041
5042 /*
5043 * If we're using invoke-super(method), make sure that the executing
5044 * method's class' superclass has a vtable entry for the target method.
5045 */
5046 if (is_super) {
5047 assert(method_type == METHOD_VIRTUAL);
5048 Class* super = method->GetDeclaringClass()->GetSuperClass();
5049 if (super == NULL || res_method->GetMethodIndex() > super->GetVTable()->GetLength()) {
5050 if (super == NULL) {
5051 LOG(ERROR) << "VFY: invalid invoke-super from "
5052 << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5053 << "." << method->GetName()->ToModifiedUtf8() << " to super -."
5054 << res_method->GetName()->ToModifiedUtf8()
5055 << " " << res_method->GetSignature()->ToModifiedUtf8();
5056 } else {
5057 LOG(ERROR) << "VFY: invalid invoke-super from "
5058 << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5059 << "." << method->GetName()->ToModifiedUtf8() << " to super "
5060 << super->GetDescriptor()->ToModifiedUtf8()
5061 << "." << res_method->GetName()->ToModifiedUtf8()
5062 << " " << res_method->GetSignature()->ToModifiedUtf8();
5063 }
5064 *failure = VERIFY_ERROR_NO_METHOD;
5065 return NULL;
5066 }
5067 }
5068
5069 /*
5070 * We use vAA as our expected arg count, rather than res_method->insSize,
jeffhaod1f0fde2011-09-08 17:25:33 -07005071 * because we need to match the call to the signature. Also, we might
jeffhaobdb76512011-09-07 11:43:16 -07005072 * might be calling through an abstract method definition (which doesn't
5073 * have register count values).
5074 */
5075 expected_args = dec_insn->vA_;
5076 actual_args = 0;
5077
5078 /* caught by static verifier */
5079 assert(is_range || expected_args <= 5);
5080
5081 if (expected_args > code_item->outs_size_) {
5082 LOG(ERROR) << "VFY: invalid arg count (" << expected_args
5083 << ") exceeds outsSize (" << code_item->outs_size_ << ")";
5084 *failure = VERIFY_ERROR_GENERIC;
5085 return NULL;
5086 }
5087
5088 sig = res_method->GetSignature()->ToModifiedUtf8();
5089 if (sig[0] != '(') {
5090 LOG(ERROR) << "VFY: descriptor doesn't start with '(': " << sig;
5091 goto bad_sig;
5092 }
5093
5094 /*
5095 * Check the "this" argument, which must be an instance of the class
jeffhaod1f0fde2011-09-08 17:25:33 -07005096 * that declared the method. For an interface class, we don't do the
jeffhaobdb76512011-09-07 11:43:16 -07005097 * full interface merge, so we can't do a rigorous check here (which
5098 * is okay since we have to do it at runtime).
5099 */
5100 if (!res_method->IsStatic()) {
5101 Class* actual_this_ref;
5102 RegType actual_arg_type;
5103
5104 actual_arg_type = GetInvocationThis(register_line, dec_insn, failure);
5105 if (*failure != VERIFY_ERROR_NONE)
5106 return NULL;
5107
5108 if (RegTypeIsUninitReference(actual_arg_type) &&
5109 !res_method->GetName()->Equals("<init>")) {
5110 LOG(ERROR) << "VFY: 'this' arg must be initialized";
5111 *failure = VERIFY_ERROR_GENERIC;
5112 return NULL;
5113 }
5114 if (method_type != METHOD_INTERFACE && actual_arg_type != kRegTypeZero) {
5115 actual_this_ref = RegTypeReferenceToClass(actual_arg_type, uninit_map);
5116 if (!res_method->GetDeclaringClass()->IsAssignableFrom(actual_this_ref)) {
5117 LOG(ERROR) << "VFY: 'this' arg '"
5118 << actual_this_ref->GetDescriptor()->ToModifiedUtf8()
5119 << "' not instance of '"
5120 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5121 << "'";
5122 *failure = VERIFY_ERROR_GENERIC;
5123 return NULL;
5124 }
5125 }
5126 actual_args++;
5127 }
5128
5129 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07005130 * Process the target method's signature. This signature may or may not
jeffhaobdb76512011-09-07 11:43:16 -07005131 * have been verified, so we can't assume it's properly formed.
5132 */
5133 for (sig_offset = 1; sig_offset < sig.size(); sig_offset++) {
jeffhaobdb76512011-09-07 11:43:16 -07005134 if (sig[sig_offset] == ')')
5135 break;
5136
5137 if (actual_args >= expected_args) {
5138 LOG(ERROR) << "VFY: expected " << expected_args << " args, found more ("
5139 << sig.substr(sig_offset) << ")";
5140 goto bad_sig;
5141 }
5142
5143 uint32_t get_reg;
5144 if (is_range)
5145 get_reg = dec_insn->vC_ + actual_args;
5146 else
5147 get_reg = dec_insn->arg_[actual_args];
5148
5149 switch (sig[sig_offset]) {
5150 case 'L':
5151 {
5152 Class* klass = LookupSignatureClass(method, sig.substr(sig_offset),
5153 failure);
5154 if (*failure != VERIFY_ERROR_NONE)
5155 goto bad_sig;
5156 VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
5157 failure);
5158 if (*failure != VERIFY_ERROR_NONE) {
5159 LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
5160 << klass->GetDescriptor()->ToModifiedUtf8() << ")";
5161 goto bad_sig;
5162 }
5163 sig_offset += sig.substr(sig_offset).find(';');
5164 }
5165 actual_args++;
5166 break;
5167 case '[':
5168 {
5169 Class* klass = LookupSignatureArrayClass(method,
5170 sig.substr(sig_offset), failure);
5171 if (*failure != VERIFY_ERROR_NONE)
5172 goto bad_sig;
5173 VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
5174 failure);
5175 if (*failure != VERIFY_ERROR_NONE) {
5176 LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
5177 << klass->GetDescriptor()->ToModifiedUtf8() << ")";
5178 goto bad_sig;
5179 }
5180 while (sig[sig_offset] == '[')
5181 sig_offset++;
5182 if (sig[sig_offset] == 'L')
5183 sig_offset += sig.substr(sig_offset).find(';');
5184 }
5185 actual_args++;
5186 break;
5187 case 'Z':
5188 VerifyRegisterType(register_line, get_reg, kRegTypeBoolean, failure);
5189 actual_args++;
5190 break;
5191 case 'C':
5192 VerifyRegisterType(register_line, get_reg, kRegTypeChar, failure);
5193 actual_args++;
5194 break;
5195 case 'B':
5196 VerifyRegisterType(register_line, get_reg, kRegTypeByte, failure);
5197 actual_args++;
5198 break;
5199 case 'I':
5200 VerifyRegisterType(register_line, get_reg, kRegTypeInteger, failure);
5201 actual_args++;
5202 break;
5203 case 'S':
5204 VerifyRegisterType(register_line, get_reg, kRegTypeShort, failure);
5205 actual_args++;
5206 break;
5207 case 'F':
5208 VerifyRegisterType(register_line, get_reg, kRegTypeFloat, failure);
5209 actual_args++;
5210 break;
5211 case 'D':
5212 VerifyRegisterType(register_line, get_reg, kRegTypeDoubleLo, failure);
5213 actual_args += 2;
5214 break;
5215 case 'J':
5216 VerifyRegisterType(register_line, get_reg, kRegTypeLongLo, failure);
5217 actual_args += 2;
5218 break;
5219 default:
5220 LOG(ERROR) << "VFY: invocation target: bad signature type char '"
5221 << sig << "'";
5222 goto bad_sig;
5223 }
5224 }
5225 if (sig[sig_offset] != ')') {
5226 LOG(ERROR) << "VFY: invocation target: bad signature '"
5227 << res_method->GetSignature()->ToModifiedUtf8() << "'";
5228 goto bad_sig;
5229 }
5230
5231 if (actual_args != expected_args) {
5232 LOG(ERROR) << "VFY: expected " << expected_args << " args, found "
5233 << actual_args;
5234 goto bad_sig;
5235 }
5236
5237 return res_method;
5238
5239bad_sig:
5240 if (res_method != NULL) {
5241 LOG(ERROR) << "VFY: rejecting call to "
5242 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5243 << "." << res_method->GetName()->ToModifiedUtf8() << " "
5244 << res_method->GetSignature()->ToModifiedUtf8();
5245 }
5246
5247 if (*failure == VERIFY_ERROR_NONE)
5248 *failure = VERIFY_ERROR_GENERIC;
5249 return NULL;
5250}
jeffhaoba5ebb92011-08-25 17:24:37 -07005251
jeffhaod1f0fde2011-09-08 17:25:33 -07005252DexVerifier::RegisterMap* DexVerifier::GenerateRegisterMapV(VerifierData* vdata)
5253{
5254 const DexFile::CodeItem* code_item = vdata->code_item_;
5255 int i, bytes_for_addr, gc_point_count;
5256
5257 if (code_item->registers_size_ >= 2048) {
5258 LOG(ERROR) << "ERROR: register map can't handle "
5259 << code_item->registers_size_ << " registers";
5260 return NULL;
5261 }
5262 uint8_t reg_width = (code_item->registers_size_ + 7) / 8;
5263
5264 /*
5265 * Decide if we need 8 or 16 bits to hold the address. Strictly speaking
5266 * we only need 16 bits if we actually encode an address >= 256 -- if
5267 * the method has a section at the end without GC points (e.g. array
5268 * data) we don't need to count it. The situation is unusual, and
5269 * detecting it requires scanning the entire method, so we don't bother.
5270 */
5271 RegisterMapFormat format;
5272 if (code_item->insns_size_ < 256) {
5273 format = kRegMapFormatCompact8;
5274 bytes_for_addr = 1;
5275 } else {
5276 format = kRegMapFormatCompact16;
5277 bytes_for_addr = 2;
5278 }
5279
5280 /*
5281 * Count up the number of GC point instructions.
5282 *
5283 * NOTE: this does not automatically include the first instruction,
5284 * since we don't count method entry as a GC point.
5285 */
5286 gc_point_count = 0;
5287 for (i = 0; i < (int) code_item->insns_size_; i++) {
5288 if (InsnIsGcPoint(vdata->insn_flags_.get(), i))
5289 gc_point_count++;
5290 }
5291 if (gc_point_count >= 65536) {
5292 /* We could handle this, but in practice we don't get near this. */
5293 LOG(ERROR) << "ERROR: register map can't handle " << gc_point_count
5294 << " gc points in one method";
5295 return NULL;
5296 }
5297
5298 /* Calculate size of buffer to hold the map data. */
5299 uint32_t data_size = gc_point_count * (bytes_for_addr + reg_width);
5300
5301 RegisterMap* map = new RegisterMap(format, reg_width, gc_point_count,
5302 true, data_size);
5303
5304 /* Populate it. */
5305 uint8_t* map_data = map->data_.get();
5306 for (i = 0; i < (int) vdata->code_item_->insns_size_; i++) {
5307 if (InsnIsGcPoint(vdata->insn_flags_.get(), i)) {
5308 assert(vdata->register_lines_[i].reg_types_.get() != NULL);
5309 if (format == kRegMapFormatCompact8) {
5310 *map_data++ = i;
5311 } else /*kRegMapFormatCompact16*/ {
5312 *map_data++ = i & 0xff;
5313 *map_data++ = i >> 8;
5314 }
5315 OutputTypeVector(vdata->register_lines_[i].reg_types_.get(),
5316 code_item->registers_size_, map_data);
5317 map_data += reg_width;
5318 }
5319 }
5320
5321 assert((uint32_t) map_data - (uint32_t) map->data_.get() == data_size);
5322
5323 // TODO: Remove this check when it's really running...
5324#if 1
5325 if (!VerifyMap(vdata, map)) {
5326 LOG(ERROR) << "Map failed to verify";
5327 return NULL;
5328 }
5329#endif
5330
5331 /* Try to compress the map. */
5332 RegisterMap* compress_map = CompressMapDifferential(map);
5333 if (compress_map != NULL) {
5334 // TODO: Remove this check when it's really running...
5335#if 1
5336 /*
5337 * Expand the compressed map we just created, and compare it
5338 * to the original. Abort the VM if it doesn't match up.
5339 */
5340 UniquePtr<RegisterMap> uncompressed_map(UncompressMapDifferential(compress_map));
5341 if (uncompressed_map.get() == NULL) {
5342 LOG(ERROR) << "Map failed to uncompress - "
5343 << vdata->method_->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5344 << "." << vdata->method_->GetName()->ToModifiedUtf8();
5345 delete map;
5346 delete compress_map;
5347 /* bad - compression is broken or we're out of memory */
5348 return NULL;
5349 } else {
5350 if (!CompareMaps(map, uncompressed_map.get())) {
5351 LOG(ERROR) << "Map comparison failed - "
5352 << vdata->method_->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5353 << "." << vdata->method_->GetName()->ToModifiedUtf8();
5354 delete map;
5355 delete compress_map;
5356 /* bad - compression is broken */
5357 return NULL;
5358 }
5359 }
5360#endif
5361 delete map;
5362 map = compress_map;
5363 }
5364
5365 return map;
5366}
5367
5368void DexVerifier::OutputTypeVector(const RegType* regs, int insn_reg_count,
5369 uint8_t* data) {
5370 uint8_t val = 0;
5371 int i;
5372
5373 for (i = 0; i < insn_reg_count; i++) {
5374 RegType type = *regs++;
5375 val >>= 1;
5376 if (IsReferenceType(type))
5377 val |= 0x80; /* set hi bit */
5378
5379 if ((i & 0x07) == 7)
5380 *data++ = val;
5381 }
5382 if ((i & 0x07) != 0) {
5383 /* Flush bits from last byte. */
5384 val >>= 8 - (i & 0x07);
5385 *data++ = val;
5386 }
5387}
5388
5389bool DexVerifier::VerifyMap(VerifierData* vdata, const RegisterMap* map) {
5390 const uint8_t* raw_map = map->data_.get();
5391 uint8_t format = map->format_;
5392 const int num_entries = map->num_entries_;
5393 int ent;
5394
5395 if ((vdata->code_item_->registers_size_ + 7) / 8 != map->reg_width_) {
5396 LOG(ERROR) << "GLITCH: registersSize=" << vdata->code_item_->registers_size_
5397 << ", reg_width=" << map->reg_width_;
5398 return false;
5399 }
5400
5401 for (ent = 0; ent < num_entries; ent++) {
5402 int addr;
5403
5404 switch (format) {
5405 case kRegMapFormatCompact8:
5406 addr = *raw_map++;
5407 break;
5408 case kRegMapFormatCompact16:
5409 addr = *raw_map++;
5410 addr |= (*raw_map++) << 8;
5411 break;
5412 default:
5413 LOG(FATAL) << "GLITCH: bad format (" << format << ")";
5414 return false;
5415 }
5416
5417 const RegType* regs = vdata->register_lines_[addr].reg_types_.get();
5418 if (regs == NULL) {
5419 LOG(ERROR) << "GLITCH: addr " << addr << " has no data";
5420 return false;
5421 }
5422
5423 uint8_t val = 0;
5424 int i;
5425
5426 for (i = 0; i < vdata->code_item_->registers_size_; i++) {
5427 bool bit_is_ref, reg_is_ref;
5428
5429 val >>= 1;
5430 if ((i & 0x07) == 0) {
5431 /* Load next byte of data. */
5432 val = *raw_map++;
5433 }
5434
5435 bit_is_ref = val & 0x01;
5436
5437 RegType type = regs[i];
5438 reg_is_ref = IsReferenceType(type);
5439
5440 if (bit_is_ref != reg_is_ref) {
5441 LOG(ERROR) << "GLITCH: addr " << addr << " reg " << i << ": bit="
5442 << bit_is_ref << " reg=" << reg_is_ref << "(" << type << ")";
5443 return false;
5444 }
5445 }
5446 /* Raw_map now points to the address field of the next entry. */
5447 }
5448
5449 return true;
5450}
5451
5452bool DexVerifier::CompareMaps(const RegisterMap* map1, const RegisterMap* map2)
5453{
5454 size_t size1, size2;
5455
5456 size1 = ComputeRegisterMapSize(map1);
5457 size2 = ComputeRegisterMapSize(map2);
5458 if (size1 != size2) {
5459 LOG(ERROR) << "CompareMaps: size mismatch (" << size1 << " vs " << size2
5460 << ")";
5461 return false;
5462 }
5463
5464 if (map1->format_ != map2->format_ || map1->reg_width_ != map2->reg_width_ ||
5465 map1->num_entries_ != map2->num_entries_ ||
5466 map1->format_on_heap_ != map2->format_on_heap_) {
5467 LOG(ERROR) << "CompareMaps: fields mismatch";
5468 }
5469 if (memcmp(map1->data_.get(), map2->data_.get(), size1) != 0) {
5470 LOG(ERROR) << "CompareMaps: data mismatch";
5471 return false;
5472 }
5473
5474 return true;
5475}
5476
5477size_t DexVerifier::ComputeRegisterMapSize(const RegisterMap* map) {
5478 uint8_t format = map->format_;
5479 uint16_t num_entries = map->num_entries_;
5480
5481 assert(map != NULL);
5482
5483 switch (format) {
5484 case kRegMapFormatNone:
5485 return 1;
5486 case kRegMapFormatCompact8:
5487 return (1 + map->reg_width_) * num_entries;
5488 case kRegMapFormatCompact16:
5489 return (2 + map->reg_width_) * num_entries;
5490 case kRegMapFormatDifferential:
5491 {
5492 /* Decoded ULEB128 length. */
5493 const uint8_t* ptr = map->data_.get();
5494 return DecodeUnsignedLeb128(&ptr);
5495 }
5496 default:
5497 LOG(FATAL) << "Bad register map format " << format;
5498 return 0;
5499 }
5500}
5501
5502int DexVerifier::ComputeBitDiff(const uint8_t* bits1, const uint8_t* bits2,
5503 int byte_width, int* first_bit_changed_ptr, int* num_bits_changed_ptr,
5504 uint8_t* leb_out_buf) {
5505 int num_bits_changed = 0;
5506 int first_bit_changed = -1;
5507 int leb_size = 0;
5508 int byte_num;
5509
5510 /*
5511 * Run through the vectors, first comparing them at the byte level. This
5512 * will yield a fairly quick result if nothing has changed between them.
5513 */
5514 for (byte_num = 0; byte_num < byte_width; byte_num++) {
5515 uint8_t byte1 = *bits1++;
5516 uint8_t byte2 = *bits2++;
5517 if (byte1 != byte2) {
5518 /* Walk through the byte, identifying the changed bits. */
5519 int bit_num;
5520 for (bit_num = 0; bit_num < 8; bit_num++) {
5521 if (((byte1 >> bit_num) & 0x01) != ((byte2 >> bit_num) & 0x01)) {
5522 int bit_offset = (byte_num << 3) + bit_num;
5523
5524 if (first_bit_changed < 0)
5525 first_bit_changed = bit_offset;
5526 num_bits_changed++;
5527
5528 if (leb_out_buf == NULL) {
5529 leb_size += UnsignedLeb128Size(bit_offset);
5530 } else {
5531 uint8_t* cur_buf = leb_out_buf;
5532 leb_out_buf = WriteUnsignedLeb128(leb_out_buf, bit_offset);
5533 leb_size += leb_out_buf - cur_buf;
5534 }
5535 }
5536 }
5537 }
5538 }
5539
5540 if (num_bits_changed > 0)
5541 assert(first_bit_changed >= 0);
5542
5543 if (first_bit_changed_ptr != NULL)
5544 *first_bit_changed_ptr = first_bit_changed;
5545 if (num_bits_changed_ptr != NULL)
5546 *num_bits_changed_ptr = num_bits_changed;
5547
5548 return leb_size;
5549}
5550
5551DexVerifier::RegisterMap* DexVerifier::CompressMapDifferential(
5552 const RegisterMap* map) {
5553 int orig_size = ComputeRegisterMapSize(map);
5554 uint8_t* tmp_ptr;
5555 int addr_width;
5556
5557 uint8_t format = map->format_;
5558 switch (format) {
5559 case kRegMapFormatCompact8:
5560 addr_width = 1;
5561 break;
5562 case kRegMapFormatCompact16:
5563 addr_width = 2;
5564 break;
5565 default:
5566 LOG(ERROR) << "ERROR: can't compress map with format=" << format;
5567 return NULL;
5568 }
5569
5570 int reg_width = map->reg_width_;
5571 int num_entries = map->num_entries_;
5572
5573 if (num_entries <= 1) {
5574 return NULL;
5575 }
5576
5577 /*
5578 * We don't know how large the compressed data will be. It's possible
5579 * for it to expand and become larger than the original. The header
5580 * itself is variable-sized, so we generate everything into a temporary
5581 * buffer and then copy it to form-fitting storage once we know how big
5582 * it will be (and that it's smaller than the original).
5583 *
5584 * If we use a size that is equal to the size of the input map plus
5585 * a value longer than a single entry can possibly expand to, we need
5586 * only check for overflow at the end of each entry. The worst case
5587 * for a single line is (1 + <ULEB8 address> + <full copy of vector>).
5588 * Addresses are 16 bits, so that's (1 + 3 + reg_width).
5589 *
5590 * The initial address offset and bit vector will take up less than
5591 * or equal to the amount of space required when uncompressed -- large
5592 * initial offsets are rejected.
5593 */
5594 UniquePtr<uint8_t[]> tmp_buf(new uint8_t[orig_size + (1 + 3 + reg_width)]);
5595
5596 tmp_ptr = tmp_buf.get();
5597
5598 const uint8_t* map_data = map->data_.get();
5599 const uint8_t* prev_bits;
5600 uint16_t addr, prev_addr;
5601
5602 addr = *map_data++;
5603 if (addr_width > 1)
5604 addr |= (*map_data++) << 8;
5605
5606 if (addr >= 128) {
5607 LOG(ERROR) << "Can't compress map with starting address >= 128";
5608 return NULL;
5609 }
5610
5611 /*
5612 * Start by writing the initial address and bit vector data. The high
5613 * bit of the initial address is used to indicate the required address
5614 * width (which the decoder can't otherwise determine without parsing
5615 * the compressed data).
5616 */
5617 *tmp_ptr++ = addr | (addr_width > 1 ? 0x80 : 0x00);
5618 memcpy(tmp_ptr, map_data, reg_width);
5619
5620 prev_bits = map_data;
5621 prev_addr = addr;
5622
5623 tmp_ptr += reg_width;
5624 map_data += reg_width;
5625
5626 /* Loop over all following entries. */
5627 for (int entry = 1; entry < num_entries; entry++) {
5628 int addr_diff;
5629 uint8_t key;
5630
5631 /* Pull out the address and figure out how to encode it. */
5632 addr = *map_data++;
5633 if (addr_width > 1)
5634 addr |= (*map_data++) << 8;
5635
5636 addr_diff = addr - prev_addr;
5637 assert(addr_diff > 0);
5638 if (addr_diff < 8) {
5639 /* Small difference, encode in 3 bits. */
5640 key = addr_diff -1; /* set 00000AAA */
5641 } else {
5642 /* Large difference, output escape code. */
5643 key = 0x07; /* escape code for AAA */
5644 }
5645
5646 int num_bits_changed, first_bit_changed, leb_size;
5647
5648 leb_size = ComputeBitDiff(prev_bits, map_data, reg_width,
5649 &first_bit_changed, &num_bits_changed, NULL);
5650
5651 if (num_bits_changed == 0) {
5652 /* set B to 1 and CCCC to zero to indicate no bits were changed */
5653 key |= 0x08;
5654 } else if (num_bits_changed == 1 && first_bit_changed < 16) {
5655 /* set B to 0 and CCCC to the index of the changed bit */
5656 key |= first_bit_changed << 4;
5657 } else if (num_bits_changed < 15 && leb_size < reg_width) {
5658 /* set B to 1 and CCCC to the number of bits */
5659 key |= 0x08 | (num_bits_changed << 4);
5660 } else {
5661 /* set B to 1 and CCCC to 0x0f so we store the entire vector */
5662 key |= 0x08 | 0xf0;
5663 }
5664
5665 /*
5666 * Encode output. Start with the key, follow with the address
5667 * diff (if it didn't fit in 3 bits), then the changed bit info.
5668 */
5669 *tmp_ptr++ = key;
5670 if ((key & 0x07) == 0x07)
5671 tmp_ptr = WriteUnsignedLeb128(tmp_ptr, addr_diff);
5672
5673 if ((key & 0x08) != 0) {
5674 int bit_count = key >> 4;
5675 if (bit_count == 0) {
5676 /* nothing changed, no additional output required */
5677 } else if (bit_count == 15) {
5678 /* full vector is most compact representation */
5679 memcpy(tmp_ptr, map_data, reg_width);
5680 tmp_ptr += reg_width;
5681 } else {
5682 /* write bit indices in ULEB128 format */
5683 (void) ComputeBitDiff(prev_bits, map_data, reg_width,
5684 NULL, NULL, tmp_ptr);
5685 tmp_ptr += leb_size;
5686 }
5687 } else {
5688 /* single-bit changed, value encoded in key byte */
5689 }
5690
5691 prev_bits = map_data;
5692 prev_addr = addr;
5693 map_data += reg_width;
5694
5695 /* See if we've run past the original size. */
5696 if (tmp_ptr - tmp_buf.get() >= orig_size) {
5697 return NULL;
5698 }
5699 }
5700
5701 /*
5702 * Create a RegisterMap with the contents.
5703 *
5704 * TODO: consider using a threshold other than merely ">=". We would
5705 * get poorer compression but potentially use less native heap space.
5706 */
5707 int new_data_size = tmp_ptr - tmp_buf.get();
5708 int new_map_size = new_data_size + UnsignedLeb128Size(new_data_size);
5709
5710 if (new_map_size >= orig_size) {
5711 return NULL;
5712 }
5713
5714 RegisterMap* new_map = new RegisterMap(kRegMapFormatDifferential, reg_width,
5715 num_entries, true, new_map_size);
5716
5717 tmp_ptr = new_map->data_.get();
5718 tmp_ptr = WriteUnsignedLeb128(tmp_ptr, new_data_size);
5719 memcpy(tmp_ptr, tmp_buf.get(), new_data_size);
5720
5721 return new_map;
5722}
5723
5724DexVerifier::RegisterMap* DexVerifier::UncompressMapDifferential(
5725 const RegisterMap* map) {
5726 uint8_t format = map->format_;
5727 RegisterMapFormat new_format;
5728 int reg_width, num_entries, new_addr_width, new_data_size;
5729
5730 if (format != kRegMapFormatDifferential) {
5731 LOG(ERROR) << "Not differential (" << format << ")";
5732 return NULL;
5733 }
5734
5735 reg_width = map->reg_width_;
5736 num_entries = map->num_entries_;
5737
5738 /* Get the data size; we can check this at the end. */
5739 const uint8_t* src_ptr = map->data_.get();
5740 int expected_src_len = DecodeUnsignedLeb128(&src_ptr);
5741 const uint8_t* src_start = src_ptr;
5742
5743 /* Get the initial address and the 16-bit address flag. */
5744 int addr = *src_ptr & 0x7f;
5745 if ((*src_ptr & 0x80) == 0) {
5746 new_format = kRegMapFormatCompact8;
5747 new_addr_width = 1;
5748 } else {
5749 new_format = kRegMapFormatCompact16;
5750 new_addr_width = 2;
5751 }
5752 src_ptr++;
5753
5754 /* Now we know enough to allocate the new map. */
5755 new_data_size = (new_addr_width + reg_width) * num_entries;
5756 RegisterMap* new_map = new RegisterMap(new_format, reg_width, num_entries,
5757 true, new_data_size);
5758
5759 /* Write the start address and initial bits to the new map. */
5760 uint8_t* dst_ptr = new_map->data_.get();
5761
5762 *dst_ptr++ = addr & 0xff;
5763 if (new_addr_width > 1)
5764 *dst_ptr++ = (uint8_t) (addr >> 8);
5765
5766 memcpy(dst_ptr, src_ptr, reg_width);
5767
5768 int prev_addr = addr;
5769 const uint8_t* prev_bits = dst_ptr; /* point at uncompressed data */
5770
5771 dst_ptr += reg_width;
5772 src_ptr += reg_width;
5773
5774 /* Walk through, uncompressing one line at a time. */
5775 int entry;
5776 for (entry = 1; entry < num_entries; entry++) {
5777 int addr_diff;
5778 uint8_t key;
5779
5780 key = *src_ptr++;
5781
5782 /* Get the address. */
5783 if ((key & 0x07) == 7) {
5784 /* Address diff follows in ULEB128. */
5785 addr_diff = DecodeUnsignedLeb128(&src_ptr);
5786 } else {
5787 addr_diff = (key & 0x07) +1;
5788 }
5789
5790 addr = prev_addr + addr_diff;
5791 *dst_ptr++ = addr & 0xff;
5792 if (new_addr_width > 1)
5793 *dst_ptr++ = (uint8_t) (addr >> 8);
5794
5795 /* Unpack the bits. */
5796 if ((key & 0x08) != 0) {
5797 int bit_count = (key >> 4);
5798 if (bit_count == 0) {
5799 /* No bits changed, just copy previous. */
5800 memcpy(dst_ptr, prev_bits, reg_width);
5801 } else if (bit_count == 15) {
5802 /* Full copy of bit vector is present; ignore prev_bits. */
5803 memcpy(dst_ptr, src_ptr, reg_width);
5804 src_ptr += reg_width;
5805 } else {
5806 /* Copy previous bits and modify listed indices. */
5807 memcpy(dst_ptr, prev_bits, reg_width);
5808 while (bit_count--) {
5809 int bit_index = DecodeUnsignedLeb128(&src_ptr);
5810 ToggleBit(dst_ptr, bit_index);
5811 }
5812 }
5813 } else {
5814 /* Copy previous bits and modify the specified one. */
5815 memcpy(dst_ptr, prev_bits, reg_width);
5816
5817 /* One bit, from 0-15 inclusive, was changed. */
5818 ToggleBit(dst_ptr, key >> 4);
5819 }
5820
5821 prev_addr = addr;
5822 prev_bits = dst_ptr;
5823 dst_ptr += reg_width;
5824 }
5825
5826 if (dst_ptr - new_map->data_.get() != new_data_size) {
5827 LOG(ERROR) << "ERROR: output " << dst_ptr - new_map->data_.get()
5828 << " bytes, expected " << new_data_size;
5829 free(new_map);
5830 return NULL;
5831 }
5832
5833 if (src_ptr - src_start != expected_src_len) {
5834 LOG(ERROR) << "ERROR: consumed " << src_ptr - src_start
5835 << " bytes, expected " << expected_src_len;
5836 free(new_map);
5837 return NULL;
5838 }
5839
5840 return new_map;
5841}
5842
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07005843} // namespace art