blob: a800f203874b45049d4b7cbf95e74b72eb4094bf [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_;
319 RegisterTable reg_table;
jeffhaoba5ebb92011-08-25 17:24:37 -0700320
jeffhaobdb76512011-09-07 11:43:16 -0700321 if (registers_size * insns_size > 4*1024*1024) {
322 LOG(ERROR) << "VFY: warning: method is huge (regs=" << registers_size
323 << " insns_size=" << insns_size << ")";
324 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700325
jeffhaobdb76512011-09-07 11:43:16 -0700326 /* Create and initialize register lists. */
jeffhaoa0a764a2011-09-16 10:43:38 -0700327 if (!InitRegisterTable(vdata, &reg_table, kTrackRegsGcPoints)) {
jeffhaobdb76512011-09-07 11:43:16 -0700328 return false;
329 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700330
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700331 vdata->register_lines_ = reg_table.register_lines_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700332
333 /* Allocate a map to hold the classes of uninitialized instances. */
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700334 vdata->uninit_map_.reset(CreateUninitInstanceMap(vdata));
jeffhaobdb76512011-09-07 11:43:16 -0700335
336 /* Initialize register types of method arguments. */
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700337 if (!SetTypesFromSignature(vdata, reg_table.register_lines_[0].reg_types_.get())) {
jeffhaobdb76512011-09-07 11:43:16 -0700338 LOG(ERROR) << "VFY: bad signature '"
339 << method->GetSignature()->ToModifiedUtf8() << "' for "
340 << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
341 << "." << method->GetName()->ToModifiedUtf8();
342 return false;
343 }
344
345 /* Perform code flow verification. */
346 if (!CodeFlowVerifyMethod(vdata, &reg_table)) {
347 return false;
348 }
349
jeffhaoa0a764a2011-09-16 10:43:38 -0700350 /* Generate a register map and add it to the method. */
351 UniquePtr<RegisterMap> map(GenerateRegisterMapV(vdata));
352 ByteArray* header = ByteArray::Alloc(sizeof(RegisterMapHeader));
353 ByteArray* data = ByteArray::Alloc(ComputeRegisterMapSize(map.get()));
jeffhaoe23d93c2011-09-15 14:48:43 -0700354
jeffhaoa0a764a2011-09-16 10:43:38 -0700355 memcpy(header->GetData(), map.get()->header_, sizeof(RegisterMapHeader));
356 memcpy(data->GetData(), map.get()->data_, ComputeRegisterMapSize(map.get()));
jeffhaoe23d93c2011-09-15 14:48:43 -0700357
jeffhaoa0a764a2011-09-16 10:43:38 -0700358 method->SetRegisterMapHeader(header);
359 method->SetRegisterMapData(data);
jeffhaoba5ebb92011-08-25 17:24:37 -0700360
jeffhaobdb76512011-09-07 11:43:16 -0700361 return true;
362}
363
364bool DexVerifier::ComputeWidthsAndCountOps(VerifierData* vdata) {
365 const uint16_t* insns = vdata->code_item_->insns_;
366 uint32_t insns_size = vdata->code_item_->insns_size_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700367 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700368 const byte* ptr = reinterpret_cast<const byte*>(insns);
369 const Instruction* inst = Instruction::At(ptr);
370 size_t new_instance_count = 0;
371 size_t monitor_enter_count = 0;
372 size_t width = 0;
373
374 while (width < insns_size) {
375 Instruction::Code opcode = inst->Opcode();
376 if (opcode == Instruction::NEW_INSTANCE) {
377 new_instance_count++;
378 } else if (opcode == Instruction::MONITOR_ENTER) {
379 monitor_enter_count++;
380 }
381
382 insn_flags[width] |= inst->Size();
383 width += inst->Size();
384 inst = inst->Next();
385 }
386
387 if (width != insns_size) {
388 LOG(ERROR) << "VFY: code did not end where expected (" << width << " vs. "
389 << insns_size << ")";
390 return false;
391 }
392
393 vdata->new_instance_count_ = new_instance_count;
394 vdata->monitor_enter_count_ = monitor_enter_count;
395 return true;
396}
397
398bool DexVerifier::ScanTryCatchBlocks(VerifierData* vdata) {
399 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700400 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700401 uint32_t insns_size = code_item->insns_size_;
402 uint32_t tries_size = code_item->tries_size_;
403
404 if (tries_size == 0) {
405 return true;
406 }
407
408 const DexFile::TryItem* tries = DexFile::dexGetTryItems(*code_item, 0);
409
410 for (uint32_t idx = 0; idx < tries_size; idx++) {
411 const DexFile::TryItem* try_item = &tries[idx];
412 uint32_t start = try_item->start_addr_;
413 uint32_t end = start + try_item->insn_count_;
414
415 if ((start >= end) || (start >= insns_size) || (end > insns_size)) {
416 LOG(ERROR) << "VFY: bad exception entry: startAddr=" << start
417 << " endAddr=" << end << " (size=" << insns_size << ")";
418 return false;
419 }
420
421 if (InsnGetWidth(insn_flags, start) == 0) {
422 LOG(ERROR) << "VFY: 'try' block starts inside an instruction ("
423 << start << ")";
424 return false;
425 }
426
427 uint32_t addr;
428 for (addr = start; addr < end; addr += InsnGetWidth(insn_flags, addr)) {
429 InsnSetInTry(insn_flags, addr);
430 }
431 }
432
433 /* Iterate over each of the handlers to verify target addresses. */
434 const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item, 0);
435 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
436 for (uint32_t idx = 0; idx < handlers_size; idx++) {
437 DexFile::CatchHandlerIterator iterator(handlers_ptr);
438
439 for (; !iterator.HasNext(); iterator.Next()) {
440 uint32_t addr = iterator.Get().address_;
441 if (InsnGetWidth(insn_flags, addr) == 0) {
442 LOG(ERROR) << "VFY: exception handler starts at bad address ("
443 << addr << ")";
444 return false;
445 }
446
447 InsnSetBranchTarget(insn_flags, addr);
448 }
449
450 handlers_ptr = iterator.GetData();
451 }
452
453 return true;
454}
455
456bool DexVerifier::GetBranchOffset(const DexFile::CodeItem* code_item,
457 const InsnFlags insn_flags[], uint32_t cur_offset, int32_t* pOffset,
jeffhaoba5ebb92011-08-25 17:24:37 -0700458 bool* pConditional, bool* selfOkay) {
459 const uint16_t* insns = code_item->insns_ + cur_offset;
460
461 switch (*insns & 0xff) {
462 case Instruction::GOTO:
463 *pOffset = ((int16_t) *insns) >> 8;
464 *pConditional = false;
465 *selfOkay = false;
466 break;
467 case Instruction::GOTO_32:
468 *pOffset = insns[1] | (((uint32_t) insns[2]) << 16);
469 *pConditional = false;
470 *selfOkay = true;
471 break;
472 case Instruction::GOTO_16:
473 *pOffset = (int16_t) insns[1];
474 *pConditional = false;
475 *selfOkay = false;
476 break;
477 case Instruction::IF_EQ:
478 case Instruction::IF_NE:
479 case Instruction::IF_LT:
480 case Instruction::IF_GE:
481 case Instruction::IF_GT:
482 case Instruction::IF_LE:
483 case Instruction::IF_EQZ:
484 case Instruction::IF_NEZ:
485 case Instruction::IF_LTZ:
486 case Instruction::IF_GEZ:
487 case Instruction::IF_GTZ:
488 case Instruction::IF_LEZ:
489 *pOffset = (int16_t) insns[1];
490 *pConditional = true;
491 *selfOkay = false;
492 break;
493 default:
494 return false;
495 break;
496 }
497
498 return true;
499}
500
jeffhaobdb76512011-09-07 11:43:16 -0700501bool DexVerifier::CheckArrayData(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700502 uint32_t cur_offset) {
503 const uint32_t insn_count = code_item->insns_size_;
504 const uint16_t* insns = code_item->insns_ + cur_offset;
505 const uint16_t* array_data;
506 int32_t array_data_offset;
507
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700508 DCHECK_LT(cur_offset, insn_count);
jeffhaoba5ebb92011-08-25 17:24:37 -0700509
510 /* make sure the start of the array data table is in range */
511 array_data_offset = insns[1] | (((int32_t) insns[2]) << 16);
512 if ((int32_t) cur_offset + array_data_offset < 0 ||
513 cur_offset + array_data_offset + 2 >= insn_count)
514 {
515 LOG(ERROR) << "VFY: invalid array data start: at " << cur_offset
516 << ", data offset " << array_data_offset << ", count "
517 << insn_count;
518 return false;
519 }
520
521 /* offset to array data table is a relative branch-style offset */
522 array_data = insns + array_data_offset;
523
524 /* make sure the table is 32-bit aligned */
525 if ((((uint32_t) array_data) & 0x03) != 0) {
526 LOG(ERROR) << "VFY: unaligned array data table: at " << cur_offset
527 << ", data offset " << array_data_offset;
528 return false;
529 }
530
531 uint32_t value_width = array_data[1];
532 uint32_t value_count = *(uint32_t*) (&array_data[2]);
533 uint32_t table_size = 4 + (value_width * value_count + 1) / 2;
534
535 /* make sure the end of the switch is in range */
536 if (cur_offset + array_data_offset + table_size > insn_count) {
537 LOG(ERROR) << "VFY: invalid array data end: at " << cur_offset
538 << ", data offset " << array_data_offset << ", end "
539 << cur_offset + array_data_offset + table_size << ", count "
540 << insn_count;
541 return false;
542 }
543
544 return true;
545}
546
jeffhaobdb76512011-09-07 11:43:16 -0700547bool DexVerifier::CheckNewInstance(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700548 if (idx >= dex_file->GetHeader().type_ids_size_) {
549 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
550 << dex_file->GetHeader().type_ids_size_ << ")";
551 return false;
552 }
553
554 const char* descriptor = dex_file->dexStringByTypeIdx(idx);
555 if (descriptor[0] != 'L') {
556 LOG(ERROR) << "VFY: can't call new-instance on type '"
557 << descriptor << "'";
558 return false;
559 }
560
561 return true;
562}
563
jeffhaobdb76512011-09-07 11:43:16 -0700564bool DexVerifier::CheckNewArray(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700565 if (idx >= dex_file->GetHeader().type_ids_size_) {
566 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
567 << dex_file->GetHeader().type_ids_size_ << ")";
568 return false;
569 }
570
571 int bracket_count = 0;
572 const char* descriptor = dex_file->dexStringByTypeIdx(idx);
573 const char* cp = descriptor;
574 while (*cp++ == '[')
575 bracket_count++;
576
577 if (bracket_count == 0) {
578 /* The given class must be an array type. */
579 LOG(ERROR) << "VFY: can't new-array class '" << descriptor
580 << "' (not an array)";
581 return false;
582 } else if (bracket_count > 255) {
583 /* It is illegal to create an array of more than 255 dimensions. */
584 LOG(ERROR) << "VFY: can't new-array class '" << descriptor
585 << "' (exceeds limit)";
586 return false;
587 }
588
589 return true;
590}
591
jeffhaobdb76512011-09-07 11:43:16 -0700592bool DexVerifier::CheckTypeIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700593 if (idx >= dex_file->GetHeader().type_ids_size_) {
594 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
595 << dex_file->GetHeader().type_ids_size_ << ")";
596 return false;
597 }
598 return true;
599}
600
jeffhaobdb76512011-09-07 11:43:16 -0700601bool DexVerifier::CheckFieldIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700602 if (idx >= dex_file->GetHeader().field_ids_size_) {
603 LOG(ERROR) << "VFY: bad field index " << idx << " (max "
604 << dex_file->GetHeader().field_ids_size_ << ")";
605 return false;
606 }
607 return true;
608}
609
jeffhaobdb76512011-09-07 11:43:16 -0700610bool DexVerifier::CheckMethodIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700611 if (idx >= dex_file->GetHeader().method_ids_size_) {
612 LOG(ERROR) << "VFY: bad method index " << idx << " (max "
613 << dex_file->GetHeader().method_ids_size_ << ")";
614 return false;
615 }
616 return true;
617}
618
jeffhaobdb76512011-09-07 11:43:16 -0700619bool DexVerifier::CheckStringIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700620 if (idx >= dex_file->GetHeader().string_ids_size_) {
621 LOG(ERROR) << "VFY: bad string index " << idx << " (max "
622 << dex_file->GetHeader().string_ids_size_ << ")";
623 return false;
624 }
625 return true;
626}
627
jeffhaobdb76512011-09-07 11:43:16 -0700628bool DexVerifier::CheckRegisterIndex(const DexFile::CodeItem* code_item,
629 uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700630 if (idx >= code_item->registers_size_) {
631 LOG(ERROR) << "VFY: register index out of range (" << idx << " >= "
632 << code_item->registers_size_ << ")";
633 return false;
634 }
635 return true;
636}
637
jeffhaobdb76512011-09-07 11:43:16 -0700638bool DexVerifier::CheckWideRegisterIndex(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700639 uint32_t idx) {
640 if (idx + 1 >= code_item->registers_size_) {
641 LOG(ERROR) << "VFY: wide register index out of range (" << idx
642 << "+1 >= " << code_item->registers_size_ << ")";
643 return false;
644 }
645 return true;
646}
647
jeffhaobdb76512011-09-07 11:43:16 -0700648bool DexVerifier::CheckVarArgRegs(const DexFile::CodeItem* code_item,
649 uint32_t vA, uint32_t arg[]) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700650 uint16_t registers_size = code_item->registers_size_;
651 uint32_t idx;
652
653 if (vA > 5) {
654 LOG(ERROR) << "VFY: invalid arg count (" << vA << ") in non-range invoke)";
655 return false;
656 }
657
658 for (idx = 0; idx < vA; idx++) {
659 if (arg[idx] > registers_size) {
660 LOG(ERROR) << "VFY: invalid reg index (" << arg[idx]
661 << ") in non-range invoke (> " << registers_size << ")";
662 return false;
663 }
664 }
665
666 return true;
667}
668
jeffhaobdb76512011-09-07 11:43:16 -0700669bool DexVerifier::CheckVarArgRangeRegs(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700670 uint32_t vA, uint32_t vC) {
671 uint16_t registers_size = code_item->registers_size_;
672
673 /*
674 * vA/vC are unsigned 8-bit/16-bit quantities for /range instructions,
675 * so there's no risk of integer overflow when adding them here.
676 */
677 if (vA + vC > registers_size) {
678 LOG(ERROR) << "VFY: invalid reg index " << vA << "+" << vC
679 << " in range invoke (> " << registers_size << ")";
680 return false;
681 }
682
683 return true;
684}
685
jeffhaobdb76512011-09-07 11:43:16 -0700686bool DexVerifier::CheckSwitchTargets(const DexFile::CodeItem* code_item,
687 InsnFlags insn_flags[], uint32_t cur_offset) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700688 const uint32_t insn_count = code_item->insns_size_;
689 const uint16_t* insns = code_item->insns_ + cur_offset;
690 const uint16_t* switch_insns;
691 uint16_t expected_signature;
692 uint32_t switch_count, table_size;
693 int32_t switch_offset, keys_offset, targets_offset;
694 int32_t offset, abs_offset;
695 uint32_t targ;
696
697 /* make sure the start of the switch is in range */
698 switch_offset = insns[1] | ((int32_t) insns[2]) << 16;
699 if ((int32_t) cur_offset + switch_offset < 0 ||
700 cur_offset + switch_offset + 2 >= insn_count) {
701 LOG(ERROR) << "VFY: invalid switch start: at " << cur_offset
702 << ", switch offset " << switch_offset << ", count "
703 << insn_count;
704 return false;
705 }
706
707 /* offset to switch table is a relative branch-style offset */
708 switch_insns = insns + switch_offset;
709
710 /* make sure the table is 32-bit aligned */
711 if ((((uint32_t) switch_insns) & 0x03) != 0) {
712 LOG(ERROR) << "VFY: unaligned switch table: at " << cur_offset
713 << ", switch offset " << switch_offset;
714 return false;
715 }
716
717 switch_count = switch_insns[1];
718
719 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
720 /* 0=sig, 1=count, 2/3=firstKey */
721 targets_offset = 4;
722 keys_offset = -1;
723 expected_signature = Instruction::kPackedSwitchSignature;
724 } else {
725 /* 0=sig, 1=count, 2..count*2 = keys */
726 keys_offset = 2;
727 targets_offset = 2 + 2 * switch_count;
728 expected_signature = Instruction::kSparseSwitchSignature;
729 }
730 table_size = targets_offset + switch_count * 2;
731
732 if (switch_insns[0] != expected_signature) {
jeffhaobdb76512011-09-07 11:43:16 -0700733 LOG(ERROR) << "VFY: wrong signature for switch table (0x" << std::hex
734 << switch_insns[0] << ", wanted 0x" << expected_signature << ")"
735 << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700736 return false;
737 }
738
739 /* make sure the end of the switch is in range */
740 if (cur_offset + switch_offset + table_size > (uint32_t) insn_count) {
741 LOG(ERROR) << "VFY: invalid switch end: at " << cur_offset
742 << ", switch offset " << switch_offset << ", end "
743 << cur_offset + switch_offset + table_size << ", count "
744 << insn_count;
745 return false;
746 }
747
748 /* for a sparse switch, verify the keys are in ascending order */
749 if (keys_offset > 0 && switch_count > 1) {
750 int32_t last_key;
751
752 last_key = switch_insns[keys_offset] |
753 (switch_insns[keys_offset + 1] << 16);
754 for (targ = 1; targ < switch_count; targ++) {
755 int32_t key = (int32_t) switch_insns[keys_offset + targ * 2] |
756 (int32_t) (switch_insns[keys_offset + targ * 2 + 1] << 16);
757 if (key <= last_key) {
758 LOG(ERROR) << "VFY: invalid packed switch: last key=" << last_key
759 << ", this=" << key;
760 return false;
761 }
762
763 last_key = key;
764 }
765 }
766
767 /* verify each switch target */
768 for (targ = 0; targ < switch_count; targ++) {
769 offset = (int32_t) switch_insns[targets_offset + targ * 2] |
770 (int32_t) (switch_insns[targets_offset + targ * 2 + 1] << 16);
771 abs_offset = cur_offset + offset;
772
773 if (abs_offset < 0 || abs_offset >= (int32_t) insn_count ||
774 !InsnIsOpcode(insn_flags, abs_offset)) {
775 LOG(ERROR) << "VFY: invalid switch target " << offset << " (-> "
jeffhaobdb76512011-09-07 11:43:16 -0700776 << std::hex << abs_offset << ") at " << cur_offset << std::dec
777 << "[" << targ << "]";
jeffhaoba5ebb92011-08-25 17:24:37 -0700778 return false;
779 }
jeffhaobdb76512011-09-07 11:43:16 -0700780 InsnSetBranchTarget(insn_flags, abs_offset);
jeffhaoba5ebb92011-08-25 17:24:37 -0700781 }
782
783 return true;
784}
785
jeffhaobdb76512011-09-07 11:43:16 -0700786bool DexVerifier::CheckBranchTarget(const DexFile::CodeItem* code_item,
787 InsnFlags insn_flags[], uint32_t cur_offset) {
788 const uint32_t insn_count = code_item->insns_size_;
jeffhaoba5ebb92011-08-25 17:24:37 -0700789 int32_t offset, abs_offset;
790 bool isConditional, selfOkay;
791
792 if (!GetBranchOffset(code_item, insn_flags, cur_offset, &offset,
793 &isConditional, &selfOkay))
794 return false;
795
796 if (!selfOkay && offset == 0) {
jeffhaobdb76512011-09-07 11:43:16 -0700797 LOG(ERROR) << "VFY: branch offset of zero not allowed at" << std::hex
798 << cur_offset << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700799 return false;
800 }
801
802 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700803 * Check for 32-bit overflow. This isn't strictly necessary if we can
jeffhaoba5ebb92011-08-25 17:24:37 -0700804 * depend on the VM to have identical "wrap-around" behavior, but
805 * it's unwise to depend on that.
806 */
807 if (((int64_t) cur_offset + (int64_t) offset) !=
jeffhaobdb76512011-09-07 11:43:16 -0700808 (int64_t) (cur_offset + offset)) {
809 LOG(ERROR) << "VFY: branch target overflow " << std::hex << cur_offset
810 << std::dec << " +" << offset;
jeffhaoba5ebb92011-08-25 17:24:37 -0700811 return false;
812 }
813 abs_offset = cur_offset + offset;
jeffhaobdb76512011-09-07 11:43:16 -0700814 if (abs_offset < 0 || (uint32_t) abs_offset >= insn_count ||
jeffhaoba5ebb92011-08-25 17:24:37 -0700815 !InsnIsOpcode(insn_flags, abs_offset))
816 {
817 LOG(ERROR) << "VFY: invalid branch target " << offset << " (-> "
jeffhaobdb76512011-09-07 11:43:16 -0700818 << std::hex << abs_offset << ") at " << cur_offset << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700819 return false;
820 }
jeffhaobdb76512011-09-07 11:43:16 -0700821 InsnSetBranchTarget(insn_flags, abs_offset);
jeffhaoba5ebb92011-08-25 17:24:37 -0700822
823 return true;
824}
825
jeffhaobdb76512011-09-07 11:43:16 -0700826bool DexVerifier::InitRegisterTable(VerifierData* vdata,
827 RegisterTable* reg_table, RegisterTrackingMode track_regs_for) {
828 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700829 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700830 uint16_t registers_size = code_item->registers_size_;
831 uint32_t insns_size = code_item->insns_size_;
832 uint32_t i;
833
834 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700835 * Every address gets a RegisterLine struct. This is wasteful, but
jeffhaobdb76512011-09-07 11:43:16 -0700836 * not so much that it's worth chasing through an extra level of
837 * indirection.
838 */
839 reg_table->insn_reg_count_plus_ = registers_size + kExtraRegs;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700840 reg_table->register_lines_.reset(new RegisterLine[insns_size]());
jeffhaobdb76512011-09-07 11:43:16 -0700841
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700842 DCHECK_GT(insns_size, 0U);
jeffhaobdb76512011-09-07 11:43:16 -0700843
844 bool track_monitors;
845 //if (gDvm.monitorVerification) {
846 //track_monitors = (vdata->monitor_enter_count_ != 0);
847 //} else {
848 track_monitors = false;
849 //}
850
851 /*
852 * Allocate entries in the sparse register line table.
853 *
854 * There is a RegisterLine associated with every address, but not
855 * every RegisterLine has non-NULL pointers to storage for its fields.
856 */
857 for (i = 0; i < insns_size; i++) {
858 bool interesting;
859
860 switch (track_regs_for) {
861 case kTrackRegsAll:
862 interesting = InsnIsOpcode(insn_flags, i);
863 break;
864 case kTrackRegsGcPoints:
865 interesting = InsnIsGcPoint(insn_flags, i) ||
866 InsnIsBranchTarget(insn_flags, i);
867 break;
868 case kTrackRegsBranches:
869 interesting = InsnIsBranchTarget(insn_flags, i);
870 break;
871 default:
872 return false;
873 }
874
875 if (interesting) {
876 reg_table->register_lines_[i].Alloc(reg_table->insn_reg_count_plus_,
877 track_monitors);
878 }
879 }
880
881 /*
882 * Allocate space for our "temporary" register lines.
883 */
884 reg_table->work_line_.Alloc(reg_table->insn_reg_count_plus_, track_monitors);
885 reg_table->saved_line_.Alloc(reg_table->insn_reg_count_plus_, track_monitors);
886
887 return true;
888}
889
890DexVerifier::UninitInstanceMap* DexVerifier::CreateUninitInstanceMap(
891 VerifierData* vdata) {
892 Method* method = vdata->method_;
893 const DexFile::CodeItem* code_item = vdata->code_item_;
894 size_t new_instance_count = vdata->new_instance_count_;
895
896 if (IsInitMethod(method)) {
897 new_instance_count++;
898 }
899
900 /*
901 * Allocate the header and map as a single unit.
902 *
903 * TODO: consider having a static instance so we can avoid allocations.
904 * I don't think the verifier is guaranteed to be single-threaded when
905 * running in the VM (rather than dexopt), so that must be taken into
906 * account.
907 */
908 UninitInstanceMap* uninit_map = new UninitInstanceMap(new_instance_count);
909
910 size_t idx = 0;
911 if (IsInitMethod(method)) {
912 uninit_map->map_[idx++].addr_ = kUninitThisArgAddr;
913 }
914
915 /*
916 * Run through and find the new-instance instructions.
917 */
918 uint32_t addr = 0;
919 uint32_t insns_size = code_item->insns_size_;
920 const byte* ptr = reinterpret_cast<const byte*>(code_item->insns_);
jeffhaoba5ebb92011-08-25 17:24:37 -0700921 const Instruction* inst = Instruction::At(ptr);
jeffhaobdb76512011-09-07 11:43:16 -0700922 while (addr < insns_size) {
923 Instruction::Code opcode = inst->Opcode();
924 if (opcode == Instruction::NEW_INSTANCE) {
925 uninit_map->map_[idx++].addr_ = addr;
926 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700927
jeffhaobdb76512011-09-07 11:43:16 -0700928 addr += inst->Size();
jeffhaoba5ebb92011-08-25 17:24:37 -0700929 inst = inst->Next();
930 }
931
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700932 CHECK_EQ(idx, new_instance_count);
jeffhaobdb76512011-09-07 11:43:16 -0700933 return uninit_map;
934}
935
936bool DexVerifier::IsInitMethod(const Method* method) {
937 return (method->GetName()->Equals("<init>"));
938}
939
940Class* DexVerifier::LookupClassByDescriptor(const Method* method,
941 const char* descriptor, VerifyError* failure) {
942 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700943 * The compiler occasionally puts references to nonexistent classes in
944 * signatures. For example, if you have a non-static inner class with no
945 * constructor, the compiler provides a private <init> for you.
946 * Constructing the class requires <init>(parent), but the outer class can't
947 * call that because the method is private. So the compiler generates a
948 * package-scope <init>(parent,bogus) method that just calls the regular
949 * <init> (the "bogus" part being necessary to distinguish the signature of
950 * the synthetic method). Treating the bogus class as an instance of
951 * java.lang.Object allows the verifier to process the class successfully.
jeffhaobdb76512011-09-07 11:43:16 -0700952 */
953 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
954 const ClassLoader* class_loader =
955 method->GetDeclaringClass()->GetClassLoader();
956 Class* klass = class_linker->FindClass(descriptor, class_loader);
957
958 if (klass == NULL) {
959 Thread::Current()->ClearException();
960 if (strchr(descriptor, '$') != NULL) {
961 LOG(INFO) << "VFY: unable to find class referenced in signature ("
962 << descriptor << ")";
963 } else {
964 LOG(ERROR) << "VFY: unable to find class referenced in signature ("
965 << descriptor << ")";
966 }
967
968 /* Check if the descriptor is an array. */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700969 if (descriptor[0] == '[' && descriptor[1] != '\0') {
jeffhaobdb76512011-09-07 11:43:16 -0700970 /*
971 * There should never be a problem loading primitive arrays.
972 */
973 if (descriptor[1] != 'L' && descriptor[1] != '[') {
974 LOG(ERROR) << "VFY: invalid char in signature in '" << descriptor
975 << "'";
976 *failure = VERIFY_ERROR_GENERIC;
977 }
978
979 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700980 * Try to continue with base array type. This will let us pass basic
981 * stuff (e.g. get array len) that wouldn't fly with an Object. This
982 * is NOT correct if the missing type is a primitive array, but we
983 * should never have a problem loading those. (I'm not convinced this
984 * is correct or even useful. Just use Object here?)
jeffhaobdb76512011-09-07 11:43:16 -0700985 */
986 klass = class_linker->FindClass("[Ljava/lang/Object;", class_loader);
987 } else if (descriptor[0] == 'L') {
988 /*
989 * We are looking at a non-array reference descriptor;
990 * try to continue with base reference type.
991 */
992 klass = class_linker->FindSystemClass("Ljava/lang/Object;");
993 } else {
994 /* We are looking at a primitive type. */
995 LOG(ERROR) << "VFY: invalid char in signature in '" << descriptor << "'";
996 *failure = VERIFY_ERROR_GENERIC;
997 }
998
999 if (klass == NULL) {
1000 *failure = VERIFY_ERROR_GENERIC;
1001 }
1002 }
1003
1004 if (klass->IsPrimitive()) {
1005 LOG(ERROR) << "VFY: invalid use of primitive type '" << descriptor << "'";
1006 *failure = VERIFY_ERROR_GENERIC;
1007 klass = NULL;
1008 }
1009
1010 return klass;
1011}
1012
1013Class* DexVerifier::LookupSignatureClass(const Method* method, std::string sig,
1014 VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001015 DCHECK_EQ(sig[0], 'L');
jeffhaobdb76512011-09-07 11:43:16 -07001016 size_t end = sig.find(';');
1017
1018 if (end == std::string::npos) {
1019 LOG(ERROR) << "VFY: bad signature component '" << sig << "' (missing ';')";
1020 *failure = VERIFY_ERROR_GENERIC;
1021 return NULL;
1022 }
1023
1024 return LookupClassByDescriptor(method, sig.substr(0, end + 1).c_str(),
1025 failure);
1026}
1027
1028Class* DexVerifier::LookupSignatureArrayClass(const Method* method,
1029 std::string sig, VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001030 DCHECK_EQ(sig[0], '[');
jeffhaobdb76512011-09-07 11:43:16 -07001031 size_t end = 0;
1032
1033 while (sig[end] == '[')
1034 end++;
1035
1036 if (sig[end] == 'L') {
1037 end = sig.find(';');
1038 if (end == std::string::npos) {
1039 LOG(ERROR) << "VFY: bad signature component '" << sig
1040 << "' (missing ';')";
1041 *failure = VERIFY_ERROR_GENERIC;
1042 return NULL;
1043 }
1044 }
1045
1046 return LookupClassByDescriptor(method, sig.substr(0, end + 1).c_str(),
1047 failure);
1048}
1049
1050bool DexVerifier::SetTypesFromSignature(VerifierData* vdata, RegType* reg_types)
1051{
1052 Method* method = vdata->method_;
1053 const DexFile* dex_file = vdata->dex_file_;
1054 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001055 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001056
1057 int arg_start = code_item->registers_size_ - code_item->ins_size_;
1058 int expected_args = code_item->ins_size_; /* long/double count as two */
1059 int actual_args = 0;
1060
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001061 DCHECK_GE(arg_start, 0); /* should have been verified earlier */
jeffhaobdb76512011-09-07 11:43:16 -07001062
1063 /*
1064 * Include the "this" pointer.
1065 */
1066 if (!method->IsStatic()) {
1067 /*
1068 * If this is a constructor for a class other than java.lang.Object,
jeffhaod1f0fde2011-09-08 17:25:33 -07001069 * mark the first ("this") argument as uninitialized. This restricts
jeffhaobdb76512011-09-07 11:43:16 -07001070 * field access until the superclass constructor is called.
1071 */
1072 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1073 Class* klass_object = class_linker->FindSystemClass("Ljava/lang/Object;");
1074 if (IsInitMethod(method) && method->GetDeclaringClass() != klass_object) {
1075 int idx = SetUninitInstance(uninit_map, kUninitThisArgAddr,
1076 method->GetDeclaringClass());
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001077 DCHECK_EQ(idx, 0);
jeffhaobdb76512011-09-07 11:43:16 -07001078 reg_types[arg_start + actual_args] = RegTypeFromUninitIndex(idx);
1079 } else {
1080 reg_types[arg_start + actual_args] =
1081 RegTypeFromClass(method->GetDeclaringClass());
1082 }
1083 actual_args++;
1084 }
1085
1086 const DexFile::ProtoId& proto_id =
1087 dex_file->GetProtoId(method->GetProtoIdx());
1088 DexFile::ParameterIterator iterator(*dex_file, proto_id);
1089 VerifyError failure = VERIFY_ERROR_NONE;
1090
1091 for (; iterator.HasNext(); iterator.Next()) {
1092 const char* descriptor = iterator.GetDescriptor();
1093
1094 if (descriptor == NULL) {
1095 break;
1096 }
1097
1098 if (actual_args >= expected_args) {
1099 LOG(ERROR) << "VFY: expected " << expected_args << " args, found more ("
1100 << descriptor << ")";
1101 return false;
1102 }
1103
1104 switch (*descriptor) {
1105 case 'L':
1106 case '[':
1107 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001108 * We assume that reference arguments are initialized. The only way
1109 * it could be otherwise (assuming the caller was verified) is if
1110 * the current method is <init>, but in that case it's effectively
1111 * considered initialized the instant we reach here (in the sense
1112 * that we can return without doing anything or call virtual methods).
jeffhaobdb76512011-09-07 11:43:16 -07001113 */
1114 {
1115 Class* klass =
1116 LookupClassByDescriptor(method, descriptor, &failure);
1117 if (failure != VERIFY_ERROR_NONE)
1118 return false;
1119 reg_types[arg_start + actual_args] = RegTypeFromClass(klass);
1120 }
1121 actual_args++;
1122 break;
1123 case 'Z':
1124 reg_types[arg_start + actual_args] = kRegTypeBoolean;
1125 actual_args++;
1126 break;
1127 case 'C':
1128 reg_types[arg_start + actual_args] = kRegTypeChar;
1129 actual_args++;
1130 break;
1131 case 'B':
1132 reg_types[arg_start + actual_args] = kRegTypeByte;
1133 actual_args++;
1134 break;
1135 case 'I':
1136 reg_types[arg_start + actual_args] = kRegTypeInteger;
1137 actual_args++;
1138 break;
1139 case 'S':
1140 reg_types[arg_start + actual_args] = kRegTypeShort;
1141 actual_args++;
1142 break;
1143 case 'F':
1144 reg_types[arg_start + actual_args] = kRegTypeFloat;
1145 actual_args++;
1146 break;
1147 case 'D':
1148 reg_types[arg_start + actual_args] = kRegTypeDoubleLo;
1149 reg_types[arg_start + actual_args +1] = kRegTypeDoubleHi;
1150 actual_args += 2;
1151 break;
1152 case 'J':
1153 reg_types[arg_start + actual_args] = kRegTypeLongLo;
1154 reg_types[arg_start + actual_args +1] = kRegTypeLongHi;
1155 actual_args += 2;
1156 break;
1157 default:
1158 LOG(ERROR) << "VFY: unexpected signature type char '" << descriptor
1159 << "'";
1160 return false;
1161 }
1162 }
1163
1164 if (actual_args != expected_args) {
1165 LOG(ERROR) << "VFY: expected " << expected_args << " args, found "
1166 << actual_args;
jeffhaoba5ebb92011-08-25 17:24:37 -07001167 return false;
1168 }
1169
jeffhaobdb76512011-09-07 11:43:16 -07001170 const char* descriptor = dex_file->GetReturnTypeDescriptor(proto_id);
1171
1172 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001173 * Validate return type. We don't do the type lookup; just want to make
1174 * sure that it has the right format. Only major difference from the
jeffhaobdb76512011-09-07 11:43:16 -07001175 * method argument format is that 'V' is supported.
1176 */
1177 switch (*descriptor) {
1178 case 'I':
1179 case 'C':
1180 case 'S':
1181 case 'B':
1182 case 'Z':
1183 case 'V':
1184 case 'F':
1185 case 'D':
1186 case 'J':
1187 if (*(descriptor + 1) != '\0')
1188 return false;
1189 break;
1190 case '[':
1191 /* single/multi, object/primitive */
1192 while (*++descriptor == '[')
1193 ;
1194 if (*descriptor == 'L') {
1195 while (*++descriptor != ';' && *descriptor != '\0')
1196 ;
1197 if (*descriptor != ';')
1198 return false;
1199 } else {
1200 if (*(descriptor+1) != '\0')
1201 return false;
1202 }
1203 break;
1204 case 'L':
1205 /* could be more thorough here, but shouldn't be required */
1206 while (*++descriptor != ';' && *descriptor != '\0')
1207 ;
1208 if (*descriptor != ';')
1209 return false;
1210 break;
1211 default:
1212 return false;
1213 }
1214
jeffhaoba5ebb92011-08-25 17:24:37 -07001215 return true;
1216}
1217
jeffhaobdb76512011-09-07 11:43:16 -07001218int DexVerifier::SetUninitInstance(UninitInstanceMap* uninit_map, int addr,
1219 Class* klass) {
1220 int idx;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001221 DCHECK(klass != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07001222
jeffhaod1f0fde2011-09-08 17:25:33 -07001223 /* TODO: binary search when num_entries > 8 */
jeffhaobdb76512011-09-07 11:43:16 -07001224 for (idx = uninit_map->num_entries_ - 1; idx >= 0; idx--) {
1225 if (uninit_map->map_[idx].addr_ == addr) {
1226 if (uninit_map->map_[idx].klass_ != NULL &&
1227 uninit_map->map_[idx].klass_ != klass) {
1228 LOG(ERROR) << "VFY: addr " << addr << " already set to "
1229 << (int) uninit_map->map_[idx].klass_ << ", not setting to "
1230 << (int) klass;
1231 return -1; // already set to something else??
1232 }
1233 uninit_map->map_[idx].klass_ = klass;
1234 return idx;
1235 }
1236 }
1237
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001238 LOG(FATAL) << "VFY: addr " << addr << " not found in uninit map";
jeffhaobdb76512011-09-07 11:43:16 -07001239 return -1;
1240}
1241
1242bool DexVerifier::CodeFlowVerifyMethod(VerifierData* vdata,
1243 RegisterTable* reg_table) {
1244 const Method* method = vdata->method_;
1245 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001246 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001247 const uint16_t* insns = code_item->insns_;
jeffhaoba5ebb92011-08-25 17:24:37 -07001248 uint32_t insns_size = code_item->insns_size_;
jeffhaobdb76512011-09-07 11:43:16 -07001249 size_t insn_idx, start_guess;
jeffhaoba5ebb92011-08-25 17:24:37 -07001250
jeffhaobdb76512011-09-07 11:43:16 -07001251 /* Begin by marking the first instruction as "changed". */
1252 InsnSetChanged(insn_flags, 0, true);
jeffhaoba5ebb92011-08-25 17:24:37 -07001253
jeffhaobdb76512011-09-07 11:43:16 -07001254 start_guess = 0;
jeffhaoba5ebb92011-08-25 17:24:37 -07001255
jeffhaobdb76512011-09-07 11:43:16 -07001256 /* Continue until no instructions are marked "changed". */
1257 while (true) {
1258 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001259 * Find the first marked one. Use "start_guess" as a way to find
jeffhaobdb76512011-09-07 11:43:16 -07001260 * one quickly.
1261 */
1262 for (insn_idx = start_guess; insn_idx < insns_size; insn_idx++) {
1263 if (InsnIsChanged(insn_flags, insn_idx))
1264 break;
1265 }
jeffhaoba5ebb92011-08-25 17:24:37 -07001266
jeffhaobdb76512011-09-07 11:43:16 -07001267 if (insn_idx == insns_size) {
1268 if (start_guess != 0) {
1269 /* try again, starting from the top */
1270 start_guess = 0;
1271 continue;
1272 } else {
1273 /* all flags are clear */
1274 break;
1275 }
1276 }
1277
1278 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001279 * We carry the working set of registers from instruction to instruction.
1280 * If this address can be the target of a branch (or throw) instruction,
1281 * or if we're skipping around chasing "changed" flags, we need to load
1282 * the set of registers from the table.
jeffhaobdb76512011-09-07 11:43:16 -07001283 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001284 * Because we always prefer to continue on to the next instruction, we
1285 * should never have a situation where we have a stray "changed" flag set
1286 * on an instruction that isn't a branch target.
jeffhaobdb76512011-09-07 11:43:16 -07001287 */
1288 if (InsnIsBranchTarget(insn_flags, insn_idx)) {
1289 RegisterLine* work_line = &reg_table->work_line_;
1290 CopyLineFromTable(work_line, reg_table, insn_idx);
1291 } else {
1292#ifndef NDEBUG
1293 /*
1294 * Sanity check: retrieve the stored register line (assuming
1295 * a full table) and make sure it actually matches.
1296 */
1297 RegisterLine* register_line = GetRegisterLine(reg_table, insn_idx);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001298 if (register_line->reg_types_.get() != NULL && CompareLineToTable(reg_table,
jeffhaobdb76512011-09-07 11:43:16 -07001299 insn_idx, &reg_table->work_line_) != 0) {
1300 Class* klass = method->GetDeclaringClass();
1301 LOG(ERROR) << "HUH? work_line diverged in "
1302 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1303 << method->GetName()->ToModifiedUtf8() << " "
1304 << method->GetSignature()->ToModifiedUtf8();
1305 }
1306#endif
1307 }
1308
1309 if (!CodeFlowVerifyInstruction(vdata, reg_table, insn_idx, &start_guess)) {
1310 Class* klass = method->GetDeclaringClass();
1311 LOG(ERROR) << "VFY: failure to verify "
1312 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1313 << method->GetName()->ToModifiedUtf8() << " "
1314 << method->GetSignature()->ToModifiedUtf8();
jeffhaoba5ebb92011-08-25 17:24:37 -07001315 return false;
1316 }
1317
jeffhaobdb76512011-09-07 11:43:16 -07001318 /* Clear "changed" and mark as visited. */
1319 InsnSetVisited(insn_flags, insn_idx, true);
1320 InsnSetChanged(insn_flags, insn_idx, false);
1321 }
jeffhaoba5ebb92011-08-25 17:24:37 -07001322
jeffhaobdb76512011-09-07 11:43:16 -07001323 if (DEAD_CODE_SCAN && ((method->GetAccessFlags() & kAccWritable) == 0)) {
1324 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001325 * Scan for dead code. There's nothing "evil" about dead code
jeffhaobdb76512011-09-07 11:43:16 -07001326 * (besides the wasted space), but it indicates a flaw somewhere
1327 * down the line, possibly in the verifier.
1328 *
1329 * If we've substituted "always throw" instructions into the stream,
1330 * we are almost certainly going to have some dead code.
1331 */
1332 int dead_start = -1;
1333 for (insn_idx = 0; insn_idx < insns_size;
1334 insn_idx += InsnGetWidth(insn_flags, insn_idx)) {
1335 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001336 * Switch-statement data doesn't get "visited" by scanner. It
jeffhaobdb76512011-09-07 11:43:16 -07001337 * may or may not be preceded by a padding NOP (for alignment).
1338 */
1339 if (insns[insn_idx] == Instruction::kPackedSwitchSignature ||
1340 insns[insn_idx] == Instruction::kSparseSwitchSignature ||
1341 insns[insn_idx] == Instruction::kArrayDataSignature ||
1342 (insns[insn_idx] == Instruction::NOP &&
1343 (insns[insn_idx + 1] == Instruction::kPackedSwitchSignature ||
1344 insns[insn_idx + 1] == Instruction::kSparseSwitchSignature ||
1345 insns[insn_idx + 1] == Instruction::kArrayDataSignature))) {
1346 InsnSetVisited(insn_flags, insn_idx, true);
1347 }
1348
1349 if (!InsnIsVisited(insn_flags, insn_idx)) {
1350 if (dead_start < 0)
1351 dead_start = insn_idx;
1352 } else if (dead_start >= 0) {
1353 Class* klass = method->GetDeclaringClass();
1354 LOG(INFO) << "VFY: dead code 0x" << std::hex << dead_start << "-"
1355 << insn_idx - 1 << std::dec << " in "
1356 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1357 << method->GetName()->ToModifiedUtf8() << " "
1358 << method->GetSignature()->ToModifiedUtf8();
1359 dead_start = -1;
1360 }
1361 }
1362 if (dead_start >= 0) {
1363 Class* klass = method->GetDeclaringClass();
1364 LOG(INFO) << "VFY: dead code 0x" << std::hex << dead_start << "-"
1365 << insn_idx - 1 << std::dec << " in "
1366 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1367 << method->GetName()->ToModifiedUtf8() << " "
1368 << method->GetSignature()->ToModifiedUtf8();
jeffhaoba5ebb92011-08-25 17:24:37 -07001369 }
1370 }
1371
jeffhaobdb76512011-09-07 11:43:16 -07001372 return true;
1373}
1374
1375bool DexVerifier::CodeFlowVerifyInstruction(VerifierData* vdata,
1376 RegisterTable* reg_table, uint32_t insn_idx, size_t* start_guess) {
1377 const Method* method = vdata->method_;
1378 Class* klass = method->GetDeclaringClass();
1379 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001380 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001381 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001382 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001383 const uint16_t* insns = code_item->insns_ + insn_idx;
1384 uint32_t insns_size = code_item->insns_size_;
1385 uint32_t registers_size = code_item->registers_size_;
1386
1387#ifdef VERIFIER_STATS
1388 if (InsnIsVisited(insn_flags, insn_idx)) {
1389 gDvm.verifierStats.instrsReexamined++;
1390 } else {
1391 gDvm.verifierStats.instrsExamined++;
1392 }
1393#endif
1394
1395 /*
1396 * Once we finish decoding the instruction, we need to figure out where
jeffhaod1f0fde2011-09-08 17:25:33 -07001397 * we can go from here. There are three possible ways to transfer
jeffhaobdb76512011-09-07 11:43:16 -07001398 * control to another statement:
1399 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001400 * (1) Continue to the next instruction. Applies to all but
jeffhaobdb76512011-09-07 11:43:16 -07001401 * unconditional branches, method returns, and exception throws.
jeffhaod1f0fde2011-09-08 17:25:33 -07001402 * (2) Branch to one or more possible locations. Applies to branches
jeffhaobdb76512011-09-07 11:43:16 -07001403 * and switch statements.
jeffhaod1f0fde2011-09-08 17:25:33 -07001404 * (3) Exception handlers. Applies to any instruction that can
jeffhaobdb76512011-09-07 11:43:16 -07001405 * throw an exception that is handled by an encompassing "try"
1406 * block.
1407 *
1408 * We can also return, in which case there is no successor instruction
1409 * from this point.
1410 *
1411 * The behavior can be determined from the OpcodeFlags.
1412 */
1413 RegisterLine* work_line = &reg_table->work_line_;
1414 const DexFile* dex_file = vdata->dex_file_;
1415 const byte* ptr = reinterpret_cast<const byte*>(insns);
1416 const Instruction* inst = Instruction::At(ptr);
1417 Instruction::DecodedInstruction dec_insn(inst);
1418 int opcode_flag = inst->Flag();
1419
1420 Class* res_class;
1421 int32_t branch_target = 0;
1422 RegType tmp_type;
1423 bool just_set_result = false;
1424 VerifyError failure = VERIFY_ERROR_NONE;
1425
1426 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001427 * Make a copy of the previous register state. If the instruction
jeffhaobdb76512011-09-07 11:43:16 -07001428 * can throw an exception, we will copy/merge this into the "catch"
1429 * address rather than work_line, because we don't want the result
1430 * from the "successful" code path (e.g. a check-cast that "improves"
1431 * a type) to be visible to the exception handler.
1432 */
1433 if ((opcode_flag & Instruction::kThrow) != 0 &&
1434 InsnIsInTry(insn_flags, insn_idx)) {
1435 CopyRegisterLine(&reg_table->saved_line_, work_line,
1436 reg_table->insn_reg_count_plus_);
1437 } else {
1438#ifndef NDEBUG
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001439 memset(reg_table->saved_line_.reg_types_.get(), 0xdd,
jeffhaobdb76512011-09-07 11:43:16 -07001440 reg_table->insn_reg_count_plus_ * sizeof(RegType));
1441#endif
1442 }
1443
1444 switch (dec_insn.opcode_) {
1445 case Instruction::NOP:
1446 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001447 * A "pure" NOP has no effect on anything. Data tables start with
jeffhaobdb76512011-09-07 11:43:16 -07001448 * a signature that looks like a NOP; if we see one of these in
1449 * the course of executing code then we have a problem.
1450 */
1451 if (dec_insn.vA_ != 0) {
1452 LOG(ERROR) << "VFY: encountered data table in instruction stream";
1453 failure = VERIFY_ERROR_GENERIC;
1454 }
1455 break;
1456
1457 case Instruction::MOVE:
1458 case Instruction::MOVE_FROM16:
1459 case Instruction::MOVE_16:
1460 CopyRegister1(work_line, dec_insn.vA_, dec_insn.vB_, kTypeCategory1nr,
1461 &failure);
1462 break;
1463 case Instruction::MOVE_WIDE:
1464 case Instruction::MOVE_WIDE_FROM16:
1465 case Instruction::MOVE_WIDE_16:
1466 CopyRegister2(work_line, dec_insn.vA_, dec_insn.vB_, &failure);
1467 break;
1468 case Instruction::MOVE_OBJECT:
1469 case Instruction::MOVE_OBJECT_FROM16:
1470 case Instruction::MOVE_OBJECT_16:
1471 CopyRegister1(work_line, dec_insn.vA_, dec_insn.vB_, kTypeCategoryRef,
1472 &failure);
1473 break;
1474
1475 /*
1476 * The move-result instructions copy data out of a "pseudo-register"
jeffhaod1f0fde2011-09-08 17:25:33 -07001477 * with the results from the last method invocation. In practice we
jeffhaobdb76512011-09-07 11:43:16 -07001478 * might want to hold the result in an actual CPU register, so the
1479 * Dalvik spec requires that these only appear immediately after an
1480 * invoke or filled-new-array.
1481 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001482 * These calls invalidate the "result" register. (This is now
jeffhaobdb76512011-09-07 11:43:16 -07001483 * redundant with the reset done below, but it can make the debug info
1484 * easier to read in some cases.)
1485 */
1486 case Instruction::MOVE_RESULT:
1487 CopyResultRegister1(work_line, registers_size, dec_insn.vA_,
1488 kTypeCategory1nr, &failure);
1489 break;
1490 case Instruction::MOVE_RESULT_WIDE:
1491 CopyResultRegister2(work_line, registers_size, dec_insn.vA_, &failure);
1492 break;
1493 case Instruction::MOVE_RESULT_OBJECT:
1494 CopyResultRegister1(work_line, registers_size, dec_insn.vA_,
1495 kTypeCategoryRef, &failure);
1496 break;
1497
1498 case Instruction::MOVE_EXCEPTION:
1499 /*
1500 * This statement can only appear as the first instruction in an
1501 * exception handler (though not all exception handlers need to
jeffhaod1f0fde2011-09-08 17:25:33 -07001502 * have one of these). We verify that as part of extracting the
jeffhaobdb76512011-09-07 11:43:16 -07001503 * exception type from the catch block list.
1504 *
1505 * "res_class" will hold the closest common superclass of all
1506 * exceptions that can be handled here.
1507 */
1508 res_class = GetCaughtExceptionType(vdata, insn_idx, &failure);
1509 if (res_class == NULL) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001510 DCHECK(failure != VERIFY_ERROR_NONE);
jeffhaobdb76512011-09-07 11:43:16 -07001511 } else {
1512 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1513 }
1514 break;
1515
1516 case Instruction::RETURN_VOID:
1517 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1518 failure = VERIFY_ERROR_GENERIC;
1519 } else if (GetMethodReturnType(dex_file, method) != kRegTypeUnknown) {
1520 LOG(ERROR) << "VFY: return-void not expected";
1521 failure = VERIFY_ERROR_GENERIC;
1522 }
1523 break;
1524 case Instruction::RETURN:
1525 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1526 failure = VERIFY_ERROR_GENERIC;
1527 } else {
1528 /* check the method signature */
1529 RegType return_type = GetMethodReturnType(dex_file, method);
1530 CheckTypeCategory(return_type, kTypeCategory1nr, &failure);
1531 if (failure != VERIFY_ERROR_NONE)
1532 LOG(ERROR) << "VFY: return-1nr not expected";
1533
1534 /*
1535 * compiler may generate synthetic functions that write byte
1536 * values into boolean fields. Also, it may use integer values
1537 * for boolean, byte, short, and character return types.
1538 */
1539 RegType src_type = GetRegisterType(work_line, dec_insn.vA_);
1540 if ((return_type == kRegTypeBoolean && src_type == kRegTypeByte) ||
1541 ((return_type == kRegTypeBoolean || return_type == kRegTypeByte ||
1542 return_type == kRegTypeShort || return_type == kRegTypeChar) &&
1543 src_type == kRegTypeInteger))
1544 return_type = src_type;
1545
1546 /* check the register contents */
1547 VerifyRegisterType(work_line, dec_insn.vA_, return_type, &failure);
1548 if (failure != VERIFY_ERROR_NONE) {
1549 LOG(ERROR) << "VFY: return-1nr on invalid register v" << dec_insn.vA_;
1550 }
1551 }
1552 break;
1553 case Instruction::RETURN_WIDE:
1554 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1555 failure = VERIFY_ERROR_GENERIC;
1556 } else {
1557 RegType return_type;
1558
1559 /* check the method signature */
1560 return_type = GetMethodReturnType(dex_file, method);
1561 CheckTypeCategory(return_type, kTypeCategory2, &failure);
1562 if (failure != VERIFY_ERROR_NONE)
1563 LOG(ERROR) << "VFY: return-wide not expected";
1564
1565 /* check the register contents */
1566 VerifyRegisterType(work_line, dec_insn.vA_, return_type, &failure);
1567 if (failure != VERIFY_ERROR_NONE) {
1568 LOG(ERROR) << "VFY: return-wide on invalid register pair v"
1569 << dec_insn.vA_;
1570 }
1571 }
1572 break;
1573 case Instruction::RETURN_OBJECT:
1574 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1575 failure = VERIFY_ERROR_GENERIC;
1576 } else {
1577 RegType return_type = GetMethodReturnType(dex_file, method);
1578 CheckTypeCategory(return_type, kTypeCategoryRef, &failure);
1579 if (failure != VERIFY_ERROR_NONE) {
1580 LOG(ERROR) << "VFY: return-object not expected";
1581 break;
1582 }
1583
1584 /* return_type is the *expected* return type, not register value */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001585 DCHECK(return_type != kRegTypeZero);
1586 DCHECK(!RegTypeIsUninitReference(return_type));
jeffhaobdb76512011-09-07 11:43:16 -07001587
1588 /*
1589 * Verify that the reference in vAA is an instance of the type
jeffhaod1f0fde2011-09-08 17:25:33 -07001590 * in "return_type". The Zero type is allowed here. If the
jeffhaobdb76512011-09-07 11:43:16 -07001591 * method is declared to return an interface, then any
1592 * initialized reference is acceptable.
1593 *
1594 * Note GetClassFromRegister fails if the register holds an
1595 * uninitialized reference, so we do not allow them to be
1596 * returned.
1597 */
1598 Class* decl_class = RegTypeInitializedReferenceToClass(return_type);
1599 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1600 if (failure != VERIFY_ERROR_NONE)
1601 break;
1602 if (res_class != NULL) {
1603 if (!decl_class->IsInterface() &&
jeffhaobdb76512011-09-07 11:43:16 -07001604 !decl_class->IsAssignableFrom(res_class)) {
1605 LOG(ERROR) << "VFY: returning " << std::hex
1606 << res_class->GetDescriptor()->ToModifiedUtf8()
1607 << " (cl=0x" << (int) res_class->GetClassLoader()
1608 << "), declared "
1609 << decl_class->GetDescriptor()->ToModifiedUtf8()
1610 << " (cl=0x" << (int) decl_class->GetClassLoader()
1611 << ")" << std::dec;
1612 failure = VERIFY_ERROR_GENERIC;
1613 break;
1614 }
1615 }
1616 }
1617 break;
1618
1619 case Instruction::CONST_4:
1620 case Instruction::CONST_16:
1621 case Instruction::CONST:
1622 /* could be boolean, int, float, or a null reference */
1623 SetRegisterType(work_line, dec_insn.vA_,
1624 DetermineCat1Const((int32_t) dec_insn.vB_));
1625 break;
1626 case Instruction::CONST_HIGH16:
1627 /* could be boolean, int, float, or a null reference */
1628 SetRegisterType(work_line, dec_insn.vA_,
1629 DetermineCat1Const((int32_t) dec_insn.vB_ << 16));
1630 break;
1631 case Instruction::CONST_WIDE_16:
1632 case Instruction::CONST_WIDE_32:
1633 case Instruction::CONST_WIDE:
1634 case Instruction::CONST_WIDE_HIGH16:
1635 /* could be long or double; resolved upon use */
1636 SetRegisterType(work_line, dec_insn.vA_, kRegTypeConstLo);
1637 break;
1638 case Instruction::CONST_STRING:
1639 case Instruction::CONST_STRING_JUMBO:
1640 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
1641 class_linker->FindSystemClass("Ljava/lang/String;")));
1642 break;
1643 case Instruction::CONST_CLASS:
1644 /* make sure we can resolve the class; access check is important */
jeffhao98eacac2011-09-14 16:11:53 -07001645 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001646 if (res_class == NULL) {
1647 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1648 LOG(ERROR) << "VFY: unable to resolve const-class " << dec_insn.vB_
1649 << " (" << bad_class_desc << ") in "
1650 << klass->GetDescriptor()->ToModifiedUtf8();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001651 DCHECK(failure != VERIFY_ERROR_GENERIC);
jeffhaobdb76512011-09-07 11:43:16 -07001652 } else {
1653 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
1654 class_linker->FindSystemClass("Ljava/lang/Class;")));
1655 }
1656 break;
1657
1658 case Instruction::MONITOR_ENTER:
1659 HandleMonitorEnter(work_line, dec_insn.vA_, insn_idx, &failure);
1660 break;
1661 case Instruction::MONITOR_EXIT:
1662 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001663 * monitor-exit instructions are odd. They can throw exceptions,
jeffhaobdb76512011-09-07 11:43:16 -07001664 * but when they do they act as if they succeeded and the PC is
jeffhaod1f0fde2011-09-08 17:25:33 -07001665 * pointing to the following instruction. (This behavior goes back
jeffhaobdb76512011-09-07 11:43:16 -07001666 * to the need to handle asynchronous exceptions, a now-deprecated
1667 * feature that Dalvik doesn't support.)
1668 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001669 * In practice we don't need to worry about this. The only
jeffhaobdb76512011-09-07 11:43:16 -07001670 * exceptions that can be thrown from monitor-exit are for a
jeffhaod1f0fde2011-09-08 17:25:33 -07001671 * null reference and -exit without a matching -enter. If the
jeffhaobdb76512011-09-07 11:43:16 -07001672 * structured locking checks are working, the former would have
1673 * failed on the -enter instruction, and the latter is impossible.
1674 *
1675 * This is fortunate, because issue 3221411 prevents us from
1676 * chasing the "can throw" path when monitor verification is
jeffhaod1f0fde2011-09-08 17:25:33 -07001677 * enabled. If we can fully verify the locking we can ignore
jeffhaobdb76512011-09-07 11:43:16 -07001678 * some catch blocks (which will show up as "dead" code when
1679 * we skip them here); if we can't, then the code path could be
1680 * "live" so we still need to check it.
1681 */
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001682 if (work_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07001683 opcode_flag &= ~Instruction::kThrow;
1684 HandleMonitorExit(work_line, dec_insn.vA_, insn_idx, &failure);
1685 break;
1686
1687 case Instruction::CHECK_CAST:
1688 /*
1689 * If this instruction succeeds, we will promote register vA to
jeffhaod1f0fde2011-09-08 17:25:33 -07001690 * the type in vB. (This could be a demotion -- not expected, so
jeffhaobdb76512011-09-07 11:43:16 -07001691 * we don't try to address it.)
1692 *
1693 * If it fails, an exception is thrown, which we deal with later
1694 * by ignoring the update to dec_insn.vA_ when branching to a handler.
1695 */
jeffhao98eacac2011-09-14 16:11:53 -07001696 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001697 if (res_class == NULL) {
1698 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1699 LOG(ERROR) << "VFY: unable to resolve check-cast " << dec_insn.vB_
1700 << " (" << bad_class_desc << ") in "
1701 << klass->GetDescriptor()->ToModifiedUtf8();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001702 DCHECK(failure != VERIFY_ERROR_GENERIC);
jeffhaobdb76512011-09-07 11:43:16 -07001703 } else {
1704 RegType orig_type;
1705
1706 orig_type = GetRegisterType(work_line, dec_insn.vA_);
1707 if (!RegTypeIsReference(orig_type)) {
1708 LOG(ERROR) << "VFY: check-cast on non-reference in v" << dec_insn.vA_;
1709 failure = VERIFY_ERROR_GENERIC;
1710 break;
1711 }
1712 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1713 }
1714 break;
1715 case Instruction::INSTANCE_OF:
1716 /* make sure we're checking a reference type */
1717 tmp_type = GetRegisterType(work_line, dec_insn.vB_);
1718 if (!RegTypeIsReference(tmp_type)) {
1719 LOG(ERROR) << "VFY: vB not a reference (" << tmp_type << ")";
1720 failure = VERIFY_ERROR_GENERIC;
1721 break;
1722 }
1723
1724 /* make sure we can resolve the class; access check is important */
jeffhao98eacac2011-09-14 16:11:53 -07001725 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vC_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001726 if (res_class == NULL) {
1727 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vC_);
1728 LOG(ERROR) << "VFY: unable to resolve instanceof " << dec_insn.vC_
1729 << " (" << bad_class_desc << ") in "
1730 << klass->GetDescriptor()->ToModifiedUtf8();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001731 DCHECK(failure != VERIFY_ERROR_GENERIC);
jeffhaobdb76512011-09-07 11:43:16 -07001732 } else {
1733 /* result is boolean */
1734 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1735 }
1736 break;
1737
1738 case Instruction::ARRAY_LENGTH:
1739 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
1740 if (failure != VERIFY_ERROR_NONE)
1741 break;
1742 if (res_class != NULL && !res_class->IsArrayClass()) {
1743 LOG(ERROR) << "VFY: array-length on non-array";
1744 failure = VERIFY_ERROR_GENERIC;
1745 break;
1746 }
1747 SetRegisterType(work_line, dec_insn.vA_, kRegTypeInteger);
1748 break;
1749
1750 case Instruction::NEW_INSTANCE:
jeffhao98eacac2011-09-14 16:11:53 -07001751 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001752 if (res_class == NULL) {
1753 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1754 LOG(ERROR) << "VFY: unable to resolve new-instance " << dec_insn.vB_
1755 << " (" << bad_class_desc << ") in "
1756 << klass->GetDescriptor()->ToModifiedUtf8();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001757 DCHECK(failure != VERIFY_ERROR_GENERIC);
jeffhaobdb76512011-09-07 11:43:16 -07001758 } else {
1759 RegType uninit_type;
1760
1761 /* can't create an instance of an interface or abstract class */
1762 if (res_class->IsAbstract() || res_class->IsInterface()) {
1763 LOG(ERROR) << "VFY: new-instance on interface or abstract class"
1764 << res_class->GetDescriptor()->ToModifiedUtf8();
1765 failure = VERIFY_ERROR_INSTANTIATION;
1766 break;
1767 }
1768
1769 /* add resolved class to uninit map if not already there */
1770 int uidx = SetUninitInstance(uninit_map, insn_idx, res_class);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001771 DCHECK_GE(uidx, 0);
jeffhaobdb76512011-09-07 11:43:16 -07001772 uninit_type = RegTypeFromUninitIndex(uidx);
1773
1774 /*
1775 * Any registers holding previous allocations from this address
1776 * that have not yet been initialized must be marked invalid.
1777 */
1778 MarkUninitRefsAsInvalid(work_line, registers_size, uninit_map,
1779 uninit_type);
1780
1781 /* add the new uninitialized reference to the register ste */
1782 SetRegisterType(work_line, dec_insn.vA_, uninit_type);
1783 }
1784 break;
1785 case Instruction::NEW_ARRAY:
jeffhao98eacac2011-09-14 16:11:53 -07001786 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vC_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001787 if (res_class == NULL) {
1788 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vC_);
1789 LOG(ERROR) << "VFY: unable to resolve new-array " << dec_insn.vC_
1790 << " (" << bad_class_desc << ") in "
1791 << klass->GetDescriptor()->ToModifiedUtf8();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001792 DCHECK(failure != VERIFY_ERROR_GENERIC);
jeffhaobdb76512011-09-07 11:43:16 -07001793 } else if (!res_class->IsArrayClass()) {
1794 LOG(ERROR) << "VFY: new-array on non-array class";
1795 failure = VERIFY_ERROR_GENERIC;
1796 } else {
1797 /* make sure "size" register is valid type */
1798 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeInteger, &failure);
1799 /* set register type to array class */
1800 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1801 }
1802 break;
1803 case Instruction::FILLED_NEW_ARRAY:
1804 case Instruction::FILLED_NEW_ARRAY_RANGE:
jeffhao98eacac2011-09-14 16:11:53 -07001805 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001806 if (res_class == NULL) {
1807 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1808 LOG(ERROR) << "VFY: unable to resolve filled-array " << dec_insn.vB_
1809 << " (" << bad_class_desc << ") in "
1810 << klass->GetDescriptor()->ToModifiedUtf8();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001811 DCHECK(failure != VERIFY_ERROR_GENERIC);
jeffhaobdb76512011-09-07 11:43:16 -07001812 } else if (!res_class->IsArrayClass()) {
1813 LOG(ERROR) << "VFY: filled-new-array on non-array class";
1814 failure = VERIFY_ERROR_GENERIC;
1815 } else {
1816 bool is_range = (dec_insn.opcode_ ==
1817 Instruction::FILLED_NEW_ARRAY_RANGE);
1818
1819 /* check the arguments to the instruction */
1820 VerifyFilledNewArrayRegs(method, work_line, &dec_insn, res_class,
1821 is_range, &failure);
1822 /* filled-array result goes into "result" register */
1823 SetResultRegisterType(work_line, registers_size,
1824 RegTypeFromClass(res_class));
1825 just_set_result = true;
1826 }
1827 break;
1828
1829 case Instruction::CMPL_FLOAT:
1830 case Instruction::CMPG_FLOAT:
1831 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeFloat, &failure);
1832 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeFloat, &failure);
1833 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1834 break;
1835 case Instruction::CMPL_DOUBLE:
1836 case Instruction::CMPG_DOUBLE:
1837 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeDoubleLo, &failure);
1838 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeDoubleLo, &failure);
1839 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1840 break;
1841 case Instruction::CMP_LONG:
1842 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeLongLo, &failure);
1843 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeLongLo, &failure);
1844 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1845 break;
1846
1847 case Instruction::THROW:
1848 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1849 if (failure == VERIFY_ERROR_NONE && res_class != NULL) {
1850 Class* throwable_class =
1851 class_linker->FindSystemClass("Ljava/lang/Throwable;");
1852 if (!throwable_class->IsAssignableFrom(res_class)) {
1853 LOG(ERROR) << "VFY: thrown class "
1854 << res_class->GetDescriptor()->ToModifiedUtf8()
1855 << " not instanceof Throwable",
1856 failure = VERIFY_ERROR_GENERIC;
1857 }
1858 }
1859 break;
1860
1861 case Instruction::GOTO:
1862 case Instruction::GOTO_16:
1863 case Instruction::GOTO_32:
1864 /* no effect on or use of registers */
1865 break;
1866
1867 case Instruction::PACKED_SWITCH:
1868 case Instruction::SPARSE_SWITCH:
1869 /* verify that vAA is an integer, or can be converted to one */
1870 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeInteger, &failure);
1871 break;
1872
1873 case Instruction::FILL_ARRAY_DATA:
1874 {
1875 RegType value_type;
1876 const uint16_t *array_data;
1877 uint16_t elem_width;
1878
1879 /* Similar to the verification done for APUT */
1880 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1881 if (failure != VERIFY_ERROR_NONE)
1882 break;
1883
1884 /* res_class can be null if the reg type is Zero */
1885 if (res_class == NULL)
1886 break;
1887
1888 Class::PrimitiveType prim_type =
1889 res_class->GetComponentType()->GetPrimitiveType();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001890 if (!res_class->IsArrayClass() ||
jeffhaobdb76512011-09-07 11:43:16 -07001891 prim_type == Class::kPrimNot || prim_type == Class::kPrimVoid) {
1892 LOG(ERROR) << "VFY: invalid fill-array-data on " <<
1893 res_class->GetDescriptor()->ToModifiedUtf8();
1894 failure = VERIFY_ERROR_GENERIC;
1895 break;
1896 }
1897
1898 value_type = PrimitiveTypeToRegType(prim_type);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001899 DCHECK(value_type != kRegTypeUnknown);
jeffhaobdb76512011-09-07 11:43:16 -07001900
1901 /*
1902 * Now verify if the element width in the table matches the element
1903 * width declared in the array
1904 */
1905 array_data = insns + (insns[1] | (((int32_t) insns[2]) << 16));
1906 if (array_data[0] != Instruction::kArrayDataSignature) {
1907 LOG(ERROR) << "VFY: invalid magic for array-data";
1908 failure = VERIFY_ERROR_GENERIC;
1909 break;
1910 }
1911
1912 switch (prim_type) {
1913 case Class::kPrimBoolean:
1914 case Class::kPrimByte:
1915 elem_width = 1;
1916 break;
1917 case Class::kPrimChar:
1918 case Class::kPrimShort:
1919 elem_width = 2;
1920 break;
1921 case Class::kPrimFloat:
1922 case Class::kPrimInt:
1923 elem_width = 4;
1924 break;
1925 case Class::kPrimDouble:
1926 case Class::kPrimLong:
1927 elem_width = 8;
1928 break;
1929 default:
1930 elem_width = 0;
1931 break;
1932 }
1933
1934 /*
1935 * Since we don't compress the data in Dex, expect to see equal
1936 * width of data stored in the table and expected from the array
1937 * class.
1938 */
1939 if (array_data[1] != elem_width) {
1940 LOG(ERROR) << "VFY: array-data size mismatch (" << array_data[1]
1941 << " vs " << elem_width << ")";
1942 failure = VERIFY_ERROR_GENERIC;
1943 }
1944 }
1945 break;
1946
1947 case Instruction::IF_EQ:
1948 case Instruction::IF_NE:
1949 {
1950 RegType type1, type2;
1951
1952 type1 = GetRegisterType(work_line, dec_insn.vA_);
1953 type2 = GetRegisterType(work_line, dec_insn.vB_);
1954
1955 /* both references? */
1956 if (RegTypeIsReference(type1) && RegTypeIsReference(type2))
1957 break;
1958
1959 /* both category-1nr? */
1960 CheckTypeCategory(type1, kTypeCategory1nr, &failure);
1961 CheckTypeCategory(type2, kTypeCategory1nr, &failure);
1962 if (failure != VERIFY_ERROR_NONE) {
1963 LOG(ERROR) << "VFY: args to if-eq/if-ne must both be refs or cat1";
1964 break;
1965 }
1966 }
1967 break;
1968 case Instruction::IF_LT:
1969 case Instruction::IF_GE:
1970 case Instruction::IF_GT:
1971 case Instruction::IF_LE:
1972 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
1973 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1974 if (failure != VERIFY_ERROR_NONE) {
1975 LOG(ERROR) << "VFY: args to 'if' must be cat-1nr";
1976 break;
1977 }
1978 tmp_type = GetRegisterType(work_line, dec_insn.vB_);
1979 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1980 if (failure != VERIFY_ERROR_NONE) {
1981 LOG(ERROR) << "VFY: args to 'if' must be cat-1nr";
1982 break;
1983 }
1984 break;
1985 case Instruction::IF_EQZ:
1986 case Instruction::IF_NEZ:
1987 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
1988 if (RegTypeIsReference(tmp_type))
1989 break;
1990 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1991 if (failure != VERIFY_ERROR_NONE)
1992 LOG(ERROR) << "VFY: expected cat-1 arg to if";
1993 break;
1994 case Instruction::IF_LTZ:
1995 case Instruction::IF_GEZ:
1996 case Instruction::IF_GTZ:
1997 case Instruction::IF_LEZ:
1998 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
1999 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
2000 if (failure != VERIFY_ERROR_NONE)
2001 LOG(ERROR) << "VFY: expected cat-1 arg to if";
2002 break;
2003
2004 case Instruction::AGET:
2005 tmp_type = kRegTypeConstInteger;
2006 goto aget_1nr_common;
2007 case Instruction::AGET_BOOLEAN:
2008 tmp_type = kRegTypeBoolean;
2009 goto aget_1nr_common;
2010 case Instruction::AGET_BYTE:
2011 tmp_type = kRegTypeByte;
2012 goto aget_1nr_common;
2013 case Instruction::AGET_CHAR:
2014 tmp_type = kRegTypeChar;
2015 goto aget_1nr_common;
2016 case Instruction::AGET_SHORT:
2017 tmp_type = kRegTypeShort;
2018 goto aget_1nr_common;
2019aget_1nr_common:
2020 {
2021 RegType src_type, index_type;
2022
2023 index_type = GetRegisterType(work_line, dec_insn.vC_);
2024 CheckArrayIndexType(method, index_type, &failure);
2025 if (failure != VERIFY_ERROR_NONE)
2026 break;
2027
2028 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2029 if (failure != VERIFY_ERROR_NONE)
2030 break;
2031 if (res_class != NULL) {
2032 /* verify the class */
2033 Class::PrimitiveType prim_type =
2034 res_class->GetComponentType()->GetPrimitiveType();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002035 if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot) {
jeffhaobdb76512011-09-07 11:43:16 -07002036 LOG(ERROR) << "VFY: invalid aget-1nr target "
2037 << res_class->GetDescriptor()->ToModifiedUtf8();
2038 failure = VERIFY_ERROR_GENERIC;
2039 break;
2040 }
2041
2042 /* make sure array type matches instruction */
2043 src_type = PrimitiveTypeToRegType(prim_type);
2044
2045 /* differentiate between float and int */
2046 if (src_type == kRegTypeFloat || src_type == kRegTypeInteger)
2047 tmp_type = src_type;
2048
2049 if (tmp_type != src_type) {
2050 LOG(ERROR) << "VFY: invalid aget-1nr, array type=" << src_type
2051 << " with inst type=" << tmp_type << " (on "
2052 << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
2053 failure = VERIFY_ERROR_GENERIC;
2054 break;
2055 }
2056
2057 }
2058 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2059 }
2060 break;
2061
2062 case Instruction::AGET_WIDE:
2063 {
2064 RegType dst_type, index_type;
2065
2066 index_type = GetRegisterType(work_line, dec_insn.vC_);
2067 CheckArrayIndexType(method, index_type, &failure);
2068 if (failure != VERIFY_ERROR_NONE)
2069 break;
2070
2071 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2072 if (failure != VERIFY_ERROR_NONE)
2073 break;
2074 if (res_class != NULL) {
2075 /* verify the class */
2076 Class::PrimitiveType prim_type =
2077 res_class->GetComponentType()->GetPrimitiveType();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002078 if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot) {
jeffhaobdb76512011-09-07 11:43:16 -07002079 LOG(ERROR) << "VFY: invalid aget-wide target "
2080 << res_class->GetDescriptor()->ToModifiedUtf8();
2081 failure = VERIFY_ERROR_GENERIC;
2082 break;
2083 }
2084
2085 /* try to refine "dst_type" */
2086 switch (prim_type) {
2087 case Class::kPrimLong:
2088 dst_type = kRegTypeLongLo;
2089 break;
2090 case Class::kPrimDouble:
2091 dst_type = kRegTypeDoubleLo;
2092 break;
2093 default:
2094 LOG(ERROR) << "VFY: invalid aget-wide on "
2095 << res_class->GetDescriptor()->ToModifiedUtf8();
2096 dst_type = kRegTypeUnknown;
2097 failure = VERIFY_ERROR_GENERIC;
2098 break;
2099 }
2100 } else {
2101 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002102 * Null array ref; this code path will fail at runtime. We
jeffhaobdb76512011-09-07 11:43:16 -07002103 * know this is either long or double, so label it const.
2104 */
2105 dst_type = kRegTypeConstLo;
2106 }
2107 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2108 }
2109 break;
2110
2111 case Instruction::AGET_OBJECT:
2112 {
2113 RegType dst_type, index_type;
2114
2115 index_type = GetRegisterType(work_line, dec_insn.vC_);
2116 CheckArrayIndexType(method, index_type, &failure);
2117 if (failure != VERIFY_ERROR_NONE)
2118 break;
2119
2120 /* get the class of the array we're pulling an object from */
2121 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2122 if (failure != VERIFY_ERROR_NONE)
2123 break;
2124 if (res_class != NULL) {
2125 Class* element_class;
2126
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002127 DCHECK(res_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07002128 if (!res_class->IsArrayClass()) {
2129 LOG(ERROR) << "VFY: aget-object on non-array class";
2130 failure = VERIFY_ERROR_GENERIC;
2131 break;
2132 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002133 DCHECK(res_class->GetComponentType() != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07002134
2135 /*
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002136 * Find the element class.
jeffhaobdb76512011-09-07 11:43:16 -07002137 */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002138 element_class = res_class->GetComponentType();
2139 if (element_class->IsPrimitive()) {
jeffhaobdb76512011-09-07 11:43:16 -07002140 LOG(ERROR) << "VFY: aget-object on non-ref array class ("
2141 << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
2142 failure = VERIFY_ERROR_GENERIC;
2143 break;
2144 }
2145
2146 dst_type = RegTypeFromClass(element_class);
2147 } else {
2148 /*
2149 * The array reference is NULL, so the current code path will
jeffhaod1f0fde2011-09-08 17:25:33 -07002150 * throw an exception. For proper merging with later code
jeffhaobdb76512011-09-07 11:43:16 -07002151 * paths, and correct handling of "if-eqz" tests on the
2152 * result of the array get, we want to treat this as a null
2153 * reference.
2154 */
2155 dst_type = kRegTypeZero;
2156 }
2157 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2158 }
2159 break;
2160 case Instruction::APUT:
2161 tmp_type = kRegTypeInteger;
2162 goto aput_1nr_common;
2163 case Instruction::APUT_BOOLEAN:
2164 tmp_type = kRegTypeBoolean;
2165 goto aput_1nr_common;
2166 case Instruction::APUT_BYTE:
2167 tmp_type = kRegTypeByte;
2168 goto aput_1nr_common;
2169 case Instruction::APUT_CHAR:
2170 tmp_type = kRegTypeChar;
2171 goto aput_1nr_common;
2172 case Instruction::APUT_SHORT:
2173 tmp_type = kRegTypeShort;
2174 goto aput_1nr_common;
2175aput_1nr_common:
2176 {
2177 RegType src_type, dst_type, index_type;
2178
2179 index_type = GetRegisterType(work_line, dec_insn.vC_);
2180 CheckArrayIndexType(method, index_type, &failure);
2181 if (failure != VERIFY_ERROR_NONE)
2182 break;
2183
2184 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2185 if (failure != VERIFY_ERROR_NONE)
2186 break;
2187
2188 /* res_class can be null if the reg type is Zero */
2189 if (res_class == NULL)
2190 break;
2191
2192 Class::PrimitiveType prim_type =
2193 res_class->GetComponentType()->GetPrimitiveType();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002194 if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot) {
jeffhaobdb76512011-09-07 11:43:16 -07002195 LOG(ERROR) << "VFY: invalid aput-1nr on "
2196 << res_class->GetDescriptor()->ToModifiedUtf8();
2197 failure = VERIFY_ERROR_GENERIC;
2198 break;
2199 }
2200
2201 /* verify that instruction matches array */
2202 dst_type = PrimitiveTypeToRegType(prim_type);
2203
2204 /* correct if float */
2205 if (dst_type == kRegTypeFloat)
2206 tmp_type = kRegTypeFloat;
2207
2208 /* make sure the source register has the correct type */
2209 src_type = GetRegisterType(work_line, dec_insn.vA_);
2210 if (!CanConvertTo1nr(src_type, tmp_type)) {
2211 LOG(ERROR) << "VFY: invalid reg type " << src_type
2212 << " on aput instr (need " << tmp_type << ")";
2213 failure = VERIFY_ERROR_GENERIC;
2214 break;
2215 }
2216
2217 VerifyRegisterType(work_line, dec_insn.vA_, dst_type, &failure);
2218
2219 if (failure != VERIFY_ERROR_NONE || dst_type == kRegTypeUnknown ||
2220 tmp_type != dst_type) {
2221 LOG(ERROR) << "VFY: invalid aput-1nr on "
2222 << res_class->GetDescriptor()->ToModifiedUtf8()
2223 << " (inst=" << tmp_type << " dst=" << dst_type << ")";
2224 failure = VERIFY_ERROR_GENERIC;
2225 break;
2226 }
2227 }
2228 break;
2229 case Instruction::APUT_WIDE:
2230 tmp_type = GetRegisterType(work_line, dec_insn.vC_);
2231 CheckArrayIndexType(method, tmp_type, &failure);
2232 if (failure != VERIFY_ERROR_NONE)
2233 break;
2234
2235 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2236 if (failure != VERIFY_ERROR_NONE)
2237 break;
2238 if (res_class != NULL) {
2239 Class::PrimitiveType prim_type =
2240 res_class->GetComponentType()->GetPrimitiveType();
2241 /* verify the class and try to refine "dst_type" */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002242 if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot)
jeffhaobdb76512011-09-07 11:43:16 -07002243 {
2244 LOG(ERROR) << "VFY: invalid aput-wide on "
2245 << res_class->GetDescriptor()->ToModifiedUtf8();
2246 failure = VERIFY_ERROR_GENERIC;
2247 break;
2248 }
2249
2250 switch (prim_type) {
2251 case Class::kPrimLong:
2252 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo,
2253 &failure);
2254 break;
2255 case Class::kPrimDouble:
2256 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2257 &failure);
2258 break;
2259 default:
2260 LOG(ERROR) << "VFY: invalid aput-wide on "
2261 << res_class->GetDescriptor()->ToModifiedUtf8();
2262 failure = VERIFY_ERROR_GENERIC;
2263 break;
2264 }
2265 }
2266 break;
2267 case Instruction::APUT_OBJECT:
2268 tmp_type = GetRegisterType(work_line, dec_insn.vC_);
2269 CheckArrayIndexType(method, tmp_type, &failure);
2270 if (failure != VERIFY_ERROR_NONE)
2271 break;
2272
2273 /* get the ref we're storing; Zero is okay, Uninit is not */
2274 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
2275 if (failure != VERIFY_ERROR_NONE)
2276 break;
2277 if (res_class != NULL) {
2278 Class* array_class;
2279 Class* element_class;
2280
2281 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002282 * Get the array class. If the array ref is null, we won't
jeffhaobdb76512011-09-07 11:43:16 -07002283 * have type information (and we'll crash at runtime with a
2284 * null pointer exception).
2285 */
2286 array_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2287
2288 if (array_class != NULL) {
2289 /* see if the array holds a compatible type */
2290 if (!array_class->IsArrayClass()) {
2291 LOG(ERROR) << "VFY: invalid aput-object on "
2292 << array_class->GetDescriptor()->ToModifiedUtf8();
2293 failure = VERIFY_ERROR_GENERIC;
2294 break;
2295 }
2296
2297 /*
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002298 * Find the element class.
jeffhaobdb76512011-09-07 11:43:16 -07002299 *
2300 * All we want to check here is that the element type is a
jeffhaod1f0fde2011-09-08 17:25:33 -07002301 * reference class. We *don't* check instanceof here, because
jeffhaobdb76512011-09-07 11:43:16 -07002302 * you can still put a String into a String[] after the latter
2303 * has been cast to an Object[].
2304 */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002305 element_class = array_class->GetComponentType();
2306 if (element_class->IsPrimitive()) {
jeffhaobdb76512011-09-07 11:43:16 -07002307 LOG(ERROR) << "VFY: invalid aput-object of "
2308 << res_class->GetDescriptor()->ToModifiedUtf8()
2309 << " into "
2310 << array_class->GetDescriptor()->ToModifiedUtf8();
2311 failure = VERIFY_ERROR_GENERIC;
2312 break;
2313 }
2314 }
2315 }
2316 break;
2317
2318 case Instruction::IGET:
2319 tmp_type = kRegTypeInteger;
2320 goto iget_1nr_common;
2321 case Instruction::IGET_BOOLEAN:
2322 tmp_type = kRegTypeBoolean;
2323 goto iget_1nr_common;
2324 case Instruction::IGET_BYTE:
2325 tmp_type = kRegTypeByte;
2326 goto iget_1nr_common;
2327 case Instruction::IGET_CHAR:
2328 tmp_type = kRegTypeChar;
2329 goto iget_1nr_common;
2330 case Instruction::IGET_SHORT:
2331 tmp_type = kRegTypeShort;
2332 goto iget_1nr_common;
2333iget_1nr_common:
2334 {
2335 Field* inst_field;
2336 RegType obj_type, field_type;
2337
2338 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2339 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2340 if (failure != VERIFY_ERROR_NONE)
2341 break;
2342
2343 /* make sure the field's type is compatible with expectation */
2344 field_type =
2345 PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
2346
2347 /* correct if float */
2348 if (field_type == kRegTypeFloat)
2349 tmp_type = kRegTypeFloat;
2350
2351 if (field_type == kRegTypeUnknown || tmp_type != field_type) {
2352 Class* inst_field_class = inst_field->GetDeclaringClass();
2353 LOG(ERROR) << "VFY: invalid iget-1nr of "
2354 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2355 << "." << inst_field->GetName()->ToModifiedUtf8()
2356 << " (inst=" << tmp_type << " field=" << field_type << ")";
2357 failure = VERIFY_ERROR_GENERIC;
2358 break;
2359 }
2360
2361 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2362 }
2363 break;
2364 case Instruction::IGET_WIDE:
2365 {
2366 RegType dst_type;
2367 Field* inst_field;
2368 RegType obj_type;
2369
2370 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2371 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2372 Class* inst_field_class = inst_field->GetDeclaringClass();
2373 if (failure != VERIFY_ERROR_NONE)
2374 break;
2375 /* check the type, which should be prim */
2376 switch (inst_field->GetType()->GetPrimitiveType()) {
2377 case Class::kPrimDouble:
2378 dst_type = kRegTypeDoubleLo;
2379 break;
2380 case Class::kPrimLong:
2381 dst_type = kRegTypeLongLo;
2382 break;
2383 default:
2384 LOG(ERROR) << "VFY: invalid iget-wide of "
2385 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2386 << "." << inst_field->GetName()->ToModifiedUtf8();
2387 dst_type = kRegTypeUnknown;
2388 failure = VERIFY_ERROR_GENERIC;
2389 break;
2390 }
2391 if (failure == VERIFY_ERROR_NONE) {
2392 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2393 }
2394 }
2395 break;
2396 case Instruction::IGET_OBJECT:
2397 {
2398 Class* field_class;
2399 Field* inst_field;
2400 RegType obj_type;
2401
2402 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2403 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2404 if (failure != VERIFY_ERROR_NONE)
2405 break;
2406 field_class = inst_field->GetType();
2407 if (field_class == NULL) {
2408 /* class not found or primitive type */
2409 LOG(ERROR) << "VFY: unable to recover field class from "
2410 << inst_field->GetName()->ToModifiedUtf8();
2411 failure = VERIFY_ERROR_GENERIC;
2412 break;
2413 }
2414 if (failure == VERIFY_ERROR_NONE) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002415 DCHECK(!field_class->IsPrimitive()) << PrettyClass(field_class);
jeffhaobdb76512011-09-07 11:43:16 -07002416 SetRegisterType(work_line, dec_insn.vA_,
2417 RegTypeFromClass(field_class));
2418 }
2419 }
2420 break;
2421 case Instruction::IPUT:
2422 tmp_type = kRegTypeInteger;
2423 goto iput_1nr_common;
2424 case Instruction::IPUT_BOOLEAN:
2425 tmp_type = kRegTypeBoolean;
2426 goto iput_1nr_common;
2427 case Instruction::IPUT_BYTE:
2428 tmp_type = kRegTypeByte;
2429 goto iput_1nr_common;
2430 case Instruction::IPUT_CHAR:
2431 tmp_type = kRegTypeChar;
2432 goto iput_1nr_common;
2433 case Instruction::IPUT_SHORT:
2434 tmp_type = kRegTypeShort;
2435 goto iput_1nr_common;
2436iput_1nr_common:
2437 {
2438 RegType src_type, field_type, obj_type;
2439 Field* inst_field;
2440
2441 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2442 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2443 if (failure != VERIFY_ERROR_NONE)
2444 break;
2445 CheckFinalFieldAccess(method, inst_field, &failure);
2446 if (failure != VERIFY_ERROR_NONE)
2447 break;
2448
2449 /* get type of field we're storing into */
2450 field_type =
2451 PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
2452 src_type = GetRegisterType(work_line, dec_insn.vA_);
2453
2454 /* correct if float */
2455 if (field_type == kRegTypeFloat)
2456 tmp_type = kRegTypeFloat;
2457
2458 /*
2459 * compiler can generate synthetic functions that write byte values
2460 * into boolean fields.
2461 */
2462 if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
2463 tmp_type = kRegTypeByte;
2464 if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
2465 field_type = kRegTypeByte;
2466
2467 /* make sure the source register has the correct type */
2468 if (!CanConvertTo1nr(src_type, tmp_type)) {
2469 LOG(ERROR) << "VFY: invalid reg type " << src_type
2470 << " on iput instr (need " << tmp_type << ")",
2471 failure = VERIFY_ERROR_GENERIC;
2472 break;
2473 }
2474
2475 VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);
2476
2477 if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
2478 tmp_type != field_type) {
2479 Class* inst_field_class = inst_field->GetDeclaringClass();
2480 LOG(ERROR) << "VFY: invalid iput-1nr of "
2481 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2482 << "." << inst_field->GetName()->ToModifiedUtf8()
2483 << " (inst=" << tmp_type << " field=" << field_type << ")";
2484 failure = VERIFY_ERROR_GENERIC;
2485 break;
2486 }
2487 }
2488 break;
2489 case Instruction::IPUT_WIDE:
2490 Field* inst_field;
2491 RegType obj_type;
2492
2493 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2494 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2495 if (failure != VERIFY_ERROR_NONE)
2496 break;
2497 CheckFinalFieldAccess(method, inst_field, &failure);
2498 if (failure != VERIFY_ERROR_NONE)
2499 break;
2500
2501 /* check the type, which should be prim */
2502 switch (inst_field->GetType()->GetPrimitiveType()) {
2503 case Class::kPrimDouble:
2504 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2505 &failure);
2506 break;
2507 case Class::kPrimLong:
2508 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
2509 break;
2510 default:
2511 LOG(ERROR) << "VFY: invalid iput-wide of "
2512 << inst_field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
2513 << "." << inst_field->GetName()->ToModifiedUtf8();
2514 failure = VERIFY_ERROR_GENERIC;
2515 break;
2516 }
2517 break;
2518 case Instruction::IPUT_OBJECT:
2519 {
2520 Class* field_class;
2521 Class* value_class;
2522 Field* inst_field;
2523 RegType obj_type, value_type;
2524
2525 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2526 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2527 if (failure != VERIFY_ERROR_NONE)
2528 break;
2529 CheckFinalFieldAccess(method, inst_field, &failure);
2530 if (failure != VERIFY_ERROR_NONE)
2531 break;
2532
2533 field_class = inst_field->GetType();
2534 if (field_class == NULL) {
2535 LOG(ERROR) << "VFY: unable to recover field class from '"
2536 << inst_field->GetName()->ToModifiedUtf8() << "'";
2537 failure = VERIFY_ERROR_GENERIC;
2538 break;
2539 }
2540
2541 value_type = GetRegisterType(work_line, dec_insn.vA_);
2542 if (!RegTypeIsReference(value_type)) {
2543 LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
2544 << " into ref field '"
2545 << inst_field->GetName()->ToModifiedUtf8() << "' ("
2546 << field_class->GetDescriptor()->ToModifiedUtf8() << ")";
2547 failure = VERIFY_ERROR_GENERIC;
2548 break;
2549 }
2550 if (value_type != kRegTypeZero) {
2551 value_class = RegTypeInitializedReferenceToClass(value_type);
2552 if (value_class == NULL) {
2553 LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
2554 << " into ref field";
2555 failure = VERIFY_ERROR_GENERIC;
2556 break;
2557 }
2558 /* allow if field is any interface or field is base class */
2559 if (!field_class->IsInterface() &&
2560 !field_class->IsAssignableFrom(value_class)) {
2561 Class* inst_field_class = inst_field->GetDeclaringClass();
2562 LOG(ERROR) << "VFY: storing type '"
2563 << value_class->GetDescriptor()->ToModifiedUtf8()
2564 << "' into field type '"
2565 << field_class->GetDescriptor()->ToModifiedUtf8()
2566 << "' ("
2567 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2568 << "." << inst_field->GetName()->ToModifiedUtf8() << ")";
2569 failure = VERIFY_ERROR_GENERIC;
2570 break;
2571 }
2572 }
2573 }
2574 break;
2575
2576 case Instruction::SGET:
2577 tmp_type = kRegTypeInteger;
2578 goto sget_1nr_common;
2579 case Instruction::SGET_BOOLEAN:
2580 tmp_type = kRegTypeBoolean;
2581 goto sget_1nr_common;
2582 case Instruction::SGET_BYTE:
2583 tmp_type = kRegTypeByte;
2584 goto sget_1nr_common;
2585 case Instruction::SGET_CHAR:
2586 tmp_type = kRegTypeChar;
2587 goto sget_1nr_common;
2588 case Instruction::SGET_SHORT:
2589 tmp_type = kRegTypeShort;
2590 goto sget_1nr_common;
2591sget_1nr_common:
2592 {
2593 Field* static_field;
2594 RegType field_type;
2595
2596 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2597 if (failure != VERIFY_ERROR_NONE)
2598 break;
2599
2600 /*
2601 * Make sure the field's type is compatible with expectation.
2602 * We can get ourselves into trouble if we mix & match loads
2603 * and stores with different widths, so rather than just checking
2604 * "CanConvertTo1nr" we require that the field types have equal
2605 * widths.
2606 */
2607 field_type =
2608 PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
2609
2610 /* correct if float */
2611 if (field_type == kRegTypeFloat)
2612 tmp_type = kRegTypeFloat;
2613
2614 if (tmp_type != field_type) {
2615 Class* static_field_class = static_field->GetDeclaringClass();
2616 LOG(ERROR) << "VFY: invalid sget-1nr of "
2617 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2618 << "." << static_field->GetName()->ToModifiedUtf8()
2619 << " (inst=" << tmp_type << " actual=" << field_type
2620 << ")";
2621 failure = VERIFY_ERROR_GENERIC;
2622 break;
2623 }
2624
2625 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2626 }
2627 break;
2628 case Instruction::SGET_WIDE:
2629 {
2630 Field* static_field;
2631 RegType dst_type;
2632
2633 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2634 Class* static_field_class = static_field->GetDeclaringClass();
2635 if (failure != VERIFY_ERROR_NONE)
2636 break;
2637 /* check the type, which should be prim */
2638 switch (static_field->GetType()->GetPrimitiveType()) {
2639 case Class::kPrimDouble:
2640 dst_type = kRegTypeDoubleLo;
2641 break;
2642 case Class::kPrimLong:
2643 dst_type = kRegTypeLongLo;
2644 break;
2645 default:
2646 LOG(ERROR) << "VFY: invalid sget-wide of "
2647 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2648 << "." << static_field->GetName()->ToModifiedUtf8();
2649 dst_type = kRegTypeUnknown;
2650 failure = VERIFY_ERROR_GENERIC;
2651 break;
2652 }
2653 if (failure == VERIFY_ERROR_NONE) {
2654 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2655 }
2656 }
2657 break;
2658 case Instruction::SGET_OBJECT:
2659 {
2660 Field* static_field;
2661 Class* field_class;
2662
2663 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2664 if (failure != VERIFY_ERROR_NONE)
2665 break;
2666 field_class = static_field->GetType();
2667 if (field_class == NULL) {
2668 LOG(ERROR) << "VFY: unable to recover field class from '"
2669 << static_field->GetName()->ToModifiedUtf8() << "'";
2670 failure = VERIFY_ERROR_GENERIC;
2671 break;
2672 }
2673 if (field_class->IsPrimitive()) {
2674 LOG(ERROR) << "VFY: attempt to get prim field with sget-object";
2675 failure = VERIFY_ERROR_GENERIC;
2676 break;
2677 }
2678 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(field_class));
2679 }
2680 break;
2681 case Instruction::SPUT:
2682 tmp_type = kRegTypeInteger;
2683 goto sput_1nr_common;
2684 case Instruction::SPUT_BOOLEAN:
2685 tmp_type = kRegTypeBoolean;
2686 goto sput_1nr_common;
2687 case Instruction::SPUT_BYTE:
2688 tmp_type = kRegTypeByte;
2689 goto sput_1nr_common;
2690 case Instruction::SPUT_CHAR:
2691 tmp_type = kRegTypeChar;
2692 goto sput_1nr_common;
2693 case Instruction::SPUT_SHORT:
2694 tmp_type = kRegTypeShort;
2695 goto sput_1nr_common;
2696sput_1nr_common:
2697 {
2698 RegType src_type, field_type;
2699 Field* static_field;
2700
2701 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2702 if (failure != VERIFY_ERROR_NONE)
2703 break;
2704 CheckFinalFieldAccess(method, static_field, &failure);
2705 if (failure != VERIFY_ERROR_NONE)
2706 break;
2707
2708 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002709 * Get type of field we're storing into. We know that the
jeffhaobdb76512011-09-07 11:43:16 -07002710 * contents of the register match the instruction, but we also
2711 * need to ensure that the instruction matches the field type.
2712 * Using e.g. sput-short to write into a 32-bit integer field
2713 * can lead to trouble if we do 16-bit writes.
2714 */
2715 field_type =
2716 PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
2717 src_type = GetRegisterType(work_line, dec_insn.vA_);
2718
2719 /* correct if float */
2720 if (field_type == kRegTypeFloat)
2721 tmp_type = kRegTypeFloat;
2722
2723 /*
2724 * compiler can generate synthetic functions that write byte values
2725 * into boolean fields.
2726 */
2727 if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
2728 tmp_type = kRegTypeByte;
2729 if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
2730 field_type = kRegTypeByte;
2731
2732 /* make sure the source register has the correct type */
2733 if (!CanConvertTo1nr(src_type, tmp_type)) {
2734 LOG(ERROR) << "VFY: invalid reg type " << src_type
2735 << " on sput instr (need " << tmp_type << ")";
2736 failure = VERIFY_ERROR_GENERIC;
2737 break;
2738 }
2739
2740 VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);
2741
2742 if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
2743 tmp_type != field_type) {
2744 Class* static_field_class = static_field->GetDeclaringClass();
2745 LOG(ERROR) << "VFY: invalid sput-1nr of "
2746 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2747 << "." << static_field->GetName()->ToModifiedUtf8()
2748 << " (inst=" << tmp_type << " actual=" << field_type
2749 << ")";
2750 failure = VERIFY_ERROR_GENERIC;
2751 break;
2752 }
2753 }
2754 break;
2755 case Instruction::SPUT_WIDE:
2756 Field* static_field;
2757
2758 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2759 if (failure != VERIFY_ERROR_NONE)
2760 break;
2761 CheckFinalFieldAccess(method, static_field, &failure);
2762 if (failure != VERIFY_ERROR_NONE)
2763 break;
2764
2765 /* check the type, which should be prim */
2766 switch (static_field->GetType()->GetPrimitiveType()) {
2767 case Class::kPrimDouble:
2768 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2769 &failure);
2770 break;
2771 case Class::kPrimLong:
2772 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
2773 break;
2774 default:
2775 LOG(ERROR) << "VFY: invalid sput-wide of "
2776 << static_field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
2777 << "." << static_field->GetName()->ToModifiedUtf8();
2778 failure = VERIFY_ERROR_GENERIC;
2779 break;
2780 }
2781 break;
2782 case Instruction::SPUT_OBJECT:
2783 {
2784 Class* field_class;
2785 Class* value_class;
2786 Field* static_field;
2787 RegType value_type;
2788
2789 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2790 if (failure != VERIFY_ERROR_NONE)
2791 break;
2792 CheckFinalFieldAccess(method, static_field, &failure);
2793 if (failure != VERIFY_ERROR_NONE)
2794 break;
2795
2796 field_class = static_field->GetType();
2797 if (field_class == NULL) {
2798 LOG(ERROR) << "VFY: unable to recover field class from '"
2799 << static_field->GetName()->ToModifiedUtf8() << "'";
2800 failure = VERIFY_ERROR_GENERIC;
2801 break;
2802 }
2803
2804 value_type = GetRegisterType(work_line, dec_insn.vA_);
2805 if (!RegTypeIsReference(value_type)) {
2806 LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
2807 << " into ref field '"
2808 << static_field->GetName()->ToModifiedUtf8() << "' ("
2809 << field_class->GetDescriptor()->ToModifiedUtf8() << ")",
2810 failure = VERIFY_ERROR_GENERIC;
2811 break;
2812 }
2813 if (value_type != kRegTypeZero) {
2814 value_class = RegTypeInitializedReferenceToClass(value_type);
2815 if (value_class == NULL) {
2816 LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
2817 << " into ref field";
2818 failure = VERIFY_ERROR_GENERIC;
2819 break;
2820 }
2821 /* allow if field is any interface or field is base class */
2822 if (!field_class->IsInterface() &&
2823 !field_class->IsAssignableFrom(value_class)) {
2824 Class* static_field_class = static_field->GetDeclaringClass();
2825 LOG(ERROR) << "VFY: storing type '"
2826 << value_class->GetDescriptor()->ToModifiedUtf8()
2827 << "' into field type '"
2828 << field_class->GetDescriptor()->ToModifiedUtf8()
2829 << "' ("
2830 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2831 << "." << static_field->GetName()->ToModifiedUtf8()
2832 << ")",
2833 failure = VERIFY_ERROR_GENERIC;
2834 break;
2835 }
2836 }
2837 }
2838 break;
2839
2840 case Instruction::INVOKE_VIRTUAL:
2841 case Instruction::INVOKE_VIRTUAL_RANGE:
2842 case Instruction::INVOKE_SUPER:
2843 case Instruction::INVOKE_SUPER_RANGE:
2844 {
2845 Method* called_method;
2846 RegType return_type;
2847 bool is_range;
2848 bool is_super;
2849
2850 is_range = (dec_insn.opcode_ == Instruction::INVOKE_VIRTUAL_RANGE ||
2851 dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
2852 is_super = (dec_insn.opcode_ == Instruction::INVOKE_SUPER ||
2853 dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
2854
2855 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2856 &dec_insn, METHOD_VIRTUAL, is_range, is_super, &failure);
2857 if (failure != VERIFY_ERROR_NONE)
2858 break;
2859 return_type = GetMethodReturnType(dex_file, called_method);
2860 SetResultRegisterType(work_line, registers_size, return_type);
2861 just_set_result = true;
2862 }
2863 break;
2864 case Instruction::INVOKE_DIRECT:
2865 case Instruction::INVOKE_DIRECT_RANGE:
2866 {
2867 RegType return_type;
2868 Method* called_method;
2869 bool is_range;
2870
2871 is_range = (dec_insn.opcode_ == Instruction::INVOKE_DIRECT_RANGE);
2872 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2873 &dec_insn, METHOD_DIRECT, is_range, false, &failure);
2874 if (failure != VERIFY_ERROR_NONE)
2875 break;
2876
2877 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002878 * Some additional checks when calling <init>. We know from
jeffhaobdb76512011-09-07 11:43:16 -07002879 * the invocation arg check that the "this" argument is an
jeffhaod1f0fde2011-09-08 17:25:33 -07002880 * instance of called_method->klass. Now we further restrict
jeffhaobdb76512011-09-07 11:43:16 -07002881 * that to require that called_method->klass is the same as
2882 * this->klass or this->super, allowing the latter only if
2883 * the "this" argument is the same as the "this" argument to
2884 * this method (which implies that we're in <init> ourselves).
2885 */
2886 if (IsInitMethod(called_method)) {
2887 RegType this_type;
2888 this_type = GetInvocationThis(work_line, &dec_insn, &failure);
2889 if (failure != VERIFY_ERROR_NONE)
2890 break;
2891
2892 /* no null refs allowed (?) */
2893 if (this_type == kRegTypeZero) {
2894 LOG(ERROR) << "VFY: unable to initialize null ref";
2895 failure = VERIFY_ERROR_GENERIC;
2896 break;
2897 }
2898
2899 Class* this_class;
2900
2901 this_class = RegTypeReferenceToClass(this_type, uninit_map);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002902 DCHECK(this_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07002903
2904 /* must be in same class or in superclass */
2905 if (called_method->GetDeclaringClass() == this_class->GetSuperClass())
2906 {
2907 if (this_class != method->GetDeclaringClass()) {
2908 LOG(ERROR) << "VFY: invoke-direct <init> on super only "
2909 << "allowed for 'this' in <init>";
2910 failure = VERIFY_ERROR_GENERIC;
2911 break;
2912 }
2913 } else if (called_method->GetDeclaringClass() != this_class) {
2914 LOG(ERROR) << "VFY: invoke-direct <init> must be on current "
2915 << "class or super";
2916 failure = VERIFY_ERROR_GENERIC;
2917 break;
2918 }
2919
2920 /* arg must be an uninitialized reference */
2921 if (!RegTypeIsUninitReference(this_type)) {
2922 LOG(ERROR) << "VFY: can only initialize the uninitialized";
2923 failure = VERIFY_ERROR_GENERIC;
2924 break;
2925 }
2926
2927 /*
2928 * Replace the uninitialized reference with an initialized
jeffhaod1f0fde2011-09-08 17:25:33 -07002929 * one, and clear the entry in the uninit map. We need to
jeffhaobdb76512011-09-07 11:43:16 -07002930 * do this for all registers that have the same object
2931 * instance in them, not just the "this" register.
2932 */
2933 MarkRefsAsInitialized(work_line, registers_size, uninit_map,
2934 this_type, &failure);
2935 if (failure != VERIFY_ERROR_NONE)
2936 break;
2937 }
2938 return_type = GetMethodReturnType(dex_file, called_method);
2939 SetResultRegisterType(work_line, registers_size, return_type);
2940 just_set_result = true;
2941 }
2942 break;
2943 case Instruction::INVOKE_STATIC:
2944 case Instruction::INVOKE_STATIC_RANGE:
2945 {
2946 RegType return_type;
2947 Method* called_method;
2948 bool is_range;
2949
2950 is_range = (dec_insn.opcode_ == Instruction::INVOKE_STATIC_RANGE);
2951 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2952 &dec_insn, METHOD_STATIC, is_range, false, &failure);
2953 if (failure != VERIFY_ERROR_NONE)
2954 break;
2955
2956 return_type = GetMethodReturnType(dex_file, called_method);
2957 SetResultRegisterType(work_line, registers_size, return_type);
2958 just_set_result = true;
2959 }
2960 break;
2961 case Instruction::INVOKE_INTERFACE:
2962 case Instruction::INVOKE_INTERFACE_RANGE:
2963 {
2964 RegType /*this_type,*/ return_type;
2965 Method* abs_method;
2966 bool is_range;
2967
2968 is_range = (dec_insn.opcode_ == Instruction::INVOKE_INTERFACE_RANGE);
2969 abs_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2970 &dec_insn, METHOD_INTERFACE, is_range, false, &failure);
2971 if (failure != VERIFY_ERROR_NONE)
2972 break;
2973
2974#if 0 /* can't do this here, fails on dalvik test 052-verifier-fun */
2975 /*
2976 * Get the type of the "this" arg, which should always be an
jeffhaod1f0fde2011-09-08 17:25:33 -07002977 * interface class. Because we don't do a full merge on
jeffhaobdb76512011-09-07 11:43:16 -07002978 * interface classes, this might have reduced to Object.
2979 */
2980 this_type = GetInvocationThis(work_line, &dec_insn, &failure);
2981 if (failure != VERIFY_ERROR_NONE)
2982 break;
2983
2984 if (this_type == kRegTypeZero) {
2985 /* null pointer always passes (and always fails at runtime) */
2986 } else {
2987 Class* this_class;
2988
2989 this_class = RegTypeInitializedReferenceToClass(this_type);
2990 if (this_class == NULL) {
2991 LOG(ERROR) << "VFY: interface call on uninitialized";
2992 failure = VERIFY_ERROR_GENERIC;
2993 break;
2994 }
2995
2996 /*
2997 * Either "this_class" needs to be the interface class that
2998 * defined abs_method, or abs_method's class needs to be one
jeffhaod1f0fde2011-09-08 17:25:33 -07002999 * of the interfaces implemented by "this_class". (Or, if
jeffhaobdb76512011-09-07 11:43:16 -07003000 * we couldn't complete the merge, this will be Object.)
3001 */
3002 if (this_class != abs_method->GetDeclaringClass() &&
3003 this_class != class_linker->FindSystemClass("Ljava/lang/Object;") &&
3004 !this_class->Implements(abs_method->GetDeclaringClass())) {
3005 LOG(ERROR) << "VFY: unable to match abs_method '"
3006 << abs_method->GetName()->ToModifiedUtf8() << "' with "
3007 << this_class->GetDescriptor()->ToModifiedUtf8()
3008 << " interfaces";
3009 failure = VERIFY_ERROR_GENERIC;
3010 break;
3011 }
3012 }
3013#endif
3014
3015 /*
3016 * We don't have an object instance, so we can't find the
jeffhaod1f0fde2011-09-08 17:25:33 -07003017 * concrete method. However, all of the type information is
jeffhaobdb76512011-09-07 11:43:16 -07003018 * in the abstract method, so we're good.
3019 */
3020 return_type = GetMethodReturnType(dex_file, abs_method);
3021 SetResultRegisterType(work_line, registers_size, return_type);
3022 just_set_result = true;
3023 }
3024 break;
3025
3026 case Instruction::NEG_INT:
3027 case Instruction::NOT_INT:
3028 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3029 &failure);
3030 break;
3031 case Instruction::NEG_LONG:
3032 case Instruction::NOT_LONG:
3033 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo, &failure);
3034 break;
3035 case Instruction::NEG_FLOAT:
3036 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat, &failure);
3037 break;
3038 case Instruction::NEG_DOUBLE:
3039 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3040 &failure);
3041 break;
3042 case Instruction::INT_TO_LONG:
3043 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeInteger,
3044 &failure);
3045 break;
3046 case Instruction::INT_TO_FLOAT:
3047 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeInteger, &failure);
3048 break;
3049 case Instruction::INT_TO_DOUBLE:
3050 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeInteger,
3051 &failure);
3052 break;
3053 case Instruction::LONG_TO_INT:
3054 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeLongLo,
3055 &failure);
3056 break;
3057 case Instruction::LONG_TO_FLOAT:
3058 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeLongLo, &failure);
3059 break;
3060 case Instruction::LONG_TO_DOUBLE:
3061 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeLongLo,
3062 &failure);
3063 break;
3064 case Instruction::FLOAT_TO_INT:
3065 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeFloat, &failure);
3066 break;
3067 case Instruction::FLOAT_TO_LONG:
3068 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeFloat, &failure);
3069 break;
3070 case Instruction::FLOAT_TO_DOUBLE:
3071 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeFloat,
3072 &failure);
3073 break;
3074 case Instruction::DOUBLE_TO_INT:
3075 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeDoubleLo,
3076 &failure);
3077 break;
3078 case Instruction::DOUBLE_TO_LONG:
3079 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeDoubleLo,
3080 &failure);
3081 break;
3082 case Instruction::DOUBLE_TO_FLOAT:
3083 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeDoubleLo,
3084 &failure);
3085 break;
3086 case Instruction::INT_TO_BYTE:
3087 CheckUnop(work_line, &dec_insn, kRegTypeByte, kRegTypeInteger, &failure);
3088 break;
3089 case Instruction::INT_TO_CHAR:
3090 CheckUnop(work_line, &dec_insn, kRegTypeChar, kRegTypeInteger, &failure);
3091 break;
3092 case Instruction::INT_TO_SHORT:
3093 CheckUnop(work_line, &dec_insn, kRegTypeShort, kRegTypeInteger, &failure);
3094 break;
3095
3096 case Instruction::ADD_INT:
3097 case Instruction::SUB_INT:
3098 case Instruction::MUL_INT:
3099 case Instruction::REM_INT:
3100 case Instruction::DIV_INT:
3101 case Instruction::SHL_INT:
3102 case Instruction::SHR_INT:
3103 case Instruction::USHR_INT:
3104 CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3105 kRegTypeInteger, false, &failure);
3106 break;
3107 case Instruction::AND_INT:
3108 case Instruction::OR_INT:
3109 case Instruction::XOR_INT:
3110 CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3111 kRegTypeInteger, true, &failure);
3112 break;
3113 case Instruction::ADD_LONG:
3114 case Instruction::SUB_LONG:
3115 case Instruction::MUL_LONG:
3116 case Instruction::DIV_LONG:
3117 case Instruction::REM_LONG:
3118 case Instruction::AND_LONG:
3119 case Instruction::OR_LONG:
3120 case Instruction::XOR_LONG:
3121 CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3122 kRegTypeLongLo, false, &failure);
3123 break;
3124 case Instruction::SHL_LONG:
3125 case Instruction::SHR_LONG:
3126 case Instruction::USHR_LONG:
3127 /* shift distance is Int, making these different from other binops */
3128 CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3129 kRegTypeInteger, false, &failure);
3130 break;
3131 case Instruction::ADD_FLOAT:
3132 case Instruction::SUB_FLOAT:
3133 case Instruction::MUL_FLOAT:
3134 case Instruction::DIV_FLOAT:
3135 case Instruction::REM_FLOAT:
3136 CheckBinop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
3137 kRegTypeFloat, false, &failure);
3138 break;
3139 case Instruction::ADD_DOUBLE:
3140 case Instruction::SUB_DOUBLE:
3141 case Instruction::MUL_DOUBLE:
3142 case Instruction::DIV_DOUBLE:
3143 case Instruction::REM_DOUBLE:
3144 CheckBinop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3145 kRegTypeDoubleLo, false, &failure);
3146 break;
3147 case Instruction::ADD_INT_2ADDR:
3148 case Instruction::SUB_INT_2ADDR:
3149 case Instruction::MUL_INT_2ADDR:
3150 case Instruction::REM_INT_2ADDR:
3151 case Instruction::SHL_INT_2ADDR:
3152 case Instruction::SHR_INT_2ADDR:
3153 case Instruction::USHR_INT_2ADDR:
3154 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3155 kRegTypeInteger, false, &failure);
3156 break;
3157 case Instruction::AND_INT_2ADDR:
3158 case Instruction::OR_INT_2ADDR:
3159 case Instruction::XOR_INT_2ADDR:
3160 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3161 kRegTypeInteger, true, &failure);
3162 break;
3163 case Instruction::DIV_INT_2ADDR:
3164 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3165 kRegTypeInteger, false, &failure);
3166 break;
3167 case Instruction::ADD_LONG_2ADDR:
3168 case Instruction::SUB_LONG_2ADDR:
3169 case Instruction::MUL_LONG_2ADDR:
3170 case Instruction::DIV_LONG_2ADDR:
3171 case Instruction::REM_LONG_2ADDR:
3172 case Instruction::AND_LONG_2ADDR:
3173 case Instruction::OR_LONG_2ADDR:
3174 case Instruction::XOR_LONG_2ADDR:
3175 CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3176 kRegTypeLongLo, false, &failure);
3177 break;
3178 case Instruction::SHL_LONG_2ADDR:
3179 case Instruction::SHR_LONG_2ADDR:
3180 case Instruction::USHR_LONG_2ADDR:
3181 CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3182 kRegTypeInteger, false, &failure);
3183 break;
3184 case Instruction::ADD_FLOAT_2ADDR:
3185 case Instruction::SUB_FLOAT_2ADDR:
3186 case Instruction::MUL_FLOAT_2ADDR:
3187 case Instruction::DIV_FLOAT_2ADDR:
3188 case Instruction::REM_FLOAT_2ADDR:
3189 CheckBinop2addr(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
3190 kRegTypeFloat, false, &failure);
3191 break;
3192 case Instruction::ADD_DOUBLE_2ADDR:
3193 case Instruction::SUB_DOUBLE_2ADDR:
3194 case Instruction::MUL_DOUBLE_2ADDR:
3195 case Instruction::DIV_DOUBLE_2ADDR:
3196 case Instruction::REM_DOUBLE_2ADDR:
3197 CheckBinop2addr(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3198 kRegTypeDoubleLo, false, &failure);
3199 break;
3200 case Instruction::ADD_INT_LIT16:
3201 case Instruction::RSUB_INT:
3202 case Instruction::MUL_INT_LIT16:
3203 case Instruction::DIV_INT_LIT16:
3204 case Instruction::REM_INT_LIT16:
3205 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
3206 &failure);
3207 break;
3208 case Instruction::AND_INT_LIT16:
3209 case Instruction::OR_INT_LIT16:
3210 case Instruction::XOR_INT_LIT16:
3211 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
3212 &failure);
3213 break;
3214 case Instruction::ADD_INT_LIT8:
3215 case Instruction::RSUB_INT_LIT8:
3216 case Instruction::MUL_INT_LIT8:
3217 case Instruction::DIV_INT_LIT8:
3218 case Instruction::REM_INT_LIT8:
3219 case Instruction::SHL_INT_LIT8:
3220 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
3221 &failure);
3222 break;
3223 case Instruction::SHR_INT_LIT8:
3224 tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
3225 false, &failure);
3226 CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
3227 &failure);
3228 break;
3229 case Instruction::USHR_INT_LIT8:
3230 tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
3231 true, &failure);
3232 CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
3233 &failure);
3234 break;
3235 case Instruction::AND_INT_LIT8:
3236 case Instruction::OR_INT_LIT8:
3237 case Instruction::XOR_INT_LIT8:
3238 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
3239 &failure);
3240 break;
3241
3242 /*
3243 * This falls into the general category of "optimized" instructions,
jeffhaod1f0fde2011-09-08 17:25:33 -07003244 * which don't generally appear during verification. Because it's
jeffhaobdb76512011-09-07 11:43:16 -07003245 * inserted in the course of verification, we can expect to see it here.
3246 */
3247 //case Instruction::THROW_VERIFICATION_ERROR:
3248 case Instruction::UNUSED_ED:
3249 break;
3250
3251 /*
3252 * Verifying "quickened" instructions is tricky, because we have
jeffhaod1f0fde2011-09-08 17:25:33 -07003253 * discarded the original field/method information. The byte offsets
jeffhaobdb76512011-09-07 11:43:16 -07003254 * and vtable indices only have meaning in the context of an object
3255 * instance.
3256 *
3257 * If a piece of code declares a local reference variable, assigns
3258 * null to it, and then issues a virtual method call on it, we
jeffhaod1f0fde2011-09-08 17:25:33 -07003259 * cannot evaluate the method call during verification. This situation
jeffhaobdb76512011-09-07 11:43:16 -07003260 * isn't hard to handle, since we know the call will always result in an
jeffhaod1f0fde2011-09-08 17:25:33 -07003261 * NPE, and the arguments and return value don't matter. Any code that
jeffhaobdb76512011-09-07 11:43:16 -07003262 * depends on the result of the method call is inaccessible, so the
3263 * fact that we can't fully verify anything that comes after the bad
3264 * call is not a problem.
3265 *
3266 * We must also consider the case of multiple code paths, only some of
jeffhaod1f0fde2011-09-08 17:25:33 -07003267 * which involve a null reference. We can completely verify the method
jeffhaobdb76512011-09-07 11:43:16 -07003268 * if we sidestep the results of executing with a null reference.
3269 * For example, if on the first pass through the code we try to do a
3270 * virtual method invocation through a null ref, we have to skip the
3271 * method checks and have the method return a "wildcard" type (which
jeffhaod1f0fde2011-09-08 17:25:33 -07003272 * merges with anything to become that other thing). The move-result
jeffhaobdb76512011-09-07 11:43:16 -07003273 * will tell us if it's a reference, single-word numeric, or double-word
jeffhaod1f0fde2011-09-08 17:25:33 -07003274 * value. We continue to perform the verification, and at the end of
jeffhaobdb76512011-09-07 11:43:16 -07003275 * the function any invocations that were never fully exercised are
3276 * marked as null-only.
3277 *
jeffhaod1f0fde2011-09-08 17:25:33 -07003278 * We would do something similar for the field accesses. The field's
jeffhaobdb76512011-09-07 11:43:16 -07003279 * type, once known, can be used to recover the width of short integers.
3280 * If the object reference was null, the field-get returns the "wildcard"
3281 * type, which is acceptable for any operation.
3282 */
3283 case Instruction::UNUSED_EE:
3284 case Instruction::UNUSED_EF:
3285 case Instruction::UNUSED_F2:
3286 case Instruction::UNUSED_F3:
3287 case Instruction::UNUSED_F4:
3288 case Instruction::UNUSED_F5:
3289 case Instruction::UNUSED_F6:
3290 case Instruction::UNUSED_F7:
3291 case Instruction::UNUSED_F8:
3292 case Instruction::UNUSED_F9:
3293 case Instruction::UNUSED_FA:
3294 case Instruction::UNUSED_FB:
3295 //case Instruction::EXECUTE_INLINE:
3296 //case Instruction::EXECUTE_INLINE_RANGE:
3297 //case Instruction::IGET_QUICK:
3298 //case Instruction::IGET_WIDE_QUICK:
3299 //case Instruction::IGET_OBJECT_QUICK:
3300 //case Instruction::IPUT_QUICK:
3301 //case Instruction::IPUT_WIDE_QUICK:
3302 //case Instruction::IPUT_OBJECT_QUICK:
3303 //case Instruction::INVOKE_VIRTUAL_QUICK:
3304 //case Instruction::INVOKE_VIRTUAL_QUICK_RANGE:
3305 //case Instruction::INVOKE_SUPER_QUICK:
3306 //case Instruction::INVOKE_SUPER_QUICK_RANGE:
3307 /* fall through to failure */
3308
3309 /*
3310 * These instructions are equivalent (from the verifier's point of view)
jeffhaod1f0fde2011-09-08 17:25:33 -07003311 * to the original form. The change was made for correctness rather
jeffhaobdb76512011-09-07 11:43:16 -07003312 * than improved performance (except for invoke-object-init, which
jeffhaod1f0fde2011-09-08 17:25:33 -07003313 * provides both). The substitution takes place after verification
jeffhaobdb76512011-09-07 11:43:16 -07003314 * completes, though, so we don't expect to see them here.
3315 */
3316 case Instruction::UNUSED_F0:
3317 case Instruction::UNUSED_F1:
3318 case Instruction::UNUSED_E3:
3319 case Instruction::UNUSED_E8:
3320 case Instruction::UNUSED_E7:
3321 case Instruction::UNUSED_E4:
3322 case Instruction::UNUSED_E9:
3323 case Instruction::UNUSED_FC:
3324 case Instruction::UNUSED_E5:
3325 case Instruction::UNUSED_EA:
3326 case Instruction::UNUSED_FD:
3327 case Instruction::UNUSED_E6:
3328 case Instruction::UNUSED_EB:
3329 case Instruction::UNUSED_FE:
3330 //case Instruction::INVOKE_OBJECT_INIT_RANGE:
3331 //case Instruction::RETURN_VOID_BARRIER:
3332 //case Instruction::IGET_VOLATILE:
3333 //case Instruction::IGET_WIDE_VOLATILE:
3334 //case Instruction::IGET_OBJECT_VOLATILE:
3335 //case Instruction::IPUT_VOLATILE:
3336 //case Instruction::IPUT_WIDE_VOLATILE:
3337 //case Instruction::IPUT_OBJECT_VOLATILE:
3338 //case Instruction::SGET_VOLATILE:
3339 //case Instruction::SGET_WIDE_VOLATILE:
3340 //case Instruction::SGET_OBJECT_VOLATILE:
3341 //case Instruction::SPUT_VOLATILE:
3342 //case Instruction::SPUT_WIDE_VOLATILE:
3343 //case Instruction::SPUT_OBJECT_VOLATILE:
3344 /* fall through to failure */
3345
3346 /* These should never appear during verification. */
3347 case Instruction::UNUSED_3E:
3348 case Instruction::UNUSED_3F:
3349 case Instruction::UNUSED_40:
3350 case Instruction::UNUSED_41:
3351 case Instruction::UNUSED_42:
3352 case Instruction::UNUSED_43:
3353 case Instruction::UNUSED_73:
3354 case Instruction::UNUSED_79:
3355 case Instruction::UNUSED_7A:
3356 case Instruction::UNUSED_EC:
3357 case Instruction::UNUSED_FF:
3358 //case Instruction::BREAKPOINT:
3359 //case Instruction::DISPATCH_FF:
3360 failure = VERIFY_ERROR_GENERIC;
3361 break;
3362
3363 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003364 * DO NOT add a "default" clause here. Without it the compiler will
jeffhaobdb76512011-09-07 11:43:16 -07003365 * complain if an instruction is missing (which is desirable).
3366 */
3367 }
3368
3369 if (failure != VERIFY_ERROR_NONE) {
jeffhaobdb76512011-09-07 11:43:16 -07003370 if (failure == VERIFY_ERROR_GENERIC) {
3371 /* immediate failure, reject class */
3372 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
3373 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3374 return false;
3375 } else {
jeffhao98eacac2011-09-14 16:11:53 -07003376 // TODO: CHECK IF THIS WILL WORK!
3377 /* ignore the failure and move on */
3378 LOG(ERROR) << "VFY: failing opcode 0x" << std::hex
3379 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3380 failure = VERIFY_ERROR_NONE;
3381#if 0
jeffhaobdb76512011-09-07 11:43:16 -07003382 /* replace opcode and continue on */
3383 LOG(ERROR) << "VFY: replacing opcode 0x" << std::hex
3384 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3385 if (!ReplaceFailingInstruction(code_item, insn_flags, insn_idx, failure))
3386 {
3387 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
3388 << (int) dec_insn.opcode_ << " at 0x" << insn_idx
3389 << std::dec;
3390 return false;
3391 }
3392 /* IMPORTANT: method->insns may have been changed */
3393 insns = code_item->insns_ + insn_idx;
3394
3395 /* continue on as if we just handled a throw-verification-error */
3396 failure = VERIFY_ERROR_NONE;
3397 opcode_flag = Instruction::kThrow;
jeffhao98eacac2011-09-14 16:11:53 -07003398#endif
jeffhaobdb76512011-09-07 11:43:16 -07003399 }
3400 }
3401
3402 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003403 * If we didn't just set the result register, clear it out. This
jeffhaobdb76512011-09-07 11:43:16 -07003404 * ensures that you can only use "move-result" immediately after the
jeffhaod1f0fde2011-09-08 17:25:33 -07003405 * result is set. (We could check this statically, but it's not
jeffhaobdb76512011-09-07 11:43:16 -07003406 * expensive and it makes our debugging output cleaner.)
3407 */
3408 if (!just_set_result) {
3409 int reg = RESULT_REGISTER(registers_size);
3410 SetRegisterType(work_line, reg, kRegTypeUnknown);
3411 SetRegisterType(work_line, reg + 1, kRegTypeUnknown);
3412 }
3413
jeffhaoa0a764a2011-09-16 10:43:38 -07003414 /* Handle "continue". Tag the next consecutive instruction. */
jeffhaobdb76512011-09-07 11:43:16 -07003415 if ((opcode_flag & Instruction::kContinue) != 0) {
3416 size_t insn_width = InsnGetWidth(insn_flags, insn_idx);
3417 if (insn_idx + insn_width >= insns_size) {
3418 LOG(ERROR) << "VFY: execution can walk off end of code area (from 0x"
3419 << std::hex << insn_idx << std::dec << ")";
3420 return false;
3421 }
3422
3423 /*
3424 * The only way to get to a move-exception instruction is to get
jeffhaod1f0fde2011-09-08 17:25:33 -07003425 * thrown there. Make sure the next instruction isn't one.
jeffhaobdb76512011-09-07 11:43:16 -07003426 */
3427 if (!CheckMoveException(code_item->insns_, insn_idx + insn_width))
3428 return false;
3429
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003430 if (GetRegisterLine(reg_table, insn_idx + insn_width)->reg_types_.get() != NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003431 /*
3432 * Merge registers into what we have for the next instruction,
3433 * and set the "changed" flag if needed.
3434 */
3435 if (!UpdateRegisters(insn_flags, reg_table, insn_idx + insn_width,
3436 work_line))
3437 return false;
3438 } else {
3439 /*
3440 * We're not recording register data for the next instruction,
jeffhaod1f0fde2011-09-08 17:25:33 -07003441 * so we don't know what the prior state was. We have to
jeffhaobdb76512011-09-07 11:43:16 -07003442 * assume that something has changed and re-evaluate it.
3443 */
3444 InsnSetChanged(insn_flags, insn_idx + insn_width, true);
3445 }
3446 }
3447
3448 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003449 * Handle "branch". Tag the branch target.
jeffhaobdb76512011-09-07 11:43:16 -07003450 *
3451 * NOTE: instructions like Instruction::EQZ provide information about the
jeffhaod1f0fde2011-09-08 17:25:33 -07003452 * state of the register when the branch is taken or not taken. For example,
jeffhaobdb76512011-09-07 11:43:16 -07003453 * somebody could get a reference field, check it for zero, and if the
3454 * branch is taken immediately store that register in a boolean field
jeffhaod1f0fde2011-09-08 17:25:33 -07003455 * since the value is known to be zero. We do not currently account for
jeffhaobdb76512011-09-07 11:43:16 -07003456 * that, and will reject the code.
3457 *
3458 * TODO: avoid re-fetching the branch target
3459 */
3460 if ((opcode_flag & Instruction::kBranch) != 0) {
3461 bool isConditional, selfOkay;
3462
3463 if (!GetBranchOffset(code_item, insn_flags, insn_idx, &branch_target,
3464 &isConditional, &selfOkay)) {
3465 /* should never happen after static verification */
3466 LOG(ERROR) << "VFY: bad branch at 0x" << std::hex << insn_idx << std::dec;
3467 return false;
3468 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003469 DCHECK_EQ(isConditional, (opcode_flag & Instruction::kContinue) != 0);
jeffhaobdb76512011-09-07 11:43:16 -07003470
3471 if (!CheckMoveException(code_item->insns_, insn_idx + branch_target))
3472 return false;
3473
3474 /* update branch target, set "changed" if appropriate */
3475 if (!UpdateRegisters(insn_flags, reg_table, insn_idx + branch_target,
3476 work_line))
3477 return false;
3478 }
3479
3480 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003481 * Handle "switch". Tag all possible branch targets.
jeffhaobdb76512011-09-07 11:43:16 -07003482 *
3483 * We've already verified that the table is structurally sound, so we
3484 * just need to walk through and tag the targets.
3485 */
3486 if ((opcode_flag & Instruction::kSwitch) != 0) {
3487 int offset_to_switch = insns[1] | (((int32_t) insns[2]) << 16);
3488 const uint16_t* switch_insns = insns + offset_to_switch;
3489 int switch_count = switch_insns[1];
3490 int offset_to_targets, targ;
3491
3492 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
3493 /* 0 = sig, 1 = count, 2/3 = first key */
3494 offset_to_targets = 4;
3495 } else {
3496 /* 0 = sig, 1 = count, 2..count * 2 = keys */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003497 DCHECK((*insns & 0xff) == Instruction::SPARSE_SWITCH);
jeffhaobdb76512011-09-07 11:43:16 -07003498 offset_to_targets = 2 + 2 * switch_count;
3499 }
3500
3501 /* verify each switch target */
3502 for (targ = 0; targ < switch_count; targ++) {
3503 int offset;
3504 uint32_t abs_offset;
3505
3506 /* offsets are 32-bit, and only partly endian-swapped */
3507 offset = switch_insns[offset_to_targets + targ * 2] |
3508 (((int32_t) switch_insns[offset_to_targets + targ * 2 + 1]) << 16);
3509 abs_offset = insn_idx + offset;
3510
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003511 DCHECK_LT(abs_offset, insns_size);
jeffhaobdb76512011-09-07 11:43:16 -07003512
3513 if (!CheckMoveException(code_item->insns_, abs_offset))
3514 return false;
3515
3516 if (!UpdateRegisters(insn_flags, reg_table, abs_offset, work_line))
3517 return false;
3518 }
3519 }
3520
3521 /*
3522 * Handle instructions that can throw and that are sitting in a
jeffhaod1f0fde2011-09-08 17:25:33 -07003523 * "try" block. (If they're not in a "try" block when they throw,
jeffhaobdb76512011-09-07 11:43:16 -07003524 * control transfers out of the method.)
3525 */
3526 if ((opcode_flag & Instruction::kThrow) != 0 &&
3527 InsnIsInTry(insn_flags, insn_idx)) {
3528 bool has_catch_all = false;
3529 DexFile::CatchHandlerIterator iterator = DexFile::dexFindCatchHandler(
3530 *code_item, insn_idx);
3531
3532 for (; !iterator.HasNext(); iterator.Next()) {
3533 if (iterator.Get().type_idx_ == DexFile::kDexNoIndex)
3534 has_catch_all = true;
3535
3536 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003537 * Merge registers into the "catch" block. We want to use the
3538 * "savedRegs" rather than "work_regs", because at runtime the
3539 * exception will be thrown before the instruction modifies any
3540 * registers.
jeffhaobdb76512011-09-07 11:43:16 -07003541 */
3542 if (!UpdateRegisters(insn_flags, reg_table, iterator.Get().address_,
3543 &reg_table->saved_line_))
3544 return false;
3545 }
3546
3547 /*
3548 * If the monitor stack depth is nonzero, there must be a "catch all"
jeffhaod1f0fde2011-09-08 17:25:33 -07003549 * handler for this instruction. This does apply to monitor-exit
jeffhaobdb76512011-09-07 11:43:16 -07003550 * because of async exception handling.
3551 */
3552 if (work_line->monitor_stack_top_ != 0 && !has_catch_all) {
3553 /*
3554 * The state in work_line reflects the post-execution state.
3555 * If the current instruction is a monitor-enter and the monitor
3556 * stack was empty, we don't need a catch-all (if it throws,
3557 * it will do so before grabbing the lock).
3558 */
3559 if (!(dec_insn.opcode_ == Instruction::MONITOR_ENTER &&
3560 work_line->monitor_stack_top_ == 1))
3561 {
3562 LOG(ERROR) << "VFY: no catch-all for instruction at 0x" << std::hex
3563 << insn_idx << std::dec;
3564 return false;
3565 }
3566 }
3567 }
3568
jeffhaod1f0fde2011-09-08 17:25:33 -07003569 /* If we're returning from the method, make sure monitor stack is empty. */
jeffhaobdb76512011-09-07 11:43:16 -07003570 if ((opcode_flag & Instruction::kReturn) != 0 &&
3571 work_line->monitor_stack_top_ != 0) {
3572 LOG(ERROR) << "VFY: return with stack depth="
3573 << work_line->monitor_stack_top_ << " at 0x" << std::hex
3574 << insn_idx << std::dec;
3575 return false;
3576 }
3577
3578 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003579 * Update start_guess. Advance to the next instruction of that's
3580 * possible, otherwise use the branch target if one was found. If
jeffhaobdb76512011-09-07 11:43:16 -07003581 * neither of those exists we're in a return or throw; leave start_guess
3582 * alone and let the caller sort it out.
3583 */
3584 if ((opcode_flag & Instruction::kContinue) != 0) {
3585 *start_guess = insn_idx + InsnGetWidth(insn_flags, insn_idx);
3586 } else if ((opcode_flag & Instruction::kBranch) != 0) {
3587 /* we're still okay if branch_target is zero */
3588 *start_guess = insn_idx + branch_target;
3589 }
3590
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003591 DCHECK_LT(*start_guess, insns_size);
Brian Carlstrom03c99df2011-09-18 10:52:00 -07003592 DCHECK_NE(InsnGetWidth(insn_flags, *start_guess), 0);
jeffhaobdb76512011-09-07 11:43:16 -07003593
3594 return true;
3595}
3596
3597bool DexVerifier::ReplaceFailingInstruction(const DexFile::CodeItem* code_item,
3598 InsnFlags* insn_flags, int insn_idx, VerifyError failure) {
3599 const uint16_t* insns = code_item->insns_ + insn_idx;
3600 const byte* ptr = reinterpret_cast<const byte*>(insns);
3601 const Instruction* inst = Instruction::At(ptr);
3602 Instruction::Code opcode = inst->Opcode();
3603 VerifyErrorRefType ref_type;
3604
3605 /*
3606 * Generate the new instruction out of the old.
3607 *
3608 * First, make sure this is an instruction we're expecting to stomp on.
3609 */
3610 switch (opcode) {
3611 case Instruction::CONST_CLASS: // insn[1] == class ref, 2 bytes
3612 case Instruction::CHECK_CAST:
3613 case Instruction::INSTANCE_OF:
3614 case Instruction::NEW_INSTANCE:
3615 case Instruction::NEW_ARRAY:
3616 case Instruction::FILLED_NEW_ARRAY: // insn[1] == class ref, 3 bytes
3617 case Instruction::FILLED_NEW_ARRAY_RANGE:
3618 ref_type = VERIFY_ERROR_REF_CLASS;
3619 break;
3620
3621 case Instruction::IGET: // insn[1] == field ref, 2 bytes
3622 case Instruction::IGET_BOOLEAN:
3623 case Instruction::IGET_BYTE:
3624 case Instruction::IGET_CHAR:
3625 case Instruction::IGET_SHORT:
3626 case Instruction::IGET_WIDE:
3627 case Instruction::IGET_OBJECT:
3628 case Instruction::IPUT:
3629 case Instruction::IPUT_BOOLEAN:
3630 case Instruction::IPUT_BYTE:
3631 case Instruction::IPUT_CHAR:
3632 case Instruction::IPUT_SHORT:
3633 case Instruction::IPUT_WIDE:
3634 case Instruction::IPUT_OBJECT:
3635 case Instruction::SGET:
3636 case Instruction::SGET_BOOLEAN:
3637 case Instruction::SGET_BYTE:
3638 case Instruction::SGET_CHAR:
3639 case Instruction::SGET_SHORT:
3640 case Instruction::SGET_WIDE:
3641 case Instruction::SGET_OBJECT:
3642 case Instruction::SPUT:
3643 case Instruction::SPUT_BOOLEAN:
3644 case Instruction::SPUT_BYTE:
3645 case Instruction::SPUT_CHAR:
3646 case Instruction::SPUT_SHORT:
3647 case Instruction::SPUT_WIDE:
3648 case Instruction::SPUT_OBJECT:
3649 ref_type = VERIFY_ERROR_REF_FIELD;
3650 break;
3651
3652 case Instruction::INVOKE_VIRTUAL: // insn[1] == method ref, 3 bytes
3653 case Instruction::INVOKE_VIRTUAL_RANGE:
3654 case Instruction::INVOKE_SUPER:
3655 case Instruction::INVOKE_SUPER_RANGE:
3656 case Instruction::INVOKE_DIRECT:
3657 case Instruction::INVOKE_DIRECT_RANGE:
3658 case Instruction::INVOKE_STATIC:
3659 case Instruction::INVOKE_STATIC_RANGE:
3660 case Instruction::INVOKE_INTERFACE:
3661 case Instruction::INVOKE_INTERFACE_RANGE:
3662 ref_type = VERIFY_ERROR_REF_METHOD;
3663 break;
3664
3665 default:
3666 /* could handle this in a generic way, but this is probably safer */
3667 LOG(ERROR) << "GLITCH: verifier asked to replace opcode 0x" << std::hex
3668 << (int) opcode << std::dec;
3669 return false;
3670 }
3671
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003672 DCHECK(inst->IsThrow());
jeffhaobdb76512011-09-07 11:43:16 -07003673
3674 /* write a NOP over the third code unit, if necessary */
3675 int width = InsnGetWidth(insn_flags, insn_idx);
3676 switch (width) {
3677 case 2:
3678 /* nothing to do */
3679 break;
3680 case 3:
3681 // TODO: Add this functionality
3682 //UpdateCodeUnit(method, insns + 2, Instruction::NOP);
3683 break;
3684 default:
3685 /* whoops */
3686 LOG(FATAL) << "ERROR: stomped a " << width
3687 << "-unit instruction with a verifier error";
3688 }
3689
3690 /* encode the opcode, with the failure code in the high byte */
3691 // TODO: REPLACE FAILING OPCODES
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003692 //DCHECK(width == 2 || width == 3);
jeffhaobdb76512011-09-07 11:43:16 -07003693 //uint16_t new_val = Instruction::THROW_VERIFICATION_ERROR |
jeffhao98eacac2011-09-14 16:11:53 -07003694 //uint16_t new_val = Instruction::UNUSED_ED |
jeffhaobdb76512011-09-07 11:43:16 -07003695 //(failure << 8) | (ref_type << (8 + kVerifyErrorRefTypeShift));
3696 //UpdateCodeUnit(method, insns, new_val);
3697
3698 return true;
3699}
3700
3701/* Handle a monitor-enter instruction. */
3702void DexVerifier::HandleMonitorEnter(RegisterLine* work_line, uint32_t reg_idx,
3703 uint32_t insn_idx, VerifyError* failure) {
3704 if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
3705 LOG(ERROR) << "VFY: monitor-enter on non-object";
3706 *failure = VERIFY_ERROR_GENERIC;
3707 return;
3708 }
3709
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003710 if (work_line->monitor_entries_.get() == NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003711 return;
3712 }
3713
3714 if (work_line->monitor_stack_top_ == kMaxMonitorStackDepth) {
3715 LOG(ERROR) << "VFY: monitor-enter stack overflow (" << kMaxMonitorStackDepth
3716 << ")";
3717 *failure = VERIFY_ERROR_GENERIC;
3718 return;
3719 }
3720
3721 /*
3722 * Push an entry on the stack, and set a bit in the register flags to
3723 * indicate that it's associated with this register.
3724 */
3725 work_line->monitor_entries_[reg_idx] |= 1 << work_line->monitor_stack_top_;
3726 work_line->monitor_stack_[work_line->monitor_stack_top_++] = insn_idx;
3727}
3728
3729/* Handle a monitor-exit instruction. */
3730void DexVerifier::HandleMonitorExit(RegisterLine* work_line, uint32_t reg_idx,
3731 uint32_t insn_idx, VerifyError* failure) {
3732 if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
3733 LOG(ERROR) << "VFY: monitor-exit on non-object";
3734 *failure = VERIFY_ERROR_GENERIC;
3735 return;
3736 }
3737
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003738 if (work_line->monitor_entries_.get() == NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003739 return;
3740 }
3741
3742 if (work_line->monitor_stack_top_ == 0) {
3743 LOG(ERROR) << "VFY: monitor-exit stack underflow";
3744 *failure = VERIFY_ERROR_GENERIC;
3745 return;
3746 }
3747
3748 /*
3749 * Confirm that the entry at the top of the stack is associated with
jeffhaod1f0fde2011-09-08 17:25:33 -07003750 * the register. Pop the top entry off.
jeffhaobdb76512011-09-07 11:43:16 -07003751 */
3752 work_line->monitor_stack_top_--;
3753#ifdef BUG_3215458_FIXED
3754 /*
3755 * TODO: This code can safely be enabled if know we are working on
3756 * a dex file of format version 036 or later. (That is, we'll need to
3757 * add a check for the version number.)
3758 */
3759 if ((work_line->monitor_entries_[reg_idx] &
3760 (1 << work_line->monitor_stack_top_)) == 0) {
3761 LOG(ERROR) << "VFY: monitor-exit bit " << work_line->monitor_stack_top_
3762 << " not set: addr=0x" << std::hex << insn_idx << std::dec
3763 << " (bits[" << reg_idx << "]=" << std::hex
3764 << work_line->monitor_entries_[reg_idx] << std::dec << ")";
3765 *failure = VERIFY_ERROR_GENERIC;
3766 return;
3767 }
3768#endif
3769 work_line->monitor_stack_[work_line->monitor_stack_top_] = 0;
3770
3771 /* Clear the bit from the register flags. */
3772 work_line->monitor_entries_[reg_idx] &= ~(1 << work_line->monitor_stack_top_);
3773}
3774
3775Field* DexVerifier::GetInstField(VerifierData* vdata, RegType obj_type,
3776 int field_idx, VerifyError* failure) {
3777 Method* method = vdata->method_;
3778 const DexFile* dex_file = vdata->dex_file_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003779 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07003780 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3781 DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
3782 const ClassLoader* class_loader =
3783 method->GetDeclaringClass()->GetClassLoader();
3784 Field* field = NULL;
3785 Class* obj_class;
3786 bool must_be_local = false;
3787
3788 if (!RegTypeIsReference(obj_type)) {
3789 LOG(ERROR) << "VFY: attempt to access field in non-reference type "
3790 << obj_type;
3791 *failure = VERIFY_ERROR_GENERIC;
3792 return field;
3793 }
3794
3795 field = class_linker->ResolveField(*dex_file, field_idx, dex_cache,
3796 class_loader, false);
3797 if (field == NULL) {
3798 LOG(ERROR) << "VFY: unable to resolve instance field " << field_idx;
3799 return field;
3800 }
3801
3802 if (obj_type == kRegTypeZero)
3803 return field;
3804
3805 /*
3806 * Access to fields in uninitialized objects is allowed if this is
3807 * the <init> method for the object and the field in question is
3808 * declared by this class.
3809 */
3810 obj_class = RegTypeReferenceToClass(obj_type, uninit_map);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003811 DCHECK(obj_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07003812 if (RegTypeIsUninitReference(obj_type)) {
3813 if (!IsInitMethod(method) || method->GetDeclaringClass() != obj_class) {
3814 LOG(ERROR) << "VFY: attempt to access field via uninitialized ref";
3815 *failure = VERIFY_ERROR_GENERIC;
3816 return field;
3817 }
3818 must_be_local = true;
3819 }
3820
jeffhaobdb76512011-09-07 11:43:16 -07003821 if (!field->GetDeclaringClass()->IsAssignableFrom(obj_class)) {
3822 LOG(ERROR) << "VFY: invalid field access (field "
3823 << field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
3824 << "." << field->GetName()->ToModifiedUtf8() << ", through "
3825 << obj_class->GetDescriptor()->ToModifiedUtf8() << " ref)";
3826 *failure = VERIFY_ERROR_NO_FIELD;
3827 return field;
3828 }
3829
3830 if (must_be_local) {
3831 bool found = false;
3832 /* for uninit ref, make sure it's defined by this class, not super */
3833 for (uint32_t i = 0; i < obj_class->NumInstanceFields(); i++) {
3834 found |= (field == obj_class->GetInstanceField(i));
3835 }
3836 if (!found) {
3837 LOG(ERROR) << "VFY: invalid constructor field access (field "
3838 << field->GetName()->ToModifiedUtf8() << " in "
3839 << obj_class->GetDescriptor()->ToModifiedUtf8() << ")";
3840 *failure = VERIFY_ERROR_GENERIC;
3841 return field;
3842 }
3843 }
3844
3845 return field;
3846}
3847
3848Field* DexVerifier::GetStaticField(VerifierData* vdata, int field_idx,
3849 VerifyError* failure) {
3850 Method* method = vdata->method_;
3851 const DexFile* dex_file = vdata->dex_file_;
3852 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3853 DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
3854 const ClassLoader* class_loader =
3855 method->GetDeclaringClass()->GetClassLoader();
3856 Field* field;
3857
3858 field = class_linker->ResolveField(*dex_file, field_idx, dex_cache,
3859 class_loader, true);
3860 if (field == NULL) {
3861 //const DexFile::FieldId field_id = dex_file->GetFieldId(field_idx);
3862
3863 //LOG(ERROR) << "VFY: unable to resolve static field " << field_idx << " ("
3864 //<< dex_file->GetFieldName(field_id) << ") in "
3865 //<< dex_file->GetFieldClassDescriptor(field_id);
3866 LOG(ERROR) << "VFY: unable to resolve static field";
3867 }
3868
3869 return field;
3870}
3871
3872Class* DexVerifier::GetCaughtExceptionType(VerifierData* vdata, int insn_idx,
3873 VerifyError* failure) {
3874 const DexFile* dex_file = vdata->dex_file_;
3875 const DexFile::CodeItem* code_item = vdata->code_item_;
3876 Method* method = vdata->method_;
3877 Class* common_super = NULL;
3878 uint32_t handlers_size;
jeffhaoba5ebb92011-08-25 17:24:37 -07003879 const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item, 0);
jeffhaobdb76512011-09-07 11:43:16 -07003880
3881 if (code_item->tries_size_ != 0) {
3882 handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
3883 } else {
3884 handlers_size = 0;
3885 }
3886
3887 for (uint32_t i = 0; i < handlers_size; i++) {
jeffhaoba5ebb92011-08-25 17:24:37 -07003888 DexFile::CatchHandlerIterator iterator(handlers_ptr);
3889
3890 for (; !iterator.HasNext(); iterator.Next()) {
jeffhaobdb76512011-09-07 11:43:16 -07003891 DexFile::CatchHandlerItem handler = iterator.Get();
3892 if (handler.address_ == (uint32_t) insn_idx) {
3893 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3894 Class* klass;
jeffhaoba5ebb92011-08-25 17:24:37 -07003895
jeffhaobdb76512011-09-07 11:43:16 -07003896 if (handler.type_idx_ == DexFile::kDexNoIndex) {
3897 klass = class_linker->FindSystemClass("Ljava/lang/Throwable;");
3898 } else {
jeffhao98eacac2011-09-14 16:11:53 -07003899 klass = ResolveClassAndCheckAccess(dex_file, handler.type_idx_,
3900 method->GetDeclaringClass(), failure);
jeffhaobdb76512011-09-07 11:43:16 -07003901 }
3902
3903 if (klass == NULL) {
3904 LOG(ERROR) << "VFY: unable to resolve exception class "
3905 << handler.type_idx_ << " ("
3906 << dex_file->dexStringByTypeIdx(handler.type_idx_) << ")";
jeffhaod1f0fde2011-09-08 17:25:33 -07003907 /* TODO: do we want to keep going? If we don't fail this we run
3908 * the risk of having a non-Throwable introduced at runtime.
3909 * However, that won't pass an instanceof test, so is essentially
3910 * harmless.
jeffhaobdb76512011-09-07 11:43:16 -07003911 */
3912 } else {
3913 if (common_super == NULL)
3914 common_super = klass;
3915 else
3916 common_super = FindCommonSuperclass(klass, common_super);
3917 }
3918 }
jeffhaoba5ebb92011-08-25 17:24:37 -07003919 }
3920
3921 handlers_ptr = iterator.GetData();
3922 }
3923
jeffhaobdb76512011-09-07 11:43:16 -07003924 if (common_super == NULL) {
3925 /* no catch blocks, or no catches with classes we can find */
3926 LOG(ERROR) << "VFY: unable to find exception handler at addr 0x" << std::hex
3927 << insn_idx << std::dec;
3928 *failure = VERIFY_ERROR_GENERIC;
3929 }
3930
3931 return common_super;
jeffhaoba5ebb92011-08-25 17:24:37 -07003932}
3933
jeffhaobdb76512011-09-07 11:43:16 -07003934DexVerifier::RegType DexVerifier::GetMethodReturnType(const DexFile* dex_file,
3935 const Method* method) {
3936 Class* klass = method->GetReturnType();
3937 if (klass->IsPrimitive())
3938 return PrimitiveTypeToRegType(klass->GetPrimitiveType());
3939 else
3940 return RegTypeFromClass(klass);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07003941}
3942
jeffhaobdb76512011-09-07 11:43:16 -07003943Class* DexVerifier::GetClassFromRegister(const RegisterLine* register_line,
3944 uint32_t vsrc, VerifyError* failure) {
3945 /* get the element type of the array held in vsrc */
3946 RegType type = GetRegisterType(register_line, vsrc);
jeffhaoba5ebb92011-08-25 17:24:37 -07003947
jeffhaobdb76512011-09-07 11:43:16 -07003948 /* if "always zero", we allow it to fail at runtime */
3949 if (type == kRegTypeZero)
3950 return NULL;
3951
3952 if (!RegTypeIsReference(type)) {
3953 LOG(ERROR) << "VFY: tried to get class from non-ref register v" << vsrc
3954 << " (type=" << type << ")",
3955 *failure = VERIFY_ERROR_GENERIC;
3956 return NULL;
3957 }
3958 if (RegTypeIsUninitReference(type)) {
3959 LOG(ERROR) << "VFY: register " << vsrc << " holds uninitialized reference";
3960 *failure = VERIFY_ERROR_GENERIC;
3961 return NULL;
jeffhaoba5ebb92011-08-25 17:24:37 -07003962 }
3963
jeffhaobdb76512011-09-07 11:43:16 -07003964 return RegTypeInitializedReferenceToClass(type);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07003965}
3966
jeffhaobdb76512011-09-07 11:43:16 -07003967DexVerifier::RegType DexVerifier::GetInvocationThis(
3968 const RegisterLine* register_line,
3969 const Instruction::DecodedInstruction* dec_insn, VerifyError* failure) {
3970 if (dec_insn->vA_ < 1) {
3971 LOG(ERROR) << "VFY: invoke lacks 'this'";
3972 *failure = VERIFY_ERROR_GENERIC;
3973 return kRegTypeUnknown;
jeffhaoba5ebb92011-08-25 17:24:37 -07003974 }
jeffhaobdb76512011-09-07 11:43:16 -07003975
3976 /* get the element type of the array held in vsrc */
3977 RegType this_type = GetRegisterType(register_line, dec_insn->vC_);
3978 if (!RegTypeIsReference(this_type)) {
3979 LOG(ERROR) << "VFY: tried to get class from non-ref register v"
3980 << dec_insn->vC_ << " (type=" << this_type << ")";
3981 *failure = VERIFY_ERROR_GENERIC;
3982 return kRegTypeUnknown;
3983 }
3984
3985 return this_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07003986}
3987
jeffhaobdb76512011-09-07 11:43:16 -07003988void DexVerifier::SetRegisterType(RegisterLine* register_line, uint32_t vdst,
3989 RegType new_type) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003990 RegType* insn_regs = register_line->reg_types_.get();
jeffhaoba5ebb92011-08-25 17:24:37 -07003991
jeffhaobdb76512011-09-07 11:43:16 -07003992 switch (new_type) {
3993 case kRegTypeUnknown:
3994 case kRegTypeBoolean:
3995 case kRegTypeOne:
3996 case kRegTypeConstByte:
3997 case kRegTypeConstPosByte:
3998 case kRegTypeConstShort:
3999 case kRegTypeConstPosShort:
4000 case kRegTypeConstChar:
4001 case kRegTypeConstInteger:
4002 case kRegTypeByte:
4003 case kRegTypePosByte:
4004 case kRegTypeShort:
4005 case kRegTypePosShort:
4006 case kRegTypeChar:
4007 case kRegTypeInteger:
4008 case kRegTypeFloat:
4009 case kRegTypeZero:
4010 case kRegTypeUninit:
4011 insn_regs[vdst] = new_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07004012 break;
jeffhaobdb76512011-09-07 11:43:16 -07004013 case kRegTypeConstLo:
4014 case kRegTypeLongLo:
4015 case kRegTypeDoubleLo:
4016 insn_regs[vdst] = new_type;
4017 insn_regs[vdst + 1] = new_type + 1;
4018 break;
4019 case kRegTypeConstHi:
4020 case kRegTypeLongHi:
4021 case kRegTypeDoubleHi:
4022 /* should never set these explicitly */
4023 LOG(FATAL) << "BUG: explicit set of high register type";
4024 break;
4025
4026 default:
4027 /* can't switch for ref types, so we check explicitly */
4028 if (RegTypeIsReference(new_type)) {
4029 insn_regs[vdst] = new_type;
4030
4031 /*
4032 * In most circumstances we won't see a reference to a primitive
4033 * class here (e.g. "D"), since that would mean the object in the
jeffhaod1f0fde2011-09-08 17:25:33 -07004034 * register is actually a primitive type. It can happen as the
jeffhaobdb76512011-09-07 11:43:16 -07004035 * result of an assumed-successful check-cast instruction in
jeffhaod1f0fde2011-09-08 17:25:33 -07004036 * which the second argument refers to a primitive class. (In
jeffhaobdb76512011-09-07 11:43:16 -07004037 * practice, such an instruction will always throw an exception.)
4038 *
4039 * This is not an issue for instructions like const-class, where
4040 * the object in the register is a java.lang.Class instance.
4041 */
4042 break;
4043 }
4044 /* bad type - fall through */
4045
4046 case kRegTypeConflict: // should only be set during a merge
4047 LOG(FATAL) << "BUG: set register to unknown type " << new_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07004048 break;
4049 }
4050
jeffhaobdb76512011-09-07 11:43:16 -07004051 /*
4052 * Clear the monitor entry bits for this register.
4053 */
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004054 if (register_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07004055 register_line->monitor_entries_[vdst] = 0;
4056}
4057
4058void DexVerifier::VerifyRegisterType(RegisterLine* register_line, uint32_t vsrc,
4059 RegType check_type, VerifyError* failure) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004060 const RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004061 RegType src_type = insn_regs[vsrc];
4062
4063 switch (check_type) {
4064 case kRegTypeFloat:
4065 case kRegTypeBoolean:
4066 case kRegTypePosByte:
4067 case kRegTypeByte:
4068 case kRegTypePosShort:
4069 case kRegTypeShort:
4070 case kRegTypeChar:
4071 case kRegTypeInteger:
4072 if (!CanConvertTo1nr(src_type, check_type)) {
4073 LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
4074 << ", wanted " << check_type;
4075 *failure = VERIFY_ERROR_GENERIC;
4076 }
4077 /* Update type if result is float */
4078 if (check_type == kRegTypeFloat) {
4079 SetRegisterType(register_line, vsrc, check_type);
4080 } else {
4081 /* Update const type to actual type after use */
4082 SetRegisterType(register_line, vsrc, ConstTypeToRegType(src_type));
4083 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004084 break;
jeffhaobdb76512011-09-07 11:43:16 -07004085 case kRegTypeLongLo:
4086 case kRegTypeDoubleLo:
4087 if (insn_regs[vsrc + 1] != src_type + 1) {
4088 LOG(ERROR) << "VFY: register2 v" << vsrc << "-" << vsrc + 1
4089 << " values " << insn_regs[vsrc] << ","
4090 << insn_regs[vsrc + 1];
4091 *failure = VERIFY_ERROR_GENERIC;
4092 } else if (!CanConvertTo2(src_type, check_type)) {
4093 LOG(ERROR) << "VFY: register2 v" << vsrc << " type " << src_type
4094 << ", wanted " << check_type;
4095 *failure = VERIFY_ERROR_GENERIC;
4096 }
4097 /* Update type if source is from const */
4098 if (src_type == kRegTypeConstLo) {
4099 SetRegisterType(register_line, vsrc, check_type);
4100 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004101 break;
jeffhaobdb76512011-09-07 11:43:16 -07004102 case kRegTypeConstLo:
4103 case kRegTypeConstHi:
4104 case kRegTypeLongHi:
4105 case kRegTypeDoubleHi:
4106 case kRegTypeZero:
4107 case kRegTypeOne:
4108 case kRegTypeUnknown:
4109 case kRegTypeConflict:
4110 /* should never be checking for these explicitly */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004111 DCHECK(false);
jeffhaobdb76512011-09-07 11:43:16 -07004112 *failure = VERIFY_ERROR_GENERIC;
4113 return;
4114 case kRegTypeUninit:
4115 default:
4116 /* make sure check_type is initialized reference */
4117 if (!RegTypeIsReference(check_type)) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004118 LOG(FATAL) << "VFY: unexpected check type " << check_type;
jeffhaobdb76512011-09-07 11:43:16 -07004119 *failure = VERIFY_ERROR_GENERIC;
4120 break;
4121 }
4122 if (RegTypeIsUninitReference(check_type)) {
4123 LOG(ERROR) << "VFY: uninitialized ref not expected as reg check";
4124 *failure = VERIFY_ERROR_GENERIC;
4125 break;
4126 }
4127 /* make sure src_type is initialized reference or always-NULL */
4128 if (!RegTypeIsReference(src_type)) {
4129 LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
4130 << ", wanted ref";
4131 *failure = VERIFY_ERROR_GENERIC;
4132 break;
4133 }
4134 if (RegTypeIsUninitReference(src_type)) {
4135 LOG(ERROR) << "VFY: register1 v" << vsrc << " holds uninitialized ref";
4136 *failure = VERIFY_ERROR_GENERIC;
4137 break;
4138 }
4139 /* if the register isn't Zero, make sure it's an instance of check */
4140 if (src_type != kRegTypeZero) {
4141 Class* src_class = RegTypeInitializedReferenceToClass(src_type);
4142 Class* check_class = RegTypeInitializedReferenceToClass(check_type);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004143 DCHECK(src_class != NULL);
4144 DCHECK(check_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004145
4146 if (!check_class->IsAssignableFrom(src_class)) {
4147 LOG(ERROR) << "VFY: " << src_class->GetDescriptor()->ToModifiedUtf8()
4148 << " is not instance of "
4149 << check_class->GetDescriptor()->ToModifiedUtf8();
4150 *failure = VERIFY_ERROR_GENERIC;
4151 }
4152 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004153 break;
4154 }
jeffhaobdb76512011-09-07 11:43:16 -07004155}
jeffhaoba5ebb92011-08-25 17:24:37 -07004156
jeffhaobdb76512011-09-07 11:43:16 -07004157void DexVerifier::SetResultRegisterType(RegisterLine* register_line,
4158 const int insn_reg_count, RegType new_type) {
4159 SetRegisterType(register_line, RESULT_REGISTER(insn_reg_count), new_type);
4160}
4161
4162void DexVerifier::MarkRefsAsInitialized(RegisterLine* register_line,
4163 int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type,
4164 VerifyError* failure) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004165 RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004166 Class* klass = GetUninitInstance(uninit_map,
4167 RegTypeToUninitIndex(uninit_type));
4168
4169 if (klass == NULL) {
4170 LOG(ERROR) << "VFY: unable to find type=" << std::hex << uninit_type
4171 << std::dec << " (idx=" << RegTypeToUninitIndex(uninit_type)
4172 << ")";
4173 *failure = VERIFY_ERROR_GENERIC;
4174 return;
jeffhaoba5ebb92011-08-25 17:24:37 -07004175 }
4176
jeffhaobdb76512011-09-07 11:43:16 -07004177 RegType init_type = RegTypeFromClass(klass);
4178 int changed = 0;
4179 for (int i = 0; i < insn_reg_count; i++) {
4180 if (insn_regs[i] == uninit_type) {
4181 insn_regs[i] = init_type;
4182 changed++;
4183 }
4184 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004185 DCHECK_GT(changed, 0);
jeffhaobdb76512011-09-07 11:43:16 -07004186
4187 return;
4188}
4189
4190void DexVerifier::MarkUninitRefsAsInvalid(RegisterLine* register_line,
4191 int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004192 RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004193
4194 for (int i = 0; i < insn_reg_count; i++) {
4195 if (insn_regs[i] == uninit_type) {
4196 insn_regs[i] = kRegTypeConflict;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004197 if (register_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07004198 register_line->monitor_entries_[i] = 0;
4199 }
4200 }
4201}
4202
4203void DexVerifier::CopyRegister1(RegisterLine* register_line, uint32_t vdst,
4204 uint32_t vsrc, TypeCategory cat, VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004205 DCHECK(cat == kTypeCategory1nr || cat == kTypeCategoryRef);
jeffhaobdb76512011-09-07 11:43:16 -07004206 RegType type = GetRegisterType(register_line, vsrc);
4207 CheckTypeCategory(type, cat, failure);
4208 if (*failure != VERIFY_ERROR_NONE) {
4209 LOG(ERROR) << "VFY: copy1 v" << vdst << "<-v" << vsrc << " type=" << type
4210 << " cat=" << (int) cat;
4211 } else {
4212 SetRegisterType(register_line, vdst, type);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004213 if (cat == kTypeCategoryRef && register_line->monitor_entries_.get() != NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07004214 register_line->monitor_entries_[vdst] =
4215 register_line->monitor_entries_[vsrc];
4216 }
4217 }
4218}
4219
4220void DexVerifier::CopyRegister2(RegisterLine* register_line, uint32_t vdst,
4221 uint32_t vsrc, VerifyError* failure) {
4222 RegType type_l = GetRegisterType(register_line, vsrc);
4223 RegType type_h = GetRegisterType(register_line, vsrc + 1);
4224
4225 CheckTypeCategory(type_l, kTypeCategory2, failure);
4226 CheckWidePair(type_l, type_h, failure);
4227 if (*failure != VERIFY_ERROR_NONE) {
4228 LOG(ERROR) << "VFY: copy2 v" << vdst << "<-v" << vsrc << " type=" << type_l
4229 << "/" << type_h;
4230 } else {
4231 SetRegisterType(register_line, vdst, type_l);
4232 }
4233}
4234
4235void DexVerifier::CopyResultRegister1(RegisterLine* register_line,
4236 const int insn_reg_count, uint32_t vdst, TypeCategory cat,
4237 VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004238 DCHECK_LT(vdst, static_cast<uint32_t>(insn_reg_count));
jeffhaobdb76512011-09-07 11:43:16 -07004239
4240 uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
4241 RegType type = GetRegisterType(register_line, vsrc);
4242 CheckTypeCategory(type, cat, failure);
4243 if (*failure != VERIFY_ERROR_NONE) {
4244 LOG(ERROR) << "VFY: copyRes1 v" << vdst << "<-v" << vsrc << " cat="
4245 << (int) cat << " type=" << type;
4246 } else {
4247 SetRegisterType(register_line, vdst, type);
4248 SetRegisterType(register_line, vsrc, kRegTypeUnknown);
4249 }
4250}
4251
4252/*
jeffhaod1f0fde2011-09-08 17:25:33 -07004253 * Implement "move-result-wide". Copy the category-2 value from the result
jeffhaobdb76512011-09-07 11:43:16 -07004254 * register to another register, and reset the result register.
4255 */
4256void DexVerifier::CopyResultRegister2(RegisterLine* register_line,
4257 const int insn_reg_count, uint32_t vdst, VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004258 DCHECK_LT(vdst, static_cast<uint32_t>(insn_reg_count));
jeffhaobdb76512011-09-07 11:43:16 -07004259
4260 uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
4261 RegType type_l = GetRegisterType(register_line, vsrc);
4262 RegType type_h = GetRegisterType(register_line, vsrc + 1);
4263 CheckTypeCategory(type_l, kTypeCategory2, failure);
4264 CheckWidePair(type_l, type_h, failure);
4265 if (*failure != VERIFY_ERROR_NONE) {
4266 LOG(ERROR) << "VFY: copyRes2 v" << vdst << "<-v" << vsrc << " type="
4267 << type_l << "/" << type_h;
4268 } else {
4269 SetRegisterType(register_line, vdst, type_l);
4270 SetRegisterType(register_line, vsrc, kRegTypeUnknown);
4271 SetRegisterType(register_line, vsrc + 1, kRegTypeUnknown);
4272 }
4273}
4274
4275int DexVerifier::GetClassDepth(Class* klass) {
4276 int depth = 0;
4277 while (klass->GetSuperClass() != NULL) {
4278 klass = klass->GetSuperClass();
4279 depth++;
4280 }
4281 return depth;
4282}
4283
4284Class* DexVerifier::DigForSuperclass(Class* c1, Class* c2) {
4285 int depth1, depth2;
4286
4287 depth1 = GetClassDepth(c1);
4288 depth2 = GetClassDepth(c2);
4289
4290 /* pull the deepest one up */
4291 if (depth1 > depth2) {
4292 while (depth1 > depth2) {
4293 c1 = c1->GetSuperClass();
4294 depth1--;
4295 }
4296 } else {
4297 while (depth2 > depth1) {
4298 c2 = c2->GetSuperClass();
4299 depth2--;
4300 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004301 }
4302
jeffhaobdb76512011-09-07 11:43:16 -07004303 /* walk up in lock-step */
4304 while (c1 != c2) {
4305 c1 = c1->GetSuperClass();
4306 c2 = c2->GetSuperClass();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004307 DCHECK(c1 != NULL);
4308 DCHECK(c2 != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004309 }
4310
4311 return c1;
4312}
4313
4314Class* DexVerifier::FindCommonArraySuperclass(Class* c1, Class* c2) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004315 DCHECK(c1->IsArrayClass());
4316 DCHECK(c2->IsArrayClass());
4317 Class* e1 = c1->GetComponentType();
4318 Class* e2 = c2->GetComponentType();
4319 if (e1->IsPrimitive() || e2->IsPrimitive()) {
4320 return c1->GetSuperClass(); // == java.lang.Object
jeffhaobdb76512011-09-07 11:43:16 -07004321 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004322 Class* common_elem = FindCommonSuperclass(c1->GetComponentType(), c2->GetComponentType());
4323 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4324 const ClassLoader* class_loader = c1->GetClassLoader();
4325 std::string descriptor = "[" + common_elem->GetDescriptor()->ToModifiedUtf8();
4326 Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
4327 DCHECK(array_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004328 return array_class;
4329}
4330
4331Class* DexVerifier::FindCommonSuperclass(Class* c1, Class* c2) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004332 DCHECK(!c1->IsPrimitive()) << PrettyClass(c1);
4333 DCHECK(!c2->IsPrimitive()) << PrettyClass(c2);
jeffhaobdb76512011-09-07 11:43:16 -07004334
4335 if (c1 == c2)
4336 return c1;
4337
jeffhao5dbddee2011-09-07 16:38:26 -07004338 if (c1->IsInterface() && c1->IsAssignableFrom(c2)) {
jeffhaobdb76512011-09-07 11:43:16 -07004339 return c1;
4340 }
jeffhao5dbddee2011-09-07 16:38:26 -07004341 if (c2->IsInterface() && c2->IsAssignableFrom(c1)) {
jeffhaobdb76512011-09-07 11:43:16 -07004342 return c2;
4343 }
4344 if (c1->IsArrayClass() && c2->IsArrayClass()) {
4345 return FindCommonArraySuperclass(c1, c2);
4346 }
4347
4348 return DigForSuperclass(c1, c2);
4349}
4350
jeffhao98eacac2011-09-14 16:11:53 -07004351Class* DexVerifier::ResolveClassAndCheckAccess(const DexFile* dex_file,
4352 uint32_t class_idx, const Class* referrer, VerifyError* failure) {
4353 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4354 Class* res_class = class_linker->ResolveType(*dex_file, class_idx, referrer);
4355
4356 if (res_class == NULL) {
4357 *failure = VERIFY_ERROR_NO_CLASS;
4358 return NULL;
4359 }
4360
4361 /* Check if access is allowed. */
4362 if (!referrer->CanAccess(res_class)) {
4363 LOG(ERROR) << "VFY: illegal class access: "
4364 << referrer->GetDescriptor()->ToModifiedUtf8() << " -> "
4365 << res_class->GetDescriptor()->ToModifiedUtf8();
4366 *failure = VERIFY_ERROR_ACCESS_CLASS;
4367 return NULL;
4368 }
4369
4370 return res_class;
4371}
4372
jeffhaobdb76512011-09-07 11:43:16 -07004373DexVerifier::RegType DexVerifier::MergeTypes(RegType type1, RegType type2,
4374 bool* changed) {
4375 RegType result;
4376
jeffhao98eacac2011-09-14 16:11:53 -07004377 /* Check for trivial case so we don't have to hit memory. */
jeffhaobdb76512011-09-07 11:43:16 -07004378 if (type1 == type2)
4379 return type1;
4380
4381 /*
4382 * Use the table if we can, and reject any attempts to merge something
4383 * from the table with a reference type.
4384 *
4385 * Uninitialized references are composed of the enum ORed with an
jeffhaod1f0fde2011-09-08 17:25:33 -07004386 * index value. The uninitialized table entry at index zero *will*
4387 * show up as a simple kRegTypeUninit value. Since this cannot be
jeffhaobdb76512011-09-07 11:43:16 -07004388 * merged with anything but itself, the rules do the right thing.
4389 */
4390 if (type1 < kRegTypeMAX) {
4391 if (type2 < kRegTypeMAX) {
4392 result = merge_table_[type1][type2];
4393 } else {
4394 /* simple + reference == conflict, usually */
4395 if (type1 == kRegTypeZero)
4396 result = type2;
4397 else
4398 result = kRegTypeConflict;
4399 }
4400 } else {
4401 if (type2 < kRegTypeMAX) {
4402 /* reference + simple == conflict, usually */
4403 if (type2 == kRegTypeZero)
4404 result = type1;
4405 else
4406 result = kRegTypeConflict;
4407 } else {
4408 /* merging two references */
4409 if (RegTypeIsUninitReference(type1) ||
4410 RegTypeIsUninitReference(type2))
4411 {
4412 /* can't merge uninit with anything but self */
4413 result = kRegTypeConflict;
4414 } else {
4415 Class* klass1 = RegTypeInitializedReferenceToClass(type1);
4416 Class* klass2 = RegTypeInitializedReferenceToClass(type2);
4417 Class* merged_class = FindCommonSuperclass(klass1, klass2);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004418 DCHECK(merged_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004419 result = RegTypeFromClass(merged_class);
4420 }
4421 }
4422 }
4423
4424 if (result != type1)
4425 *changed = true;
jeffhaoba5ebb92011-08-25 17:24:37 -07004426 return result;
jeffhaobdb76512011-09-07 11:43:16 -07004427}
4428
4429DexVerifier::MonitorEntries DexVerifier::MergeMonitorEntries(
4430 MonitorEntries ents1, MonitorEntries ents2, bool* changed) {
4431 MonitorEntries result = ents1 & ents2;
4432 if (result != ents1)
4433 *changed = true;
4434 return result;
4435}
4436
4437bool DexVerifier::UpdateRegisters(InsnFlags* insn_flags,
4438 RegisterTable* reg_table, int next_insn, const RegisterLine* work_line) {
4439 const size_t insn_reg_count_plus = reg_table->insn_reg_count_plus_;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004440 DCHECK(work_line != NULL);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004441 const RegType* work_regs = work_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004442
4443 if (!InsnIsVisitedOrChanged(insn_flags, next_insn)) {
4444 /*
4445 * We haven't processed this instruction before, and we haven't
jeffhaod1f0fde2011-09-08 17:25:33 -07004446 * touched the registers here, so there's nothing to "merge". Copy
4447 * the registers over and mark it as changed. (This is the only
jeffhaobdb76512011-09-07 11:43:16 -07004448 * way a register can transition out of "unknown", so this is not
4449 * just an optimization.)
4450 */
4451 CopyLineToTable(reg_table, next_insn, work_line);
4452 InsnSetChanged(insn_flags, next_insn, true);
4453 } else {
4454 /* Merge registers, set Changed only if different */
4455 RegisterLine* target_line = GetRegisterLine(reg_table, next_insn);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004456 RegType* target_regs = target_line->reg_types_.get();
4457 MonitorEntries* work_mon_ents = work_line->monitor_entries_.get();
4458 MonitorEntries* target_mon_ents = target_line->monitor_entries_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004459 bool changed = false;
4460 unsigned int idx;
4461
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004462 DCHECK(target_regs != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004463 if (target_mon_ents != NULL) {
4464 /* Monitor stacks must be identical. */
4465 if (target_line->monitor_stack_top_ != work_line->monitor_stack_top_) {
4466 LOG(ERROR) << "VFY: mismatched stack depth "
4467 << target_line->monitor_stack_top_ << " vs. "
4468 << work_line->monitor_stack_top_ << " at 0x"
4469 << std::hex << next_insn << std::dec;
4470 return false;
4471 }
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004472 if (memcmp(target_line->monitor_stack_.get(), work_line->monitor_stack_.get(),
jeffhaobdb76512011-09-07 11:43:16 -07004473 target_line->monitor_stack_top_ * sizeof(uint32_t)) != 0) {
4474 LOG(ERROR) << "VFY: mismatched monitor stacks at 0x" << std::hex
4475 << next_insn << std::dec;
4476 return false;
4477 }
4478 }
4479
4480 for (idx = 0; idx < insn_reg_count_plus; idx++) {
4481 target_regs[idx] = MergeTypes(target_regs[idx], work_regs[idx], &changed);
4482
4483 if (target_mon_ents != NULL) {
4484 target_mon_ents[idx] = MergeMonitorEntries(target_mon_ents[idx],
4485 work_mon_ents[idx], &changed);
4486 }
4487 }
4488
4489 if (changed) {
4490 InsnSetChanged(insn_flags, next_insn, true);
4491 }
4492 }
4493
4494 return true;
4495}
4496
4497bool DexVerifier::CanConvertTo1nr(RegType src_type, RegType check_type) {
4498 static const char conv_tab[kRegType1nrEND - kRegType1nrSTART + 1]
4499 [kRegType1nrEND - kRegType1nrSTART + 1] =
4500 {
4501 /* chk: 0 1 Z y Y h H c i b B s S C I F */
4502 { /*0*/ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4503 { /*1*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4504 { /*Z*/ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
4505 { /*y*/ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4506 { /*Y*/ 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1 },
4507 { /*h*/ 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1 },
4508 { /*H*/ 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1 },
4509 { /*c*/ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1 },
4510 { /*i*/ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1 },
4511 { /*b*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0 },
4512 { /*B*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0 },
4513 { /*s*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 },
4514 { /*S*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 },
4515 { /*C*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 },
4516 { /*I*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },
4517 { /*F*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
4518 };
4519
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004520 DCHECK(check_type >= kRegType1nrSTART);
4521 DCHECK(check_type <= kRegType1nrEND);
jeffhaobdb76512011-09-07 11:43:16 -07004522
4523 if (src_type >= kRegType1nrSTART && src_type <= kRegType1nrEND)
4524 return (bool) conv_tab[src_type - kRegType1nrSTART]
4525 [check_type - kRegType1nrSTART];
4526
4527 return false;
4528}
4529
4530bool DexVerifier::CanConvertTo2(RegType src_type, RegType check_type) {
4531 return ((src_type == kRegTypeConstLo || src_type == check_type) &&
4532 (check_type == kRegTypeLongLo || check_type == kRegTypeDoubleLo));
4533}
4534
4535DexVerifier::RegType DexVerifier::PrimitiveTypeToRegType(
4536 Class::PrimitiveType prim_type) {
4537 switch (prim_type) {
4538 case Class::kPrimBoolean: return kRegTypeBoolean;
4539 case Class::kPrimByte: return kRegTypeByte;
4540 case Class::kPrimShort: return kRegTypeShort;
4541 case Class::kPrimChar: return kRegTypeChar;
4542 case Class::kPrimInt: return kRegTypeInteger;
4543 case Class::kPrimLong: return kRegTypeLongLo;
4544 case Class::kPrimFloat: return kRegTypeFloat;
4545 case Class::kPrimDouble: return kRegTypeDoubleLo;
4546 case Class::kPrimVoid:
4547 default: {
4548 return kRegTypeUnknown;
4549 }
4550 }
4551}
4552
4553DexVerifier::RegType DexVerifier::ConstTypeToRegType(RegType const_type) {
4554 switch (const_type) {
4555 case kRegTypeConstPosByte: return kRegTypePosByte;
4556 case kRegTypeConstByte: return kRegTypeByte;
4557 case kRegTypeConstPosShort: return kRegTypePosShort;
4558 case kRegTypeConstShort: return kRegTypeShort;
4559 case kRegTypeConstChar: return kRegTypeChar;
4560 case kRegTypeConstInteger: return kRegTypeInteger;
4561 default: {
4562 return const_type;
4563 }
4564 }
4565}
4566
4567char DexVerifier::DetermineCat1Const(int32_t value) {
4568 if (value < -32768)
4569 return kRegTypeConstInteger;
4570 else if (value < -128)
4571 return kRegTypeConstShort;
4572 else if (value < 0)
4573 return kRegTypeConstByte;
4574 else if (value == 0)
4575 return kRegTypeZero;
4576 else if (value == 1)
4577 return kRegTypeOne;
4578 else if (value < 128)
4579 return kRegTypeConstPosByte;
4580 else if (value < 32768)
4581 return kRegTypeConstPosShort;
4582 else if (value < 65536)
4583 return kRegTypeConstChar;
4584 else
4585 return kRegTypeConstInteger;
4586}
4587
4588void DexVerifier::CheckFinalFieldAccess(const Method* method,
4589 const Field* field, VerifyError* failure) {
4590 if (!field->IsFinal())
4591 return;
4592
4593 /* make sure we're in the same class */
4594 if (method->GetDeclaringClass() != field->GetDeclaringClass()) {
4595 LOG(ERROR) << "VFY: can't modify final field "
4596 << field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
4597 << "." << field->GetName()->ToModifiedUtf8();
4598 *failure = VERIFY_ERROR_ACCESS_FIELD;
4599 return;
4600 }
4601}
4602
4603void DexVerifier::CheckArrayIndexType(const Method* method, RegType reg_type,
4604 VerifyError* failure) {
4605 if (*failure == VERIFY_ERROR_NONE) {
4606 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004607 * The 1nr types are interchangeable at this level. We could
jeffhaobdb76512011-09-07 11:43:16 -07004608 * do something special if we can definitively identify it as a
4609 * float, but there's no real value in doing so.
4610 */
4611 CheckTypeCategory(reg_type, kTypeCategory1nr, failure);
4612 if (*failure != VERIFY_ERROR_NONE) {
4613 LOG(ERROR) << "Invalid reg type for array index (" << reg_type << ")";
4614 }
4615 }
4616}
4617
4618bool DexVerifier::CheckConstructorReturn(const Method* method,
4619 const RegisterLine* register_line, const int insn_reg_count) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004620 const RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004621
4622 if (!IsInitMethod(method))
4623 return true;
4624
4625 RegType uninit_this = RegTypeFromUninitIndex(kUninitThisArgSlot);
4626
4627 for (int i = 0; i < insn_reg_count; i++) {
4628 if (insn_regs[i] == uninit_this) {
4629 LOG(ERROR) << "VFY: <init> returning without calling superclass init";
4630 return false;
4631 }
4632 }
4633 return true;
4634}
4635
4636bool DexVerifier::CheckMoveException(const uint16_t* insns, int insn_idx) {
4637 if ((insns[insn_idx] & 0xff) == Instruction::MOVE_EXCEPTION) {
4638 LOG(ERROR) << "VFY: invalid use of move-exception";
4639 return false;
4640 }
4641 return true;
4642}
4643
4644void DexVerifier::CheckTypeCategory(RegType type, TypeCategory cat,
4645 VerifyError* failure) {
4646 switch (cat) {
4647 case kTypeCategory1nr:
4648 switch (type) {
4649 case kRegTypeZero:
4650 case kRegTypeOne:
4651 case kRegTypeBoolean:
4652 case kRegTypeConstPosByte:
4653 case kRegTypeConstByte:
4654 case kRegTypeConstPosShort:
4655 case kRegTypeConstShort:
4656 case kRegTypeConstChar:
4657 case kRegTypeConstInteger:
4658 case kRegTypePosByte:
4659 case kRegTypeByte:
4660 case kRegTypePosShort:
4661 case kRegTypeShort:
4662 case kRegTypeChar:
4663 case kRegTypeInteger:
4664 case kRegTypeFloat:
4665 break;
4666 default:
4667 *failure = VERIFY_ERROR_GENERIC;
4668 break;
4669 }
4670 break;
4671 case kTypeCategory2:
4672 switch (type) {
4673 case kRegTypeConstLo:
4674 case kRegTypeLongLo:
4675 case kRegTypeDoubleLo:
4676 break;
4677 default:
4678 *failure = VERIFY_ERROR_GENERIC;
4679 break;
4680 }
4681 break;
4682 case kTypeCategoryRef:
4683 if (type != kRegTypeZero && !RegTypeIsReference(type))
4684 *failure = VERIFY_ERROR_GENERIC;
4685 break;
4686 default:
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004687 DCHECK(false);
jeffhaobdb76512011-09-07 11:43:16 -07004688 *failure = VERIFY_ERROR_GENERIC;
4689 break;
4690 }
4691}
4692
4693void DexVerifier::CheckWidePair(RegType type_l, RegType type_h,
4694 VerifyError* failure) {
4695 if ((type_h != type_l + 1))
4696 *failure = VERIFY_ERROR_GENERIC;
4697}
4698
4699void DexVerifier::CheckUnop(RegisterLine* register_line,
4700 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4701 RegType src_type, VerifyError* failure) {
4702 VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
4703 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4704}
4705
4706bool DexVerifier::UpcastBooleanOp(RegisterLine* register_line, uint32_t reg1,
4707 uint32_t reg2) {
4708 RegType type1, type2;
4709
4710 type1 = GetRegisterType(register_line, reg1);
4711 type2 = GetRegisterType(register_line, reg2);
4712
4713 if ((type1 == kRegTypeBoolean || type1 == kRegTypeZero || type1 == kRegTypeOne) &&
4714 (type2 == kRegTypeBoolean || type2 == kRegTypeZero || type2 == kRegTypeOne)) {
4715 return true;
4716 }
4717 return false;
4718}
4719
4720void DexVerifier::CheckLitop(RegisterLine* register_line,
4721 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4722 RegType src_type, bool check_boolean_op, VerifyError* failure) {
4723 VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
4724
4725 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004726 DCHECK(dst_type == kRegTypeInteger);
jeffhaobdb76512011-09-07 11:43:16 -07004727
4728 /* check vB with the call, then check the constant manually */
4729 if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vB_)
4730 && (dec_insn->vC_ == 0 || dec_insn->vC_ == 1)) {
4731 dst_type = kRegTypeBoolean;
4732 }
4733 }
4734
4735 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4736}
4737
4738void DexVerifier::CheckBinop(RegisterLine* register_line,
4739 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4740 RegType src_type1, RegType src_type2, bool check_boolean_op,
4741 VerifyError* failure) {
4742 VerifyRegisterType(register_line, dec_insn->vB_, src_type1, failure);
4743 VerifyRegisterType(register_line, dec_insn->vC_, src_type2, failure);
4744
4745 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004746 DCHECK(dst_type == kRegTypeInteger);
jeffhaobdb76512011-09-07 11:43:16 -07004747 if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vC_))
4748 dst_type = kRegTypeBoolean;
4749 }
4750
4751 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4752}
4753
4754void DexVerifier::CheckBinop2addr(RegisterLine* register_line,
4755 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4756 RegType src_type1, RegType src_type2, bool check_boolean_op,
4757 VerifyError* failure) {
4758 VerifyRegisterType(register_line, dec_insn->vA_, src_type1, failure);
4759 VerifyRegisterType(register_line, dec_insn->vB_, src_type2, failure);
4760
4761 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004762 DCHECK(dst_type == kRegTypeInteger);
jeffhaobdb76512011-09-07 11:43:16 -07004763 if (UpcastBooleanOp(register_line, dec_insn->vA_, dec_insn->vB_))
4764 dst_type = kRegTypeBoolean;
4765 }
4766
4767 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4768}
4769
4770DexVerifier::RegType DexVerifier::AdjustForRightShift(
4771 RegisterLine* register_line, int reg, unsigned int shift_count,
4772 bool is_unsigned_shift, VerifyError* failure) {
4773 RegType src_type = GetRegisterType(register_line, reg);
4774 RegType new_type;
4775
4776 /* convert const derived types to their actual types */
4777 src_type = ConstTypeToRegType(src_type);
4778
4779 /* no-op */
4780 if (shift_count == 0)
4781 return src_type;
4782
4783 /* safe defaults */
4784 if (is_unsigned_shift)
4785 new_type = kRegTypeInteger;
4786 else
4787 new_type = src_type;
4788
4789 if (shift_count >= 32) {
4790 LOG(ERROR) << "Got unexpectedly large shift count " << shift_count;
4791 /* fail? */
4792 return new_type;
4793 }
4794
4795 switch (src_type) {
4796 case kRegTypeInteger: /* 32-bit signed value */
4797 if (is_unsigned_shift) {
4798 if (shift_count > 24)
4799 new_type = kRegTypePosByte;
4800 else if (shift_count >= 16)
4801 new_type = kRegTypeChar;
4802 } else {
4803 if (shift_count >= 24)
4804 new_type = kRegTypeByte;
4805 else if (shift_count >= 16)
4806 new_type = kRegTypeShort;
4807 }
4808 break;
4809 case kRegTypeShort: /* 16-bit signed value */
4810 if (is_unsigned_shift) {
4811 /* default (kRegTypeInteger) is correct */
4812 } else {
4813 if (shift_count >= 8)
4814 new_type = kRegTypeByte;
4815 }
4816 break;
4817 case kRegTypePosShort: /* 15-bit unsigned value */
4818 if (shift_count >= 8)
4819 new_type = kRegTypePosByte;
4820 break;
4821 case kRegTypeChar: /* 16-bit unsigned value */
4822 if (shift_count > 8)
4823 new_type = kRegTypePosByte;
4824 break;
4825 case kRegTypeByte: /* 8-bit signed value */
4826 /* defaults (u=kRegTypeInteger / s=src_type) are correct */
4827 break;
4828 case kRegTypePosByte: /* 7-bit unsigned value */
4829 /* always use new_type=src_type */
4830 new_type = src_type;
4831 break;
4832 case kRegTypeZero: /* 1-bit unsigned value */
4833 case kRegTypeOne:
4834 case kRegTypeBoolean:
4835 /* unnecessary? */
4836 new_type = kRegTypeZero;
4837 break;
4838 default:
4839 /* long, double, references; shouldn't be here! */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004840 DCHECK(false);
jeffhaobdb76512011-09-07 11:43:16 -07004841 break;
4842 }
4843
4844 return new_type;
4845}
4846
4847void DexVerifier::VerifyFilledNewArrayRegs(const Method* method,
4848 RegisterLine* register_line,
4849 const Instruction::DecodedInstruction* dec_insn, Class* res_class,
4850 bool is_range, VerifyError* failure) {
4851 uint32_t arg_count = dec_insn->vA_;
4852 RegType expected_type;
4853 Class::PrimitiveType elem_type;
4854 unsigned int ui;
4855
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004856 DCHECK(res_class->IsArrayClass()) << PrettyClass(res_class);
jeffhaobdb76512011-09-07 11:43:16 -07004857 elem_type = res_class->GetComponentType()->GetPrimitiveType();
4858 if (elem_type == Class::kPrimNot) {
4859 expected_type = RegTypeFromClass(res_class->GetComponentType());
4860 } else {
4861 expected_type = PrimitiveTypeToRegType(elem_type);
4862 }
4863
4864 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004865 * Verify each register. If "arg_count" is bad, VerifyRegisterType()
4866 * will run off the end of the list and fail. It's legal, if silly,
jeffhaobdb76512011-09-07 11:43:16 -07004867 * for arg_count to be zero.
4868 */
4869 for (ui = 0; ui < arg_count; ui++) {
4870 uint32_t get_reg;
4871
4872 if (is_range)
4873 get_reg = dec_insn->vC_ + ui;
4874 else
4875 get_reg = dec_insn->arg_[ui];
4876
4877 VerifyRegisterType(register_line, get_reg, expected_type, failure);
4878 if (*failure != VERIFY_ERROR_NONE) {
4879 LOG(ERROR) << "VFY: filled-new-array arg " << ui << "(" << get_reg
4880 << ") not valid";
4881 return;
4882 }
4883 }
4884}
4885
4886bool DexVerifier::IsCorrectInvokeKind(MethodType method_type,
4887 Method* res_method) {
4888 switch (method_type) {
4889 case METHOD_DIRECT:
4890 return res_method->IsDirect();
4891 case METHOD_STATIC:
4892 return res_method->IsStatic();
4893 case METHOD_VIRTUAL:
4894 case METHOD_INTERFACE:
4895 return !res_method->IsDirect();
4896 default:
4897 return false;
4898 }
4899}
4900
4901Method* DexVerifier::VerifyInvocationArgs(VerifierData* vdata,
4902 RegisterLine* register_line, const int insn_reg_count,
4903 const Instruction::DecodedInstruction* dec_insn, MethodType method_type,
4904 bool is_range, bool is_super, VerifyError* failure) {
4905 Method* method = vdata->method_;
4906 const DexFile* dex_file = vdata->dex_file_;
4907 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004908 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004909 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4910 DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
4911 const ClassLoader* class_loader =
4912 method->GetDeclaringClass()->GetClassLoader();
4913
4914 Method* res_method;
4915 std::string sig;
4916 size_t sig_offset;
4917 int expected_args;
4918 int actual_args;
4919
4920 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004921 * Resolve the method. This could be an abstract or concrete method
jeffhaobdb76512011-09-07 11:43:16 -07004922 * depending on what sort of call we're making.
4923 */
4924 res_method = class_linker->ResolveMethod(*dex_file, dec_insn->vB_, dex_cache,
4925 class_loader, (method_type == METHOD_DIRECT || method_type == METHOD_STATIC));
4926
jeffhaobdb76512011-09-07 11:43:16 -07004927 if (res_method == NULL) {
jeffhao98eacac2011-09-14 16:11:53 -07004928 const DexFile::MethodId& method_id = dex_file->GetMethodId(dec_insn->vB_);
4929 const char* method_name = dex_file->GetMethodName(method_id);
4930 const char* method_proto = dex_file->GetMethodPrototype(method_id);
4931 const char* class_descriptor = dex_file->GetMethodClassDescriptor(method_id);
4932
4933 LOG(ERROR) << "VFY: unable to resolve method " << dec_insn->vB_ << ": "
4934 << class_descriptor << "." << method_name << " " << method_proto;
jeffhaobdb76512011-09-07 11:43:16 -07004935 *failure = VERIFY_ERROR_NO_METHOD;
4936 return NULL;
4937 }
jeffhaobdb76512011-09-07 11:43:16 -07004938
4939 /*
4940 * Only time you can explicitly call a method starting with '<' is when
jeffhaod1f0fde2011-09-08 17:25:33 -07004941 * making a "direct" invocation on "<init>". There are additional
jeffhaobdb76512011-09-07 11:43:16 -07004942 * restrictions but we don't enforce them here.
4943 */
4944 if (res_method->GetName()->Equals("<init>")) {
4945 if (method_type != METHOD_DIRECT || !IsInitMethod(res_method)) {
4946 LOG(ERROR) << "VFY: invalid call to "
jeffhao98eacac2011-09-14 16:11:53 -07004947 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
jeffhaobdb76512011-09-07 11:43:16 -07004948 << "." << res_method->GetName();
4949 goto bad_sig;
4950 }
4951 }
4952
4953 /*
4954 * See if the method type implied by the invoke instruction matches the
4955 * access flags for the target method.
4956 */
4957 if (!IsCorrectInvokeKind(method_type, res_method)) {
4958 LOG(ERROR) << "VFY: invoke type does not match method type of "
jeffhao98eacac2011-09-14 16:11:53 -07004959 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
jeffhaobdb76512011-09-07 11:43:16 -07004960 << "." << res_method->GetName()->ToModifiedUtf8();
4961
4962 *failure = VERIFY_ERROR_GENERIC;
4963 return NULL;
4964 }
4965
4966 /*
4967 * If we're using invoke-super(method), make sure that the executing
4968 * method's class' superclass has a vtable entry for the target method.
4969 */
4970 if (is_super) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004971 DCHECK(method_type == METHOD_VIRTUAL);
jeffhaobdb76512011-09-07 11:43:16 -07004972 Class* super = method->GetDeclaringClass()->GetSuperClass();
4973 if (super == NULL || res_method->GetMethodIndex() > super->GetVTable()->GetLength()) {
4974 if (super == NULL) {
4975 LOG(ERROR) << "VFY: invalid invoke-super from "
4976 << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
4977 << "." << method->GetName()->ToModifiedUtf8() << " to super -."
4978 << res_method->GetName()->ToModifiedUtf8()
4979 << " " << res_method->GetSignature()->ToModifiedUtf8();
4980 } else {
4981 LOG(ERROR) << "VFY: invalid invoke-super from "
4982 << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
4983 << "." << method->GetName()->ToModifiedUtf8() << " to super "
4984 << super->GetDescriptor()->ToModifiedUtf8()
4985 << "." << res_method->GetName()->ToModifiedUtf8()
4986 << " " << res_method->GetSignature()->ToModifiedUtf8();
4987 }
4988 *failure = VERIFY_ERROR_NO_METHOD;
4989 return NULL;
4990 }
4991 }
4992
4993 /*
4994 * We use vAA as our expected arg count, rather than res_method->insSize,
jeffhaod1f0fde2011-09-08 17:25:33 -07004995 * because we need to match the call to the signature. Also, we might
jeffhaobdb76512011-09-07 11:43:16 -07004996 * might be calling through an abstract method definition (which doesn't
4997 * have register count values).
4998 */
4999 expected_args = dec_insn->vA_;
5000 actual_args = 0;
5001
5002 /* caught by static verifier */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005003 DCHECK(is_range || expected_args <= 5);
jeffhaobdb76512011-09-07 11:43:16 -07005004
5005 if (expected_args > code_item->outs_size_) {
5006 LOG(ERROR) << "VFY: invalid arg count (" << expected_args
5007 << ") exceeds outsSize (" << code_item->outs_size_ << ")";
5008 *failure = VERIFY_ERROR_GENERIC;
5009 return NULL;
5010 }
5011
5012 sig = res_method->GetSignature()->ToModifiedUtf8();
5013 if (sig[0] != '(') {
5014 LOG(ERROR) << "VFY: descriptor doesn't start with '(': " << sig;
5015 goto bad_sig;
5016 }
5017
5018 /*
5019 * Check the "this" argument, which must be an instance of the class
jeffhaod1f0fde2011-09-08 17:25:33 -07005020 * that declared the method. For an interface class, we don't do the
jeffhaobdb76512011-09-07 11:43:16 -07005021 * full interface merge, so we can't do a rigorous check here (which
5022 * is okay since we have to do it at runtime).
5023 */
5024 if (!res_method->IsStatic()) {
5025 Class* actual_this_ref;
5026 RegType actual_arg_type;
5027
5028 actual_arg_type = GetInvocationThis(register_line, dec_insn, failure);
5029 if (*failure != VERIFY_ERROR_NONE)
5030 return NULL;
5031
5032 if (RegTypeIsUninitReference(actual_arg_type) &&
5033 !res_method->GetName()->Equals("<init>")) {
5034 LOG(ERROR) << "VFY: 'this' arg must be initialized";
5035 *failure = VERIFY_ERROR_GENERIC;
5036 return NULL;
5037 }
5038 if (method_type != METHOD_INTERFACE && actual_arg_type != kRegTypeZero) {
5039 actual_this_ref = RegTypeReferenceToClass(actual_arg_type, uninit_map);
5040 if (!res_method->GetDeclaringClass()->IsAssignableFrom(actual_this_ref)) {
5041 LOG(ERROR) << "VFY: 'this' arg '"
5042 << actual_this_ref->GetDescriptor()->ToModifiedUtf8()
5043 << "' not instance of '"
5044 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5045 << "'";
5046 *failure = VERIFY_ERROR_GENERIC;
5047 return NULL;
5048 }
5049 }
5050 actual_args++;
5051 }
5052
5053 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07005054 * Process the target method's signature. This signature may or may not
jeffhaobdb76512011-09-07 11:43:16 -07005055 * have been verified, so we can't assume it's properly formed.
5056 */
5057 for (sig_offset = 1; sig_offset < sig.size(); sig_offset++) {
jeffhaobdb76512011-09-07 11:43:16 -07005058 if (sig[sig_offset] == ')')
5059 break;
5060
5061 if (actual_args >= expected_args) {
5062 LOG(ERROR) << "VFY: expected " << expected_args << " args, found more ("
5063 << sig.substr(sig_offset) << ")";
5064 goto bad_sig;
5065 }
5066
5067 uint32_t get_reg;
5068 if (is_range)
5069 get_reg = dec_insn->vC_ + actual_args;
5070 else
5071 get_reg = dec_insn->arg_[actual_args];
5072
5073 switch (sig[sig_offset]) {
5074 case 'L':
5075 {
5076 Class* klass = LookupSignatureClass(method, sig.substr(sig_offset),
5077 failure);
5078 if (*failure != VERIFY_ERROR_NONE)
5079 goto bad_sig;
5080 VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
5081 failure);
5082 if (*failure != VERIFY_ERROR_NONE) {
5083 LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
5084 << klass->GetDescriptor()->ToModifiedUtf8() << ")";
5085 goto bad_sig;
5086 }
5087 sig_offset += sig.substr(sig_offset).find(';');
5088 }
5089 actual_args++;
5090 break;
5091 case '[':
5092 {
5093 Class* klass = LookupSignatureArrayClass(method,
5094 sig.substr(sig_offset), failure);
5095 if (*failure != VERIFY_ERROR_NONE)
5096 goto bad_sig;
5097 VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
5098 failure);
5099 if (*failure != VERIFY_ERROR_NONE) {
5100 LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
5101 << klass->GetDescriptor()->ToModifiedUtf8() << ")";
5102 goto bad_sig;
5103 }
5104 while (sig[sig_offset] == '[')
5105 sig_offset++;
5106 if (sig[sig_offset] == 'L')
5107 sig_offset += sig.substr(sig_offset).find(';');
5108 }
5109 actual_args++;
5110 break;
5111 case 'Z':
5112 VerifyRegisterType(register_line, get_reg, kRegTypeBoolean, failure);
5113 actual_args++;
5114 break;
5115 case 'C':
5116 VerifyRegisterType(register_line, get_reg, kRegTypeChar, failure);
5117 actual_args++;
5118 break;
5119 case 'B':
5120 VerifyRegisterType(register_line, get_reg, kRegTypeByte, failure);
5121 actual_args++;
5122 break;
5123 case 'I':
5124 VerifyRegisterType(register_line, get_reg, kRegTypeInteger, failure);
5125 actual_args++;
5126 break;
5127 case 'S':
5128 VerifyRegisterType(register_line, get_reg, kRegTypeShort, failure);
5129 actual_args++;
5130 break;
5131 case 'F':
5132 VerifyRegisterType(register_line, get_reg, kRegTypeFloat, failure);
5133 actual_args++;
5134 break;
5135 case 'D':
5136 VerifyRegisterType(register_line, get_reg, kRegTypeDoubleLo, failure);
5137 actual_args += 2;
5138 break;
5139 case 'J':
5140 VerifyRegisterType(register_line, get_reg, kRegTypeLongLo, failure);
5141 actual_args += 2;
5142 break;
5143 default:
5144 LOG(ERROR) << "VFY: invocation target: bad signature type char '"
5145 << sig << "'";
5146 goto bad_sig;
5147 }
5148 }
5149 if (sig[sig_offset] != ')') {
5150 LOG(ERROR) << "VFY: invocation target: bad signature '"
5151 << res_method->GetSignature()->ToModifiedUtf8() << "'";
5152 goto bad_sig;
5153 }
5154
5155 if (actual_args != expected_args) {
5156 LOG(ERROR) << "VFY: expected " << expected_args << " args, found "
5157 << actual_args;
5158 goto bad_sig;
5159 }
5160
5161 return res_method;
5162
5163bad_sig:
5164 if (res_method != NULL) {
5165 LOG(ERROR) << "VFY: rejecting call to "
5166 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5167 << "." << res_method->GetName()->ToModifiedUtf8() << " "
5168 << res_method->GetSignature()->ToModifiedUtf8();
5169 }
5170
5171 if (*failure == VERIFY_ERROR_NONE)
5172 *failure = VERIFY_ERROR_GENERIC;
5173 return NULL;
5174}
jeffhaoba5ebb92011-08-25 17:24:37 -07005175
jeffhaod1f0fde2011-09-08 17:25:33 -07005176DexVerifier::RegisterMap* DexVerifier::GenerateRegisterMapV(VerifierData* vdata)
5177{
5178 const DexFile::CodeItem* code_item = vdata->code_item_;
5179 int i, bytes_for_addr, gc_point_count;
5180
5181 if (code_item->registers_size_ >= 2048) {
5182 LOG(ERROR) << "ERROR: register map can't handle "
5183 << code_item->registers_size_ << " registers";
5184 return NULL;
5185 }
5186 uint8_t reg_width = (code_item->registers_size_ + 7) / 8;
5187
5188 /*
5189 * Decide if we need 8 or 16 bits to hold the address. Strictly speaking
5190 * we only need 16 bits if we actually encode an address >= 256 -- if
5191 * the method has a section at the end without GC points (e.g. array
5192 * data) we don't need to count it. The situation is unusual, and
5193 * detecting it requires scanning the entire method, so we don't bother.
5194 */
5195 RegisterMapFormat format;
5196 if (code_item->insns_size_ < 256) {
5197 format = kRegMapFormatCompact8;
5198 bytes_for_addr = 1;
5199 } else {
5200 format = kRegMapFormatCompact16;
5201 bytes_for_addr = 2;
5202 }
5203
5204 /*
5205 * Count up the number of GC point instructions.
5206 *
5207 * NOTE: this does not automatically include the first instruction,
5208 * since we don't count method entry as a GC point.
5209 */
5210 gc_point_count = 0;
5211 for (i = 0; i < (int) code_item->insns_size_; i++) {
5212 if (InsnIsGcPoint(vdata->insn_flags_.get(), i))
5213 gc_point_count++;
5214 }
5215 if (gc_point_count >= 65536) {
5216 /* We could handle this, but in practice we don't get near this. */
5217 LOG(ERROR) << "ERROR: register map can't handle " << gc_point_count
5218 << " gc points in one method";
5219 return NULL;
5220 }
5221
5222 /* Calculate size of buffer to hold the map data. */
5223 uint32_t data_size = gc_point_count * (bytes_for_addr + reg_width);
5224
5225 RegisterMap* map = new RegisterMap(format, reg_width, gc_point_count,
jeffhaoa0a764a2011-09-16 10:43:38 -07005226 data_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005227
5228 /* Populate it. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005229 uint8_t* map_data = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005230 for (i = 0; i < (int) vdata->code_item_->insns_size_; i++) {
5231 if (InsnIsGcPoint(vdata->insn_flags_.get(), i)) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005232 DCHECK(vdata->register_lines_[i].reg_types_.get() != NULL);
jeffhaod1f0fde2011-09-08 17:25:33 -07005233 if (format == kRegMapFormatCompact8) {
5234 *map_data++ = i;
5235 } else /*kRegMapFormatCompact16*/ {
5236 *map_data++ = i & 0xff;
5237 *map_data++ = i >> 8;
5238 }
5239 OutputTypeVector(vdata->register_lines_[i].reg_types_.get(),
5240 code_item->registers_size_, map_data);
5241 map_data += reg_width;
5242 }
5243 }
5244
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005245 DCHECK_EQ((uint32_t) map_data - (uint32_t) map->data_, data_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005246
5247 // TODO: Remove this check when it's really running...
5248#if 1
5249 if (!VerifyMap(vdata, map)) {
5250 LOG(ERROR) << "Map failed to verify";
5251 return NULL;
5252 }
5253#endif
5254
5255 /* Try to compress the map. */
5256 RegisterMap* compress_map = CompressMapDifferential(map);
5257 if (compress_map != NULL) {
5258 // TODO: Remove this check when it's really running...
5259#if 1
5260 /*
5261 * Expand the compressed map we just created, and compare it
5262 * to the original. Abort the VM if it doesn't match up.
5263 */
5264 UniquePtr<RegisterMap> uncompressed_map(UncompressMapDifferential(compress_map));
5265 if (uncompressed_map.get() == NULL) {
5266 LOG(ERROR) << "Map failed to uncompress - "
5267 << vdata->method_->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5268 << "." << vdata->method_->GetName()->ToModifiedUtf8();
5269 delete map;
5270 delete compress_map;
5271 /* bad - compression is broken or we're out of memory */
5272 return NULL;
5273 } else {
5274 if (!CompareMaps(map, uncompressed_map.get())) {
5275 LOG(ERROR) << "Map comparison failed - "
5276 << vdata->method_->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5277 << "." << vdata->method_->GetName()->ToModifiedUtf8();
5278 delete map;
5279 delete compress_map;
5280 /* bad - compression is broken */
5281 return NULL;
5282 }
5283 }
5284#endif
5285 delete map;
5286 map = compress_map;
5287 }
5288
5289 return map;
5290}
5291
jeffhaoa0a764a2011-09-16 10:43:38 -07005292DexVerifier::RegisterMap* DexVerifier::GetExpandedRegisterMapHelper(
5293 Method* method, RegisterMap* map) {
5294 RegisterMap* new_map;
5295
5296 if (map == NULL)
5297 return NULL;
5298
5299 /* TODO: sanity check to ensure this isn't called w/o external locking */
5300
5301 uint8_t format = map->header_->format_;
5302 switch (format) {
5303 case kRegMapFormatCompact8:
5304 case kRegMapFormatCompact16:
5305 /* already expanded */
5306 return map;
5307 case kRegMapFormatDifferential:
5308 new_map = UncompressMapDifferential(map);
5309 break;
5310 default:
5311 LOG(ERROR) << "Unknown format " << format
5312 << " in dvmGetExpandedRegisterMap";
5313 return NULL;
5314 }
5315
5316 if (new_map == NULL) {
5317 LOG(ERROR) << "Map failed to uncompress (fmt=" << format << ") "
5318 << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5319 << "." << method->GetName();
5320 return NULL;
5321 }
5322
5323 /* Update method, and free compressed map if it was sitting on the heap. */
5324 ByteArray* header = ByteArray::Alloc(sizeof(RegisterMapHeader));
5325 ByteArray* data = ByteArray::Alloc(ComputeRegisterMapSize(map));
5326
5327 memcpy(header->GetData(), map->header_, sizeof(RegisterMapHeader));
5328 memcpy(data->GetData(), map->data_, ComputeRegisterMapSize(map));
5329
5330 method->SetRegisterMapHeader(header);
5331 method->SetRegisterMapData(data);
5332
5333 delete map;
5334 return new_map;
5335}
5336
5337const uint8_t* DexVerifier::RegisterMapGetLine(const RegisterMap* map, int addr) {
5338 int addr_width, line_width;
5339 uint8_t format = map->header_->format_;
5340 uint16_t num_entries = map->header_->num_entries_;
5341
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005342 DCHECK_GT(num_entries, 0);
jeffhaoa0a764a2011-09-16 10:43:38 -07005343
5344 switch (format) {
5345 case kRegMapFormatNone:
5346 return NULL;
5347 case kRegMapFormatCompact8:
5348 addr_width = 1;
5349 break;
5350 case kRegMapFormatCompact16:
5351 addr_width = 2;
5352 break;
5353 default:
5354 LOG(ERROR) << "Unknown format " << format;
5355 return NULL;
5356 }
5357
5358 line_width = addr_width + map->header_->reg_width_;
5359
5360 /*
5361 * Find the appropriate entry. Many maps are very small, some are very large.
5362 */
5363 static const int kSearchThreshold = 8;
5364 const uint8_t* data = NULL;
5365 int line_addr;
5366
5367 if (num_entries < kSearchThreshold) {
5368 int i;
5369 data = map->data_;
5370 for (i = num_entries; i > 0; i--) {
5371 line_addr = data[0];
5372 if (addr_width > 1)
5373 line_addr |= data[1] << 8;
5374 if (line_addr == addr)
5375 return data + addr_width;
5376
5377 data += line_width;
5378 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005379 DCHECK_EQ(data, map->data_ + line_width * num_entries);
jeffhaoa0a764a2011-09-16 10:43:38 -07005380 } else {
5381 int hi, lo, mid;
5382
5383 lo = 0;
5384 hi = num_entries -1;
5385
5386 while (hi >= lo) {
5387 mid = (hi + lo) / 2;
5388 data = map->data_ + line_width * mid;
5389
5390 line_addr = data[0];
5391 if (addr_width > 1)
5392 line_addr |= data[1] << 8;
5393
5394 if (addr > line_addr) {
5395 lo = mid + 1;
5396 } else if (addr < line_addr) {
5397 hi = mid - 1;
5398 } else {
5399 return data + addr_width;
5400 }
5401 }
5402 }
5403
5404 return NULL;
5405}
5406
jeffhaod1f0fde2011-09-08 17:25:33 -07005407void DexVerifier::OutputTypeVector(const RegType* regs, int insn_reg_count,
5408 uint8_t* data) {
5409 uint8_t val = 0;
5410 int i;
5411
5412 for (i = 0; i < insn_reg_count; i++) {
5413 RegType type = *regs++;
5414 val >>= 1;
5415 if (IsReferenceType(type))
5416 val |= 0x80; /* set hi bit */
5417
5418 if ((i & 0x07) == 7)
5419 *data++ = val;
5420 }
5421 if ((i & 0x07) != 0) {
5422 /* Flush bits from last byte. */
5423 val >>= 8 - (i & 0x07);
5424 *data++ = val;
5425 }
5426}
5427
5428bool DexVerifier::VerifyMap(VerifierData* vdata, const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005429 const uint8_t* raw_map = map->data_;
5430 uint8_t format = map->header_->format_;
5431 const int num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005432 int ent;
5433
jeffhaoe23d93c2011-09-15 14:48:43 -07005434 if ((vdata->code_item_->registers_size_ + 7) / 8 != map->header_->reg_width_) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005435 LOG(ERROR) << "GLITCH: registersSize=" << vdata->code_item_->registers_size_
jeffhaoe23d93c2011-09-15 14:48:43 -07005436 << ", reg_width=" << map->header_->reg_width_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005437 return false;
5438 }
5439
5440 for (ent = 0; ent < num_entries; ent++) {
5441 int addr;
5442
5443 switch (format) {
5444 case kRegMapFormatCompact8:
5445 addr = *raw_map++;
5446 break;
5447 case kRegMapFormatCompact16:
5448 addr = *raw_map++;
5449 addr |= (*raw_map++) << 8;
5450 break;
5451 default:
5452 LOG(FATAL) << "GLITCH: bad format (" << format << ")";
5453 return false;
5454 }
5455
5456 const RegType* regs = vdata->register_lines_[addr].reg_types_.get();
5457 if (regs == NULL) {
5458 LOG(ERROR) << "GLITCH: addr " << addr << " has no data";
5459 return false;
5460 }
5461
5462 uint8_t val = 0;
5463 int i;
5464
5465 for (i = 0; i < vdata->code_item_->registers_size_; i++) {
5466 bool bit_is_ref, reg_is_ref;
5467
5468 val >>= 1;
5469 if ((i & 0x07) == 0) {
5470 /* Load next byte of data. */
5471 val = *raw_map++;
5472 }
5473
5474 bit_is_ref = val & 0x01;
5475
5476 RegType type = regs[i];
5477 reg_is_ref = IsReferenceType(type);
5478
5479 if (bit_is_ref != reg_is_ref) {
5480 LOG(ERROR) << "GLITCH: addr " << addr << " reg " << i << ": bit="
5481 << bit_is_ref << " reg=" << reg_is_ref << "(" << type << ")";
5482 return false;
5483 }
5484 }
5485 /* Raw_map now points to the address field of the next entry. */
5486 }
5487
5488 return true;
5489}
5490
5491bool DexVerifier::CompareMaps(const RegisterMap* map1, const RegisterMap* map2)
5492{
5493 size_t size1, size2;
5494
5495 size1 = ComputeRegisterMapSize(map1);
5496 size2 = ComputeRegisterMapSize(map2);
5497 if (size1 != size2) {
5498 LOG(ERROR) << "CompareMaps: size mismatch (" << size1 << " vs " << size2
5499 << ")";
5500 return false;
5501 }
5502
jeffhaoe23d93c2011-09-15 14:48:43 -07005503 if (map1->header_->format_ != map2->header_->format_ ||
5504 map1->header_->reg_width_ != map2->header_->reg_width_ ||
jeffhaoa0a764a2011-09-16 10:43:38 -07005505 map1->header_->num_entries_ != map2->header_->num_entries_) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005506 LOG(ERROR) << "CompareMaps: fields mismatch";
5507 }
jeffhaoe23d93c2011-09-15 14:48:43 -07005508 if (memcmp(map1->data_, map2->data_, size1) != 0) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005509 LOG(ERROR) << "CompareMaps: data mismatch";
5510 return false;
5511 }
5512
5513 return true;
5514}
5515
5516size_t DexVerifier::ComputeRegisterMapSize(const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005517 uint8_t format = map->header_->format_;
5518 uint16_t num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005519
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005520 DCHECK(map != NULL);
jeffhaod1f0fde2011-09-08 17:25:33 -07005521
5522 switch (format) {
5523 case kRegMapFormatNone:
5524 return 1;
5525 case kRegMapFormatCompact8:
jeffhaoe23d93c2011-09-15 14:48:43 -07005526 return (1 + map->header_->reg_width_) * num_entries;
jeffhaod1f0fde2011-09-08 17:25:33 -07005527 case kRegMapFormatCompact16:
jeffhaoe23d93c2011-09-15 14:48:43 -07005528 return (2 + map->header_->reg_width_) * num_entries;
jeffhaod1f0fde2011-09-08 17:25:33 -07005529 case kRegMapFormatDifferential:
5530 {
5531 /* Decoded ULEB128 length. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005532 const uint8_t* ptr = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005533 return DecodeUnsignedLeb128(&ptr);
5534 }
5535 default:
5536 LOG(FATAL) << "Bad register map format " << format;
5537 return 0;
5538 }
5539}
5540
5541int DexVerifier::ComputeBitDiff(const uint8_t* bits1, const uint8_t* bits2,
5542 int byte_width, int* first_bit_changed_ptr, int* num_bits_changed_ptr,
5543 uint8_t* leb_out_buf) {
5544 int num_bits_changed = 0;
5545 int first_bit_changed = -1;
5546 int leb_size = 0;
5547 int byte_num;
5548
5549 /*
5550 * Run through the vectors, first comparing them at the byte level. This
5551 * will yield a fairly quick result if nothing has changed between them.
5552 */
5553 for (byte_num = 0; byte_num < byte_width; byte_num++) {
5554 uint8_t byte1 = *bits1++;
5555 uint8_t byte2 = *bits2++;
5556 if (byte1 != byte2) {
5557 /* Walk through the byte, identifying the changed bits. */
5558 int bit_num;
5559 for (bit_num = 0; bit_num < 8; bit_num++) {
5560 if (((byte1 >> bit_num) & 0x01) != ((byte2 >> bit_num) & 0x01)) {
5561 int bit_offset = (byte_num << 3) + bit_num;
5562
5563 if (first_bit_changed < 0)
5564 first_bit_changed = bit_offset;
5565 num_bits_changed++;
5566
5567 if (leb_out_buf == NULL) {
5568 leb_size += UnsignedLeb128Size(bit_offset);
5569 } else {
5570 uint8_t* cur_buf = leb_out_buf;
5571 leb_out_buf = WriteUnsignedLeb128(leb_out_buf, bit_offset);
5572 leb_size += leb_out_buf - cur_buf;
5573 }
5574 }
5575 }
5576 }
5577 }
5578
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005579 if (num_bits_changed > 0) {
5580 DCHECK_GE(first_bit_changed, 0);
5581 }
jeffhaod1f0fde2011-09-08 17:25:33 -07005582
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005583 if (first_bit_changed_ptr != NULL) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005584 *first_bit_changed_ptr = first_bit_changed;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005585 }
5586
5587 if (num_bits_changed_ptr != NULL) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005588 *num_bits_changed_ptr = num_bits_changed;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005589 }
jeffhaod1f0fde2011-09-08 17:25:33 -07005590
5591 return leb_size;
5592}
5593
5594DexVerifier::RegisterMap* DexVerifier::CompressMapDifferential(
5595 const RegisterMap* map) {
5596 int orig_size = ComputeRegisterMapSize(map);
5597 uint8_t* tmp_ptr;
5598 int addr_width;
5599
jeffhaoe23d93c2011-09-15 14:48:43 -07005600 uint8_t format = map->header_->format_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005601 switch (format) {
5602 case kRegMapFormatCompact8:
5603 addr_width = 1;
5604 break;
5605 case kRegMapFormatCompact16:
5606 addr_width = 2;
5607 break;
5608 default:
5609 LOG(ERROR) << "ERROR: can't compress map with format=" << format;
5610 return NULL;
5611 }
5612
jeffhaoe23d93c2011-09-15 14:48:43 -07005613 int reg_width = map->header_->reg_width_;
5614 int num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005615
5616 if (num_entries <= 1) {
5617 return NULL;
5618 }
5619
5620 /*
5621 * We don't know how large the compressed data will be. It's possible
5622 * for it to expand and become larger than the original. The header
5623 * itself is variable-sized, so we generate everything into a temporary
5624 * buffer and then copy it to form-fitting storage once we know how big
5625 * it will be (and that it's smaller than the original).
5626 *
5627 * If we use a size that is equal to the size of the input map plus
5628 * a value longer than a single entry can possibly expand to, we need
5629 * only check for overflow at the end of each entry. The worst case
5630 * for a single line is (1 + <ULEB8 address> + <full copy of vector>).
5631 * Addresses are 16 bits, so that's (1 + 3 + reg_width).
5632 *
5633 * The initial address offset and bit vector will take up less than
5634 * or equal to the amount of space required when uncompressed -- large
5635 * initial offsets are rejected.
5636 */
5637 UniquePtr<uint8_t[]> tmp_buf(new uint8_t[orig_size + (1 + 3 + reg_width)]);
5638
5639 tmp_ptr = tmp_buf.get();
5640
jeffhaoe23d93c2011-09-15 14:48:43 -07005641 const uint8_t* map_data = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005642 const uint8_t* prev_bits;
5643 uint16_t addr, prev_addr;
5644
5645 addr = *map_data++;
5646 if (addr_width > 1)
5647 addr |= (*map_data++) << 8;
5648
5649 if (addr >= 128) {
5650 LOG(ERROR) << "Can't compress map with starting address >= 128";
5651 return NULL;
5652 }
5653
5654 /*
5655 * Start by writing the initial address and bit vector data. The high
5656 * bit of the initial address is used to indicate the required address
5657 * width (which the decoder can't otherwise determine without parsing
5658 * the compressed data).
5659 */
5660 *tmp_ptr++ = addr | (addr_width > 1 ? 0x80 : 0x00);
5661 memcpy(tmp_ptr, map_data, reg_width);
5662
5663 prev_bits = map_data;
5664 prev_addr = addr;
5665
5666 tmp_ptr += reg_width;
5667 map_data += reg_width;
5668
5669 /* Loop over all following entries. */
5670 for (int entry = 1; entry < num_entries; entry++) {
5671 int addr_diff;
5672 uint8_t key;
5673
5674 /* Pull out the address and figure out how to encode it. */
5675 addr = *map_data++;
5676 if (addr_width > 1)
5677 addr |= (*map_data++) << 8;
5678
5679 addr_diff = addr - prev_addr;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005680 DCHECK_GT(addr_diff, 0);
jeffhaod1f0fde2011-09-08 17:25:33 -07005681 if (addr_diff < 8) {
5682 /* Small difference, encode in 3 bits. */
5683 key = addr_diff -1; /* set 00000AAA */
5684 } else {
5685 /* Large difference, output escape code. */
5686 key = 0x07; /* escape code for AAA */
5687 }
5688
5689 int num_bits_changed, first_bit_changed, leb_size;
5690
5691 leb_size = ComputeBitDiff(prev_bits, map_data, reg_width,
5692 &first_bit_changed, &num_bits_changed, NULL);
5693
5694 if (num_bits_changed == 0) {
5695 /* set B to 1 and CCCC to zero to indicate no bits were changed */
5696 key |= 0x08;
5697 } else if (num_bits_changed == 1 && first_bit_changed < 16) {
5698 /* set B to 0 and CCCC to the index of the changed bit */
5699 key |= first_bit_changed << 4;
5700 } else if (num_bits_changed < 15 && leb_size < reg_width) {
5701 /* set B to 1 and CCCC to the number of bits */
5702 key |= 0x08 | (num_bits_changed << 4);
5703 } else {
5704 /* set B to 1 and CCCC to 0x0f so we store the entire vector */
5705 key |= 0x08 | 0xf0;
5706 }
5707
5708 /*
5709 * Encode output. Start with the key, follow with the address
5710 * diff (if it didn't fit in 3 bits), then the changed bit info.
5711 */
5712 *tmp_ptr++ = key;
5713 if ((key & 0x07) == 0x07)
5714 tmp_ptr = WriteUnsignedLeb128(tmp_ptr, addr_diff);
5715
5716 if ((key & 0x08) != 0) {
5717 int bit_count = key >> 4;
5718 if (bit_count == 0) {
5719 /* nothing changed, no additional output required */
5720 } else if (bit_count == 15) {
5721 /* full vector is most compact representation */
5722 memcpy(tmp_ptr, map_data, reg_width);
5723 tmp_ptr += reg_width;
5724 } else {
5725 /* write bit indices in ULEB128 format */
5726 (void) ComputeBitDiff(prev_bits, map_data, reg_width,
5727 NULL, NULL, tmp_ptr);
5728 tmp_ptr += leb_size;
5729 }
5730 } else {
5731 /* single-bit changed, value encoded in key byte */
5732 }
5733
5734 prev_bits = map_data;
5735 prev_addr = addr;
5736 map_data += reg_width;
5737
5738 /* See if we've run past the original size. */
5739 if (tmp_ptr - tmp_buf.get() >= orig_size) {
5740 return NULL;
5741 }
5742 }
5743
5744 /*
5745 * Create a RegisterMap with the contents.
5746 *
5747 * TODO: consider using a threshold other than merely ">=". We would
5748 * get poorer compression but potentially use less native heap space.
5749 */
5750 int new_data_size = tmp_ptr - tmp_buf.get();
5751 int new_map_size = new_data_size + UnsignedLeb128Size(new_data_size);
5752
5753 if (new_map_size >= orig_size) {
5754 return NULL;
5755 }
5756
5757 RegisterMap* new_map = new RegisterMap(kRegMapFormatDifferential, reg_width,
jeffhaoa0a764a2011-09-16 10:43:38 -07005758 num_entries, new_map_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005759
jeffhaoe23d93c2011-09-15 14:48:43 -07005760 tmp_ptr = new_map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005761 tmp_ptr = WriteUnsignedLeb128(tmp_ptr, new_data_size);
5762 memcpy(tmp_ptr, tmp_buf.get(), new_data_size);
5763
5764 return new_map;
5765}
5766
5767DexVerifier::RegisterMap* DexVerifier::UncompressMapDifferential(
5768 const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005769 uint8_t format = map->header_->format_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005770 RegisterMapFormat new_format;
5771 int reg_width, num_entries, new_addr_width, new_data_size;
5772
5773 if (format != kRegMapFormatDifferential) {
5774 LOG(ERROR) << "Not differential (" << format << ")";
5775 return NULL;
5776 }
5777
jeffhaoe23d93c2011-09-15 14:48:43 -07005778 reg_width = map->header_->reg_width_;
5779 num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005780
5781 /* Get the data size; we can check this at the end. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005782 const uint8_t* src_ptr = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005783 int expected_src_len = DecodeUnsignedLeb128(&src_ptr);
5784 const uint8_t* src_start = src_ptr;
5785
5786 /* Get the initial address and the 16-bit address flag. */
5787 int addr = *src_ptr & 0x7f;
5788 if ((*src_ptr & 0x80) == 0) {
5789 new_format = kRegMapFormatCompact8;
5790 new_addr_width = 1;
5791 } else {
5792 new_format = kRegMapFormatCompact16;
5793 new_addr_width = 2;
5794 }
5795 src_ptr++;
5796
5797 /* Now we know enough to allocate the new map. */
5798 new_data_size = (new_addr_width + reg_width) * num_entries;
5799 RegisterMap* new_map = new RegisterMap(new_format, reg_width, num_entries,
jeffhaoa0a764a2011-09-16 10:43:38 -07005800 new_data_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005801
5802 /* Write the start address and initial bits to the new map. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005803 uint8_t* dst_ptr = new_map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005804
5805 *dst_ptr++ = addr & 0xff;
5806 if (new_addr_width > 1)
5807 *dst_ptr++ = (uint8_t) (addr >> 8);
5808
5809 memcpy(dst_ptr, src_ptr, reg_width);
5810
5811 int prev_addr = addr;
5812 const uint8_t* prev_bits = dst_ptr; /* point at uncompressed data */
5813
5814 dst_ptr += reg_width;
5815 src_ptr += reg_width;
5816
5817 /* Walk through, uncompressing one line at a time. */
5818 int entry;
5819 for (entry = 1; entry < num_entries; entry++) {
5820 int addr_diff;
5821 uint8_t key;
5822
5823 key = *src_ptr++;
5824
5825 /* Get the address. */
5826 if ((key & 0x07) == 7) {
5827 /* Address diff follows in ULEB128. */
5828 addr_diff = DecodeUnsignedLeb128(&src_ptr);
5829 } else {
5830 addr_diff = (key & 0x07) +1;
5831 }
5832
5833 addr = prev_addr + addr_diff;
5834 *dst_ptr++ = addr & 0xff;
5835 if (new_addr_width > 1)
5836 *dst_ptr++ = (uint8_t) (addr >> 8);
5837
5838 /* Unpack the bits. */
5839 if ((key & 0x08) != 0) {
5840 int bit_count = (key >> 4);
5841 if (bit_count == 0) {
5842 /* No bits changed, just copy previous. */
5843 memcpy(dst_ptr, prev_bits, reg_width);
5844 } else if (bit_count == 15) {
5845 /* Full copy of bit vector is present; ignore prev_bits. */
5846 memcpy(dst_ptr, src_ptr, reg_width);
5847 src_ptr += reg_width;
5848 } else {
5849 /* Copy previous bits and modify listed indices. */
5850 memcpy(dst_ptr, prev_bits, reg_width);
5851 while (bit_count--) {
5852 int bit_index = DecodeUnsignedLeb128(&src_ptr);
5853 ToggleBit(dst_ptr, bit_index);
5854 }
5855 }
5856 } else {
5857 /* Copy previous bits and modify the specified one. */
5858 memcpy(dst_ptr, prev_bits, reg_width);
5859
5860 /* One bit, from 0-15 inclusive, was changed. */
5861 ToggleBit(dst_ptr, key >> 4);
5862 }
5863
5864 prev_addr = addr;
5865 prev_bits = dst_ptr;
5866 dst_ptr += reg_width;
5867 }
5868
jeffhaoe23d93c2011-09-15 14:48:43 -07005869 if (dst_ptr - new_map->data_ != new_data_size) {
5870 LOG(ERROR) << "ERROR: output " << dst_ptr - new_map->data_
jeffhaod1f0fde2011-09-08 17:25:33 -07005871 << " bytes, expected " << new_data_size;
5872 free(new_map);
5873 return NULL;
5874 }
5875
5876 if (src_ptr - src_start != expected_src_len) {
5877 LOG(ERROR) << "ERROR: consumed " << src_ptr - src_start
5878 << " bytes, expected " << expected_src_len;
5879 free(new_map);
5880 return NULL;
5881 }
5882
5883 return new_map;
5884}
5885
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07005886} // namespace art