blob: b15e7bd2668155d9f29513088b6e1500ad7bd6f8 [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
508 assert(cur_offset < insn_count);
509
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
842 assert(insns_size > 0);
843
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
jeffhaobdb76512011-09-07 11:43:16 -0700932 assert(idx == new_instance_count);
933 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. */
969 if (descriptor[0] == '[') {
970 /*
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) {
1015 assert(sig[0] == 'L');
1016 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) {
1030 assert(sig[0] == '[');
1031 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
1061 assert(arg_start >= 0); /* should have been verified earlier */
1062
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());
1077 assert(idx == 0);
1078 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;
1221 assert(klass != NULL);
1222
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
1238 LOG(ERROR) << "VFY: addr " << addr << " not found in uninit map";
1239 assert(false); // shouldn't happen
1240 return -1;
1241}
1242
1243bool DexVerifier::CodeFlowVerifyMethod(VerifierData* vdata,
1244 RegisterTable* reg_table) {
1245 const Method* method = vdata->method_;
1246 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001247 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001248 const uint16_t* insns = code_item->insns_;
jeffhaoba5ebb92011-08-25 17:24:37 -07001249 uint32_t insns_size = code_item->insns_size_;
jeffhaobdb76512011-09-07 11:43:16 -07001250 size_t insn_idx, start_guess;
jeffhaoba5ebb92011-08-25 17:24:37 -07001251
jeffhaobdb76512011-09-07 11:43:16 -07001252 /* Begin by marking the first instruction as "changed". */
1253 InsnSetChanged(insn_flags, 0, true);
jeffhaoba5ebb92011-08-25 17:24:37 -07001254
jeffhaobdb76512011-09-07 11:43:16 -07001255 start_guess = 0;
jeffhaoba5ebb92011-08-25 17:24:37 -07001256
jeffhaobdb76512011-09-07 11:43:16 -07001257 /* Continue until no instructions are marked "changed". */
1258 while (true) {
1259 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001260 * Find the first marked one. Use "start_guess" as a way to find
jeffhaobdb76512011-09-07 11:43:16 -07001261 * one quickly.
1262 */
1263 for (insn_idx = start_guess; insn_idx < insns_size; insn_idx++) {
1264 if (InsnIsChanged(insn_flags, insn_idx))
1265 break;
1266 }
jeffhaoba5ebb92011-08-25 17:24:37 -07001267
jeffhaobdb76512011-09-07 11:43:16 -07001268 if (insn_idx == insns_size) {
1269 if (start_guess != 0) {
1270 /* try again, starting from the top */
1271 start_guess = 0;
1272 continue;
1273 } else {
1274 /* all flags are clear */
1275 break;
1276 }
1277 }
1278
1279 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001280 * We carry the working set of registers from instruction to instruction.
1281 * If this address can be the target of a branch (or throw) instruction,
1282 * or if we're skipping around chasing "changed" flags, we need to load
1283 * the set of registers from the table.
jeffhaobdb76512011-09-07 11:43:16 -07001284 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001285 * Because we always prefer to continue on to the next instruction, we
1286 * should never have a situation where we have a stray "changed" flag set
1287 * on an instruction that isn't a branch target.
jeffhaobdb76512011-09-07 11:43:16 -07001288 */
1289 if (InsnIsBranchTarget(insn_flags, insn_idx)) {
1290 RegisterLine* work_line = &reg_table->work_line_;
1291 CopyLineFromTable(work_line, reg_table, insn_idx);
1292 } else {
1293#ifndef NDEBUG
1294 /*
1295 * Sanity check: retrieve the stored register line (assuming
1296 * a full table) and make sure it actually matches.
1297 */
1298 RegisterLine* register_line = GetRegisterLine(reg_table, insn_idx);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001299 if (register_line->reg_types_.get() != NULL && CompareLineToTable(reg_table,
jeffhaobdb76512011-09-07 11:43:16 -07001300 insn_idx, &reg_table->work_line_) != 0) {
1301 Class* klass = method->GetDeclaringClass();
1302 LOG(ERROR) << "HUH? work_line diverged in "
1303 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1304 << method->GetName()->ToModifiedUtf8() << " "
1305 << method->GetSignature()->ToModifiedUtf8();
1306 }
1307#endif
1308 }
1309
1310 if (!CodeFlowVerifyInstruction(vdata, reg_table, insn_idx, &start_guess)) {
1311 Class* klass = method->GetDeclaringClass();
1312 LOG(ERROR) << "VFY: failure to verify "
1313 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1314 << method->GetName()->ToModifiedUtf8() << " "
1315 << method->GetSignature()->ToModifiedUtf8();
jeffhaoba5ebb92011-08-25 17:24:37 -07001316 return false;
1317 }
1318
jeffhaobdb76512011-09-07 11:43:16 -07001319 /* Clear "changed" and mark as visited. */
1320 InsnSetVisited(insn_flags, insn_idx, true);
1321 InsnSetChanged(insn_flags, insn_idx, false);
1322 }
jeffhaoba5ebb92011-08-25 17:24:37 -07001323
jeffhaobdb76512011-09-07 11:43:16 -07001324 if (DEAD_CODE_SCAN && ((method->GetAccessFlags() & kAccWritable) == 0)) {
1325 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001326 * Scan for dead code. There's nothing "evil" about dead code
jeffhaobdb76512011-09-07 11:43:16 -07001327 * (besides the wasted space), but it indicates a flaw somewhere
1328 * down the line, possibly in the verifier.
1329 *
1330 * If we've substituted "always throw" instructions into the stream,
1331 * we are almost certainly going to have some dead code.
1332 */
1333 int dead_start = -1;
1334 for (insn_idx = 0; insn_idx < insns_size;
1335 insn_idx += InsnGetWidth(insn_flags, insn_idx)) {
1336 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001337 * Switch-statement data doesn't get "visited" by scanner. It
jeffhaobdb76512011-09-07 11:43:16 -07001338 * may or may not be preceded by a padding NOP (for alignment).
1339 */
1340 if (insns[insn_idx] == Instruction::kPackedSwitchSignature ||
1341 insns[insn_idx] == Instruction::kSparseSwitchSignature ||
1342 insns[insn_idx] == Instruction::kArrayDataSignature ||
1343 (insns[insn_idx] == Instruction::NOP &&
1344 (insns[insn_idx + 1] == Instruction::kPackedSwitchSignature ||
1345 insns[insn_idx + 1] == Instruction::kSparseSwitchSignature ||
1346 insns[insn_idx + 1] == Instruction::kArrayDataSignature))) {
1347 InsnSetVisited(insn_flags, insn_idx, true);
1348 }
1349
1350 if (!InsnIsVisited(insn_flags, insn_idx)) {
1351 if (dead_start < 0)
1352 dead_start = insn_idx;
1353 } else if (dead_start >= 0) {
1354 Class* klass = method->GetDeclaringClass();
1355 LOG(INFO) << "VFY: dead code 0x" << std::hex << dead_start << "-"
1356 << insn_idx - 1 << std::dec << " in "
1357 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1358 << method->GetName()->ToModifiedUtf8() << " "
1359 << method->GetSignature()->ToModifiedUtf8();
1360 dead_start = -1;
1361 }
1362 }
1363 if (dead_start >= 0) {
1364 Class* klass = method->GetDeclaringClass();
1365 LOG(INFO) << "VFY: dead code 0x" << std::hex << dead_start << "-"
1366 << insn_idx - 1 << std::dec << " in "
1367 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1368 << method->GetName()->ToModifiedUtf8() << " "
1369 << method->GetSignature()->ToModifiedUtf8();
jeffhaoba5ebb92011-08-25 17:24:37 -07001370 }
1371 }
1372
jeffhaobdb76512011-09-07 11:43:16 -07001373 return true;
1374}
1375
1376bool DexVerifier::CodeFlowVerifyInstruction(VerifierData* vdata,
1377 RegisterTable* reg_table, uint32_t insn_idx, size_t* start_guess) {
1378 const Method* method = vdata->method_;
1379 Class* klass = method->GetDeclaringClass();
1380 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001381 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001382 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001383 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001384 const uint16_t* insns = code_item->insns_ + insn_idx;
1385 uint32_t insns_size = code_item->insns_size_;
1386 uint32_t registers_size = code_item->registers_size_;
1387
1388#ifdef VERIFIER_STATS
1389 if (InsnIsVisited(insn_flags, insn_idx)) {
1390 gDvm.verifierStats.instrsReexamined++;
1391 } else {
1392 gDvm.verifierStats.instrsExamined++;
1393 }
1394#endif
1395
1396 /*
1397 * Once we finish decoding the instruction, we need to figure out where
jeffhaod1f0fde2011-09-08 17:25:33 -07001398 * we can go from here. There are three possible ways to transfer
jeffhaobdb76512011-09-07 11:43:16 -07001399 * control to another statement:
1400 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001401 * (1) Continue to the next instruction. Applies to all but
jeffhaobdb76512011-09-07 11:43:16 -07001402 * unconditional branches, method returns, and exception throws.
jeffhaod1f0fde2011-09-08 17:25:33 -07001403 * (2) Branch to one or more possible locations. Applies to branches
jeffhaobdb76512011-09-07 11:43:16 -07001404 * and switch statements.
jeffhaod1f0fde2011-09-08 17:25:33 -07001405 * (3) Exception handlers. Applies to any instruction that can
jeffhaobdb76512011-09-07 11:43:16 -07001406 * throw an exception that is handled by an encompassing "try"
1407 * block.
1408 *
1409 * We can also return, in which case there is no successor instruction
1410 * from this point.
1411 *
1412 * The behavior can be determined from the OpcodeFlags.
1413 */
1414 RegisterLine* work_line = &reg_table->work_line_;
1415 const DexFile* dex_file = vdata->dex_file_;
1416 const byte* ptr = reinterpret_cast<const byte*>(insns);
1417 const Instruction* inst = Instruction::At(ptr);
1418 Instruction::DecodedInstruction dec_insn(inst);
1419 int opcode_flag = inst->Flag();
1420
1421 Class* res_class;
1422 int32_t branch_target = 0;
1423 RegType tmp_type;
1424 bool just_set_result = false;
1425 VerifyError failure = VERIFY_ERROR_NONE;
1426
1427 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001428 * Make a copy of the previous register state. If the instruction
jeffhaobdb76512011-09-07 11:43:16 -07001429 * can throw an exception, we will copy/merge this into the "catch"
1430 * address rather than work_line, because we don't want the result
1431 * from the "successful" code path (e.g. a check-cast that "improves"
1432 * a type) to be visible to the exception handler.
1433 */
1434 if ((opcode_flag & Instruction::kThrow) != 0 &&
1435 InsnIsInTry(insn_flags, insn_idx)) {
1436 CopyRegisterLine(&reg_table->saved_line_, work_line,
1437 reg_table->insn_reg_count_plus_);
1438 } else {
1439#ifndef NDEBUG
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001440 memset(reg_table->saved_line_.reg_types_.get(), 0xdd,
jeffhaobdb76512011-09-07 11:43:16 -07001441 reg_table->insn_reg_count_plus_ * sizeof(RegType));
1442#endif
1443 }
1444
1445 switch (dec_insn.opcode_) {
1446 case Instruction::NOP:
1447 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001448 * A "pure" NOP has no effect on anything. Data tables start with
jeffhaobdb76512011-09-07 11:43:16 -07001449 * a signature that looks like a NOP; if we see one of these in
1450 * the course of executing code then we have a problem.
1451 */
1452 if (dec_insn.vA_ != 0) {
1453 LOG(ERROR) << "VFY: encountered data table in instruction stream";
1454 failure = VERIFY_ERROR_GENERIC;
1455 }
1456 break;
1457
1458 case Instruction::MOVE:
1459 case Instruction::MOVE_FROM16:
1460 case Instruction::MOVE_16:
1461 CopyRegister1(work_line, dec_insn.vA_, dec_insn.vB_, kTypeCategory1nr,
1462 &failure);
1463 break;
1464 case Instruction::MOVE_WIDE:
1465 case Instruction::MOVE_WIDE_FROM16:
1466 case Instruction::MOVE_WIDE_16:
1467 CopyRegister2(work_line, dec_insn.vA_, dec_insn.vB_, &failure);
1468 break;
1469 case Instruction::MOVE_OBJECT:
1470 case Instruction::MOVE_OBJECT_FROM16:
1471 case Instruction::MOVE_OBJECT_16:
1472 CopyRegister1(work_line, dec_insn.vA_, dec_insn.vB_, kTypeCategoryRef,
1473 &failure);
1474 break;
1475
1476 /*
1477 * The move-result instructions copy data out of a "pseudo-register"
jeffhaod1f0fde2011-09-08 17:25:33 -07001478 * with the results from the last method invocation. In practice we
jeffhaobdb76512011-09-07 11:43:16 -07001479 * might want to hold the result in an actual CPU register, so the
1480 * Dalvik spec requires that these only appear immediately after an
1481 * invoke or filled-new-array.
1482 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001483 * These calls invalidate the "result" register. (This is now
jeffhaobdb76512011-09-07 11:43:16 -07001484 * redundant with the reset done below, but it can make the debug info
1485 * easier to read in some cases.)
1486 */
1487 case Instruction::MOVE_RESULT:
1488 CopyResultRegister1(work_line, registers_size, dec_insn.vA_,
1489 kTypeCategory1nr, &failure);
1490 break;
1491 case Instruction::MOVE_RESULT_WIDE:
1492 CopyResultRegister2(work_line, registers_size, dec_insn.vA_, &failure);
1493 break;
1494 case Instruction::MOVE_RESULT_OBJECT:
1495 CopyResultRegister1(work_line, registers_size, dec_insn.vA_,
1496 kTypeCategoryRef, &failure);
1497 break;
1498
1499 case Instruction::MOVE_EXCEPTION:
1500 /*
1501 * This statement can only appear as the first instruction in an
1502 * exception handler (though not all exception handlers need to
jeffhaod1f0fde2011-09-08 17:25:33 -07001503 * have one of these). We verify that as part of extracting the
jeffhaobdb76512011-09-07 11:43:16 -07001504 * exception type from the catch block list.
1505 *
1506 * "res_class" will hold the closest common superclass of all
1507 * exceptions that can be handled here.
1508 */
1509 res_class = GetCaughtExceptionType(vdata, insn_idx, &failure);
1510 if (res_class == NULL) {
1511 assert(failure != VERIFY_ERROR_NONE);
1512 } else {
1513 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1514 }
1515 break;
1516
1517 case Instruction::RETURN_VOID:
1518 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1519 failure = VERIFY_ERROR_GENERIC;
1520 } else if (GetMethodReturnType(dex_file, method) != kRegTypeUnknown) {
1521 LOG(ERROR) << "VFY: return-void not expected";
1522 failure = VERIFY_ERROR_GENERIC;
1523 }
1524 break;
1525 case Instruction::RETURN:
1526 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1527 failure = VERIFY_ERROR_GENERIC;
1528 } else {
1529 /* check the method signature */
1530 RegType return_type = GetMethodReturnType(dex_file, method);
1531 CheckTypeCategory(return_type, kTypeCategory1nr, &failure);
1532 if (failure != VERIFY_ERROR_NONE)
1533 LOG(ERROR) << "VFY: return-1nr not expected";
1534
1535 /*
1536 * compiler may generate synthetic functions that write byte
1537 * values into boolean fields. Also, it may use integer values
1538 * for boolean, byte, short, and character return types.
1539 */
1540 RegType src_type = GetRegisterType(work_line, dec_insn.vA_);
1541 if ((return_type == kRegTypeBoolean && src_type == kRegTypeByte) ||
1542 ((return_type == kRegTypeBoolean || return_type == kRegTypeByte ||
1543 return_type == kRegTypeShort || return_type == kRegTypeChar) &&
1544 src_type == kRegTypeInteger))
1545 return_type = src_type;
1546
1547 /* check the register contents */
1548 VerifyRegisterType(work_line, dec_insn.vA_, return_type, &failure);
1549 if (failure != VERIFY_ERROR_NONE) {
1550 LOG(ERROR) << "VFY: return-1nr on invalid register v" << dec_insn.vA_;
1551 }
1552 }
1553 break;
1554 case Instruction::RETURN_WIDE:
1555 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1556 failure = VERIFY_ERROR_GENERIC;
1557 } else {
1558 RegType return_type;
1559
1560 /* check the method signature */
1561 return_type = GetMethodReturnType(dex_file, method);
1562 CheckTypeCategory(return_type, kTypeCategory2, &failure);
1563 if (failure != VERIFY_ERROR_NONE)
1564 LOG(ERROR) << "VFY: return-wide not expected";
1565
1566 /* check the register contents */
1567 VerifyRegisterType(work_line, dec_insn.vA_, return_type, &failure);
1568 if (failure != VERIFY_ERROR_NONE) {
1569 LOG(ERROR) << "VFY: return-wide on invalid register pair v"
1570 << dec_insn.vA_;
1571 }
1572 }
1573 break;
1574 case Instruction::RETURN_OBJECT:
1575 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1576 failure = VERIFY_ERROR_GENERIC;
1577 } else {
1578 RegType return_type = GetMethodReturnType(dex_file, method);
1579 CheckTypeCategory(return_type, kTypeCategoryRef, &failure);
1580 if (failure != VERIFY_ERROR_NONE) {
1581 LOG(ERROR) << "VFY: return-object not expected";
1582 break;
1583 }
1584
1585 /* return_type is the *expected* return type, not register value */
1586 assert(return_type != kRegTypeZero);
1587 assert(!RegTypeIsUninitReference(return_type));
1588
1589 /*
1590 * Verify that the reference in vAA is an instance of the type
jeffhaod1f0fde2011-09-08 17:25:33 -07001591 * in "return_type". The Zero type is allowed here. If the
jeffhaobdb76512011-09-07 11:43:16 -07001592 * method is declared to return an interface, then any
1593 * initialized reference is acceptable.
1594 *
1595 * Note GetClassFromRegister fails if the register holds an
1596 * uninitialized reference, so we do not allow them to be
1597 * returned.
1598 */
1599 Class* decl_class = RegTypeInitializedReferenceToClass(return_type);
1600 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1601 if (failure != VERIFY_ERROR_NONE)
1602 break;
1603 if (res_class != NULL) {
1604 if (!decl_class->IsInterface() &&
jeffhaobdb76512011-09-07 11:43:16 -07001605 !decl_class->IsAssignableFrom(res_class)) {
1606 LOG(ERROR) << "VFY: returning " << std::hex
1607 << res_class->GetDescriptor()->ToModifiedUtf8()
1608 << " (cl=0x" << (int) res_class->GetClassLoader()
1609 << "), declared "
1610 << decl_class->GetDescriptor()->ToModifiedUtf8()
1611 << " (cl=0x" << (int) decl_class->GetClassLoader()
1612 << ")" << std::dec;
1613 failure = VERIFY_ERROR_GENERIC;
1614 break;
1615 }
1616 }
1617 }
1618 break;
1619
1620 case Instruction::CONST_4:
1621 case Instruction::CONST_16:
1622 case Instruction::CONST:
1623 /* could be boolean, int, float, or a null reference */
1624 SetRegisterType(work_line, dec_insn.vA_,
1625 DetermineCat1Const((int32_t) dec_insn.vB_));
1626 break;
1627 case Instruction::CONST_HIGH16:
1628 /* could be boolean, int, float, or a null reference */
1629 SetRegisterType(work_line, dec_insn.vA_,
1630 DetermineCat1Const((int32_t) dec_insn.vB_ << 16));
1631 break;
1632 case Instruction::CONST_WIDE_16:
1633 case Instruction::CONST_WIDE_32:
1634 case Instruction::CONST_WIDE:
1635 case Instruction::CONST_WIDE_HIGH16:
1636 /* could be long or double; resolved upon use */
1637 SetRegisterType(work_line, dec_insn.vA_, kRegTypeConstLo);
1638 break;
1639 case Instruction::CONST_STRING:
1640 case Instruction::CONST_STRING_JUMBO:
1641 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
1642 class_linker->FindSystemClass("Ljava/lang/String;")));
1643 break;
1644 case Instruction::CONST_CLASS:
1645 /* make sure we can resolve the class; access check is important */
jeffhao98eacac2011-09-14 16:11:53 -07001646 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001647 if (res_class == NULL) {
1648 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1649 LOG(ERROR) << "VFY: unable to resolve const-class " << dec_insn.vB_
1650 << " (" << bad_class_desc << ") in "
1651 << klass->GetDescriptor()->ToModifiedUtf8();
1652 assert(failure != VERIFY_ERROR_GENERIC);
1653 } else {
1654 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
1655 class_linker->FindSystemClass("Ljava/lang/Class;")));
1656 }
1657 break;
1658
1659 case Instruction::MONITOR_ENTER:
1660 HandleMonitorEnter(work_line, dec_insn.vA_, insn_idx, &failure);
1661 break;
1662 case Instruction::MONITOR_EXIT:
1663 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001664 * monitor-exit instructions are odd. They can throw exceptions,
jeffhaobdb76512011-09-07 11:43:16 -07001665 * but when they do they act as if they succeeded and the PC is
jeffhaod1f0fde2011-09-08 17:25:33 -07001666 * pointing to the following instruction. (This behavior goes back
jeffhaobdb76512011-09-07 11:43:16 -07001667 * to the need to handle asynchronous exceptions, a now-deprecated
1668 * feature that Dalvik doesn't support.)
1669 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001670 * In practice we don't need to worry about this. The only
jeffhaobdb76512011-09-07 11:43:16 -07001671 * exceptions that can be thrown from monitor-exit are for a
jeffhaod1f0fde2011-09-08 17:25:33 -07001672 * null reference and -exit without a matching -enter. If the
jeffhaobdb76512011-09-07 11:43:16 -07001673 * structured locking checks are working, the former would have
1674 * failed on the -enter instruction, and the latter is impossible.
1675 *
1676 * This is fortunate, because issue 3221411 prevents us from
1677 * chasing the "can throw" path when monitor verification is
jeffhaod1f0fde2011-09-08 17:25:33 -07001678 * enabled. If we can fully verify the locking we can ignore
jeffhaobdb76512011-09-07 11:43:16 -07001679 * some catch blocks (which will show up as "dead" code when
1680 * we skip them here); if we can't, then the code path could be
1681 * "live" so we still need to check it.
1682 */
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001683 if (work_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07001684 opcode_flag &= ~Instruction::kThrow;
1685 HandleMonitorExit(work_line, dec_insn.vA_, insn_idx, &failure);
1686 break;
1687
1688 case Instruction::CHECK_CAST:
1689 /*
1690 * If this instruction succeeds, we will promote register vA to
jeffhaod1f0fde2011-09-08 17:25:33 -07001691 * the type in vB. (This could be a demotion -- not expected, so
jeffhaobdb76512011-09-07 11:43:16 -07001692 * we don't try to address it.)
1693 *
1694 * If it fails, an exception is thrown, which we deal with later
1695 * by ignoring the update to dec_insn.vA_ when branching to a handler.
1696 */
jeffhao98eacac2011-09-14 16:11:53 -07001697 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001698 if (res_class == NULL) {
1699 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1700 LOG(ERROR) << "VFY: unable to resolve check-cast " << dec_insn.vB_
1701 << " (" << bad_class_desc << ") in "
1702 << klass->GetDescriptor()->ToModifiedUtf8();
1703 assert(failure != VERIFY_ERROR_GENERIC);
1704 } else {
1705 RegType orig_type;
1706
1707 orig_type = GetRegisterType(work_line, dec_insn.vA_);
1708 if (!RegTypeIsReference(orig_type)) {
1709 LOG(ERROR) << "VFY: check-cast on non-reference in v" << dec_insn.vA_;
1710 failure = VERIFY_ERROR_GENERIC;
1711 break;
1712 }
1713 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1714 }
1715 break;
1716 case Instruction::INSTANCE_OF:
1717 /* make sure we're checking a reference type */
1718 tmp_type = GetRegisterType(work_line, dec_insn.vB_);
1719 if (!RegTypeIsReference(tmp_type)) {
1720 LOG(ERROR) << "VFY: vB not a reference (" << tmp_type << ")";
1721 failure = VERIFY_ERROR_GENERIC;
1722 break;
1723 }
1724
1725 /* make sure we can resolve the class; access check is important */
jeffhao98eacac2011-09-14 16:11:53 -07001726 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vC_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001727 if (res_class == NULL) {
1728 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vC_);
1729 LOG(ERROR) << "VFY: unable to resolve instanceof " << dec_insn.vC_
1730 << " (" << bad_class_desc << ") in "
1731 << klass->GetDescriptor()->ToModifiedUtf8();
1732 assert(failure != VERIFY_ERROR_GENERIC);
1733 } else {
1734 /* result is boolean */
1735 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1736 }
1737 break;
1738
1739 case Instruction::ARRAY_LENGTH:
1740 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
1741 if (failure != VERIFY_ERROR_NONE)
1742 break;
1743 if (res_class != NULL && !res_class->IsArrayClass()) {
1744 LOG(ERROR) << "VFY: array-length on non-array";
1745 failure = VERIFY_ERROR_GENERIC;
1746 break;
1747 }
1748 SetRegisterType(work_line, dec_insn.vA_, kRegTypeInteger);
1749 break;
1750
1751 case Instruction::NEW_INSTANCE:
jeffhao98eacac2011-09-14 16:11:53 -07001752 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001753 if (res_class == NULL) {
1754 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1755 LOG(ERROR) << "VFY: unable to resolve new-instance " << dec_insn.vB_
1756 << " (" << bad_class_desc << ") in "
1757 << klass->GetDescriptor()->ToModifiedUtf8();
1758 assert(failure != VERIFY_ERROR_GENERIC);
1759 } else {
1760 RegType uninit_type;
1761
1762 /* can't create an instance of an interface or abstract class */
1763 if (res_class->IsAbstract() || res_class->IsInterface()) {
1764 LOG(ERROR) << "VFY: new-instance on interface or abstract class"
1765 << res_class->GetDescriptor()->ToModifiedUtf8();
1766 failure = VERIFY_ERROR_INSTANTIATION;
1767 break;
1768 }
1769
1770 /* add resolved class to uninit map if not already there */
1771 int uidx = SetUninitInstance(uninit_map, insn_idx, res_class);
1772 assert(uidx >= 0);
1773 uninit_type = RegTypeFromUninitIndex(uidx);
1774
1775 /*
1776 * Any registers holding previous allocations from this address
1777 * that have not yet been initialized must be marked invalid.
1778 */
1779 MarkUninitRefsAsInvalid(work_line, registers_size, uninit_map,
1780 uninit_type);
1781
1782 /* add the new uninitialized reference to the register ste */
1783 SetRegisterType(work_line, dec_insn.vA_, uninit_type);
1784 }
1785 break;
1786 case Instruction::NEW_ARRAY:
jeffhao98eacac2011-09-14 16:11:53 -07001787 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vC_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001788 if (res_class == NULL) {
1789 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vC_);
1790 LOG(ERROR) << "VFY: unable to resolve new-array " << dec_insn.vC_
1791 << " (" << bad_class_desc << ") in "
1792 << klass->GetDescriptor()->ToModifiedUtf8();
1793 assert(failure != VERIFY_ERROR_GENERIC);
1794 } else if (!res_class->IsArrayClass()) {
1795 LOG(ERROR) << "VFY: new-array on non-array class";
1796 failure = VERIFY_ERROR_GENERIC;
1797 } else {
1798 /* make sure "size" register is valid type */
1799 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeInteger, &failure);
1800 /* set register type to array class */
1801 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1802 }
1803 break;
1804 case Instruction::FILLED_NEW_ARRAY:
1805 case Instruction::FILLED_NEW_ARRAY_RANGE:
jeffhao98eacac2011-09-14 16:11:53 -07001806 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001807 if (res_class == NULL) {
1808 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1809 LOG(ERROR) << "VFY: unable to resolve filled-array " << dec_insn.vB_
1810 << " (" << bad_class_desc << ") in "
1811 << klass->GetDescriptor()->ToModifiedUtf8();
1812 assert(failure != VERIFY_ERROR_GENERIC);
1813 } else if (!res_class->IsArrayClass()) {
1814 LOG(ERROR) << "VFY: filled-new-array on non-array class";
1815 failure = VERIFY_ERROR_GENERIC;
1816 } else {
1817 bool is_range = (dec_insn.opcode_ ==
1818 Instruction::FILLED_NEW_ARRAY_RANGE);
1819
1820 /* check the arguments to the instruction */
1821 VerifyFilledNewArrayRegs(method, work_line, &dec_insn, res_class,
1822 is_range, &failure);
1823 /* filled-array result goes into "result" register */
1824 SetResultRegisterType(work_line, registers_size,
1825 RegTypeFromClass(res_class));
1826 just_set_result = true;
1827 }
1828 break;
1829
1830 case Instruction::CMPL_FLOAT:
1831 case Instruction::CMPG_FLOAT:
1832 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeFloat, &failure);
1833 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeFloat, &failure);
1834 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1835 break;
1836 case Instruction::CMPL_DOUBLE:
1837 case Instruction::CMPG_DOUBLE:
1838 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeDoubleLo, &failure);
1839 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeDoubleLo, &failure);
1840 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1841 break;
1842 case Instruction::CMP_LONG:
1843 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeLongLo, &failure);
1844 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeLongLo, &failure);
1845 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1846 break;
1847
1848 case Instruction::THROW:
1849 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1850 if (failure == VERIFY_ERROR_NONE && res_class != NULL) {
1851 Class* throwable_class =
1852 class_linker->FindSystemClass("Ljava/lang/Throwable;");
1853 if (!throwable_class->IsAssignableFrom(res_class)) {
1854 LOG(ERROR) << "VFY: thrown class "
1855 << res_class->GetDescriptor()->ToModifiedUtf8()
1856 << " not instanceof Throwable",
1857 failure = VERIFY_ERROR_GENERIC;
1858 }
1859 }
1860 break;
1861
1862 case Instruction::GOTO:
1863 case Instruction::GOTO_16:
1864 case Instruction::GOTO_32:
1865 /* no effect on or use of registers */
1866 break;
1867
1868 case Instruction::PACKED_SWITCH:
1869 case Instruction::SPARSE_SWITCH:
1870 /* verify that vAA is an integer, or can be converted to one */
1871 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeInteger, &failure);
1872 break;
1873
1874 case Instruction::FILL_ARRAY_DATA:
1875 {
1876 RegType value_type;
1877 const uint16_t *array_data;
1878 uint16_t elem_width;
1879
1880 /* Similar to the verification done for APUT */
1881 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1882 if (failure != VERIFY_ERROR_NONE)
1883 break;
1884
1885 /* res_class can be null if the reg type is Zero */
1886 if (res_class == NULL)
1887 break;
1888
1889 Class::PrimitiveType prim_type =
1890 res_class->GetComponentType()->GetPrimitiveType();
1891 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
1892 prim_type == Class::kPrimNot || prim_type == Class::kPrimVoid) {
1893 LOG(ERROR) << "VFY: invalid fill-array-data on " <<
1894 res_class->GetDescriptor()->ToModifiedUtf8();
1895 failure = VERIFY_ERROR_GENERIC;
1896 break;
1897 }
1898
1899 value_type = PrimitiveTypeToRegType(prim_type);
1900 assert(value_type != kRegTypeUnknown);
1901
1902 /*
1903 * Now verify if the element width in the table matches the element
1904 * width declared in the array
1905 */
1906 array_data = insns + (insns[1] | (((int32_t) insns[2]) << 16));
1907 if (array_data[0] != Instruction::kArrayDataSignature) {
1908 LOG(ERROR) << "VFY: invalid magic for array-data";
1909 failure = VERIFY_ERROR_GENERIC;
1910 break;
1911 }
1912
1913 switch (prim_type) {
1914 case Class::kPrimBoolean:
1915 case Class::kPrimByte:
1916 elem_width = 1;
1917 break;
1918 case Class::kPrimChar:
1919 case Class::kPrimShort:
1920 elem_width = 2;
1921 break;
1922 case Class::kPrimFloat:
1923 case Class::kPrimInt:
1924 elem_width = 4;
1925 break;
1926 case Class::kPrimDouble:
1927 case Class::kPrimLong:
1928 elem_width = 8;
1929 break;
1930 default:
1931 elem_width = 0;
1932 break;
1933 }
1934
1935 /*
1936 * Since we don't compress the data in Dex, expect to see equal
1937 * width of data stored in the table and expected from the array
1938 * class.
1939 */
1940 if (array_data[1] != elem_width) {
1941 LOG(ERROR) << "VFY: array-data size mismatch (" << array_data[1]
1942 << " vs " << elem_width << ")";
1943 failure = VERIFY_ERROR_GENERIC;
1944 }
1945 }
1946 break;
1947
1948 case Instruction::IF_EQ:
1949 case Instruction::IF_NE:
1950 {
1951 RegType type1, type2;
1952
1953 type1 = GetRegisterType(work_line, dec_insn.vA_);
1954 type2 = GetRegisterType(work_line, dec_insn.vB_);
1955
1956 /* both references? */
1957 if (RegTypeIsReference(type1) && RegTypeIsReference(type2))
1958 break;
1959
1960 /* both category-1nr? */
1961 CheckTypeCategory(type1, kTypeCategory1nr, &failure);
1962 CheckTypeCategory(type2, kTypeCategory1nr, &failure);
1963 if (failure != VERIFY_ERROR_NONE) {
1964 LOG(ERROR) << "VFY: args to if-eq/if-ne must both be refs or cat1";
1965 break;
1966 }
1967 }
1968 break;
1969 case Instruction::IF_LT:
1970 case Instruction::IF_GE:
1971 case Instruction::IF_GT:
1972 case Instruction::IF_LE:
1973 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
1974 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1975 if (failure != VERIFY_ERROR_NONE) {
1976 LOG(ERROR) << "VFY: args to 'if' must be cat-1nr";
1977 break;
1978 }
1979 tmp_type = GetRegisterType(work_line, dec_insn.vB_);
1980 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1981 if (failure != VERIFY_ERROR_NONE) {
1982 LOG(ERROR) << "VFY: args to 'if' must be cat-1nr";
1983 break;
1984 }
1985 break;
1986 case Instruction::IF_EQZ:
1987 case Instruction::IF_NEZ:
1988 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
1989 if (RegTypeIsReference(tmp_type))
1990 break;
1991 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1992 if (failure != VERIFY_ERROR_NONE)
1993 LOG(ERROR) << "VFY: expected cat-1 arg to if";
1994 break;
1995 case Instruction::IF_LTZ:
1996 case Instruction::IF_GEZ:
1997 case Instruction::IF_GTZ:
1998 case Instruction::IF_LEZ:
1999 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
2000 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
2001 if (failure != VERIFY_ERROR_NONE)
2002 LOG(ERROR) << "VFY: expected cat-1 arg to if";
2003 break;
2004
2005 case Instruction::AGET:
2006 tmp_type = kRegTypeConstInteger;
2007 goto aget_1nr_common;
2008 case Instruction::AGET_BOOLEAN:
2009 tmp_type = kRegTypeBoolean;
2010 goto aget_1nr_common;
2011 case Instruction::AGET_BYTE:
2012 tmp_type = kRegTypeByte;
2013 goto aget_1nr_common;
2014 case Instruction::AGET_CHAR:
2015 tmp_type = kRegTypeChar;
2016 goto aget_1nr_common;
2017 case Instruction::AGET_SHORT:
2018 tmp_type = kRegTypeShort;
2019 goto aget_1nr_common;
2020aget_1nr_common:
2021 {
2022 RegType src_type, index_type;
2023
2024 index_type = GetRegisterType(work_line, dec_insn.vC_);
2025 CheckArrayIndexType(method, index_type, &failure);
2026 if (failure != VERIFY_ERROR_NONE)
2027 break;
2028
2029 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2030 if (failure != VERIFY_ERROR_NONE)
2031 break;
2032 if (res_class != NULL) {
2033 /* verify the class */
2034 Class::PrimitiveType prim_type =
2035 res_class->GetComponentType()->GetPrimitiveType();
2036 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
2037 prim_type == Class::kPrimNot) {
2038 LOG(ERROR) << "VFY: invalid aget-1nr target "
2039 << res_class->GetDescriptor()->ToModifiedUtf8();
2040 failure = VERIFY_ERROR_GENERIC;
2041 break;
2042 }
2043
2044 /* make sure array type matches instruction */
2045 src_type = PrimitiveTypeToRegType(prim_type);
2046
2047 /* differentiate between float and int */
2048 if (src_type == kRegTypeFloat || src_type == kRegTypeInteger)
2049 tmp_type = src_type;
2050
2051 if (tmp_type != src_type) {
2052 LOG(ERROR) << "VFY: invalid aget-1nr, array type=" << src_type
2053 << " with inst type=" << tmp_type << " (on "
2054 << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
2055 failure = VERIFY_ERROR_GENERIC;
2056 break;
2057 }
2058
2059 }
2060 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2061 }
2062 break;
2063
2064 case Instruction::AGET_WIDE:
2065 {
2066 RegType dst_type, index_type;
2067
2068 index_type = GetRegisterType(work_line, dec_insn.vC_);
2069 CheckArrayIndexType(method, index_type, &failure);
2070 if (failure != VERIFY_ERROR_NONE)
2071 break;
2072
2073 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2074 if (failure != VERIFY_ERROR_NONE)
2075 break;
2076 if (res_class != NULL) {
2077 /* verify the class */
2078 Class::PrimitiveType prim_type =
2079 res_class->GetComponentType()->GetPrimitiveType();
2080 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
2081 prim_type == Class::kPrimNot) {
2082 LOG(ERROR) << "VFY: invalid aget-wide target "
2083 << res_class->GetDescriptor()->ToModifiedUtf8();
2084 failure = VERIFY_ERROR_GENERIC;
2085 break;
2086 }
2087
2088 /* try to refine "dst_type" */
2089 switch (prim_type) {
2090 case Class::kPrimLong:
2091 dst_type = kRegTypeLongLo;
2092 break;
2093 case Class::kPrimDouble:
2094 dst_type = kRegTypeDoubleLo;
2095 break;
2096 default:
2097 LOG(ERROR) << "VFY: invalid aget-wide on "
2098 << res_class->GetDescriptor()->ToModifiedUtf8();
2099 dst_type = kRegTypeUnknown;
2100 failure = VERIFY_ERROR_GENERIC;
2101 break;
2102 }
2103 } else {
2104 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002105 * Null array ref; this code path will fail at runtime. We
jeffhaobdb76512011-09-07 11:43:16 -07002106 * know this is either long or double, so label it const.
2107 */
2108 dst_type = kRegTypeConstLo;
2109 }
2110 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2111 }
2112 break;
2113
2114 case Instruction::AGET_OBJECT:
2115 {
2116 RegType dst_type, index_type;
2117
2118 index_type = GetRegisterType(work_line, dec_insn.vC_);
2119 CheckArrayIndexType(method, index_type, &failure);
2120 if (failure != VERIFY_ERROR_NONE)
2121 break;
2122
2123 /* get the class of the array we're pulling an object from */
2124 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2125 if (failure != VERIFY_ERROR_NONE)
2126 break;
2127 if (res_class != NULL) {
2128 Class* element_class;
2129
2130 assert(res_class != NULL);
2131 if (!res_class->IsArrayClass()) {
2132 LOG(ERROR) << "VFY: aget-object on non-array class";
2133 failure = VERIFY_ERROR_GENERIC;
2134 break;
2135 }
2136 assert(res_class->GetComponentType() != NULL);
2137
2138 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002139 * Find the element class. res_class->GetComponentType() indicates
jeffhaobdb76512011-09-07 11:43:16 -07002140 * the basic type, which won't be what we want for a
2141 * multi-dimensional array.
2142 */
2143 if (res_class->GetDescriptor()->CharAt(1) == '[') {
2144 assert(res_class->GetArrayRank() > 1);
2145 std::string descriptor =
2146 res_class->GetDescriptor()->ToModifiedUtf8();
2147 element_class = class_linker->FindClass(descriptor.c_str() + 1,
2148 res_class->GetClassLoader());
2149 } else if (res_class->GetDescriptor()->CharAt(1) == 'L') {
2150 assert(res_class->GetArrayRank() == 1);
2151 element_class = res_class->GetComponentType();
2152 } else {
2153 LOG(ERROR) << "VFY: aget-object on non-ref array class ("
2154 << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
2155 failure = VERIFY_ERROR_GENERIC;
2156 break;
2157 }
2158
2159 dst_type = RegTypeFromClass(element_class);
2160 } else {
2161 /*
2162 * The array reference is NULL, so the current code path will
jeffhaod1f0fde2011-09-08 17:25:33 -07002163 * throw an exception. For proper merging with later code
jeffhaobdb76512011-09-07 11:43:16 -07002164 * paths, and correct handling of "if-eqz" tests on the
2165 * result of the array get, we want to treat this as a null
2166 * reference.
2167 */
2168 dst_type = kRegTypeZero;
2169 }
2170 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2171 }
2172 break;
2173 case Instruction::APUT:
2174 tmp_type = kRegTypeInteger;
2175 goto aput_1nr_common;
2176 case Instruction::APUT_BOOLEAN:
2177 tmp_type = kRegTypeBoolean;
2178 goto aput_1nr_common;
2179 case Instruction::APUT_BYTE:
2180 tmp_type = kRegTypeByte;
2181 goto aput_1nr_common;
2182 case Instruction::APUT_CHAR:
2183 tmp_type = kRegTypeChar;
2184 goto aput_1nr_common;
2185 case Instruction::APUT_SHORT:
2186 tmp_type = kRegTypeShort;
2187 goto aput_1nr_common;
2188aput_1nr_common:
2189 {
2190 RegType src_type, dst_type, index_type;
2191
2192 index_type = GetRegisterType(work_line, dec_insn.vC_);
2193 CheckArrayIndexType(method, index_type, &failure);
2194 if (failure != VERIFY_ERROR_NONE)
2195 break;
2196
2197 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2198 if (failure != VERIFY_ERROR_NONE)
2199 break;
2200
2201 /* res_class can be null if the reg type is Zero */
2202 if (res_class == NULL)
2203 break;
2204
2205 Class::PrimitiveType prim_type =
2206 res_class->GetComponentType()->GetPrimitiveType();
2207 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
2208 prim_type == Class::kPrimNot) {
2209 LOG(ERROR) << "VFY: invalid aput-1nr on "
2210 << res_class->GetDescriptor()->ToModifiedUtf8();
2211 failure = VERIFY_ERROR_GENERIC;
2212 break;
2213 }
2214
2215 /* verify that instruction matches array */
2216 dst_type = PrimitiveTypeToRegType(prim_type);
2217
2218 /* correct if float */
2219 if (dst_type == kRegTypeFloat)
2220 tmp_type = kRegTypeFloat;
2221
2222 /* make sure the source register has the correct type */
2223 src_type = GetRegisterType(work_line, dec_insn.vA_);
2224 if (!CanConvertTo1nr(src_type, tmp_type)) {
2225 LOG(ERROR) << "VFY: invalid reg type " << src_type
2226 << " on aput instr (need " << tmp_type << ")";
2227 failure = VERIFY_ERROR_GENERIC;
2228 break;
2229 }
2230
2231 VerifyRegisterType(work_line, dec_insn.vA_, dst_type, &failure);
2232
2233 if (failure != VERIFY_ERROR_NONE || dst_type == kRegTypeUnknown ||
2234 tmp_type != dst_type) {
2235 LOG(ERROR) << "VFY: invalid aput-1nr on "
2236 << res_class->GetDescriptor()->ToModifiedUtf8()
2237 << " (inst=" << tmp_type << " dst=" << dst_type << ")";
2238 failure = VERIFY_ERROR_GENERIC;
2239 break;
2240 }
2241 }
2242 break;
2243 case Instruction::APUT_WIDE:
2244 tmp_type = GetRegisterType(work_line, dec_insn.vC_);
2245 CheckArrayIndexType(method, tmp_type, &failure);
2246 if (failure != VERIFY_ERROR_NONE)
2247 break;
2248
2249 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2250 if (failure != VERIFY_ERROR_NONE)
2251 break;
2252 if (res_class != NULL) {
2253 Class::PrimitiveType prim_type =
2254 res_class->GetComponentType()->GetPrimitiveType();
2255 /* verify the class and try to refine "dst_type" */
2256 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
2257 prim_type == Class::kPrimNot)
2258 {
2259 LOG(ERROR) << "VFY: invalid aput-wide on "
2260 << res_class->GetDescriptor()->ToModifiedUtf8();
2261 failure = VERIFY_ERROR_GENERIC;
2262 break;
2263 }
2264
2265 switch (prim_type) {
2266 case Class::kPrimLong:
2267 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo,
2268 &failure);
2269 break;
2270 case Class::kPrimDouble:
2271 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2272 &failure);
2273 break;
2274 default:
2275 LOG(ERROR) << "VFY: invalid aput-wide on "
2276 << res_class->GetDescriptor()->ToModifiedUtf8();
2277 failure = VERIFY_ERROR_GENERIC;
2278 break;
2279 }
2280 }
2281 break;
2282 case Instruction::APUT_OBJECT:
2283 tmp_type = GetRegisterType(work_line, dec_insn.vC_);
2284 CheckArrayIndexType(method, tmp_type, &failure);
2285 if (failure != VERIFY_ERROR_NONE)
2286 break;
2287
2288 /* get the ref we're storing; Zero is okay, Uninit is not */
2289 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
2290 if (failure != VERIFY_ERROR_NONE)
2291 break;
2292 if (res_class != NULL) {
2293 Class* array_class;
2294 Class* element_class;
2295
2296 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002297 * Get the array class. If the array ref is null, we won't
jeffhaobdb76512011-09-07 11:43:16 -07002298 * have type information (and we'll crash at runtime with a
2299 * null pointer exception).
2300 */
2301 array_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2302
2303 if (array_class != NULL) {
2304 /* see if the array holds a compatible type */
2305 if (!array_class->IsArrayClass()) {
2306 LOG(ERROR) << "VFY: invalid aput-object on "
2307 << array_class->GetDescriptor()->ToModifiedUtf8();
2308 failure = VERIFY_ERROR_GENERIC;
2309 break;
2310 }
2311
2312 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002313 * Find the element class. res_class->GetComponentType() indicates
jeffhaobdb76512011-09-07 11:43:16 -07002314 * the basic type, which won't be what we want for a
2315 * multi-dimensional array.
2316 *
2317 * All we want to check here is that the element type is a
jeffhaod1f0fde2011-09-08 17:25:33 -07002318 * reference class. We *don't* check instanceof here, because
jeffhaobdb76512011-09-07 11:43:16 -07002319 * you can still put a String into a String[] after the latter
2320 * has been cast to an Object[].
2321 */
2322 if (array_class->GetDescriptor()->CharAt(1) == '[') {
2323 assert(array_class->GetArrayRank() > 1);
2324 std::string descriptor =
2325 array_class->GetDescriptor()->ToModifiedUtf8();
2326 element_class = class_linker->FindClass(descriptor.c_str() + 1,
2327 array_class->GetClassLoader());
2328 } else {
2329 assert(array_class->GetArrayRank() == 1);
2330 element_class = array_class->GetComponentType();
2331 }
2332 if (element_class->GetPrimitiveType() != Class::kPrimNot) {
2333 LOG(ERROR) << "VFY: invalid aput-object of "
2334 << res_class->GetDescriptor()->ToModifiedUtf8()
2335 << " into "
2336 << array_class->GetDescriptor()->ToModifiedUtf8();
2337 failure = VERIFY_ERROR_GENERIC;
2338 break;
2339 }
2340 }
2341 }
2342 break;
2343
2344 case Instruction::IGET:
2345 tmp_type = kRegTypeInteger;
2346 goto iget_1nr_common;
2347 case Instruction::IGET_BOOLEAN:
2348 tmp_type = kRegTypeBoolean;
2349 goto iget_1nr_common;
2350 case Instruction::IGET_BYTE:
2351 tmp_type = kRegTypeByte;
2352 goto iget_1nr_common;
2353 case Instruction::IGET_CHAR:
2354 tmp_type = kRegTypeChar;
2355 goto iget_1nr_common;
2356 case Instruction::IGET_SHORT:
2357 tmp_type = kRegTypeShort;
2358 goto iget_1nr_common;
2359iget_1nr_common:
2360 {
2361 Field* inst_field;
2362 RegType obj_type, field_type;
2363
2364 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2365 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2366 if (failure != VERIFY_ERROR_NONE)
2367 break;
2368
2369 /* make sure the field's type is compatible with expectation */
2370 field_type =
2371 PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
2372
2373 /* correct if float */
2374 if (field_type == kRegTypeFloat)
2375 tmp_type = kRegTypeFloat;
2376
2377 if (field_type == kRegTypeUnknown || tmp_type != field_type) {
2378 Class* inst_field_class = inst_field->GetDeclaringClass();
2379 LOG(ERROR) << "VFY: invalid iget-1nr of "
2380 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2381 << "." << inst_field->GetName()->ToModifiedUtf8()
2382 << " (inst=" << tmp_type << " field=" << field_type << ")";
2383 failure = VERIFY_ERROR_GENERIC;
2384 break;
2385 }
2386
2387 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2388 }
2389 break;
2390 case Instruction::IGET_WIDE:
2391 {
2392 RegType dst_type;
2393 Field* inst_field;
2394 RegType obj_type;
2395
2396 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2397 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2398 Class* inst_field_class = inst_field->GetDeclaringClass();
2399 if (failure != VERIFY_ERROR_NONE)
2400 break;
2401 /* check the type, which should be prim */
2402 switch (inst_field->GetType()->GetPrimitiveType()) {
2403 case Class::kPrimDouble:
2404 dst_type = kRegTypeDoubleLo;
2405 break;
2406 case Class::kPrimLong:
2407 dst_type = kRegTypeLongLo;
2408 break;
2409 default:
2410 LOG(ERROR) << "VFY: invalid iget-wide of "
2411 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2412 << "." << inst_field->GetName()->ToModifiedUtf8();
2413 dst_type = kRegTypeUnknown;
2414 failure = VERIFY_ERROR_GENERIC;
2415 break;
2416 }
2417 if (failure == VERIFY_ERROR_NONE) {
2418 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2419 }
2420 }
2421 break;
2422 case Instruction::IGET_OBJECT:
2423 {
2424 Class* field_class;
2425 Field* inst_field;
2426 RegType obj_type;
2427
2428 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2429 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2430 if (failure != VERIFY_ERROR_NONE)
2431 break;
2432 field_class = inst_field->GetType();
2433 if (field_class == NULL) {
2434 /* class not found or primitive type */
2435 LOG(ERROR) << "VFY: unable to recover field class from "
2436 << inst_field->GetName()->ToModifiedUtf8();
2437 failure = VERIFY_ERROR_GENERIC;
2438 break;
2439 }
2440 if (failure == VERIFY_ERROR_NONE) {
2441 assert(!field_class->IsPrimitive());
2442 SetRegisterType(work_line, dec_insn.vA_,
2443 RegTypeFromClass(field_class));
2444 }
2445 }
2446 break;
2447 case Instruction::IPUT:
2448 tmp_type = kRegTypeInteger;
2449 goto iput_1nr_common;
2450 case Instruction::IPUT_BOOLEAN:
2451 tmp_type = kRegTypeBoolean;
2452 goto iput_1nr_common;
2453 case Instruction::IPUT_BYTE:
2454 tmp_type = kRegTypeByte;
2455 goto iput_1nr_common;
2456 case Instruction::IPUT_CHAR:
2457 tmp_type = kRegTypeChar;
2458 goto iput_1nr_common;
2459 case Instruction::IPUT_SHORT:
2460 tmp_type = kRegTypeShort;
2461 goto iput_1nr_common;
2462iput_1nr_common:
2463 {
2464 RegType src_type, field_type, obj_type;
2465 Field* inst_field;
2466
2467 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2468 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2469 if (failure != VERIFY_ERROR_NONE)
2470 break;
2471 CheckFinalFieldAccess(method, inst_field, &failure);
2472 if (failure != VERIFY_ERROR_NONE)
2473 break;
2474
2475 /* get type of field we're storing into */
2476 field_type =
2477 PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
2478 src_type = GetRegisterType(work_line, dec_insn.vA_);
2479
2480 /* correct if float */
2481 if (field_type == kRegTypeFloat)
2482 tmp_type = kRegTypeFloat;
2483
2484 /*
2485 * compiler can generate synthetic functions that write byte values
2486 * into boolean fields.
2487 */
2488 if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
2489 tmp_type = kRegTypeByte;
2490 if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
2491 field_type = kRegTypeByte;
2492
2493 /* make sure the source register has the correct type */
2494 if (!CanConvertTo1nr(src_type, tmp_type)) {
2495 LOG(ERROR) << "VFY: invalid reg type " << src_type
2496 << " on iput instr (need " << tmp_type << ")",
2497 failure = VERIFY_ERROR_GENERIC;
2498 break;
2499 }
2500
2501 VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);
2502
2503 if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
2504 tmp_type != field_type) {
2505 Class* inst_field_class = inst_field->GetDeclaringClass();
2506 LOG(ERROR) << "VFY: invalid iput-1nr of "
2507 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2508 << "." << inst_field->GetName()->ToModifiedUtf8()
2509 << " (inst=" << tmp_type << " field=" << field_type << ")";
2510 failure = VERIFY_ERROR_GENERIC;
2511 break;
2512 }
2513 }
2514 break;
2515 case Instruction::IPUT_WIDE:
2516 Field* inst_field;
2517 RegType obj_type;
2518
2519 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2520 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2521 if (failure != VERIFY_ERROR_NONE)
2522 break;
2523 CheckFinalFieldAccess(method, inst_field, &failure);
2524 if (failure != VERIFY_ERROR_NONE)
2525 break;
2526
2527 /* check the type, which should be prim */
2528 switch (inst_field->GetType()->GetPrimitiveType()) {
2529 case Class::kPrimDouble:
2530 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2531 &failure);
2532 break;
2533 case Class::kPrimLong:
2534 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
2535 break;
2536 default:
2537 LOG(ERROR) << "VFY: invalid iput-wide of "
2538 << inst_field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
2539 << "." << inst_field->GetName()->ToModifiedUtf8();
2540 failure = VERIFY_ERROR_GENERIC;
2541 break;
2542 }
2543 break;
2544 case Instruction::IPUT_OBJECT:
2545 {
2546 Class* field_class;
2547 Class* value_class;
2548 Field* inst_field;
2549 RegType obj_type, value_type;
2550
2551 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2552 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2553 if (failure != VERIFY_ERROR_NONE)
2554 break;
2555 CheckFinalFieldAccess(method, inst_field, &failure);
2556 if (failure != VERIFY_ERROR_NONE)
2557 break;
2558
2559 field_class = inst_field->GetType();
2560 if (field_class == NULL) {
2561 LOG(ERROR) << "VFY: unable to recover field class from '"
2562 << inst_field->GetName()->ToModifiedUtf8() << "'";
2563 failure = VERIFY_ERROR_GENERIC;
2564 break;
2565 }
2566
2567 value_type = GetRegisterType(work_line, dec_insn.vA_);
2568 if (!RegTypeIsReference(value_type)) {
2569 LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
2570 << " into ref field '"
2571 << inst_field->GetName()->ToModifiedUtf8() << "' ("
2572 << field_class->GetDescriptor()->ToModifiedUtf8() << ")";
2573 failure = VERIFY_ERROR_GENERIC;
2574 break;
2575 }
2576 if (value_type != kRegTypeZero) {
2577 value_class = RegTypeInitializedReferenceToClass(value_type);
2578 if (value_class == NULL) {
2579 LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
2580 << " into ref field";
2581 failure = VERIFY_ERROR_GENERIC;
2582 break;
2583 }
2584 /* allow if field is any interface or field is base class */
2585 if (!field_class->IsInterface() &&
2586 !field_class->IsAssignableFrom(value_class)) {
2587 Class* inst_field_class = inst_field->GetDeclaringClass();
2588 LOG(ERROR) << "VFY: storing type '"
2589 << value_class->GetDescriptor()->ToModifiedUtf8()
2590 << "' into field type '"
2591 << field_class->GetDescriptor()->ToModifiedUtf8()
2592 << "' ("
2593 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2594 << "." << inst_field->GetName()->ToModifiedUtf8() << ")";
2595 failure = VERIFY_ERROR_GENERIC;
2596 break;
2597 }
2598 }
2599 }
2600 break;
2601
2602 case Instruction::SGET:
2603 tmp_type = kRegTypeInteger;
2604 goto sget_1nr_common;
2605 case Instruction::SGET_BOOLEAN:
2606 tmp_type = kRegTypeBoolean;
2607 goto sget_1nr_common;
2608 case Instruction::SGET_BYTE:
2609 tmp_type = kRegTypeByte;
2610 goto sget_1nr_common;
2611 case Instruction::SGET_CHAR:
2612 tmp_type = kRegTypeChar;
2613 goto sget_1nr_common;
2614 case Instruction::SGET_SHORT:
2615 tmp_type = kRegTypeShort;
2616 goto sget_1nr_common;
2617sget_1nr_common:
2618 {
2619 Field* static_field;
2620 RegType field_type;
2621
2622 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2623 if (failure != VERIFY_ERROR_NONE)
2624 break;
2625
2626 /*
2627 * Make sure the field's type is compatible with expectation.
2628 * We can get ourselves into trouble if we mix & match loads
2629 * and stores with different widths, so rather than just checking
2630 * "CanConvertTo1nr" we require that the field types have equal
2631 * widths.
2632 */
2633 field_type =
2634 PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
2635
2636 /* correct if float */
2637 if (field_type == kRegTypeFloat)
2638 tmp_type = kRegTypeFloat;
2639
2640 if (tmp_type != field_type) {
2641 Class* static_field_class = static_field->GetDeclaringClass();
2642 LOG(ERROR) << "VFY: invalid sget-1nr of "
2643 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2644 << "." << static_field->GetName()->ToModifiedUtf8()
2645 << " (inst=" << tmp_type << " actual=" << field_type
2646 << ")";
2647 failure = VERIFY_ERROR_GENERIC;
2648 break;
2649 }
2650
2651 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2652 }
2653 break;
2654 case Instruction::SGET_WIDE:
2655 {
2656 Field* static_field;
2657 RegType dst_type;
2658
2659 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2660 Class* static_field_class = static_field->GetDeclaringClass();
2661 if (failure != VERIFY_ERROR_NONE)
2662 break;
2663 /* check the type, which should be prim */
2664 switch (static_field->GetType()->GetPrimitiveType()) {
2665 case Class::kPrimDouble:
2666 dst_type = kRegTypeDoubleLo;
2667 break;
2668 case Class::kPrimLong:
2669 dst_type = kRegTypeLongLo;
2670 break;
2671 default:
2672 LOG(ERROR) << "VFY: invalid sget-wide of "
2673 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2674 << "." << static_field->GetName()->ToModifiedUtf8();
2675 dst_type = kRegTypeUnknown;
2676 failure = VERIFY_ERROR_GENERIC;
2677 break;
2678 }
2679 if (failure == VERIFY_ERROR_NONE) {
2680 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2681 }
2682 }
2683 break;
2684 case Instruction::SGET_OBJECT:
2685 {
2686 Field* static_field;
2687 Class* field_class;
2688
2689 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2690 if (failure != VERIFY_ERROR_NONE)
2691 break;
2692 field_class = static_field->GetType();
2693 if (field_class == NULL) {
2694 LOG(ERROR) << "VFY: unable to recover field class from '"
2695 << static_field->GetName()->ToModifiedUtf8() << "'";
2696 failure = VERIFY_ERROR_GENERIC;
2697 break;
2698 }
2699 if (field_class->IsPrimitive()) {
2700 LOG(ERROR) << "VFY: attempt to get prim field with sget-object";
2701 failure = VERIFY_ERROR_GENERIC;
2702 break;
2703 }
2704 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(field_class));
2705 }
2706 break;
2707 case Instruction::SPUT:
2708 tmp_type = kRegTypeInteger;
2709 goto sput_1nr_common;
2710 case Instruction::SPUT_BOOLEAN:
2711 tmp_type = kRegTypeBoolean;
2712 goto sput_1nr_common;
2713 case Instruction::SPUT_BYTE:
2714 tmp_type = kRegTypeByte;
2715 goto sput_1nr_common;
2716 case Instruction::SPUT_CHAR:
2717 tmp_type = kRegTypeChar;
2718 goto sput_1nr_common;
2719 case Instruction::SPUT_SHORT:
2720 tmp_type = kRegTypeShort;
2721 goto sput_1nr_common;
2722sput_1nr_common:
2723 {
2724 RegType src_type, field_type;
2725 Field* static_field;
2726
2727 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2728 if (failure != VERIFY_ERROR_NONE)
2729 break;
2730 CheckFinalFieldAccess(method, static_field, &failure);
2731 if (failure != VERIFY_ERROR_NONE)
2732 break;
2733
2734 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002735 * Get type of field we're storing into. We know that the
jeffhaobdb76512011-09-07 11:43:16 -07002736 * contents of the register match the instruction, but we also
2737 * need to ensure that the instruction matches the field type.
2738 * Using e.g. sput-short to write into a 32-bit integer field
2739 * can lead to trouble if we do 16-bit writes.
2740 */
2741 field_type =
2742 PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
2743 src_type = GetRegisterType(work_line, dec_insn.vA_);
2744
2745 /* correct if float */
2746 if (field_type == kRegTypeFloat)
2747 tmp_type = kRegTypeFloat;
2748
2749 /*
2750 * compiler can generate synthetic functions that write byte values
2751 * into boolean fields.
2752 */
2753 if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
2754 tmp_type = kRegTypeByte;
2755 if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
2756 field_type = kRegTypeByte;
2757
2758 /* make sure the source register has the correct type */
2759 if (!CanConvertTo1nr(src_type, tmp_type)) {
2760 LOG(ERROR) << "VFY: invalid reg type " << src_type
2761 << " on sput instr (need " << tmp_type << ")";
2762 failure = VERIFY_ERROR_GENERIC;
2763 break;
2764 }
2765
2766 VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);
2767
2768 if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
2769 tmp_type != field_type) {
2770 Class* static_field_class = static_field->GetDeclaringClass();
2771 LOG(ERROR) << "VFY: invalid sput-1nr of "
2772 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2773 << "." << static_field->GetName()->ToModifiedUtf8()
2774 << " (inst=" << tmp_type << " actual=" << field_type
2775 << ")";
2776 failure = VERIFY_ERROR_GENERIC;
2777 break;
2778 }
2779 }
2780 break;
2781 case Instruction::SPUT_WIDE:
2782 Field* static_field;
2783
2784 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2785 if (failure != VERIFY_ERROR_NONE)
2786 break;
2787 CheckFinalFieldAccess(method, static_field, &failure);
2788 if (failure != VERIFY_ERROR_NONE)
2789 break;
2790
2791 /* check the type, which should be prim */
2792 switch (static_field->GetType()->GetPrimitiveType()) {
2793 case Class::kPrimDouble:
2794 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2795 &failure);
2796 break;
2797 case Class::kPrimLong:
2798 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
2799 break;
2800 default:
2801 LOG(ERROR) << "VFY: invalid sput-wide of "
2802 << static_field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
2803 << "." << static_field->GetName()->ToModifiedUtf8();
2804 failure = VERIFY_ERROR_GENERIC;
2805 break;
2806 }
2807 break;
2808 case Instruction::SPUT_OBJECT:
2809 {
2810 Class* field_class;
2811 Class* value_class;
2812 Field* static_field;
2813 RegType value_type;
2814
2815 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2816 if (failure != VERIFY_ERROR_NONE)
2817 break;
2818 CheckFinalFieldAccess(method, static_field, &failure);
2819 if (failure != VERIFY_ERROR_NONE)
2820 break;
2821
2822 field_class = static_field->GetType();
2823 if (field_class == NULL) {
2824 LOG(ERROR) << "VFY: unable to recover field class from '"
2825 << static_field->GetName()->ToModifiedUtf8() << "'";
2826 failure = VERIFY_ERROR_GENERIC;
2827 break;
2828 }
2829
2830 value_type = GetRegisterType(work_line, dec_insn.vA_);
2831 if (!RegTypeIsReference(value_type)) {
2832 LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
2833 << " into ref field '"
2834 << static_field->GetName()->ToModifiedUtf8() << "' ("
2835 << field_class->GetDescriptor()->ToModifiedUtf8() << ")",
2836 failure = VERIFY_ERROR_GENERIC;
2837 break;
2838 }
2839 if (value_type != kRegTypeZero) {
2840 value_class = RegTypeInitializedReferenceToClass(value_type);
2841 if (value_class == NULL) {
2842 LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
2843 << " into ref field";
2844 failure = VERIFY_ERROR_GENERIC;
2845 break;
2846 }
2847 /* allow if field is any interface or field is base class */
2848 if (!field_class->IsInterface() &&
2849 !field_class->IsAssignableFrom(value_class)) {
2850 Class* static_field_class = static_field->GetDeclaringClass();
2851 LOG(ERROR) << "VFY: storing type '"
2852 << value_class->GetDescriptor()->ToModifiedUtf8()
2853 << "' into field type '"
2854 << field_class->GetDescriptor()->ToModifiedUtf8()
2855 << "' ("
2856 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2857 << "." << static_field->GetName()->ToModifiedUtf8()
2858 << ")",
2859 failure = VERIFY_ERROR_GENERIC;
2860 break;
2861 }
2862 }
2863 }
2864 break;
2865
2866 case Instruction::INVOKE_VIRTUAL:
2867 case Instruction::INVOKE_VIRTUAL_RANGE:
2868 case Instruction::INVOKE_SUPER:
2869 case Instruction::INVOKE_SUPER_RANGE:
2870 {
2871 Method* called_method;
2872 RegType return_type;
2873 bool is_range;
2874 bool is_super;
2875
2876 is_range = (dec_insn.opcode_ == Instruction::INVOKE_VIRTUAL_RANGE ||
2877 dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
2878 is_super = (dec_insn.opcode_ == Instruction::INVOKE_SUPER ||
2879 dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
2880
2881 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2882 &dec_insn, METHOD_VIRTUAL, is_range, is_super, &failure);
2883 if (failure != VERIFY_ERROR_NONE)
2884 break;
2885 return_type = GetMethodReturnType(dex_file, called_method);
2886 SetResultRegisterType(work_line, registers_size, return_type);
2887 just_set_result = true;
2888 }
2889 break;
2890 case Instruction::INVOKE_DIRECT:
2891 case Instruction::INVOKE_DIRECT_RANGE:
2892 {
2893 RegType return_type;
2894 Method* called_method;
2895 bool is_range;
2896
2897 is_range = (dec_insn.opcode_ == Instruction::INVOKE_DIRECT_RANGE);
2898 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2899 &dec_insn, METHOD_DIRECT, is_range, false, &failure);
2900 if (failure != VERIFY_ERROR_NONE)
2901 break;
2902
2903 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002904 * Some additional checks when calling <init>. We know from
jeffhaobdb76512011-09-07 11:43:16 -07002905 * the invocation arg check that the "this" argument is an
jeffhaod1f0fde2011-09-08 17:25:33 -07002906 * instance of called_method->klass. Now we further restrict
jeffhaobdb76512011-09-07 11:43:16 -07002907 * that to require that called_method->klass is the same as
2908 * this->klass or this->super, allowing the latter only if
2909 * the "this" argument is the same as the "this" argument to
2910 * this method (which implies that we're in <init> ourselves).
2911 */
2912 if (IsInitMethod(called_method)) {
2913 RegType this_type;
2914 this_type = GetInvocationThis(work_line, &dec_insn, &failure);
2915 if (failure != VERIFY_ERROR_NONE)
2916 break;
2917
2918 /* no null refs allowed (?) */
2919 if (this_type == kRegTypeZero) {
2920 LOG(ERROR) << "VFY: unable to initialize null ref";
2921 failure = VERIFY_ERROR_GENERIC;
2922 break;
2923 }
2924
2925 Class* this_class;
2926
2927 this_class = RegTypeReferenceToClass(this_type, uninit_map);
2928 assert(this_class != NULL);
2929
2930 /* must be in same class or in superclass */
2931 if (called_method->GetDeclaringClass() == this_class->GetSuperClass())
2932 {
2933 if (this_class != method->GetDeclaringClass()) {
2934 LOG(ERROR) << "VFY: invoke-direct <init> on super only "
2935 << "allowed for 'this' in <init>";
2936 failure = VERIFY_ERROR_GENERIC;
2937 break;
2938 }
2939 } else if (called_method->GetDeclaringClass() != this_class) {
2940 LOG(ERROR) << "VFY: invoke-direct <init> must be on current "
2941 << "class or super";
2942 failure = VERIFY_ERROR_GENERIC;
2943 break;
2944 }
2945
2946 /* arg must be an uninitialized reference */
2947 if (!RegTypeIsUninitReference(this_type)) {
2948 LOG(ERROR) << "VFY: can only initialize the uninitialized";
2949 failure = VERIFY_ERROR_GENERIC;
2950 break;
2951 }
2952
2953 /*
2954 * Replace the uninitialized reference with an initialized
jeffhaod1f0fde2011-09-08 17:25:33 -07002955 * one, and clear the entry in the uninit map. We need to
jeffhaobdb76512011-09-07 11:43:16 -07002956 * do this for all registers that have the same object
2957 * instance in them, not just the "this" register.
2958 */
2959 MarkRefsAsInitialized(work_line, registers_size, uninit_map,
2960 this_type, &failure);
2961 if (failure != VERIFY_ERROR_NONE)
2962 break;
2963 }
2964 return_type = GetMethodReturnType(dex_file, called_method);
2965 SetResultRegisterType(work_line, registers_size, return_type);
2966 just_set_result = true;
2967 }
2968 break;
2969 case Instruction::INVOKE_STATIC:
2970 case Instruction::INVOKE_STATIC_RANGE:
2971 {
2972 RegType return_type;
2973 Method* called_method;
2974 bool is_range;
2975
2976 is_range = (dec_insn.opcode_ == Instruction::INVOKE_STATIC_RANGE);
2977 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2978 &dec_insn, METHOD_STATIC, is_range, false, &failure);
2979 if (failure != VERIFY_ERROR_NONE)
2980 break;
2981
2982 return_type = GetMethodReturnType(dex_file, called_method);
2983 SetResultRegisterType(work_line, registers_size, return_type);
2984 just_set_result = true;
2985 }
2986 break;
2987 case Instruction::INVOKE_INTERFACE:
2988 case Instruction::INVOKE_INTERFACE_RANGE:
2989 {
2990 RegType /*this_type,*/ return_type;
2991 Method* abs_method;
2992 bool is_range;
2993
2994 is_range = (dec_insn.opcode_ == Instruction::INVOKE_INTERFACE_RANGE);
2995 abs_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2996 &dec_insn, METHOD_INTERFACE, is_range, false, &failure);
2997 if (failure != VERIFY_ERROR_NONE)
2998 break;
2999
3000#if 0 /* can't do this here, fails on dalvik test 052-verifier-fun */
3001 /*
3002 * Get the type of the "this" arg, which should always be an
jeffhaod1f0fde2011-09-08 17:25:33 -07003003 * interface class. Because we don't do a full merge on
jeffhaobdb76512011-09-07 11:43:16 -07003004 * interface classes, this might have reduced to Object.
3005 */
3006 this_type = GetInvocationThis(work_line, &dec_insn, &failure);
3007 if (failure != VERIFY_ERROR_NONE)
3008 break;
3009
3010 if (this_type == kRegTypeZero) {
3011 /* null pointer always passes (and always fails at runtime) */
3012 } else {
3013 Class* this_class;
3014
3015 this_class = RegTypeInitializedReferenceToClass(this_type);
3016 if (this_class == NULL) {
3017 LOG(ERROR) << "VFY: interface call on uninitialized";
3018 failure = VERIFY_ERROR_GENERIC;
3019 break;
3020 }
3021
3022 /*
3023 * Either "this_class" needs to be the interface class that
3024 * defined abs_method, or abs_method's class needs to be one
jeffhaod1f0fde2011-09-08 17:25:33 -07003025 * of the interfaces implemented by "this_class". (Or, if
jeffhaobdb76512011-09-07 11:43:16 -07003026 * we couldn't complete the merge, this will be Object.)
3027 */
3028 if (this_class != abs_method->GetDeclaringClass() &&
3029 this_class != class_linker->FindSystemClass("Ljava/lang/Object;") &&
3030 !this_class->Implements(abs_method->GetDeclaringClass())) {
3031 LOG(ERROR) << "VFY: unable to match abs_method '"
3032 << abs_method->GetName()->ToModifiedUtf8() << "' with "
3033 << this_class->GetDescriptor()->ToModifiedUtf8()
3034 << " interfaces";
3035 failure = VERIFY_ERROR_GENERIC;
3036 break;
3037 }
3038 }
3039#endif
3040
3041 /*
3042 * We don't have an object instance, so we can't find the
jeffhaod1f0fde2011-09-08 17:25:33 -07003043 * concrete method. However, all of the type information is
jeffhaobdb76512011-09-07 11:43:16 -07003044 * in the abstract method, so we're good.
3045 */
3046 return_type = GetMethodReturnType(dex_file, abs_method);
3047 SetResultRegisterType(work_line, registers_size, return_type);
3048 just_set_result = true;
3049 }
3050 break;
3051
3052 case Instruction::NEG_INT:
3053 case Instruction::NOT_INT:
3054 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3055 &failure);
3056 break;
3057 case Instruction::NEG_LONG:
3058 case Instruction::NOT_LONG:
3059 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo, &failure);
3060 break;
3061 case Instruction::NEG_FLOAT:
3062 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat, &failure);
3063 break;
3064 case Instruction::NEG_DOUBLE:
3065 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3066 &failure);
3067 break;
3068 case Instruction::INT_TO_LONG:
3069 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeInteger,
3070 &failure);
3071 break;
3072 case Instruction::INT_TO_FLOAT:
3073 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeInteger, &failure);
3074 break;
3075 case Instruction::INT_TO_DOUBLE:
3076 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeInteger,
3077 &failure);
3078 break;
3079 case Instruction::LONG_TO_INT:
3080 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeLongLo,
3081 &failure);
3082 break;
3083 case Instruction::LONG_TO_FLOAT:
3084 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeLongLo, &failure);
3085 break;
3086 case Instruction::LONG_TO_DOUBLE:
3087 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeLongLo,
3088 &failure);
3089 break;
3090 case Instruction::FLOAT_TO_INT:
3091 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeFloat, &failure);
3092 break;
3093 case Instruction::FLOAT_TO_LONG:
3094 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeFloat, &failure);
3095 break;
3096 case Instruction::FLOAT_TO_DOUBLE:
3097 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeFloat,
3098 &failure);
3099 break;
3100 case Instruction::DOUBLE_TO_INT:
3101 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeDoubleLo,
3102 &failure);
3103 break;
3104 case Instruction::DOUBLE_TO_LONG:
3105 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeDoubleLo,
3106 &failure);
3107 break;
3108 case Instruction::DOUBLE_TO_FLOAT:
3109 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeDoubleLo,
3110 &failure);
3111 break;
3112 case Instruction::INT_TO_BYTE:
3113 CheckUnop(work_line, &dec_insn, kRegTypeByte, kRegTypeInteger, &failure);
3114 break;
3115 case Instruction::INT_TO_CHAR:
3116 CheckUnop(work_line, &dec_insn, kRegTypeChar, kRegTypeInteger, &failure);
3117 break;
3118 case Instruction::INT_TO_SHORT:
3119 CheckUnop(work_line, &dec_insn, kRegTypeShort, kRegTypeInteger, &failure);
3120 break;
3121
3122 case Instruction::ADD_INT:
3123 case Instruction::SUB_INT:
3124 case Instruction::MUL_INT:
3125 case Instruction::REM_INT:
3126 case Instruction::DIV_INT:
3127 case Instruction::SHL_INT:
3128 case Instruction::SHR_INT:
3129 case Instruction::USHR_INT:
3130 CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3131 kRegTypeInteger, false, &failure);
3132 break;
3133 case Instruction::AND_INT:
3134 case Instruction::OR_INT:
3135 case Instruction::XOR_INT:
3136 CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3137 kRegTypeInteger, true, &failure);
3138 break;
3139 case Instruction::ADD_LONG:
3140 case Instruction::SUB_LONG:
3141 case Instruction::MUL_LONG:
3142 case Instruction::DIV_LONG:
3143 case Instruction::REM_LONG:
3144 case Instruction::AND_LONG:
3145 case Instruction::OR_LONG:
3146 case Instruction::XOR_LONG:
3147 CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3148 kRegTypeLongLo, false, &failure);
3149 break;
3150 case Instruction::SHL_LONG:
3151 case Instruction::SHR_LONG:
3152 case Instruction::USHR_LONG:
3153 /* shift distance is Int, making these different from other binops */
3154 CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3155 kRegTypeInteger, false, &failure);
3156 break;
3157 case Instruction::ADD_FLOAT:
3158 case Instruction::SUB_FLOAT:
3159 case Instruction::MUL_FLOAT:
3160 case Instruction::DIV_FLOAT:
3161 case Instruction::REM_FLOAT:
3162 CheckBinop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
3163 kRegTypeFloat, false, &failure);
3164 break;
3165 case Instruction::ADD_DOUBLE:
3166 case Instruction::SUB_DOUBLE:
3167 case Instruction::MUL_DOUBLE:
3168 case Instruction::DIV_DOUBLE:
3169 case Instruction::REM_DOUBLE:
3170 CheckBinop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3171 kRegTypeDoubleLo, false, &failure);
3172 break;
3173 case Instruction::ADD_INT_2ADDR:
3174 case Instruction::SUB_INT_2ADDR:
3175 case Instruction::MUL_INT_2ADDR:
3176 case Instruction::REM_INT_2ADDR:
3177 case Instruction::SHL_INT_2ADDR:
3178 case Instruction::SHR_INT_2ADDR:
3179 case Instruction::USHR_INT_2ADDR:
3180 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3181 kRegTypeInteger, false, &failure);
3182 break;
3183 case Instruction::AND_INT_2ADDR:
3184 case Instruction::OR_INT_2ADDR:
3185 case Instruction::XOR_INT_2ADDR:
3186 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3187 kRegTypeInteger, true, &failure);
3188 break;
3189 case Instruction::DIV_INT_2ADDR:
3190 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3191 kRegTypeInteger, false, &failure);
3192 break;
3193 case Instruction::ADD_LONG_2ADDR:
3194 case Instruction::SUB_LONG_2ADDR:
3195 case Instruction::MUL_LONG_2ADDR:
3196 case Instruction::DIV_LONG_2ADDR:
3197 case Instruction::REM_LONG_2ADDR:
3198 case Instruction::AND_LONG_2ADDR:
3199 case Instruction::OR_LONG_2ADDR:
3200 case Instruction::XOR_LONG_2ADDR:
3201 CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3202 kRegTypeLongLo, false, &failure);
3203 break;
3204 case Instruction::SHL_LONG_2ADDR:
3205 case Instruction::SHR_LONG_2ADDR:
3206 case Instruction::USHR_LONG_2ADDR:
3207 CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3208 kRegTypeInteger, false, &failure);
3209 break;
3210 case Instruction::ADD_FLOAT_2ADDR:
3211 case Instruction::SUB_FLOAT_2ADDR:
3212 case Instruction::MUL_FLOAT_2ADDR:
3213 case Instruction::DIV_FLOAT_2ADDR:
3214 case Instruction::REM_FLOAT_2ADDR:
3215 CheckBinop2addr(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
3216 kRegTypeFloat, false, &failure);
3217 break;
3218 case Instruction::ADD_DOUBLE_2ADDR:
3219 case Instruction::SUB_DOUBLE_2ADDR:
3220 case Instruction::MUL_DOUBLE_2ADDR:
3221 case Instruction::DIV_DOUBLE_2ADDR:
3222 case Instruction::REM_DOUBLE_2ADDR:
3223 CheckBinop2addr(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3224 kRegTypeDoubleLo, false, &failure);
3225 break;
3226 case Instruction::ADD_INT_LIT16:
3227 case Instruction::RSUB_INT:
3228 case Instruction::MUL_INT_LIT16:
3229 case Instruction::DIV_INT_LIT16:
3230 case Instruction::REM_INT_LIT16:
3231 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
3232 &failure);
3233 break;
3234 case Instruction::AND_INT_LIT16:
3235 case Instruction::OR_INT_LIT16:
3236 case Instruction::XOR_INT_LIT16:
3237 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
3238 &failure);
3239 break;
3240 case Instruction::ADD_INT_LIT8:
3241 case Instruction::RSUB_INT_LIT8:
3242 case Instruction::MUL_INT_LIT8:
3243 case Instruction::DIV_INT_LIT8:
3244 case Instruction::REM_INT_LIT8:
3245 case Instruction::SHL_INT_LIT8:
3246 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
3247 &failure);
3248 break;
3249 case Instruction::SHR_INT_LIT8:
3250 tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
3251 false, &failure);
3252 CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
3253 &failure);
3254 break;
3255 case Instruction::USHR_INT_LIT8:
3256 tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
3257 true, &failure);
3258 CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
3259 &failure);
3260 break;
3261 case Instruction::AND_INT_LIT8:
3262 case Instruction::OR_INT_LIT8:
3263 case Instruction::XOR_INT_LIT8:
3264 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
3265 &failure);
3266 break;
3267
3268 /*
3269 * This falls into the general category of "optimized" instructions,
jeffhaod1f0fde2011-09-08 17:25:33 -07003270 * which don't generally appear during verification. Because it's
jeffhaobdb76512011-09-07 11:43:16 -07003271 * inserted in the course of verification, we can expect to see it here.
3272 */
3273 //case Instruction::THROW_VERIFICATION_ERROR:
3274 case Instruction::UNUSED_ED:
3275 break;
3276
3277 /*
3278 * Verifying "quickened" instructions is tricky, because we have
jeffhaod1f0fde2011-09-08 17:25:33 -07003279 * discarded the original field/method information. The byte offsets
jeffhaobdb76512011-09-07 11:43:16 -07003280 * and vtable indices only have meaning in the context of an object
3281 * instance.
3282 *
3283 * If a piece of code declares a local reference variable, assigns
3284 * null to it, and then issues a virtual method call on it, we
jeffhaod1f0fde2011-09-08 17:25:33 -07003285 * cannot evaluate the method call during verification. This situation
jeffhaobdb76512011-09-07 11:43:16 -07003286 * isn't hard to handle, since we know the call will always result in an
jeffhaod1f0fde2011-09-08 17:25:33 -07003287 * NPE, and the arguments and return value don't matter. Any code that
jeffhaobdb76512011-09-07 11:43:16 -07003288 * depends on the result of the method call is inaccessible, so the
3289 * fact that we can't fully verify anything that comes after the bad
3290 * call is not a problem.
3291 *
3292 * We must also consider the case of multiple code paths, only some of
jeffhaod1f0fde2011-09-08 17:25:33 -07003293 * which involve a null reference. We can completely verify the method
jeffhaobdb76512011-09-07 11:43:16 -07003294 * if we sidestep the results of executing with a null reference.
3295 * For example, if on the first pass through the code we try to do a
3296 * virtual method invocation through a null ref, we have to skip the
3297 * method checks and have the method return a "wildcard" type (which
jeffhaod1f0fde2011-09-08 17:25:33 -07003298 * merges with anything to become that other thing). The move-result
jeffhaobdb76512011-09-07 11:43:16 -07003299 * will tell us if it's a reference, single-word numeric, or double-word
jeffhaod1f0fde2011-09-08 17:25:33 -07003300 * value. We continue to perform the verification, and at the end of
jeffhaobdb76512011-09-07 11:43:16 -07003301 * the function any invocations that were never fully exercised are
3302 * marked as null-only.
3303 *
jeffhaod1f0fde2011-09-08 17:25:33 -07003304 * We would do something similar for the field accesses. The field's
jeffhaobdb76512011-09-07 11:43:16 -07003305 * type, once known, can be used to recover the width of short integers.
3306 * If the object reference was null, the field-get returns the "wildcard"
3307 * type, which is acceptable for any operation.
3308 */
3309 case Instruction::UNUSED_EE:
3310 case Instruction::UNUSED_EF:
3311 case Instruction::UNUSED_F2:
3312 case Instruction::UNUSED_F3:
3313 case Instruction::UNUSED_F4:
3314 case Instruction::UNUSED_F5:
3315 case Instruction::UNUSED_F6:
3316 case Instruction::UNUSED_F7:
3317 case Instruction::UNUSED_F8:
3318 case Instruction::UNUSED_F9:
3319 case Instruction::UNUSED_FA:
3320 case Instruction::UNUSED_FB:
3321 //case Instruction::EXECUTE_INLINE:
3322 //case Instruction::EXECUTE_INLINE_RANGE:
3323 //case Instruction::IGET_QUICK:
3324 //case Instruction::IGET_WIDE_QUICK:
3325 //case Instruction::IGET_OBJECT_QUICK:
3326 //case Instruction::IPUT_QUICK:
3327 //case Instruction::IPUT_WIDE_QUICK:
3328 //case Instruction::IPUT_OBJECT_QUICK:
3329 //case Instruction::INVOKE_VIRTUAL_QUICK:
3330 //case Instruction::INVOKE_VIRTUAL_QUICK_RANGE:
3331 //case Instruction::INVOKE_SUPER_QUICK:
3332 //case Instruction::INVOKE_SUPER_QUICK_RANGE:
3333 /* fall through to failure */
3334
3335 /*
3336 * These instructions are equivalent (from the verifier's point of view)
jeffhaod1f0fde2011-09-08 17:25:33 -07003337 * to the original form. The change was made for correctness rather
jeffhaobdb76512011-09-07 11:43:16 -07003338 * than improved performance (except for invoke-object-init, which
jeffhaod1f0fde2011-09-08 17:25:33 -07003339 * provides both). The substitution takes place after verification
jeffhaobdb76512011-09-07 11:43:16 -07003340 * completes, though, so we don't expect to see them here.
3341 */
3342 case Instruction::UNUSED_F0:
3343 case Instruction::UNUSED_F1:
3344 case Instruction::UNUSED_E3:
3345 case Instruction::UNUSED_E8:
3346 case Instruction::UNUSED_E7:
3347 case Instruction::UNUSED_E4:
3348 case Instruction::UNUSED_E9:
3349 case Instruction::UNUSED_FC:
3350 case Instruction::UNUSED_E5:
3351 case Instruction::UNUSED_EA:
3352 case Instruction::UNUSED_FD:
3353 case Instruction::UNUSED_E6:
3354 case Instruction::UNUSED_EB:
3355 case Instruction::UNUSED_FE:
3356 //case Instruction::INVOKE_OBJECT_INIT_RANGE:
3357 //case Instruction::RETURN_VOID_BARRIER:
3358 //case Instruction::IGET_VOLATILE:
3359 //case Instruction::IGET_WIDE_VOLATILE:
3360 //case Instruction::IGET_OBJECT_VOLATILE:
3361 //case Instruction::IPUT_VOLATILE:
3362 //case Instruction::IPUT_WIDE_VOLATILE:
3363 //case Instruction::IPUT_OBJECT_VOLATILE:
3364 //case Instruction::SGET_VOLATILE:
3365 //case Instruction::SGET_WIDE_VOLATILE:
3366 //case Instruction::SGET_OBJECT_VOLATILE:
3367 //case Instruction::SPUT_VOLATILE:
3368 //case Instruction::SPUT_WIDE_VOLATILE:
3369 //case Instruction::SPUT_OBJECT_VOLATILE:
3370 /* fall through to failure */
3371
3372 /* These should never appear during verification. */
3373 case Instruction::UNUSED_3E:
3374 case Instruction::UNUSED_3F:
3375 case Instruction::UNUSED_40:
3376 case Instruction::UNUSED_41:
3377 case Instruction::UNUSED_42:
3378 case Instruction::UNUSED_43:
3379 case Instruction::UNUSED_73:
3380 case Instruction::UNUSED_79:
3381 case Instruction::UNUSED_7A:
3382 case Instruction::UNUSED_EC:
3383 case Instruction::UNUSED_FF:
3384 //case Instruction::BREAKPOINT:
3385 //case Instruction::DISPATCH_FF:
3386 failure = VERIFY_ERROR_GENERIC;
3387 break;
3388
3389 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003390 * DO NOT add a "default" clause here. Without it the compiler will
jeffhaobdb76512011-09-07 11:43:16 -07003391 * complain if an instruction is missing (which is desirable).
3392 */
3393 }
3394
3395 if (failure != VERIFY_ERROR_NONE) {
jeffhaobdb76512011-09-07 11:43:16 -07003396 if (failure == VERIFY_ERROR_GENERIC) {
3397 /* immediate failure, reject class */
3398 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
3399 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3400 return false;
3401 } else {
jeffhao98eacac2011-09-14 16:11:53 -07003402 // TODO: CHECK IF THIS WILL WORK!
3403 /* ignore the failure and move on */
3404 LOG(ERROR) << "VFY: failing opcode 0x" << std::hex
3405 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3406 failure = VERIFY_ERROR_NONE;
3407#if 0
jeffhaobdb76512011-09-07 11:43:16 -07003408 /* replace opcode and continue on */
3409 LOG(ERROR) << "VFY: replacing opcode 0x" << std::hex
3410 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3411 if (!ReplaceFailingInstruction(code_item, insn_flags, insn_idx, failure))
3412 {
3413 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
3414 << (int) dec_insn.opcode_ << " at 0x" << insn_idx
3415 << std::dec;
3416 return false;
3417 }
3418 /* IMPORTANT: method->insns may have been changed */
3419 insns = code_item->insns_ + insn_idx;
3420
3421 /* continue on as if we just handled a throw-verification-error */
3422 failure = VERIFY_ERROR_NONE;
3423 opcode_flag = Instruction::kThrow;
jeffhao98eacac2011-09-14 16:11:53 -07003424#endif
jeffhaobdb76512011-09-07 11:43:16 -07003425 }
3426 }
3427
3428 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003429 * If we didn't just set the result register, clear it out. This
jeffhaobdb76512011-09-07 11:43:16 -07003430 * ensures that you can only use "move-result" immediately after the
jeffhaod1f0fde2011-09-08 17:25:33 -07003431 * result is set. (We could check this statically, but it's not
jeffhaobdb76512011-09-07 11:43:16 -07003432 * expensive and it makes our debugging output cleaner.)
3433 */
3434 if (!just_set_result) {
3435 int reg = RESULT_REGISTER(registers_size);
3436 SetRegisterType(work_line, reg, kRegTypeUnknown);
3437 SetRegisterType(work_line, reg + 1, kRegTypeUnknown);
3438 }
3439
jeffhaoa0a764a2011-09-16 10:43:38 -07003440 /* Handle "continue". Tag the next consecutive instruction. */
jeffhaobdb76512011-09-07 11:43:16 -07003441 if ((opcode_flag & Instruction::kContinue) != 0) {
3442 size_t insn_width = InsnGetWidth(insn_flags, insn_idx);
3443 if (insn_idx + insn_width >= insns_size) {
3444 LOG(ERROR) << "VFY: execution can walk off end of code area (from 0x"
3445 << std::hex << insn_idx << std::dec << ")";
3446 return false;
3447 }
3448
3449 /*
3450 * The only way to get to a move-exception instruction is to get
jeffhaod1f0fde2011-09-08 17:25:33 -07003451 * thrown there. Make sure the next instruction isn't one.
jeffhaobdb76512011-09-07 11:43:16 -07003452 */
3453 if (!CheckMoveException(code_item->insns_, insn_idx + insn_width))
3454 return false;
3455
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003456 if (GetRegisterLine(reg_table, insn_idx + insn_width)->reg_types_.get() != NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003457 /*
3458 * Merge registers into what we have for the next instruction,
3459 * and set the "changed" flag if needed.
3460 */
3461 if (!UpdateRegisters(insn_flags, reg_table, insn_idx + insn_width,
3462 work_line))
3463 return false;
3464 } else {
3465 /*
3466 * We're not recording register data for the next instruction,
jeffhaod1f0fde2011-09-08 17:25:33 -07003467 * so we don't know what the prior state was. We have to
jeffhaobdb76512011-09-07 11:43:16 -07003468 * assume that something has changed and re-evaluate it.
3469 */
3470 InsnSetChanged(insn_flags, insn_idx + insn_width, true);
3471 }
3472 }
3473
3474 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003475 * Handle "branch". Tag the branch target.
jeffhaobdb76512011-09-07 11:43:16 -07003476 *
3477 * NOTE: instructions like Instruction::EQZ provide information about the
jeffhaod1f0fde2011-09-08 17:25:33 -07003478 * state of the register when the branch is taken or not taken. For example,
jeffhaobdb76512011-09-07 11:43:16 -07003479 * somebody could get a reference field, check it for zero, and if the
3480 * branch is taken immediately store that register in a boolean field
jeffhaod1f0fde2011-09-08 17:25:33 -07003481 * since the value is known to be zero. We do not currently account for
jeffhaobdb76512011-09-07 11:43:16 -07003482 * that, and will reject the code.
3483 *
3484 * TODO: avoid re-fetching the branch target
3485 */
3486 if ((opcode_flag & Instruction::kBranch) != 0) {
3487 bool isConditional, selfOkay;
3488
3489 if (!GetBranchOffset(code_item, insn_flags, insn_idx, &branch_target,
3490 &isConditional, &selfOkay)) {
3491 /* should never happen after static verification */
3492 LOG(ERROR) << "VFY: bad branch at 0x" << std::hex << insn_idx << std::dec;
3493 return false;
3494 }
3495 assert(isConditional || (opcode_flag & Instruction::kContinue) == 0);
3496 assert(!isConditional || (opcode_flag & Instruction::kContinue) != 0);
3497
3498 if (!CheckMoveException(code_item->insns_, insn_idx + branch_target))
3499 return false;
3500
3501 /* update branch target, set "changed" if appropriate */
3502 if (!UpdateRegisters(insn_flags, reg_table, insn_idx + branch_target,
3503 work_line))
3504 return false;
3505 }
3506
3507 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003508 * Handle "switch". Tag all possible branch targets.
jeffhaobdb76512011-09-07 11:43:16 -07003509 *
3510 * We've already verified that the table is structurally sound, so we
3511 * just need to walk through and tag the targets.
3512 */
3513 if ((opcode_flag & Instruction::kSwitch) != 0) {
3514 int offset_to_switch = insns[1] | (((int32_t) insns[2]) << 16);
3515 const uint16_t* switch_insns = insns + offset_to_switch;
3516 int switch_count = switch_insns[1];
3517 int offset_to_targets, targ;
3518
3519 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
3520 /* 0 = sig, 1 = count, 2/3 = first key */
3521 offset_to_targets = 4;
3522 } else {
3523 /* 0 = sig, 1 = count, 2..count * 2 = keys */
3524 assert((*insns & 0xff) == Instruction::SPARSE_SWITCH);
3525 offset_to_targets = 2 + 2 * switch_count;
3526 }
3527
3528 /* verify each switch target */
3529 for (targ = 0; targ < switch_count; targ++) {
3530 int offset;
3531 uint32_t abs_offset;
3532
3533 /* offsets are 32-bit, and only partly endian-swapped */
3534 offset = switch_insns[offset_to_targets + targ * 2] |
3535 (((int32_t) switch_insns[offset_to_targets + targ * 2 + 1]) << 16);
3536 abs_offset = insn_idx + offset;
3537
3538 assert(abs_offset < insns_size);
3539
3540 if (!CheckMoveException(code_item->insns_, abs_offset))
3541 return false;
3542
3543 if (!UpdateRegisters(insn_flags, reg_table, abs_offset, work_line))
3544 return false;
3545 }
3546 }
3547
3548 /*
3549 * Handle instructions that can throw and that are sitting in a
jeffhaod1f0fde2011-09-08 17:25:33 -07003550 * "try" block. (If they're not in a "try" block when they throw,
jeffhaobdb76512011-09-07 11:43:16 -07003551 * control transfers out of the method.)
3552 */
3553 if ((opcode_flag & Instruction::kThrow) != 0 &&
3554 InsnIsInTry(insn_flags, insn_idx)) {
3555 bool has_catch_all = false;
3556 DexFile::CatchHandlerIterator iterator = DexFile::dexFindCatchHandler(
3557 *code_item, insn_idx);
3558
3559 for (; !iterator.HasNext(); iterator.Next()) {
3560 if (iterator.Get().type_idx_ == DexFile::kDexNoIndex)
3561 has_catch_all = true;
3562
3563 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003564 * Merge registers into the "catch" block. We want to use the
3565 * "savedRegs" rather than "work_regs", because at runtime the
3566 * exception will be thrown before the instruction modifies any
3567 * registers.
jeffhaobdb76512011-09-07 11:43:16 -07003568 */
3569 if (!UpdateRegisters(insn_flags, reg_table, iterator.Get().address_,
3570 &reg_table->saved_line_))
3571 return false;
3572 }
3573
3574 /*
3575 * If the monitor stack depth is nonzero, there must be a "catch all"
jeffhaod1f0fde2011-09-08 17:25:33 -07003576 * handler for this instruction. This does apply to monitor-exit
jeffhaobdb76512011-09-07 11:43:16 -07003577 * because of async exception handling.
3578 */
3579 if (work_line->monitor_stack_top_ != 0 && !has_catch_all) {
3580 /*
3581 * The state in work_line reflects the post-execution state.
3582 * If the current instruction is a monitor-enter and the monitor
3583 * stack was empty, we don't need a catch-all (if it throws,
3584 * it will do so before grabbing the lock).
3585 */
3586 if (!(dec_insn.opcode_ == Instruction::MONITOR_ENTER &&
3587 work_line->monitor_stack_top_ == 1))
3588 {
3589 LOG(ERROR) << "VFY: no catch-all for instruction at 0x" << std::hex
3590 << insn_idx << std::dec;
3591 return false;
3592 }
3593 }
3594 }
3595
jeffhaod1f0fde2011-09-08 17:25:33 -07003596 /* If we're returning from the method, make sure monitor stack is empty. */
jeffhaobdb76512011-09-07 11:43:16 -07003597 if ((opcode_flag & Instruction::kReturn) != 0 &&
3598 work_line->monitor_stack_top_ != 0) {
3599 LOG(ERROR) << "VFY: return with stack depth="
3600 << work_line->monitor_stack_top_ << " at 0x" << std::hex
3601 << insn_idx << std::dec;
3602 return false;
3603 }
3604
3605 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003606 * Update start_guess. Advance to the next instruction of that's
3607 * possible, otherwise use the branch target if one was found. If
jeffhaobdb76512011-09-07 11:43:16 -07003608 * neither of those exists we're in a return or throw; leave start_guess
3609 * alone and let the caller sort it out.
3610 */
3611 if ((opcode_flag & Instruction::kContinue) != 0) {
3612 *start_guess = insn_idx + InsnGetWidth(insn_flags, insn_idx);
3613 } else if ((opcode_flag & Instruction::kBranch) != 0) {
3614 /* we're still okay if branch_target is zero */
3615 *start_guess = insn_idx + branch_target;
3616 }
3617
3618 assert(*start_guess < insns_size &&
3619 InsnGetWidth(insn_flags, *start_guess) != 0);
3620
3621 return true;
3622}
3623
3624bool DexVerifier::ReplaceFailingInstruction(const DexFile::CodeItem* code_item,
3625 InsnFlags* insn_flags, int insn_idx, VerifyError failure) {
3626 const uint16_t* insns = code_item->insns_ + insn_idx;
3627 const byte* ptr = reinterpret_cast<const byte*>(insns);
3628 const Instruction* inst = Instruction::At(ptr);
3629 Instruction::Code opcode = inst->Opcode();
3630 VerifyErrorRefType ref_type;
3631
3632 /*
3633 * Generate the new instruction out of the old.
3634 *
3635 * First, make sure this is an instruction we're expecting to stomp on.
3636 */
3637 switch (opcode) {
3638 case Instruction::CONST_CLASS: // insn[1] == class ref, 2 bytes
3639 case Instruction::CHECK_CAST:
3640 case Instruction::INSTANCE_OF:
3641 case Instruction::NEW_INSTANCE:
3642 case Instruction::NEW_ARRAY:
3643 case Instruction::FILLED_NEW_ARRAY: // insn[1] == class ref, 3 bytes
3644 case Instruction::FILLED_NEW_ARRAY_RANGE:
3645 ref_type = VERIFY_ERROR_REF_CLASS;
3646 break;
3647
3648 case Instruction::IGET: // insn[1] == field ref, 2 bytes
3649 case Instruction::IGET_BOOLEAN:
3650 case Instruction::IGET_BYTE:
3651 case Instruction::IGET_CHAR:
3652 case Instruction::IGET_SHORT:
3653 case Instruction::IGET_WIDE:
3654 case Instruction::IGET_OBJECT:
3655 case Instruction::IPUT:
3656 case Instruction::IPUT_BOOLEAN:
3657 case Instruction::IPUT_BYTE:
3658 case Instruction::IPUT_CHAR:
3659 case Instruction::IPUT_SHORT:
3660 case Instruction::IPUT_WIDE:
3661 case Instruction::IPUT_OBJECT:
3662 case Instruction::SGET:
3663 case Instruction::SGET_BOOLEAN:
3664 case Instruction::SGET_BYTE:
3665 case Instruction::SGET_CHAR:
3666 case Instruction::SGET_SHORT:
3667 case Instruction::SGET_WIDE:
3668 case Instruction::SGET_OBJECT:
3669 case Instruction::SPUT:
3670 case Instruction::SPUT_BOOLEAN:
3671 case Instruction::SPUT_BYTE:
3672 case Instruction::SPUT_CHAR:
3673 case Instruction::SPUT_SHORT:
3674 case Instruction::SPUT_WIDE:
3675 case Instruction::SPUT_OBJECT:
3676 ref_type = VERIFY_ERROR_REF_FIELD;
3677 break;
3678
3679 case Instruction::INVOKE_VIRTUAL: // insn[1] == method ref, 3 bytes
3680 case Instruction::INVOKE_VIRTUAL_RANGE:
3681 case Instruction::INVOKE_SUPER:
3682 case Instruction::INVOKE_SUPER_RANGE:
3683 case Instruction::INVOKE_DIRECT:
3684 case Instruction::INVOKE_DIRECT_RANGE:
3685 case Instruction::INVOKE_STATIC:
3686 case Instruction::INVOKE_STATIC_RANGE:
3687 case Instruction::INVOKE_INTERFACE:
3688 case Instruction::INVOKE_INTERFACE_RANGE:
3689 ref_type = VERIFY_ERROR_REF_METHOD;
3690 break;
3691
3692 default:
3693 /* could handle this in a generic way, but this is probably safer */
3694 LOG(ERROR) << "GLITCH: verifier asked to replace opcode 0x" << std::hex
3695 << (int) opcode << std::dec;
3696 return false;
3697 }
3698
3699 assert(inst->IsThrow());
3700
3701 /* write a NOP over the third code unit, if necessary */
3702 int width = InsnGetWidth(insn_flags, insn_idx);
3703 switch (width) {
3704 case 2:
3705 /* nothing to do */
3706 break;
3707 case 3:
3708 // TODO: Add this functionality
3709 //UpdateCodeUnit(method, insns + 2, Instruction::NOP);
3710 break;
3711 default:
3712 /* whoops */
3713 LOG(FATAL) << "ERROR: stomped a " << width
3714 << "-unit instruction with a verifier error";
3715 }
3716
3717 /* encode the opcode, with the failure code in the high byte */
3718 // TODO: REPLACE FAILING OPCODES
3719 //assert(width == 2 || width == 3);
3720 //uint16_t new_val = Instruction::THROW_VERIFICATION_ERROR |
jeffhao98eacac2011-09-14 16:11:53 -07003721 //uint16_t new_val = Instruction::UNUSED_ED |
jeffhaobdb76512011-09-07 11:43:16 -07003722 //(failure << 8) | (ref_type << (8 + kVerifyErrorRefTypeShift));
3723 //UpdateCodeUnit(method, insns, new_val);
3724
3725 return true;
3726}
3727
3728/* Handle a monitor-enter instruction. */
3729void DexVerifier::HandleMonitorEnter(RegisterLine* work_line, uint32_t reg_idx,
3730 uint32_t insn_idx, VerifyError* failure) {
3731 if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
3732 LOG(ERROR) << "VFY: monitor-enter on non-object";
3733 *failure = VERIFY_ERROR_GENERIC;
3734 return;
3735 }
3736
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003737 if (work_line->monitor_entries_.get() == NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003738 return;
3739 }
3740
3741 if (work_line->monitor_stack_top_ == kMaxMonitorStackDepth) {
3742 LOG(ERROR) << "VFY: monitor-enter stack overflow (" << kMaxMonitorStackDepth
3743 << ")";
3744 *failure = VERIFY_ERROR_GENERIC;
3745 return;
3746 }
3747
3748 /*
3749 * Push an entry on the stack, and set a bit in the register flags to
3750 * indicate that it's associated with this register.
3751 */
3752 work_line->monitor_entries_[reg_idx] |= 1 << work_line->monitor_stack_top_;
3753 work_line->monitor_stack_[work_line->monitor_stack_top_++] = insn_idx;
3754}
3755
3756/* Handle a monitor-exit instruction. */
3757void DexVerifier::HandleMonitorExit(RegisterLine* work_line, uint32_t reg_idx,
3758 uint32_t insn_idx, VerifyError* failure) {
3759 if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
3760 LOG(ERROR) << "VFY: monitor-exit on non-object";
3761 *failure = VERIFY_ERROR_GENERIC;
3762 return;
3763 }
3764
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003765 if (work_line->monitor_entries_.get() == NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003766 return;
3767 }
3768
3769 if (work_line->monitor_stack_top_ == 0) {
3770 LOG(ERROR) << "VFY: monitor-exit stack underflow";
3771 *failure = VERIFY_ERROR_GENERIC;
3772 return;
3773 }
3774
3775 /*
3776 * Confirm that the entry at the top of the stack is associated with
jeffhaod1f0fde2011-09-08 17:25:33 -07003777 * the register. Pop the top entry off.
jeffhaobdb76512011-09-07 11:43:16 -07003778 */
3779 work_line->monitor_stack_top_--;
3780#ifdef BUG_3215458_FIXED
3781 /*
3782 * TODO: This code can safely be enabled if know we are working on
3783 * a dex file of format version 036 or later. (That is, we'll need to
3784 * add a check for the version number.)
3785 */
3786 if ((work_line->monitor_entries_[reg_idx] &
3787 (1 << work_line->monitor_stack_top_)) == 0) {
3788 LOG(ERROR) << "VFY: monitor-exit bit " << work_line->monitor_stack_top_
3789 << " not set: addr=0x" << std::hex << insn_idx << std::dec
3790 << " (bits[" << reg_idx << "]=" << std::hex
3791 << work_line->monitor_entries_[reg_idx] << std::dec << ")";
3792 *failure = VERIFY_ERROR_GENERIC;
3793 return;
3794 }
3795#endif
3796 work_line->monitor_stack_[work_line->monitor_stack_top_] = 0;
3797
3798 /* Clear the bit from the register flags. */
3799 work_line->monitor_entries_[reg_idx] &= ~(1 << work_line->monitor_stack_top_);
3800}
3801
3802Field* DexVerifier::GetInstField(VerifierData* vdata, RegType obj_type,
3803 int field_idx, VerifyError* failure) {
3804 Method* method = vdata->method_;
3805 const DexFile* dex_file = vdata->dex_file_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003806 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07003807 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3808 DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
3809 const ClassLoader* class_loader =
3810 method->GetDeclaringClass()->GetClassLoader();
3811 Field* field = NULL;
3812 Class* obj_class;
3813 bool must_be_local = false;
3814
3815 if (!RegTypeIsReference(obj_type)) {
3816 LOG(ERROR) << "VFY: attempt to access field in non-reference type "
3817 << obj_type;
3818 *failure = VERIFY_ERROR_GENERIC;
3819 return field;
3820 }
3821
3822 field = class_linker->ResolveField(*dex_file, field_idx, dex_cache,
3823 class_loader, false);
3824 if (field == NULL) {
3825 LOG(ERROR) << "VFY: unable to resolve instance field " << field_idx;
3826 return field;
3827 }
3828
3829 if (obj_type == kRegTypeZero)
3830 return field;
3831
3832 /*
3833 * Access to fields in uninitialized objects is allowed if this is
3834 * the <init> method for the object and the field in question is
3835 * declared by this class.
3836 */
3837 obj_class = RegTypeReferenceToClass(obj_type, uninit_map);
3838 assert(obj_class != NULL);
3839 if (RegTypeIsUninitReference(obj_type)) {
3840 if (!IsInitMethod(method) || method->GetDeclaringClass() != obj_class) {
3841 LOG(ERROR) << "VFY: attempt to access field via uninitialized ref";
3842 *failure = VERIFY_ERROR_GENERIC;
3843 return field;
3844 }
3845 must_be_local = true;
3846 }
3847
jeffhaobdb76512011-09-07 11:43:16 -07003848 if (!field->GetDeclaringClass()->IsAssignableFrom(obj_class)) {
3849 LOG(ERROR) << "VFY: invalid field access (field "
3850 << field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
3851 << "." << field->GetName()->ToModifiedUtf8() << ", through "
3852 << obj_class->GetDescriptor()->ToModifiedUtf8() << " ref)";
3853 *failure = VERIFY_ERROR_NO_FIELD;
3854 return field;
3855 }
3856
3857 if (must_be_local) {
3858 bool found = false;
3859 /* for uninit ref, make sure it's defined by this class, not super */
3860 for (uint32_t i = 0; i < obj_class->NumInstanceFields(); i++) {
3861 found |= (field == obj_class->GetInstanceField(i));
3862 }
3863 if (!found) {
3864 LOG(ERROR) << "VFY: invalid constructor field access (field "
3865 << field->GetName()->ToModifiedUtf8() << " in "
3866 << obj_class->GetDescriptor()->ToModifiedUtf8() << ")";
3867 *failure = VERIFY_ERROR_GENERIC;
3868 return field;
3869 }
3870 }
3871
3872 return field;
3873}
3874
3875Field* DexVerifier::GetStaticField(VerifierData* vdata, int field_idx,
3876 VerifyError* failure) {
3877 Method* method = vdata->method_;
3878 const DexFile* dex_file = vdata->dex_file_;
3879 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3880 DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
3881 const ClassLoader* class_loader =
3882 method->GetDeclaringClass()->GetClassLoader();
3883 Field* field;
3884
3885 field = class_linker->ResolveField(*dex_file, field_idx, dex_cache,
3886 class_loader, true);
3887 if (field == NULL) {
3888 //const DexFile::FieldId field_id = dex_file->GetFieldId(field_idx);
3889
3890 //LOG(ERROR) << "VFY: unable to resolve static field " << field_idx << " ("
3891 //<< dex_file->GetFieldName(field_id) << ") in "
3892 //<< dex_file->GetFieldClassDescriptor(field_id);
3893 LOG(ERROR) << "VFY: unable to resolve static field";
3894 }
3895
3896 return field;
3897}
3898
3899Class* DexVerifier::GetCaughtExceptionType(VerifierData* vdata, int insn_idx,
3900 VerifyError* failure) {
3901 const DexFile* dex_file = vdata->dex_file_;
3902 const DexFile::CodeItem* code_item = vdata->code_item_;
3903 Method* method = vdata->method_;
3904 Class* common_super = NULL;
3905 uint32_t handlers_size;
jeffhaoba5ebb92011-08-25 17:24:37 -07003906 const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item, 0);
jeffhaobdb76512011-09-07 11:43:16 -07003907
3908 if (code_item->tries_size_ != 0) {
3909 handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
3910 } else {
3911 handlers_size = 0;
3912 }
3913
3914 for (uint32_t i = 0; i < handlers_size; i++) {
jeffhaoba5ebb92011-08-25 17:24:37 -07003915 DexFile::CatchHandlerIterator iterator(handlers_ptr);
3916
3917 for (; !iterator.HasNext(); iterator.Next()) {
jeffhaobdb76512011-09-07 11:43:16 -07003918 DexFile::CatchHandlerItem handler = iterator.Get();
3919 if (handler.address_ == (uint32_t) insn_idx) {
3920 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3921 Class* klass;
jeffhaoba5ebb92011-08-25 17:24:37 -07003922
jeffhaobdb76512011-09-07 11:43:16 -07003923 if (handler.type_idx_ == DexFile::kDexNoIndex) {
3924 klass = class_linker->FindSystemClass("Ljava/lang/Throwable;");
3925 } else {
jeffhao98eacac2011-09-14 16:11:53 -07003926 klass = ResolveClassAndCheckAccess(dex_file, handler.type_idx_,
3927 method->GetDeclaringClass(), failure);
jeffhaobdb76512011-09-07 11:43:16 -07003928 }
3929
3930 if (klass == NULL) {
3931 LOG(ERROR) << "VFY: unable to resolve exception class "
3932 << handler.type_idx_ << " ("
3933 << dex_file->dexStringByTypeIdx(handler.type_idx_) << ")";
jeffhaod1f0fde2011-09-08 17:25:33 -07003934 /* TODO: do we want to keep going? If we don't fail this we run
3935 * the risk of having a non-Throwable introduced at runtime.
3936 * However, that won't pass an instanceof test, so is essentially
3937 * harmless.
jeffhaobdb76512011-09-07 11:43:16 -07003938 */
3939 } else {
3940 if (common_super == NULL)
3941 common_super = klass;
3942 else
3943 common_super = FindCommonSuperclass(klass, common_super);
3944 }
3945 }
jeffhaoba5ebb92011-08-25 17:24:37 -07003946 }
3947
3948 handlers_ptr = iterator.GetData();
3949 }
3950
jeffhaobdb76512011-09-07 11:43:16 -07003951 if (common_super == NULL) {
3952 /* no catch blocks, or no catches with classes we can find */
3953 LOG(ERROR) << "VFY: unable to find exception handler at addr 0x" << std::hex
3954 << insn_idx << std::dec;
3955 *failure = VERIFY_ERROR_GENERIC;
3956 }
3957
3958 return common_super;
jeffhaoba5ebb92011-08-25 17:24:37 -07003959}
3960
jeffhaobdb76512011-09-07 11:43:16 -07003961DexVerifier::RegType DexVerifier::GetMethodReturnType(const DexFile* dex_file,
3962 const Method* method) {
3963 Class* klass = method->GetReturnType();
3964 if (klass->IsPrimitive())
3965 return PrimitiveTypeToRegType(klass->GetPrimitiveType());
3966 else
3967 return RegTypeFromClass(klass);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07003968}
3969
jeffhaobdb76512011-09-07 11:43:16 -07003970Class* DexVerifier::GetClassFromRegister(const RegisterLine* register_line,
3971 uint32_t vsrc, VerifyError* failure) {
3972 /* get the element type of the array held in vsrc */
3973 RegType type = GetRegisterType(register_line, vsrc);
jeffhaoba5ebb92011-08-25 17:24:37 -07003974
jeffhaobdb76512011-09-07 11:43:16 -07003975 /* if "always zero", we allow it to fail at runtime */
3976 if (type == kRegTypeZero)
3977 return NULL;
3978
3979 if (!RegTypeIsReference(type)) {
3980 LOG(ERROR) << "VFY: tried to get class from non-ref register v" << vsrc
3981 << " (type=" << type << ")",
3982 *failure = VERIFY_ERROR_GENERIC;
3983 return NULL;
3984 }
3985 if (RegTypeIsUninitReference(type)) {
3986 LOG(ERROR) << "VFY: register " << vsrc << " holds uninitialized reference";
3987 *failure = VERIFY_ERROR_GENERIC;
3988 return NULL;
jeffhaoba5ebb92011-08-25 17:24:37 -07003989 }
3990
jeffhaobdb76512011-09-07 11:43:16 -07003991 return RegTypeInitializedReferenceToClass(type);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07003992}
3993
jeffhaobdb76512011-09-07 11:43:16 -07003994DexVerifier::RegType DexVerifier::GetInvocationThis(
3995 const RegisterLine* register_line,
3996 const Instruction::DecodedInstruction* dec_insn, VerifyError* failure) {
3997 if (dec_insn->vA_ < 1) {
3998 LOG(ERROR) << "VFY: invoke lacks 'this'";
3999 *failure = VERIFY_ERROR_GENERIC;
4000 return kRegTypeUnknown;
jeffhaoba5ebb92011-08-25 17:24:37 -07004001 }
jeffhaobdb76512011-09-07 11:43:16 -07004002
4003 /* get the element type of the array held in vsrc */
4004 RegType this_type = GetRegisterType(register_line, dec_insn->vC_);
4005 if (!RegTypeIsReference(this_type)) {
4006 LOG(ERROR) << "VFY: tried to get class from non-ref register v"
4007 << dec_insn->vC_ << " (type=" << this_type << ")";
4008 *failure = VERIFY_ERROR_GENERIC;
4009 return kRegTypeUnknown;
4010 }
4011
4012 return this_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07004013}
4014
jeffhaobdb76512011-09-07 11:43:16 -07004015void DexVerifier::SetRegisterType(RegisterLine* register_line, uint32_t vdst,
4016 RegType new_type) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004017 RegType* insn_regs = register_line->reg_types_.get();
jeffhaoba5ebb92011-08-25 17:24:37 -07004018
jeffhaobdb76512011-09-07 11:43:16 -07004019 switch (new_type) {
4020 case kRegTypeUnknown:
4021 case kRegTypeBoolean:
4022 case kRegTypeOne:
4023 case kRegTypeConstByte:
4024 case kRegTypeConstPosByte:
4025 case kRegTypeConstShort:
4026 case kRegTypeConstPosShort:
4027 case kRegTypeConstChar:
4028 case kRegTypeConstInteger:
4029 case kRegTypeByte:
4030 case kRegTypePosByte:
4031 case kRegTypeShort:
4032 case kRegTypePosShort:
4033 case kRegTypeChar:
4034 case kRegTypeInteger:
4035 case kRegTypeFloat:
4036 case kRegTypeZero:
4037 case kRegTypeUninit:
4038 insn_regs[vdst] = new_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07004039 break;
jeffhaobdb76512011-09-07 11:43:16 -07004040 case kRegTypeConstLo:
4041 case kRegTypeLongLo:
4042 case kRegTypeDoubleLo:
4043 insn_regs[vdst] = new_type;
4044 insn_regs[vdst + 1] = new_type + 1;
4045 break;
4046 case kRegTypeConstHi:
4047 case kRegTypeLongHi:
4048 case kRegTypeDoubleHi:
4049 /* should never set these explicitly */
4050 LOG(FATAL) << "BUG: explicit set of high register type";
4051 break;
4052
4053 default:
4054 /* can't switch for ref types, so we check explicitly */
4055 if (RegTypeIsReference(new_type)) {
4056 insn_regs[vdst] = new_type;
4057
4058 /*
4059 * In most circumstances we won't see a reference to a primitive
4060 * class here (e.g. "D"), since that would mean the object in the
jeffhaod1f0fde2011-09-08 17:25:33 -07004061 * register is actually a primitive type. It can happen as the
jeffhaobdb76512011-09-07 11:43:16 -07004062 * result of an assumed-successful check-cast instruction in
jeffhaod1f0fde2011-09-08 17:25:33 -07004063 * which the second argument refers to a primitive class. (In
jeffhaobdb76512011-09-07 11:43:16 -07004064 * practice, such an instruction will always throw an exception.)
4065 *
4066 * This is not an issue for instructions like const-class, where
4067 * the object in the register is a java.lang.Class instance.
4068 */
4069 break;
4070 }
4071 /* bad type - fall through */
4072
4073 case kRegTypeConflict: // should only be set during a merge
4074 LOG(FATAL) << "BUG: set register to unknown type " << new_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07004075 break;
4076 }
4077
jeffhaobdb76512011-09-07 11:43:16 -07004078 /*
4079 * Clear the monitor entry bits for this register.
4080 */
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004081 if (register_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07004082 register_line->monitor_entries_[vdst] = 0;
4083}
4084
4085void DexVerifier::VerifyRegisterType(RegisterLine* register_line, uint32_t vsrc,
4086 RegType check_type, VerifyError* failure) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004087 const RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004088 RegType src_type = insn_regs[vsrc];
4089
4090 switch (check_type) {
4091 case kRegTypeFloat:
4092 case kRegTypeBoolean:
4093 case kRegTypePosByte:
4094 case kRegTypeByte:
4095 case kRegTypePosShort:
4096 case kRegTypeShort:
4097 case kRegTypeChar:
4098 case kRegTypeInteger:
4099 if (!CanConvertTo1nr(src_type, check_type)) {
4100 LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
4101 << ", wanted " << check_type;
4102 *failure = VERIFY_ERROR_GENERIC;
4103 }
4104 /* Update type if result is float */
4105 if (check_type == kRegTypeFloat) {
4106 SetRegisterType(register_line, vsrc, check_type);
4107 } else {
4108 /* Update const type to actual type after use */
4109 SetRegisterType(register_line, vsrc, ConstTypeToRegType(src_type));
4110 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004111 break;
jeffhaobdb76512011-09-07 11:43:16 -07004112 case kRegTypeLongLo:
4113 case kRegTypeDoubleLo:
4114 if (insn_regs[vsrc + 1] != src_type + 1) {
4115 LOG(ERROR) << "VFY: register2 v" << vsrc << "-" << vsrc + 1
4116 << " values " << insn_regs[vsrc] << ","
4117 << insn_regs[vsrc + 1];
4118 *failure = VERIFY_ERROR_GENERIC;
4119 } else if (!CanConvertTo2(src_type, check_type)) {
4120 LOG(ERROR) << "VFY: register2 v" << vsrc << " type " << src_type
4121 << ", wanted " << check_type;
4122 *failure = VERIFY_ERROR_GENERIC;
4123 }
4124 /* Update type if source is from const */
4125 if (src_type == kRegTypeConstLo) {
4126 SetRegisterType(register_line, vsrc, check_type);
4127 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004128 break;
jeffhaobdb76512011-09-07 11:43:16 -07004129 case kRegTypeConstLo:
4130 case kRegTypeConstHi:
4131 case kRegTypeLongHi:
4132 case kRegTypeDoubleHi:
4133 case kRegTypeZero:
4134 case kRegTypeOne:
4135 case kRegTypeUnknown:
4136 case kRegTypeConflict:
4137 /* should never be checking for these explicitly */
4138 assert(false);
4139 *failure = VERIFY_ERROR_GENERIC;
4140 return;
4141 case kRegTypeUninit:
4142 default:
4143 /* make sure check_type is initialized reference */
4144 if (!RegTypeIsReference(check_type)) {
4145 LOG(ERROR) << "VFY: unexpected check type " << check_type;
4146 assert(false);
4147 *failure = VERIFY_ERROR_GENERIC;
4148 break;
4149 }
4150 if (RegTypeIsUninitReference(check_type)) {
4151 LOG(ERROR) << "VFY: uninitialized ref not expected as reg check";
4152 *failure = VERIFY_ERROR_GENERIC;
4153 break;
4154 }
4155 /* make sure src_type is initialized reference or always-NULL */
4156 if (!RegTypeIsReference(src_type)) {
4157 LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
4158 << ", wanted ref";
4159 *failure = VERIFY_ERROR_GENERIC;
4160 break;
4161 }
4162 if (RegTypeIsUninitReference(src_type)) {
4163 LOG(ERROR) << "VFY: register1 v" << vsrc << " holds uninitialized ref";
4164 *failure = VERIFY_ERROR_GENERIC;
4165 break;
4166 }
4167 /* if the register isn't Zero, make sure it's an instance of check */
4168 if (src_type != kRegTypeZero) {
4169 Class* src_class = RegTypeInitializedReferenceToClass(src_type);
4170 Class* check_class = RegTypeInitializedReferenceToClass(check_type);
4171 assert(src_class != NULL);
4172 assert(check_class != NULL);
4173
4174 if (!check_class->IsAssignableFrom(src_class)) {
4175 LOG(ERROR) << "VFY: " << src_class->GetDescriptor()->ToModifiedUtf8()
4176 << " is not instance of "
4177 << check_class->GetDescriptor()->ToModifiedUtf8();
4178 *failure = VERIFY_ERROR_GENERIC;
4179 }
4180 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004181 break;
4182 }
jeffhaobdb76512011-09-07 11:43:16 -07004183}
jeffhaoba5ebb92011-08-25 17:24:37 -07004184
jeffhaobdb76512011-09-07 11:43:16 -07004185void DexVerifier::SetResultRegisterType(RegisterLine* register_line,
4186 const int insn_reg_count, RegType new_type) {
4187 SetRegisterType(register_line, RESULT_REGISTER(insn_reg_count), new_type);
4188}
4189
4190void DexVerifier::MarkRefsAsInitialized(RegisterLine* register_line,
4191 int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type,
4192 VerifyError* failure) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004193 RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004194 Class* klass = GetUninitInstance(uninit_map,
4195 RegTypeToUninitIndex(uninit_type));
4196
4197 if (klass == NULL) {
4198 LOG(ERROR) << "VFY: unable to find type=" << std::hex << uninit_type
4199 << std::dec << " (idx=" << RegTypeToUninitIndex(uninit_type)
4200 << ")";
4201 *failure = VERIFY_ERROR_GENERIC;
4202 return;
jeffhaoba5ebb92011-08-25 17:24:37 -07004203 }
4204
jeffhaobdb76512011-09-07 11:43:16 -07004205 RegType init_type = RegTypeFromClass(klass);
4206 int changed = 0;
4207 for (int i = 0; i < insn_reg_count; i++) {
4208 if (insn_regs[i] == uninit_type) {
4209 insn_regs[i] = init_type;
4210 changed++;
4211 }
4212 }
4213 assert(changed > 0);
4214
4215 return;
4216}
4217
4218void DexVerifier::MarkUninitRefsAsInvalid(RegisterLine* register_line,
4219 int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004220 RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004221
4222 for (int i = 0; i < insn_reg_count; i++) {
4223 if (insn_regs[i] == uninit_type) {
4224 insn_regs[i] = kRegTypeConflict;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004225 if (register_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07004226 register_line->monitor_entries_[i] = 0;
4227 }
4228 }
4229}
4230
4231void DexVerifier::CopyRegister1(RegisterLine* register_line, uint32_t vdst,
4232 uint32_t vsrc, TypeCategory cat, VerifyError* failure) {
4233 assert(cat == kTypeCategory1nr || cat == kTypeCategoryRef);
4234 RegType type = GetRegisterType(register_line, vsrc);
4235 CheckTypeCategory(type, cat, failure);
4236 if (*failure != VERIFY_ERROR_NONE) {
4237 LOG(ERROR) << "VFY: copy1 v" << vdst << "<-v" << vsrc << " type=" << type
4238 << " cat=" << (int) cat;
4239 } else {
4240 SetRegisterType(register_line, vdst, type);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004241 if (cat == kTypeCategoryRef && register_line->monitor_entries_.get() != NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07004242 register_line->monitor_entries_[vdst] =
4243 register_line->monitor_entries_[vsrc];
4244 }
4245 }
4246}
4247
4248void DexVerifier::CopyRegister2(RegisterLine* register_line, uint32_t vdst,
4249 uint32_t vsrc, VerifyError* failure) {
4250 RegType type_l = GetRegisterType(register_line, vsrc);
4251 RegType type_h = GetRegisterType(register_line, vsrc + 1);
4252
4253 CheckTypeCategory(type_l, kTypeCategory2, failure);
4254 CheckWidePair(type_l, type_h, failure);
4255 if (*failure != VERIFY_ERROR_NONE) {
4256 LOG(ERROR) << "VFY: copy2 v" << vdst << "<-v" << vsrc << " type=" << type_l
4257 << "/" << type_h;
4258 } else {
4259 SetRegisterType(register_line, vdst, type_l);
4260 }
4261}
4262
4263void DexVerifier::CopyResultRegister1(RegisterLine* register_line,
4264 const int insn_reg_count, uint32_t vdst, TypeCategory cat,
4265 VerifyError* failure) {
4266 assert(vdst < (uint32_t) insn_reg_count);
4267
4268 uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
4269 RegType type = GetRegisterType(register_line, vsrc);
4270 CheckTypeCategory(type, cat, failure);
4271 if (*failure != VERIFY_ERROR_NONE) {
4272 LOG(ERROR) << "VFY: copyRes1 v" << vdst << "<-v" << vsrc << " cat="
4273 << (int) cat << " type=" << type;
4274 } else {
4275 SetRegisterType(register_line, vdst, type);
4276 SetRegisterType(register_line, vsrc, kRegTypeUnknown);
4277 }
4278}
4279
4280/*
jeffhaod1f0fde2011-09-08 17:25:33 -07004281 * Implement "move-result-wide". Copy the category-2 value from the result
jeffhaobdb76512011-09-07 11:43:16 -07004282 * register to another register, and reset the result register.
4283 */
4284void DexVerifier::CopyResultRegister2(RegisterLine* register_line,
4285 const int insn_reg_count, uint32_t vdst, VerifyError* failure) {
4286 assert(vdst < (uint32_t) insn_reg_count);
4287
4288 uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
4289 RegType type_l = GetRegisterType(register_line, vsrc);
4290 RegType type_h = GetRegisterType(register_line, vsrc + 1);
4291 CheckTypeCategory(type_l, kTypeCategory2, failure);
4292 CheckWidePair(type_l, type_h, failure);
4293 if (*failure != VERIFY_ERROR_NONE) {
4294 LOG(ERROR) << "VFY: copyRes2 v" << vdst << "<-v" << vsrc << " type="
4295 << type_l << "/" << type_h;
4296 } else {
4297 SetRegisterType(register_line, vdst, type_l);
4298 SetRegisterType(register_line, vsrc, kRegTypeUnknown);
4299 SetRegisterType(register_line, vsrc + 1, kRegTypeUnknown);
4300 }
4301}
4302
4303int DexVerifier::GetClassDepth(Class* klass) {
4304 int depth = 0;
4305 while (klass->GetSuperClass() != NULL) {
4306 klass = klass->GetSuperClass();
4307 depth++;
4308 }
4309 return depth;
4310}
4311
4312Class* DexVerifier::DigForSuperclass(Class* c1, Class* c2) {
4313 int depth1, depth2;
4314
4315 depth1 = GetClassDepth(c1);
4316 depth2 = GetClassDepth(c2);
4317
4318 /* pull the deepest one up */
4319 if (depth1 > depth2) {
4320 while (depth1 > depth2) {
4321 c1 = c1->GetSuperClass();
4322 depth1--;
4323 }
4324 } else {
4325 while (depth2 > depth1) {
4326 c2 = c2->GetSuperClass();
4327 depth2--;
4328 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004329 }
4330
jeffhaobdb76512011-09-07 11:43:16 -07004331 /* walk up in lock-step */
4332 while (c1 != c2) {
4333 c1 = c1->GetSuperClass();
4334 c2 = c2->GetSuperClass();
4335
4336 assert(c1 != NULL && c2 != NULL);
4337 }
4338
4339 return c1;
4340}
4341
4342Class* DexVerifier::FindCommonArraySuperclass(Class* c1, Class* c2) {
4343 Class* array_class = NULL;
4344 Class* common_elem;
4345 int array_dim1, array_dim2;
4346 int i, num_dims;
4347 bool has_primitive = false;
4348
4349 array_dim1 = c1->GetArrayRank();
4350 array_dim2 = c2->GetArrayRank();
4351 assert(c1->GetArrayRank() > 0);
4352 assert(c2->GetArrayRank() > 0);
4353
4354 if (c1->GetComponentType()->IsPrimitive()) {
4355 array_dim1--;
4356 has_primitive = true;
4357 }
4358 if (c2->GetComponentType()->IsPrimitive()) {
4359 array_dim2--;
4360 has_primitive = true;
4361 }
4362
4363 if (!has_primitive && array_dim1 == array_dim2) {
4364 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004365 * Two arrays of reference types with equal dimensions. Try to
jeffhaobdb76512011-09-07 11:43:16 -07004366 * find a good match.
4367 */
4368 common_elem = FindCommonSuperclass(c1->GetComponentType(),
4369 c2->GetComponentType());
4370 num_dims = array_dim1;
4371 } else {
4372 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004373 * Mismatched array depths and/or array(s) of primitives. We want
jeffhaobdb76512011-09-07 11:43:16 -07004374 * Object, or an Object array with appropriate dimensions.
4375 *
4376 * We initialize array_class to Object here, because it's possible
4377 * for us to set num_dims=0.
4378 */
4379 if (array_dim1 < array_dim2)
4380 num_dims = array_dim1;
4381 else
4382 num_dims = array_dim2;
4383 array_class = common_elem = c1->GetSuperClass(); // == java.lang.Object
4384 }
4385
4386 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004387 * Find an appropriately-dimensioned array class. This is easiest
jeffhaobdb76512011-09-07 11:43:16 -07004388 * to do iteratively, using the array class found by the current round
4389 * as the element type for the next round.
4390 */
4391 for (i = 0; i < num_dims; i++) {
4392 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4393 const ClassLoader* class_loader = c1->GetClassLoader();
4394 std::string descriptor = "[" +
4395 common_elem->GetDescriptor()->ToModifiedUtf8();
4396 array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
4397 common_elem = array_class;
4398 }
4399 assert(array_class != NULL);
4400
4401 return array_class;
4402}
4403
4404Class* DexVerifier::FindCommonSuperclass(Class* c1, Class* c2) {
4405 assert(!c1->IsPrimitive() && !c2->IsPrimitive());
4406
4407 if (c1 == c2)
4408 return c1;
4409
jeffhao5dbddee2011-09-07 16:38:26 -07004410 if (c1->IsInterface() && c1->IsAssignableFrom(c2)) {
jeffhaobdb76512011-09-07 11:43:16 -07004411 return c1;
4412 }
jeffhao5dbddee2011-09-07 16:38:26 -07004413 if (c2->IsInterface() && c2->IsAssignableFrom(c1)) {
jeffhaobdb76512011-09-07 11:43:16 -07004414 return c2;
4415 }
4416 if (c1->IsArrayClass() && c2->IsArrayClass()) {
4417 return FindCommonArraySuperclass(c1, c2);
4418 }
4419
4420 return DigForSuperclass(c1, c2);
4421}
4422
jeffhao98eacac2011-09-14 16:11:53 -07004423Class* DexVerifier::ResolveClassAndCheckAccess(const DexFile* dex_file,
4424 uint32_t class_idx, const Class* referrer, VerifyError* failure) {
4425 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4426 Class* res_class = class_linker->ResolveType(*dex_file, class_idx, referrer);
4427
4428 if (res_class == NULL) {
4429 *failure = VERIFY_ERROR_NO_CLASS;
4430 return NULL;
4431 }
4432
4433 /* Check if access is allowed. */
4434 if (!referrer->CanAccess(res_class)) {
4435 LOG(ERROR) << "VFY: illegal class access: "
4436 << referrer->GetDescriptor()->ToModifiedUtf8() << " -> "
4437 << res_class->GetDescriptor()->ToModifiedUtf8();
4438 *failure = VERIFY_ERROR_ACCESS_CLASS;
4439 return NULL;
4440 }
4441
4442 return res_class;
4443}
4444
jeffhaobdb76512011-09-07 11:43:16 -07004445DexVerifier::RegType DexVerifier::MergeTypes(RegType type1, RegType type2,
4446 bool* changed) {
4447 RegType result;
4448
jeffhao98eacac2011-09-14 16:11:53 -07004449 /* Check for trivial case so we don't have to hit memory. */
jeffhaobdb76512011-09-07 11:43:16 -07004450 if (type1 == type2)
4451 return type1;
4452
4453 /*
4454 * Use the table if we can, and reject any attempts to merge something
4455 * from the table with a reference type.
4456 *
4457 * Uninitialized references are composed of the enum ORed with an
jeffhaod1f0fde2011-09-08 17:25:33 -07004458 * index value. The uninitialized table entry at index zero *will*
4459 * show up as a simple kRegTypeUninit value. Since this cannot be
jeffhaobdb76512011-09-07 11:43:16 -07004460 * merged with anything but itself, the rules do the right thing.
4461 */
4462 if (type1 < kRegTypeMAX) {
4463 if (type2 < kRegTypeMAX) {
4464 result = merge_table_[type1][type2];
4465 } else {
4466 /* simple + reference == conflict, usually */
4467 if (type1 == kRegTypeZero)
4468 result = type2;
4469 else
4470 result = kRegTypeConflict;
4471 }
4472 } else {
4473 if (type2 < kRegTypeMAX) {
4474 /* reference + simple == conflict, usually */
4475 if (type2 == kRegTypeZero)
4476 result = type1;
4477 else
4478 result = kRegTypeConflict;
4479 } else {
4480 /* merging two references */
4481 if (RegTypeIsUninitReference(type1) ||
4482 RegTypeIsUninitReference(type2))
4483 {
4484 /* can't merge uninit with anything but self */
4485 result = kRegTypeConflict;
4486 } else {
4487 Class* klass1 = RegTypeInitializedReferenceToClass(type1);
4488 Class* klass2 = RegTypeInitializedReferenceToClass(type2);
4489 Class* merged_class = FindCommonSuperclass(klass1, klass2);
4490 assert(merged_class != NULL);
4491 result = RegTypeFromClass(merged_class);
4492 }
4493 }
4494 }
4495
4496 if (result != type1)
4497 *changed = true;
jeffhaoba5ebb92011-08-25 17:24:37 -07004498 return result;
jeffhaobdb76512011-09-07 11:43:16 -07004499}
4500
4501DexVerifier::MonitorEntries DexVerifier::MergeMonitorEntries(
4502 MonitorEntries ents1, MonitorEntries ents2, bool* changed) {
4503 MonitorEntries result = ents1 & ents2;
4504 if (result != ents1)
4505 *changed = true;
4506 return result;
4507}
4508
4509bool DexVerifier::UpdateRegisters(InsnFlags* insn_flags,
4510 RegisterTable* reg_table, int next_insn, const RegisterLine* work_line) {
4511 const size_t insn_reg_count_plus = reg_table->insn_reg_count_plus_;
4512 assert(work_line != NULL);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004513 const RegType* work_regs = work_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004514
4515 if (!InsnIsVisitedOrChanged(insn_flags, next_insn)) {
4516 /*
4517 * We haven't processed this instruction before, and we haven't
jeffhaod1f0fde2011-09-08 17:25:33 -07004518 * touched the registers here, so there's nothing to "merge". Copy
4519 * the registers over and mark it as changed. (This is the only
jeffhaobdb76512011-09-07 11:43:16 -07004520 * way a register can transition out of "unknown", so this is not
4521 * just an optimization.)
4522 */
4523 CopyLineToTable(reg_table, next_insn, work_line);
4524 InsnSetChanged(insn_flags, next_insn, true);
4525 } else {
4526 /* Merge registers, set Changed only if different */
4527 RegisterLine* target_line = GetRegisterLine(reg_table, next_insn);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004528 RegType* target_regs = target_line->reg_types_.get();
4529 MonitorEntries* work_mon_ents = work_line->monitor_entries_.get();
4530 MonitorEntries* target_mon_ents = target_line->monitor_entries_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004531 bool changed = false;
4532 unsigned int idx;
4533
4534 assert(target_regs != NULL);
4535 if (target_mon_ents != NULL) {
4536 /* Monitor stacks must be identical. */
4537 if (target_line->monitor_stack_top_ != work_line->monitor_stack_top_) {
4538 LOG(ERROR) << "VFY: mismatched stack depth "
4539 << target_line->monitor_stack_top_ << " vs. "
4540 << work_line->monitor_stack_top_ << " at 0x"
4541 << std::hex << next_insn << std::dec;
4542 return false;
4543 }
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004544 if (memcmp(target_line->monitor_stack_.get(), work_line->monitor_stack_.get(),
jeffhaobdb76512011-09-07 11:43:16 -07004545 target_line->monitor_stack_top_ * sizeof(uint32_t)) != 0) {
4546 LOG(ERROR) << "VFY: mismatched monitor stacks at 0x" << std::hex
4547 << next_insn << std::dec;
4548 return false;
4549 }
4550 }
4551
4552 for (idx = 0; idx < insn_reg_count_plus; idx++) {
4553 target_regs[idx] = MergeTypes(target_regs[idx], work_regs[idx], &changed);
4554
4555 if (target_mon_ents != NULL) {
4556 target_mon_ents[idx] = MergeMonitorEntries(target_mon_ents[idx],
4557 work_mon_ents[idx], &changed);
4558 }
4559 }
4560
4561 if (changed) {
4562 InsnSetChanged(insn_flags, next_insn, true);
4563 }
4564 }
4565
4566 return true;
4567}
4568
4569bool DexVerifier::CanConvertTo1nr(RegType src_type, RegType check_type) {
4570 static const char conv_tab[kRegType1nrEND - kRegType1nrSTART + 1]
4571 [kRegType1nrEND - kRegType1nrSTART + 1] =
4572 {
4573 /* chk: 0 1 Z y Y h H c i b B s S C I F */
4574 { /*0*/ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4575 { /*1*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4576 { /*Z*/ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
4577 { /*y*/ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4578 { /*Y*/ 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1 },
4579 { /*h*/ 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1 },
4580 { /*H*/ 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1 },
4581 { /*c*/ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1 },
4582 { /*i*/ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1 },
4583 { /*b*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0 },
4584 { /*B*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0 },
4585 { /*s*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 },
4586 { /*S*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 },
4587 { /*C*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 },
4588 { /*I*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },
4589 { /*F*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
4590 };
4591
4592 assert(check_type >= kRegType1nrSTART && check_type <= kRegType1nrEND);
4593
4594 if (src_type >= kRegType1nrSTART && src_type <= kRegType1nrEND)
4595 return (bool) conv_tab[src_type - kRegType1nrSTART]
4596 [check_type - kRegType1nrSTART];
4597
4598 return false;
4599}
4600
4601bool DexVerifier::CanConvertTo2(RegType src_type, RegType check_type) {
4602 return ((src_type == kRegTypeConstLo || src_type == check_type) &&
4603 (check_type == kRegTypeLongLo || check_type == kRegTypeDoubleLo));
4604}
4605
4606DexVerifier::RegType DexVerifier::PrimitiveTypeToRegType(
4607 Class::PrimitiveType prim_type) {
4608 switch (prim_type) {
4609 case Class::kPrimBoolean: return kRegTypeBoolean;
4610 case Class::kPrimByte: return kRegTypeByte;
4611 case Class::kPrimShort: return kRegTypeShort;
4612 case Class::kPrimChar: return kRegTypeChar;
4613 case Class::kPrimInt: return kRegTypeInteger;
4614 case Class::kPrimLong: return kRegTypeLongLo;
4615 case Class::kPrimFloat: return kRegTypeFloat;
4616 case Class::kPrimDouble: return kRegTypeDoubleLo;
4617 case Class::kPrimVoid:
4618 default: {
4619 return kRegTypeUnknown;
4620 }
4621 }
4622}
4623
4624DexVerifier::RegType DexVerifier::ConstTypeToRegType(RegType const_type) {
4625 switch (const_type) {
4626 case kRegTypeConstPosByte: return kRegTypePosByte;
4627 case kRegTypeConstByte: return kRegTypeByte;
4628 case kRegTypeConstPosShort: return kRegTypePosShort;
4629 case kRegTypeConstShort: return kRegTypeShort;
4630 case kRegTypeConstChar: return kRegTypeChar;
4631 case kRegTypeConstInteger: return kRegTypeInteger;
4632 default: {
4633 return const_type;
4634 }
4635 }
4636}
4637
4638char DexVerifier::DetermineCat1Const(int32_t value) {
4639 if (value < -32768)
4640 return kRegTypeConstInteger;
4641 else if (value < -128)
4642 return kRegTypeConstShort;
4643 else if (value < 0)
4644 return kRegTypeConstByte;
4645 else if (value == 0)
4646 return kRegTypeZero;
4647 else if (value == 1)
4648 return kRegTypeOne;
4649 else if (value < 128)
4650 return kRegTypeConstPosByte;
4651 else if (value < 32768)
4652 return kRegTypeConstPosShort;
4653 else if (value < 65536)
4654 return kRegTypeConstChar;
4655 else
4656 return kRegTypeConstInteger;
4657}
4658
4659void DexVerifier::CheckFinalFieldAccess(const Method* method,
4660 const Field* field, VerifyError* failure) {
4661 if (!field->IsFinal())
4662 return;
4663
4664 /* make sure we're in the same class */
4665 if (method->GetDeclaringClass() != field->GetDeclaringClass()) {
4666 LOG(ERROR) << "VFY: can't modify final field "
4667 << field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
4668 << "." << field->GetName()->ToModifiedUtf8();
4669 *failure = VERIFY_ERROR_ACCESS_FIELD;
4670 return;
4671 }
4672}
4673
4674void DexVerifier::CheckArrayIndexType(const Method* method, RegType reg_type,
4675 VerifyError* failure) {
4676 if (*failure == VERIFY_ERROR_NONE) {
4677 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004678 * The 1nr types are interchangeable at this level. We could
jeffhaobdb76512011-09-07 11:43:16 -07004679 * do something special if we can definitively identify it as a
4680 * float, but there's no real value in doing so.
4681 */
4682 CheckTypeCategory(reg_type, kTypeCategory1nr, failure);
4683 if (*failure != VERIFY_ERROR_NONE) {
4684 LOG(ERROR) << "Invalid reg type for array index (" << reg_type << ")";
4685 }
4686 }
4687}
4688
4689bool DexVerifier::CheckConstructorReturn(const Method* method,
4690 const RegisterLine* register_line, const int insn_reg_count) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004691 const RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004692
4693 if (!IsInitMethod(method))
4694 return true;
4695
4696 RegType uninit_this = RegTypeFromUninitIndex(kUninitThisArgSlot);
4697
4698 for (int i = 0; i < insn_reg_count; i++) {
4699 if (insn_regs[i] == uninit_this) {
4700 LOG(ERROR) << "VFY: <init> returning without calling superclass init";
4701 return false;
4702 }
4703 }
4704 return true;
4705}
4706
4707bool DexVerifier::CheckMoveException(const uint16_t* insns, int insn_idx) {
4708 if ((insns[insn_idx] & 0xff) == Instruction::MOVE_EXCEPTION) {
4709 LOG(ERROR) << "VFY: invalid use of move-exception";
4710 return false;
4711 }
4712 return true;
4713}
4714
4715void DexVerifier::CheckTypeCategory(RegType type, TypeCategory cat,
4716 VerifyError* failure) {
4717 switch (cat) {
4718 case kTypeCategory1nr:
4719 switch (type) {
4720 case kRegTypeZero:
4721 case kRegTypeOne:
4722 case kRegTypeBoolean:
4723 case kRegTypeConstPosByte:
4724 case kRegTypeConstByte:
4725 case kRegTypeConstPosShort:
4726 case kRegTypeConstShort:
4727 case kRegTypeConstChar:
4728 case kRegTypeConstInteger:
4729 case kRegTypePosByte:
4730 case kRegTypeByte:
4731 case kRegTypePosShort:
4732 case kRegTypeShort:
4733 case kRegTypeChar:
4734 case kRegTypeInteger:
4735 case kRegTypeFloat:
4736 break;
4737 default:
4738 *failure = VERIFY_ERROR_GENERIC;
4739 break;
4740 }
4741 break;
4742 case kTypeCategory2:
4743 switch (type) {
4744 case kRegTypeConstLo:
4745 case kRegTypeLongLo:
4746 case kRegTypeDoubleLo:
4747 break;
4748 default:
4749 *failure = VERIFY_ERROR_GENERIC;
4750 break;
4751 }
4752 break;
4753 case kTypeCategoryRef:
4754 if (type != kRegTypeZero && !RegTypeIsReference(type))
4755 *failure = VERIFY_ERROR_GENERIC;
4756 break;
4757 default:
4758 assert(false);
4759 *failure = VERIFY_ERROR_GENERIC;
4760 break;
4761 }
4762}
4763
4764void DexVerifier::CheckWidePair(RegType type_l, RegType type_h,
4765 VerifyError* failure) {
4766 if ((type_h != type_l + 1))
4767 *failure = VERIFY_ERROR_GENERIC;
4768}
4769
4770void DexVerifier::CheckUnop(RegisterLine* register_line,
4771 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4772 RegType src_type, VerifyError* failure) {
4773 VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
4774 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4775}
4776
4777bool DexVerifier::UpcastBooleanOp(RegisterLine* register_line, uint32_t reg1,
4778 uint32_t reg2) {
4779 RegType type1, type2;
4780
4781 type1 = GetRegisterType(register_line, reg1);
4782 type2 = GetRegisterType(register_line, reg2);
4783
4784 if ((type1 == kRegTypeBoolean || type1 == kRegTypeZero || type1 == kRegTypeOne) &&
4785 (type2 == kRegTypeBoolean || type2 == kRegTypeZero || type2 == kRegTypeOne)) {
4786 return true;
4787 }
4788 return false;
4789}
4790
4791void DexVerifier::CheckLitop(RegisterLine* register_line,
4792 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4793 RegType src_type, bool check_boolean_op, VerifyError* failure) {
4794 VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
4795
4796 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
4797 assert(dst_type == kRegTypeInteger);
4798
4799 /* check vB with the call, then check the constant manually */
4800 if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vB_)
4801 && (dec_insn->vC_ == 0 || dec_insn->vC_ == 1)) {
4802 dst_type = kRegTypeBoolean;
4803 }
4804 }
4805
4806 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4807}
4808
4809void DexVerifier::CheckBinop(RegisterLine* register_line,
4810 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4811 RegType src_type1, RegType src_type2, bool check_boolean_op,
4812 VerifyError* failure) {
4813 VerifyRegisterType(register_line, dec_insn->vB_, src_type1, failure);
4814 VerifyRegisterType(register_line, dec_insn->vC_, src_type2, failure);
4815
4816 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
4817 assert(dst_type == kRegTypeInteger);
4818 if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vC_))
4819 dst_type = kRegTypeBoolean;
4820 }
4821
4822 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4823}
4824
4825void DexVerifier::CheckBinop2addr(RegisterLine* register_line,
4826 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4827 RegType src_type1, RegType src_type2, bool check_boolean_op,
4828 VerifyError* failure) {
4829 VerifyRegisterType(register_line, dec_insn->vA_, src_type1, failure);
4830 VerifyRegisterType(register_line, dec_insn->vB_, src_type2, failure);
4831
4832 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
4833 assert(dst_type == kRegTypeInteger);
4834 if (UpcastBooleanOp(register_line, dec_insn->vA_, dec_insn->vB_))
4835 dst_type = kRegTypeBoolean;
4836 }
4837
4838 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4839}
4840
4841DexVerifier::RegType DexVerifier::AdjustForRightShift(
4842 RegisterLine* register_line, int reg, unsigned int shift_count,
4843 bool is_unsigned_shift, VerifyError* failure) {
4844 RegType src_type = GetRegisterType(register_line, reg);
4845 RegType new_type;
4846
4847 /* convert const derived types to their actual types */
4848 src_type = ConstTypeToRegType(src_type);
4849
4850 /* no-op */
4851 if (shift_count == 0)
4852 return src_type;
4853
4854 /* safe defaults */
4855 if (is_unsigned_shift)
4856 new_type = kRegTypeInteger;
4857 else
4858 new_type = src_type;
4859
4860 if (shift_count >= 32) {
4861 LOG(ERROR) << "Got unexpectedly large shift count " << shift_count;
4862 /* fail? */
4863 return new_type;
4864 }
4865
4866 switch (src_type) {
4867 case kRegTypeInteger: /* 32-bit signed value */
4868 if (is_unsigned_shift) {
4869 if (shift_count > 24)
4870 new_type = kRegTypePosByte;
4871 else if (shift_count >= 16)
4872 new_type = kRegTypeChar;
4873 } else {
4874 if (shift_count >= 24)
4875 new_type = kRegTypeByte;
4876 else if (shift_count >= 16)
4877 new_type = kRegTypeShort;
4878 }
4879 break;
4880 case kRegTypeShort: /* 16-bit signed value */
4881 if (is_unsigned_shift) {
4882 /* default (kRegTypeInteger) is correct */
4883 } else {
4884 if (shift_count >= 8)
4885 new_type = kRegTypeByte;
4886 }
4887 break;
4888 case kRegTypePosShort: /* 15-bit unsigned value */
4889 if (shift_count >= 8)
4890 new_type = kRegTypePosByte;
4891 break;
4892 case kRegTypeChar: /* 16-bit unsigned value */
4893 if (shift_count > 8)
4894 new_type = kRegTypePosByte;
4895 break;
4896 case kRegTypeByte: /* 8-bit signed value */
4897 /* defaults (u=kRegTypeInteger / s=src_type) are correct */
4898 break;
4899 case kRegTypePosByte: /* 7-bit unsigned value */
4900 /* always use new_type=src_type */
4901 new_type = src_type;
4902 break;
4903 case kRegTypeZero: /* 1-bit unsigned value */
4904 case kRegTypeOne:
4905 case kRegTypeBoolean:
4906 /* unnecessary? */
4907 new_type = kRegTypeZero;
4908 break;
4909 default:
4910 /* long, double, references; shouldn't be here! */
4911 assert(false);
4912 break;
4913 }
4914
4915 return new_type;
4916}
4917
4918void DexVerifier::VerifyFilledNewArrayRegs(const Method* method,
4919 RegisterLine* register_line,
4920 const Instruction::DecodedInstruction* dec_insn, Class* res_class,
4921 bool is_range, VerifyError* failure) {
4922 uint32_t arg_count = dec_insn->vA_;
4923 RegType expected_type;
4924 Class::PrimitiveType elem_type;
4925 unsigned int ui;
4926
4927 assert(res_class->IsArrayClass());
4928 elem_type = res_class->GetComponentType()->GetPrimitiveType();
4929 if (elem_type == Class::kPrimNot) {
4930 expected_type = RegTypeFromClass(res_class->GetComponentType());
4931 } else {
4932 expected_type = PrimitiveTypeToRegType(elem_type);
4933 }
4934
4935 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004936 * Verify each register. If "arg_count" is bad, VerifyRegisterType()
4937 * will run off the end of the list and fail. It's legal, if silly,
jeffhaobdb76512011-09-07 11:43:16 -07004938 * for arg_count to be zero.
4939 */
4940 for (ui = 0; ui < arg_count; ui++) {
4941 uint32_t get_reg;
4942
4943 if (is_range)
4944 get_reg = dec_insn->vC_ + ui;
4945 else
4946 get_reg = dec_insn->arg_[ui];
4947
4948 VerifyRegisterType(register_line, get_reg, expected_type, failure);
4949 if (*failure != VERIFY_ERROR_NONE) {
4950 LOG(ERROR) << "VFY: filled-new-array arg " << ui << "(" << get_reg
4951 << ") not valid";
4952 return;
4953 }
4954 }
4955}
4956
4957bool DexVerifier::IsCorrectInvokeKind(MethodType method_type,
4958 Method* res_method) {
4959 switch (method_type) {
4960 case METHOD_DIRECT:
4961 return res_method->IsDirect();
4962 case METHOD_STATIC:
4963 return res_method->IsStatic();
4964 case METHOD_VIRTUAL:
4965 case METHOD_INTERFACE:
4966 return !res_method->IsDirect();
4967 default:
4968 return false;
4969 }
4970}
4971
4972Method* DexVerifier::VerifyInvocationArgs(VerifierData* vdata,
4973 RegisterLine* register_line, const int insn_reg_count,
4974 const Instruction::DecodedInstruction* dec_insn, MethodType method_type,
4975 bool is_range, bool is_super, VerifyError* failure) {
4976 Method* method = vdata->method_;
4977 const DexFile* dex_file = vdata->dex_file_;
4978 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004979 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004980 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4981 DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
4982 const ClassLoader* class_loader =
4983 method->GetDeclaringClass()->GetClassLoader();
4984
4985 Method* res_method;
4986 std::string sig;
4987 size_t sig_offset;
4988 int expected_args;
4989 int actual_args;
4990
4991 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004992 * Resolve the method. This could be an abstract or concrete method
jeffhaobdb76512011-09-07 11:43:16 -07004993 * depending on what sort of call we're making.
4994 */
4995 res_method = class_linker->ResolveMethod(*dex_file, dec_insn->vB_, dex_cache,
4996 class_loader, (method_type == METHOD_DIRECT || method_type == METHOD_STATIC));
4997
jeffhaobdb76512011-09-07 11:43:16 -07004998 if (res_method == NULL) {
jeffhao98eacac2011-09-14 16:11:53 -07004999 const DexFile::MethodId& method_id = dex_file->GetMethodId(dec_insn->vB_);
5000 const char* method_name = dex_file->GetMethodName(method_id);
5001 const char* method_proto = dex_file->GetMethodPrototype(method_id);
5002 const char* class_descriptor = dex_file->GetMethodClassDescriptor(method_id);
5003
5004 LOG(ERROR) << "VFY: unable to resolve method " << dec_insn->vB_ << ": "
5005 << class_descriptor << "." << method_name << " " << method_proto;
jeffhaobdb76512011-09-07 11:43:16 -07005006 *failure = VERIFY_ERROR_NO_METHOD;
5007 return NULL;
5008 }
jeffhaobdb76512011-09-07 11:43:16 -07005009
5010 /*
5011 * Only time you can explicitly call a method starting with '<' is when
jeffhaod1f0fde2011-09-08 17:25:33 -07005012 * making a "direct" invocation on "<init>". There are additional
jeffhaobdb76512011-09-07 11:43:16 -07005013 * restrictions but we don't enforce them here.
5014 */
5015 if (res_method->GetName()->Equals("<init>")) {
5016 if (method_type != METHOD_DIRECT || !IsInitMethod(res_method)) {
5017 LOG(ERROR) << "VFY: invalid call to "
jeffhao98eacac2011-09-14 16:11:53 -07005018 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
jeffhaobdb76512011-09-07 11:43:16 -07005019 << "." << res_method->GetName();
5020 goto bad_sig;
5021 }
5022 }
5023
5024 /*
5025 * See if the method type implied by the invoke instruction matches the
5026 * access flags for the target method.
5027 */
5028 if (!IsCorrectInvokeKind(method_type, res_method)) {
5029 LOG(ERROR) << "VFY: invoke type does not match method type of "
jeffhao98eacac2011-09-14 16:11:53 -07005030 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
jeffhaobdb76512011-09-07 11:43:16 -07005031 << "." << res_method->GetName()->ToModifiedUtf8();
5032
5033 *failure = VERIFY_ERROR_GENERIC;
5034 return NULL;
5035 }
5036
5037 /*
5038 * If we're using invoke-super(method), make sure that the executing
5039 * method's class' superclass has a vtable entry for the target method.
5040 */
5041 if (is_super) {
5042 assert(method_type == METHOD_VIRTUAL);
5043 Class* super = method->GetDeclaringClass()->GetSuperClass();
5044 if (super == NULL || res_method->GetMethodIndex() > super->GetVTable()->GetLength()) {
5045 if (super == NULL) {
5046 LOG(ERROR) << "VFY: invalid invoke-super from "
5047 << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5048 << "." << method->GetName()->ToModifiedUtf8() << " to super -."
5049 << res_method->GetName()->ToModifiedUtf8()
5050 << " " << res_method->GetSignature()->ToModifiedUtf8();
5051 } else {
5052 LOG(ERROR) << "VFY: invalid invoke-super from "
5053 << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5054 << "." << method->GetName()->ToModifiedUtf8() << " to super "
5055 << super->GetDescriptor()->ToModifiedUtf8()
5056 << "." << res_method->GetName()->ToModifiedUtf8()
5057 << " " << res_method->GetSignature()->ToModifiedUtf8();
5058 }
5059 *failure = VERIFY_ERROR_NO_METHOD;
5060 return NULL;
5061 }
5062 }
5063
5064 /*
5065 * We use vAA as our expected arg count, rather than res_method->insSize,
jeffhaod1f0fde2011-09-08 17:25:33 -07005066 * because we need to match the call to the signature. Also, we might
jeffhaobdb76512011-09-07 11:43:16 -07005067 * might be calling through an abstract method definition (which doesn't
5068 * have register count values).
5069 */
5070 expected_args = dec_insn->vA_;
5071 actual_args = 0;
5072
5073 /* caught by static verifier */
5074 assert(is_range || expected_args <= 5);
5075
5076 if (expected_args > code_item->outs_size_) {
5077 LOG(ERROR) << "VFY: invalid arg count (" << expected_args
5078 << ") exceeds outsSize (" << code_item->outs_size_ << ")";
5079 *failure = VERIFY_ERROR_GENERIC;
5080 return NULL;
5081 }
5082
5083 sig = res_method->GetSignature()->ToModifiedUtf8();
5084 if (sig[0] != '(') {
5085 LOG(ERROR) << "VFY: descriptor doesn't start with '(': " << sig;
5086 goto bad_sig;
5087 }
5088
5089 /*
5090 * Check the "this" argument, which must be an instance of the class
jeffhaod1f0fde2011-09-08 17:25:33 -07005091 * that declared the method. For an interface class, we don't do the
jeffhaobdb76512011-09-07 11:43:16 -07005092 * full interface merge, so we can't do a rigorous check here (which
5093 * is okay since we have to do it at runtime).
5094 */
5095 if (!res_method->IsStatic()) {
5096 Class* actual_this_ref;
5097 RegType actual_arg_type;
5098
5099 actual_arg_type = GetInvocationThis(register_line, dec_insn, failure);
5100 if (*failure != VERIFY_ERROR_NONE)
5101 return NULL;
5102
5103 if (RegTypeIsUninitReference(actual_arg_type) &&
5104 !res_method->GetName()->Equals("<init>")) {
5105 LOG(ERROR) << "VFY: 'this' arg must be initialized";
5106 *failure = VERIFY_ERROR_GENERIC;
5107 return NULL;
5108 }
5109 if (method_type != METHOD_INTERFACE && actual_arg_type != kRegTypeZero) {
5110 actual_this_ref = RegTypeReferenceToClass(actual_arg_type, uninit_map);
5111 if (!res_method->GetDeclaringClass()->IsAssignableFrom(actual_this_ref)) {
5112 LOG(ERROR) << "VFY: 'this' arg '"
5113 << actual_this_ref->GetDescriptor()->ToModifiedUtf8()
5114 << "' not instance of '"
5115 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5116 << "'";
5117 *failure = VERIFY_ERROR_GENERIC;
5118 return NULL;
5119 }
5120 }
5121 actual_args++;
5122 }
5123
5124 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07005125 * Process the target method's signature. This signature may or may not
jeffhaobdb76512011-09-07 11:43:16 -07005126 * have been verified, so we can't assume it's properly formed.
5127 */
5128 for (sig_offset = 1; sig_offset < sig.size(); sig_offset++) {
jeffhaobdb76512011-09-07 11:43:16 -07005129 if (sig[sig_offset] == ')')
5130 break;
5131
5132 if (actual_args >= expected_args) {
5133 LOG(ERROR) << "VFY: expected " << expected_args << " args, found more ("
5134 << sig.substr(sig_offset) << ")";
5135 goto bad_sig;
5136 }
5137
5138 uint32_t get_reg;
5139 if (is_range)
5140 get_reg = dec_insn->vC_ + actual_args;
5141 else
5142 get_reg = dec_insn->arg_[actual_args];
5143
5144 switch (sig[sig_offset]) {
5145 case 'L':
5146 {
5147 Class* klass = LookupSignatureClass(method, sig.substr(sig_offset),
5148 failure);
5149 if (*failure != VERIFY_ERROR_NONE)
5150 goto bad_sig;
5151 VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
5152 failure);
5153 if (*failure != VERIFY_ERROR_NONE) {
5154 LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
5155 << klass->GetDescriptor()->ToModifiedUtf8() << ")";
5156 goto bad_sig;
5157 }
5158 sig_offset += sig.substr(sig_offset).find(';');
5159 }
5160 actual_args++;
5161 break;
5162 case '[':
5163 {
5164 Class* klass = LookupSignatureArrayClass(method,
5165 sig.substr(sig_offset), failure);
5166 if (*failure != VERIFY_ERROR_NONE)
5167 goto bad_sig;
5168 VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
5169 failure);
5170 if (*failure != VERIFY_ERROR_NONE) {
5171 LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
5172 << klass->GetDescriptor()->ToModifiedUtf8() << ")";
5173 goto bad_sig;
5174 }
5175 while (sig[sig_offset] == '[')
5176 sig_offset++;
5177 if (sig[sig_offset] == 'L')
5178 sig_offset += sig.substr(sig_offset).find(';');
5179 }
5180 actual_args++;
5181 break;
5182 case 'Z':
5183 VerifyRegisterType(register_line, get_reg, kRegTypeBoolean, failure);
5184 actual_args++;
5185 break;
5186 case 'C':
5187 VerifyRegisterType(register_line, get_reg, kRegTypeChar, failure);
5188 actual_args++;
5189 break;
5190 case 'B':
5191 VerifyRegisterType(register_line, get_reg, kRegTypeByte, failure);
5192 actual_args++;
5193 break;
5194 case 'I':
5195 VerifyRegisterType(register_line, get_reg, kRegTypeInteger, failure);
5196 actual_args++;
5197 break;
5198 case 'S':
5199 VerifyRegisterType(register_line, get_reg, kRegTypeShort, failure);
5200 actual_args++;
5201 break;
5202 case 'F':
5203 VerifyRegisterType(register_line, get_reg, kRegTypeFloat, failure);
5204 actual_args++;
5205 break;
5206 case 'D':
5207 VerifyRegisterType(register_line, get_reg, kRegTypeDoubleLo, failure);
5208 actual_args += 2;
5209 break;
5210 case 'J':
5211 VerifyRegisterType(register_line, get_reg, kRegTypeLongLo, failure);
5212 actual_args += 2;
5213 break;
5214 default:
5215 LOG(ERROR) << "VFY: invocation target: bad signature type char '"
5216 << sig << "'";
5217 goto bad_sig;
5218 }
5219 }
5220 if (sig[sig_offset] != ')') {
5221 LOG(ERROR) << "VFY: invocation target: bad signature '"
5222 << res_method->GetSignature()->ToModifiedUtf8() << "'";
5223 goto bad_sig;
5224 }
5225
5226 if (actual_args != expected_args) {
5227 LOG(ERROR) << "VFY: expected " << expected_args << " args, found "
5228 << actual_args;
5229 goto bad_sig;
5230 }
5231
5232 return res_method;
5233
5234bad_sig:
5235 if (res_method != NULL) {
5236 LOG(ERROR) << "VFY: rejecting call to "
5237 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5238 << "." << res_method->GetName()->ToModifiedUtf8() << " "
5239 << res_method->GetSignature()->ToModifiedUtf8();
5240 }
5241
5242 if (*failure == VERIFY_ERROR_NONE)
5243 *failure = VERIFY_ERROR_GENERIC;
5244 return NULL;
5245}
jeffhaoba5ebb92011-08-25 17:24:37 -07005246
jeffhaod1f0fde2011-09-08 17:25:33 -07005247DexVerifier::RegisterMap* DexVerifier::GenerateRegisterMapV(VerifierData* vdata)
5248{
5249 const DexFile::CodeItem* code_item = vdata->code_item_;
5250 int i, bytes_for_addr, gc_point_count;
5251
5252 if (code_item->registers_size_ >= 2048) {
5253 LOG(ERROR) << "ERROR: register map can't handle "
5254 << code_item->registers_size_ << " registers";
5255 return NULL;
5256 }
5257 uint8_t reg_width = (code_item->registers_size_ + 7) / 8;
5258
5259 /*
5260 * Decide if we need 8 or 16 bits to hold the address. Strictly speaking
5261 * we only need 16 bits if we actually encode an address >= 256 -- if
5262 * the method has a section at the end without GC points (e.g. array
5263 * data) we don't need to count it. The situation is unusual, and
5264 * detecting it requires scanning the entire method, so we don't bother.
5265 */
5266 RegisterMapFormat format;
5267 if (code_item->insns_size_ < 256) {
5268 format = kRegMapFormatCompact8;
5269 bytes_for_addr = 1;
5270 } else {
5271 format = kRegMapFormatCompact16;
5272 bytes_for_addr = 2;
5273 }
5274
5275 /*
5276 * Count up the number of GC point instructions.
5277 *
5278 * NOTE: this does not automatically include the first instruction,
5279 * since we don't count method entry as a GC point.
5280 */
5281 gc_point_count = 0;
5282 for (i = 0; i < (int) code_item->insns_size_; i++) {
5283 if (InsnIsGcPoint(vdata->insn_flags_.get(), i))
5284 gc_point_count++;
5285 }
5286 if (gc_point_count >= 65536) {
5287 /* We could handle this, but in practice we don't get near this. */
5288 LOG(ERROR) << "ERROR: register map can't handle " << gc_point_count
5289 << " gc points in one method";
5290 return NULL;
5291 }
5292
5293 /* Calculate size of buffer to hold the map data. */
5294 uint32_t data_size = gc_point_count * (bytes_for_addr + reg_width);
5295
5296 RegisterMap* map = new RegisterMap(format, reg_width, gc_point_count,
jeffhaoa0a764a2011-09-16 10:43:38 -07005297 data_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005298
5299 /* Populate it. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005300 uint8_t* map_data = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005301 for (i = 0; i < (int) vdata->code_item_->insns_size_; i++) {
5302 if (InsnIsGcPoint(vdata->insn_flags_.get(), i)) {
5303 assert(vdata->register_lines_[i].reg_types_.get() != NULL);
5304 if (format == kRegMapFormatCompact8) {
5305 *map_data++ = i;
5306 } else /*kRegMapFormatCompact16*/ {
5307 *map_data++ = i & 0xff;
5308 *map_data++ = i >> 8;
5309 }
5310 OutputTypeVector(vdata->register_lines_[i].reg_types_.get(),
5311 code_item->registers_size_, map_data);
5312 map_data += reg_width;
5313 }
5314 }
5315
jeffhaoe23d93c2011-09-15 14:48:43 -07005316 assert((uint32_t) map_data - (uint32_t) map->data_ == data_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005317
5318 // TODO: Remove this check when it's really running...
5319#if 1
5320 if (!VerifyMap(vdata, map)) {
5321 LOG(ERROR) << "Map failed to verify";
5322 return NULL;
5323 }
5324#endif
5325
5326 /* Try to compress the map. */
5327 RegisterMap* compress_map = CompressMapDifferential(map);
5328 if (compress_map != NULL) {
5329 // TODO: Remove this check when it's really running...
5330#if 1
5331 /*
5332 * Expand the compressed map we just created, and compare it
5333 * to the original. Abort the VM if it doesn't match up.
5334 */
5335 UniquePtr<RegisterMap> uncompressed_map(UncompressMapDifferential(compress_map));
5336 if (uncompressed_map.get() == NULL) {
5337 LOG(ERROR) << "Map failed to uncompress - "
5338 << vdata->method_->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5339 << "." << vdata->method_->GetName()->ToModifiedUtf8();
5340 delete map;
5341 delete compress_map;
5342 /* bad - compression is broken or we're out of memory */
5343 return NULL;
5344 } else {
5345 if (!CompareMaps(map, uncompressed_map.get())) {
5346 LOG(ERROR) << "Map comparison failed - "
5347 << vdata->method_->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5348 << "." << vdata->method_->GetName()->ToModifiedUtf8();
5349 delete map;
5350 delete compress_map;
5351 /* bad - compression is broken */
5352 return NULL;
5353 }
5354 }
5355#endif
5356 delete map;
5357 map = compress_map;
5358 }
5359
5360 return map;
5361}
5362
jeffhaoa0a764a2011-09-16 10:43:38 -07005363DexVerifier::RegisterMap* DexVerifier::GetExpandedRegisterMapHelper(
5364 Method* method, RegisterMap* map) {
5365 RegisterMap* new_map;
5366
5367 if (map == NULL)
5368 return NULL;
5369
5370 /* TODO: sanity check to ensure this isn't called w/o external locking */
5371
5372 uint8_t format = map->header_->format_;
5373 switch (format) {
5374 case kRegMapFormatCompact8:
5375 case kRegMapFormatCompact16:
5376 /* already expanded */
5377 return map;
5378 case kRegMapFormatDifferential:
5379 new_map = UncompressMapDifferential(map);
5380 break;
5381 default:
5382 LOG(ERROR) << "Unknown format " << format
5383 << " in dvmGetExpandedRegisterMap";
5384 return NULL;
5385 }
5386
5387 if (new_map == NULL) {
5388 LOG(ERROR) << "Map failed to uncompress (fmt=" << format << ") "
5389 << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5390 << "." << method->GetName();
5391 return NULL;
5392 }
5393
5394 /* Update method, and free compressed map if it was sitting on the heap. */
5395 ByteArray* header = ByteArray::Alloc(sizeof(RegisterMapHeader));
5396 ByteArray* data = ByteArray::Alloc(ComputeRegisterMapSize(map));
5397
5398 memcpy(header->GetData(), map->header_, sizeof(RegisterMapHeader));
5399 memcpy(data->GetData(), map->data_, ComputeRegisterMapSize(map));
5400
5401 method->SetRegisterMapHeader(header);
5402 method->SetRegisterMapData(data);
5403
5404 delete map;
5405 return new_map;
5406}
5407
5408const uint8_t* DexVerifier::RegisterMapGetLine(const RegisterMap* map, int addr) {
5409 int addr_width, line_width;
5410 uint8_t format = map->header_->format_;
5411 uint16_t num_entries = map->header_->num_entries_;
5412
5413 assert(num_entries > 0);
5414
5415 switch (format) {
5416 case kRegMapFormatNone:
5417 return NULL;
5418 case kRegMapFormatCompact8:
5419 addr_width = 1;
5420 break;
5421 case kRegMapFormatCompact16:
5422 addr_width = 2;
5423 break;
5424 default:
5425 LOG(ERROR) << "Unknown format " << format;
5426 return NULL;
5427 }
5428
5429 line_width = addr_width + map->header_->reg_width_;
5430
5431 /*
5432 * Find the appropriate entry. Many maps are very small, some are very large.
5433 */
5434 static const int kSearchThreshold = 8;
5435 const uint8_t* data = NULL;
5436 int line_addr;
5437
5438 if (num_entries < kSearchThreshold) {
5439 int i;
5440 data = map->data_;
5441 for (i = num_entries; i > 0; i--) {
5442 line_addr = data[0];
5443 if (addr_width > 1)
5444 line_addr |= data[1] << 8;
5445 if (line_addr == addr)
5446 return data + addr_width;
5447
5448 data += line_width;
5449 }
5450 assert(data == map->data_ + line_width * num_entries);
5451 } else {
5452 int hi, lo, mid;
5453
5454 lo = 0;
5455 hi = num_entries -1;
5456
5457 while (hi >= lo) {
5458 mid = (hi + lo) / 2;
5459 data = map->data_ + line_width * mid;
5460
5461 line_addr = data[0];
5462 if (addr_width > 1)
5463 line_addr |= data[1] << 8;
5464
5465 if (addr > line_addr) {
5466 lo = mid + 1;
5467 } else if (addr < line_addr) {
5468 hi = mid - 1;
5469 } else {
5470 return data + addr_width;
5471 }
5472 }
5473 }
5474
5475 return NULL;
5476}
5477
jeffhaod1f0fde2011-09-08 17:25:33 -07005478void DexVerifier::OutputTypeVector(const RegType* regs, int insn_reg_count,
5479 uint8_t* data) {
5480 uint8_t val = 0;
5481 int i;
5482
5483 for (i = 0; i < insn_reg_count; i++) {
5484 RegType type = *regs++;
5485 val >>= 1;
5486 if (IsReferenceType(type))
5487 val |= 0x80; /* set hi bit */
5488
5489 if ((i & 0x07) == 7)
5490 *data++ = val;
5491 }
5492 if ((i & 0x07) != 0) {
5493 /* Flush bits from last byte. */
5494 val >>= 8 - (i & 0x07);
5495 *data++ = val;
5496 }
5497}
5498
5499bool DexVerifier::VerifyMap(VerifierData* vdata, const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005500 const uint8_t* raw_map = map->data_;
5501 uint8_t format = map->header_->format_;
5502 const int num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005503 int ent;
5504
jeffhaoe23d93c2011-09-15 14:48:43 -07005505 if ((vdata->code_item_->registers_size_ + 7) / 8 != map->header_->reg_width_) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005506 LOG(ERROR) << "GLITCH: registersSize=" << vdata->code_item_->registers_size_
jeffhaoe23d93c2011-09-15 14:48:43 -07005507 << ", reg_width=" << map->header_->reg_width_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005508 return false;
5509 }
5510
5511 for (ent = 0; ent < num_entries; ent++) {
5512 int addr;
5513
5514 switch (format) {
5515 case kRegMapFormatCompact8:
5516 addr = *raw_map++;
5517 break;
5518 case kRegMapFormatCompact16:
5519 addr = *raw_map++;
5520 addr |= (*raw_map++) << 8;
5521 break;
5522 default:
5523 LOG(FATAL) << "GLITCH: bad format (" << format << ")";
5524 return false;
5525 }
5526
5527 const RegType* regs = vdata->register_lines_[addr].reg_types_.get();
5528 if (regs == NULL) {
5529 LOG(ERROR) << "GLITCH: addr " << addr << " has no data";
5530 return false;
5531 }
5532
5533 uint8_t val = 0;
5534 int i;
5535
5536 for (i = 0; i < vdata->code_item_->registers_size_; i++) {
5537 bool bit_is_ref, reg_is_ref;
5538
5539 val >>= 1;
5540 if ((i & 0x07) == 0) {
5541 /* Load next byte of data. */
5542 val = *raw_map++;
5543 }
5544
5545 bit_is_ref = val & 0x01;
5546
5547 RegType type = regs[i];
5548 reg_is_ref = IsReferenceType(type);
5549
5550 if (bit_is_ref != reg_is_ref) {
5551 LOG(ERROR) << "GLITCH: addr " << addr << " reg " << i << ": bit="
5552 << bit_is_ref << " reg=" << reg_is_ref << "(" << type << ")";
5553 return false;
5554 }
5555 }
5556 /* Raw_map now points to the address field of the next entry. */
5557 }
5558
5559 return true;
5560}
5561
5562bool DexVerifier::CompareMaps(const RegisterMap* map1, const RegisterMap* map2)
5563{
5564 size_t size1, size2;
5565
5566 size1 = ComputeRegisterMapSize(map1);
5567 size2 = ComputeRegisterMapSize(map2);
5568 if (size1 != size2) {
5569 LOG(ERROR) << "CompareMaps: size mismatch (" << size1 << " vs " << size2
5570 << ")";
5571 return false;
5572 }
5573
jeffhaoe23d93c2011-09-15 14:48:43 -07005574 if (map1->header_->format_ != map2->header_->format_ ||
5575 map1->header_->reg_width_ != map2->header_->reg_width_ ||
jeffhaoa0a764a2011-09-16 10:43:38 -07005576 map1->header_->num_entries_ != map2->header_->num_entries_) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005577 LOG(ERROR) << "CompareMaps: fields mismatch";
5578 }
jeffhaoe23d93c2011-09-15 14:48:43 -07005579 if (memcmp(map1->data_, map2->data_, size1) != 0) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005580 LOG(ERROR) << "CompareMaps: data mismatch";
5581 return false;
5582 }
5583
5584 return true;
5585}
5586
5587size_t DexVerifier::ComputeRegisterMapSize(const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005588 uint8_t format = map->header_->format_;
5589 uint16_t num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005590
5591 assert(map != NULL);
5592
5593 switch (format) {
5594 case kRegMapFormatNone:
5595 return 1;
5596 case kRegMapFormatCompact8:
jeffhaoe23d93c2011-09-15 14:48:43 -07005597 return (1 + map->header_->reg_width_) * num_entries;
jeffhaod1f0fde2011-09-08 17:25:33 -07005598 case kRegMapFormatCompact16:
jeffhaoe23d93c2011-09-15 14:48:43 -07005599 return (2 + map->header_->reg_width_) * num_entries;
jeffhaod1f0fde2011-09-08 17:25:33 -07005600 case kRegMapFormatDifferential:
5601 {
5602 /* Decoded ULEB128 length. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005603 const uint8_t* ptr = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005604 return DecodeUnsignedLeb128(&ptr);
5605 }
5606 default:
5607 LOG(FATAL) << "Bad register map format " << format;
5608 return 0;
5609 }
5610}
5611
5612int DexVerifier::ComputeBitDiff(const uint8_t* bits1, const uint8_t* bits2,
5613 int byte_width, int* first_bit_changed_ptr, int* num_bits_changed_ptr,
5614 uint8_t* leb_out_buf) {
5615 int num_bits_changed = 0;
5616 int first_bit_changed = -1;
5617 int leb_size = 0;
5618 int byte_num;
5619
5620 /*
5621 * Run through the vectors, first comparing them at the byte level. This
5622 * will yield a fairly quick result if nothing has changed between them.
5623 */
5624 for (byte_num = 0; byte_num < byte_width; byte_num++) {
5625 uint8_t byte1 = *bits1++;
5626 uint8_t byte2 = *bits2++;
5627 if (byte1 != byte2) {
5628 /* Walk through the byte, identifying the changed bits. */
5629 int bit_num;
5630 for (bit_num = 0; bit_num < 8; bit_num++) {
5631 if (((byte1 >> bit_num) & 0x01) != ((byte2 >> bit_num) & 0x01)) {
5632 int bit_offset = (byte_num << 3) + bit_num;
5633
5634 if (first_bit_changed < 0)
5635 first_bit_changed = bit_offset;
5636 num_bits_changed++;
5637
5638 if (leb_out_buf == NULL) {
5639 leb_size += UnsignedLeb128Size(bit_offset);
5640 } else {
5641 uint8_t* cur_buf = leb_out_buf;
5642 leb_out_buf = WriteUnsignedLeb128(leb_out_buf, bit_offset);
5643 leb_size += leb_out_buf - cur_buf;
5644 }
5645 }
5646 }
5647 }
5648 }
5649
5650 if (num_bits_changed > 0)
5651 assert(first_bit_changed >= 0);
5652
5653 if (first_bit_changed_ptr != NULL)
5654 *first_bit_changed_ptr = first_bit_changed;
5655 if (num_bits_changed_ptr != NULL)
5656 *num_bits_changed_ptr = num_bits_changed;
5657
5658 return leb_size;
5659}
5660
5661DexVerifier::RegisterMap* DexVerifier::CompressMapDifferential(
5662 const RegisterMap* map) {
5663 int orig_size = ComputeRegisterMapSize(map);
5664 uint8_t* tmp_ptr;
5665 int addr_width;
5666
jeffhaoe23d93c2011-09-15 14:48:43 -07005667 uint8_t format = map->header_->format_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005668 switch (format) {
5669 case kRegMapFormatCompact8:
5670 addr_width = 1;
5671 break;
5672 case kRegMapFormatCompact16:
5673 addr_width = 2;
5674 break;
5675 default:
5676 LOG(ERROR) << "ERROR: can't compress map with format=" << format;
5677 return NULL;
5678 }
5679
jeffhaoe23d93c2011-09-15 14:48:43 -07005680 int reg_width = map->header_->reg_width_;
5681 int num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005682
5683 if (num_entries <= 1) {
5684 return NULL;
5685 }
5686
5687 /*
5688 * We don't know how large the compressed data will be. It's possible
5689 * for it to expand and become larger than the original. The header
5690 * itself is variable-sized, so we generate everything into a temporary
5691 * buffer and then copy it to form-fitting storage once we know how big
5692 * it will be (and that it's smaller than the original).
5693 *
5694 * If we use a size that is equal to the size of the input map plus
5695 * a value longer than a single entry can possibly expand to, we need
5696 * only check for overflow at the end of each entry. The worst case
5697 * for a single line is (1 + <ULEB8 address> + <full copy of vector>).
5698 * Addresses are 16 bits, so that's (1 + 3 + reg_width).
5699 *
5700 * The initial address offset and bit vector will take up less than
5701 * or equal to the amount of space required when uncompressed -- large
5702 * initial offsets are rejected.
5703 */
5704 UniquePtr<uint8_t[]> tmp_buf(new uint8_t[orig_size + (1 + 3 + reg_width)]);
5705
5706 tmp_ptr = tmp_buf.get();
5707
jeffhaoe23d93c2011-09-15 14:48:43 -07005708 const uint8_t* map_data = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005709 const uint8_t* prev_bits;
5710 uint16_t addr, prev_addr;
5711
5712 addr = *map_data++;
5713 if (addr_width > 1)
5714 addr |= (*map_data++) << 8;
5715
5716 if (addr >= 128) {
5717 LOG(ERROR) << "Can't compress map with starting address >= 128";
5718 return NULL;
5719 }
5720
5721 /*
5722 * Start by writing the initial address and bit vector data. The high
5723 * bit of the initial address is used to indicate the required address
5724 * width (which the decoder can't otherwise determine without parsing
5725 * the compressed data).
5726 */
5727 *tmp_ptr++ = addr | (addr_width > 1 ? 0x80 : 0x00);
5728 memcpy(tmp_ptr, map_data, reg_width);
5729
5730 prev_bits = map_data;
5731 prev_addr = addr;
5732
5733 tmp_ptr += reg_width;
5734 map_data += reg_width;
5735
5736 /* Loop over all following entries. */
5737 for (int entry = 1; entry < num_entries; entry++) {
5738 int addr_diff;
5739 uint8_t key;
5740
5741 /* Pull out the address and figure out how to encode it. */
5742 addr = *map_data++;
5743 if (addr_width > 1)
5744 addr |= (*map_data++) << 8;
5745
5746 addr_diff = addr - prev_addr;
5747 assert(addr_diff > 0);
5748 if (addr_diff < 8) {
5749 /* Small difference, encode in 3 bits. */
5750 key = addr_diff -1; /* set 00000AAA */
5751 } else {
5752 /* Large difference, output escape code. */
5753 key = 0x07; /* escape code for AAA */
5754 }
5755
5756 int num_bits_changed, first_bit_changed, leb_size;
5757
5758 leb_size = ComputeBitDiff(prev_bits, map_data, reg_width,
5759 &first_bit_changed, &num_bits_changed, NULL);
5760
5761 if (num_bits_changed == 0) {
5762 /* set B to 1 and CCCC to zero to indicate no bits were changed */
5763 key |= 0x08;
5764 } else if (num_bits_changed == 1 && first_bit_changed < 16) {
5765 /* set B to 0 and CCCC to the index of the changed bit */
5766 key |= first_bit_changed << 4;
5767 } else if (num_bits_changed < 15 && leb_size < reg_width) {
5768 /* set B to 1 and CCCC to the number of bits */
5769 key |= 0x08 | (num_bits_changed << 4);
5770 } else {
5771 /* set B to 1 and CCCC to 0x0f so we store the entire vector */
5772 key |= 0x08 | 0xf0;
5773 }
5774
5775 /*
5776 * Encode output. Start with the key, follow with the address
5777 * diff (if it didn't fit in 3 bits), then the changed bit info.
5778 */
5779 *tmp_ptr++ = key;
5780 if ((key & 0x07) == 0x07)
5781 tmp_ptr = WriteUnsignedLeb128(tmp_ptr, addr_diff);
5782
5783 if ((key & 0x08) != 0) {
5784 int bit_count = key >> 4;
5785 if (bit_count == 0) {
5786 /* nothing changed, no additional output required */
5787 } else if (bit_count == 15) {
5788 /* full vector is most compact representation */
5789 memcpy(tmp_ptr, map_data, reg_width);
5790 tmp_ptr += reg_width;
5791 } else {
5792 /* write bit indices in ULEB128 format */
5793 (void) ComputeBitDiff(prev_bits, map_data, reg_width,
5794 NULL, NULL, tmp_ptr);
5795 tmp_ptr += leb_size;
5796 }
5797 } else {
5798 /* single-bit changed, value encoded in key byte */
5799 }
5800
5801 prev_bits = map_data;
5802 prev_addr = addr;
5803 map_data += reg_width;
5804
5805 /* See if we've run past the original size. */
5806 if (tmp_ptr - tmp_buf.get() >= orig_size) {
5807 return NULL;
5808 }
5809 }
5810
5811 /*
5812 * Create a RegisterMap with the contents.
5813 *
5814 * TODO: consider using a threshold other than merely ">=". We would
5815 * get poorer compression but potentially use less native heap space.
5816 */
5817 int new_data_size = tmp_ptr - tmp_buf.get();
5818 int new_map_size = new_data_size + UnsignedLeb128Size(new_data_size);
5819
5820 if (new_map_size >= orig_size) {
5821 return NULL;
5822 }
5823
5824 RegisterMap* new_map = new RegisterMap(kRegMapFormatDifferential, reg_width,
jeffhaoa0a764a2011-09-16 10:43:38 -07005825 num_entries, new_map_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005826
jeffhaoe23d93c2011-09-15 14:48:43 -07005827 tmp_ptr = new_map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005828 tmp_ptr = WriteUnsignedLeb128(tmp_ptr, new_data_size);
5829 memcpy(tmp_ptr, tmp_buf.get(), new_data_size);
5830
5831 return new_map;
5832}
5833
5834DexVerifier::RegisterMap* DexVerifier::UncompressMapDifferential(
5835 const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005836 uint8_t format = map->header_->format_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005837 RegisterMapFormat new_format;
5838 int reg_width, num_entries, new_addr_width, new_data_size;
5839
5840 if (format != kRegMapFormatDifferential) {
5841 LOG(ERROR) << "Not differential (" << format << ")";
5842 return NULL;
5843 }
5844
jeffhaoe23d93c2011-09-15 14:48:43 -07005845 reg_width = map->header_->reg_width_;
5846 num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005847
5848 /* Get the data size; we can check this at the end. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005849 const uint8_t* src_ptr = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005850 int expected_src_len = DecodeUnsignedLeb128(&src_ptr);
5851 const uint8_t* src_start = src_ptr;
5852
5853 /* Get the initial address and the 16-bit address flag. */
5854 int addr = *src_ptr & 0x7f;
5855 if ((*src_ptr & 0x80) == 0) {
5856 new_format = kRegMapFormatCompact8;
5857 new_addr_width = 1;
5858 } else {
5859 new_format = kRegMapFormatCompact16;
5860 new_addr_width = 2;
5861 }
5862 src_ptr++;
5863
5864 /* Now we know enough to allocate the new map. */
5865 new_data_size = (new_addr_width + reg_width) * num_entries;
5866 RegisterMap* new_map = new RegisterMap(new_format, reg_width, num_entries,
jeffhaoa0a764a2011-09-16 10:43:38 -07005867 new_data_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005868
5869 /* Write the start address and initial bits to the new map. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005870 uint8_t* dst_ptr = new_map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005871
5872 *dst_ptr++ = addr & 0xff;
5873 if (new_addr_width > 1)
5874 *dst_ptr++ = (uint8_t) (addr >> 8);
5875
5876 memcpy(dst_ptr, src_ptr, reg_width);
5877
5878 int prev_addr = addr;
5879 const uint8_t* prev_bits = dst_ptr; /* point at uncompressed data */
5880
5881 dst_ptr += reg_width;
5882 src_ptr += reg_width;
5883
5884 /* Walk through, uncompressing one line at a time. */
5885 int entry;
5886 for (entry = 1; entry < num_entries; entry++) {
5887 int addr_diff;
5888 uint8_t key;
5889
5890 key = *src_ptr++;
5891
5892 /* Get the address. */
5893 if ((key & 0x07) == 7) {
5894 /* Address diff follows in ULEB128. */
5895 addr_diff = DecodeUnsignedLeb128(&src_ptr);
5896 } else {
5897 addr_diff = (key & 0x07) +1;
5898 }
5899
5900 addr = prev_addr + addr_diff;
5901 *dst_ptr++ = addr & 0xff;
5902 if (new_addr_width > 1)
5903 *dst_ptr++ = (uint8_t) (addr >> 8);
5904
5905 /* Unpack the bits. */
5906 if ((key & 0x08) != 0) {
5907 int bit_count = (key >> 4);
5908 if (bit_count == 0) {
5909 /* No bits changed, just copy previous. */
5910 memcpy(dst_ptr, prev_bits, reg_width);
5911 } else if (bit_count == 15) {
5912 /* Full copy of bit vector is present; ignore prev_bits. */
5913 memcpy(dst_ptr, src_ptr, reg_width);
5914 src_ptr += reg_width;
5915 } else {
5916 /* Copy previous bits and modify listed indices. */
5917 memcpy(dst_ptr, prev_bits, reg_width);
5918 while (bit_count--) {
5919 int bit_index = DecodeUnsignedLeb128(&src_ptr);
5920 ToggleBit(dst_ptr, bit_index);
5921 }
5922 }
5923 } else {
5924 /* Copy previous bits and modify the specified one. */
5925 memcpy(dst_ptr, prev_bits, reg_width);
5926
5927 /* One bit, from 0-15 inclusive, was changed. */
5928 ToggleBit(dst_ptr, key >> 4);
5929 }
5930
5931 prev_addr = addr;
5932 prev_bits = dst_ptr;
5933 dst_ptr += reg_width;
5934 }
5935
jeffhaoe23d93c2011-09-15 14:48:43 -07005936 if (dst_ptr - new_map->data_ != new_data_size) {
5937 LOG(ERROR) << "ERROR: output " << dst_ptr - new_map->data_
jeffhaod1f0fde2011-09-08 17:25:33 -07005938 << " bytes, expected " << new_data_size;
5939 free(new_map);
5940 return NULL;
5941 }
5942
5943 if (src_ptr - src_start != expected_src_len) {
5944 LOG(ERROR) << "ERROR: consumed " << src_ptr - src_start
5945 << " bytes, expected " << expected_src_len;
5946 free(new_map);
5947 return NULL;
5948 }
5949
5950 return new_map;
5951}
5952
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07005953} // namespace art