blob: b6739f8302892caba597cb2046baad73f4e7bd22 [file] [log] [blame]
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07003#include "dex_verifier.h"
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07004
Elliott Hughes1f359b02011-07-17 14:27:17 -07005#include <iostream>
6
Brian Carlstrom1f870082011-08-23 16:02:11 -07007#include "class_linker.h"
8#include "dex_file.h"
9#include "dex_instruction.h"
10#include "dex_instruction_visitor.h"
jeffhaobdb76512011-09-07 11:43:16 -070011#include "dex_verifier.h"
Elliott Hughes1f359b02011-07-17 14:27:17 -070012#include "logging.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070013#include "runtime.h"
Elliott Hughes1f359b02011-07-17 14:27:17 -070014#include "stringpiece.h"
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070015
16namespace art {
17
jeffhaobdb76512011-09-07 11:43:16 -070018#define k_ kRegTypeUnknown
19#define kU kRegTypeUninit
20#define kX kRegTypeConflict
21#define k0 kRegTypeZero
22#define k1 kRegTypeOne
23#define kZ kRegTypeBoolean
24#define ky kRegTypeConstPosByte
25#define kY kRegTypeConstByte
26#define kh kRegTypeConstPosShort
27#define kH kRegTypeConstShort
28#define kc kRegTypeConstChar
29#define ki kRegTypeConstInteger
30#define kb kRegTypePosByte
31#define kB kRegTypeByte
32#define ks kRegTypePosShort
33#define kS kRegTypeShort
34#define kC kRegTypeChar
35#define kI kRegTypeInteger
36#define kF kRegTypeFloat
37#define kN kRegTypeConstLo
38#define kn kRegTypeConstHi
39#define kJ kRegTypeLongLo
40#define kj kRegTypeLongHi
41#define kD kRegTypeDoubleLo
42#define kd kRegTypeDoubleHi
43
44const char DexVerifier::merge_table_[kRegTypeMAX][kRegTypeMAX] =
45 {
46 /* chk: _ U X 0 1 Z y Y h H c i b B s S C I F N n J j D d */
47 { /*_*/ k_,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX },
48 { /*U*/ kX,kU,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX },
49 { /*X*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX },
50 { /*0*/ kX,kX,kX,k0,kZ,kZ,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
51 { /*1*/ kX,kX,kX,kZ,k1,kZ,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
52 { /*Z*/ kX,kX,kX,kZ,kZ,kZ,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
53 { /*y*/ kX,kX,kX,ky,ky,ky,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
54 { /*Y*/ kX,kX,kX,kY,kY,kY,kY,kY,kh,kH,kc,ki,kB,kB,kS,kS,kI,kI,kF,kX,kX,kX,kX,kX,kX },
55 { /*h*/ kX,kX,kX,kh,kh,kh,kh,kh,kh,kH,kc,ki,ks,kS,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
56 { /*H*/ kX,kX,kX,kH,kH,kH,kH,kH,kH,kH,kc,ki,kS,kS,kS,kS,kI,kI,kF,kX,kX,kX,kX,kX,kX },
57 { /*c*/ kX,kX,kX,kc,kc,kc,kc,kc,kc,kc,kc,ki,kC,kI,kC,kI,kC,kI,kF,kX,kX,kX,kX,kX,kX },
58 { /*i*/ kX,kX,kX,ki,ki,ki,ki,ki,ki,ki,ki,ki,kI,kI,kI,kI,kI,kI,kF,kX,kX,kX,kX,kX,kX },
59 { /*b*/ kX,kX,kX,kb,kb,kb,kb,kB,ks,kS,kC,kI,kb,kB,ks,kS,kC,kI,kX,kX,kX,kX,kX,kX,kX },
60 { /*B*/ kX,kX,kX,kB,kB,kB,kB,kB,kS,kS,kI,kI,kB,kB,kS,kS,kI,kI,kX,kX,kX,kX,kX,kX,kX },
61 { /*s*/ kX,kX,kX,ks,ks,ks,ks,kS,ks,kS,kC,kI,ks,kS,ks,kS,kC,kI,kX,kX,kX,kX,kX,kX,kX },
62 { /*S*/ kX,kX,kX,kS,kS,kS,kS,kS,kS,kS,kI,kI,kS,kS,kS,kS,kI,kI,kX,kX,kX,kX,kX,kX,kX },
63 { /*C*/ kX,kX,kX,kC,kC,kC,kC,kI,kC,kI,kC,kI,kC,kI,kC,kI,kC,kI,kX,kX,kX,kX,kX,kX,kX },
64 { /*I*/ kX,kX,kX,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kX,kX,kX,kX,kX,kX,kX },
65 { /*F*/ kX,kX,kX,kF,kF,kF,kF,kF,kF,kF,kF,kF,kX,kX,kX,kX,kX,kX,kF,kX,kX,kX,kX,kX,kX },
66 { /*N*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kN,kX,kJ,kX,kD,kX },
67 { /*n*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kn,kX,kj,kX,kd },
68 { /*J*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kJ,kX,kJ,kX,kX,kX },
69 { /*j*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kj,kX,kj,kX,kX },
70 { /*D*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kD,kX,kX,kX,kD,kX },
71 { /*d*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kd,kX,kX,kX,kd },
72 };
73
74#undef k_
75#undef kU
76#undef kX
77#undef k0
78#undef k1
79#undef kZ
80#undef ky
81#undef kY
82#undef kh
83#undef kH
84#undef kc
85#undef ki
86#undef kb
87#undef kB
88#undef ks
89#undef kS
90#undef kC
91#undef kI
92#undef kF
93#undef kN
94#undef kn
95#undef kJ
96#undef kj
97#undef kD
98#undef kd
99
100bool DexVerifier::VerifyClass(Class* klass) {
101 if (klass->IsVerified()) {
102 return true;
103 }
104 for (size_t i = 0; i < klass->NumDirectMethods(); ++i) {
105 Method* method = klass->GetDirectMethod(i);
106 if (!VerifyMethod(method)) {
jeffhao98eacac2011-09-14 16:11:53 -0700107 LOG(ERROR) << "Verifier rejected class "
108 << klass->GetDescriptor()->ToModifiedUtf8();
jeffhaobdb76512011-09-07 11:43:16 -0700109 return false;
110 }
111 }
112 for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
113 Method* method = klass->GetVirtualMethod(i);
114 if (!VerifyMethod(method)) {
jeffhao98eacac2011-09-14 16:11:53 -0700115 LOG(ERROR) << "Verifier rejected class "
116 << klass->GetDescriptor()->ToModifiedUtf8();
jeffhaobdb76512011-09-07 11:43:16 -0700117 return false;
118 }
119 }
120 return true;
jeffhaoba5ebb92011-08-25 17:24:37 -0700121}
122
jeffhaobdb76512011-09-07 11:43:16 -0700123bool DexVerifier::VerifyMethod(Method* method) {
124 const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
125 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
126 const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700127 const DexFile::CodeItem* code_item =
jeffhaobdb76512011-09-07 11:43:16 -0700128 dex_file.GetCodeItem(method->GetCodeItemOffset());
129
130 /*
131 * Construct the verifier state container object.
132 */
133 VerifierData vdata(method, &dex_file, code_item);
134
135 /*
136 * If there aren't any instructions, make sure that's expected, then
137 * exit successfully.
138 */
139 if (code_item == NULL) {
140 if (!method->IsNative() && !method->IsAbstract()) {
141 LOG(ERROR) << "VFY: zero-length code in concrete non-native method";
142 return false;
143 }
144 return true;
145 }
146
147 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700148 * Sanity-check the register counts. ins + locals = registers, so make
jeffhaobdb76512011-09-07 11:43:16 -0700149 * sure that ins <= registers.
150 */
151 if (code_item->ins_size_ > code_item->registers_size_) {
152 LOG(ERROR) << "VFY: bad register counts (ins=" << code_item->ins_size_
153 << " regs=" << code_item->registers_size_;
154 return false;
155 }
156
157 /*
158 * Allocate and initialize an array to hold instruction data.
159 */
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700160 vdata.insn_flags_.reset(new InsnFlags[code_item->insns_size_]());
jeffhaobdb76512011-09-07 11:43:16 -0700161
162 /*
163 * Run through the instructions and see if the width checks out.
164 */
165 if (!ComputeWidthsAndCountOps(&vdata)) {
166 return false;
167 }
168
169 /*
170 * Flag instructions guarded by a "try" block and check exception handlers.
171 */
172 if (!ScanTryCatchBlocks(&vdata)) {
173 return false;
174 }
175
176 /*
177 * Perform static instruction verification.
178 */
179 if (!VerifyInstructions(&vdata)) {
180 return false;
181 }
182
183 /*
184 * Perform code flow analysis.
185 */
186 if (!VerifyCodeFlow(&vdata)) {
187 return false;
188 }
189
190 return true;
jeffhaoba5ebb92011-08-25 17:24:37 -0700191}
192
jeffhaobdb76512011-09-07 11:43:16 -0700193bool DexVerifier::VerifyInstructions(VerifierData* vdata) {
194 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700195 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700196 const byte* ptr = reinterpret_cast<const byte*>(code_item->insns_);
197 const Instruction* inst = Instruction::At(ptr);
198
199 /* Flag the start of the method as a branch target. */
200 InsnSetBranchTarget(insn_flags, 0);
201
202 uint32_t width = 0;
203 uint32_t insns_size = code_item->insns_size_;
204
205 while (width < insns_size) {
206 if (!VerifyInstruction(vdata, inst, width)) {
jeffhaod1f0fde2011-09-08 17:25:33 -0700207 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
jeffhaobdb76512011-09-07 11:43:16 -0700208 << (int) inst->Opcode() << " at 0x" << width << std::dec;
209 return false;
210 }
211
212 /* Flag instructions that are garbage collection points */
213 if (inst->IsBranch() || inst->IsSwitch() || inst->IsThrow() ||
214 inst->IsReturn()) {
215 InsnSetGcPoint(insn_flags, width);
216 }
217
218 width += inst->Size();
219 inst = inst->Next();
220 }
221 return true;
jeffhaoba5ebb92011-08-25 17:24:37 -0700222}
223
jeffhaobdb76512011-09-07 11:43:16 -0700224bool DexVerifier::VerifyInstruction(VerifierData* vdata,
225 const Instruction* inst, uint32_t code_offset) {
226 const DexFile* dex_file = vdata->dex_file_;
227 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700228 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700229 Instruction::DecodedInstruction dec_insn(inst);
230 bool result = true;
231
232 int argumentA = inst->GetVerifyTypeArgumentA();
233 int argumentB = inst->GetVerifyTypeArgumentB();
234 int argumentC = inst->GetVerifyTypeArgumentC();
235 int extra_flags = inst->GetVerifyExtraFlags();
236
237 switch (argumentA) {
238 case Instruction::kVerifyRegA:
239 result &= CheckRegisterIndex(code_item, dec_insn.vA_);
240 break;
241 case Instruction::kVerifyRegAWide:
242 result &= CheckWideRegisterIndex(code_item, dec_insn.vA_);
243 break;
244 }
245
246 switch (argumentB) {
247 case Instruction::kVerifyRegB:
248 result &= CheckRegisterIndex(code_item, dec_insn.vB_);
249 break;
250 case Instruction::kVerifyRegBField:
251 result &= CheckFieldIndex(dex_file, dec_insn.vB_);
252 break;
253 case Instruction::kVerifyRegBMethod:
254 result &= CheckMethodIndex(dex_file, dec_insn.vB_);
255 break;
256 case Instruction::kVerifyRegBNewInstance:
257 result &= CheckNewInstance(dex_file, dec_insn.vB_);
258 break;
259 case Instruction::kVerifyRegBString:
260 result &= CheckStringIndex(dex_file, dec_insn.vB_);
261 break;
262 case Instruction::kVerifyRegBType:
263 result &= CheckTypeIndex(dex_file, dec_insn.vB_);
264 break;
265 case Instruction::kVerifyRegBWide:
266 result &= CheckWideRegisterIndex(code_item, dec_insn.vB_);
267 break;
268 }
269
270 switch (argumentC) {
271 case Instruction::kVerifyRegC:
272 result &= CheckRegisterIndex(code_item, dec_insn.vC_);
273 break;
274 case Instruction::kVerifyRegCField:
275 result &= CheckFieldIndex(dex_file, dec_insn.vC_);
276 break;
277 case Instruction::kVerifyRegCNewArray:
278 result &= CheckNewArray(dex_file, dec_insn.vC_);
279 break;
280 case Instruction::kVerifyRegCType:
281 result &= CheckTypeIndex(dex_file, dec_insn.vC_);
282 break;
283 case Instruction::kVerifyRegCWide:
284 result &= CheckWideRegisterIndex(code_item, dec_insn.vC_);
285 break;
286 }
287
288 switch (extra_flags) {
289 case Instruction::kVerifyArrayData:
290 result &= CheckArrayData(code_item, code_offset);
291 break;
292 case Instruction::kVerifyBranchTarget:
293 result &= CheckBranchTarget(code_item, insn_flags, code_offset);
294 break;
295 case Instruction::kVerifySwitchTargets:
296 result &= CheckSwitchTargets(code_item, insn_flags, code_offset);
297 break;
298 case Instruction::kVerifyVarArg:
299 result &= CheckVarArgRegs(code_item, dec_insn.vA_, dec_insn.arg_);
300 break;
301 case Instruction::kVerifyVarArgRange:
302 result &= CheckVarArgRangeRegs(code_item, dec_insn.vA_, dec_insn.vC_);
303 break;
304 case Instruction::kVerifyError:
305 LOG(ERROR) << "VFY: unexpected opcode " << std::hex
306 << (int) dec_insn.opcode_ << std::dec;
307 result = false;
308 break;
309 }
310
311 return result;
jeffhaoba5ebb92011-08-25 17:24:37 -0700312}
313
jeffhaobdb76512011-09-07 11:43:16 -0700314bool DexVerifier::VerifyCodeFlow(VerifierData* vdata) {
315 Method* method = vdata->method_;
316 const DexFile::CodeItem* code_item = vdata->code_item_;
317 uint16_t registers_size = code_item->registers_size_;
318 uint32_t insns_size = code_item->insns_size_;
jeffhaod1f0fde2011-09-08 17:25:33 -0700319 bool generate_register_map = true;
jeffhaobdb76512011-09-07 11:43:16 -0700320 RegisterTable reg_table;
jeffhaoba5ebb92011-08-25 17:24:37 -0700321
jeffhaobdb76512011-09-07 11:43:16 -0700322 if (registers_size * insns_size > 4*1024*1024) {
323 LOG(ERROR) << "VFY: warning: method is huge (regs=" << registers_size
324 << " insns_size=" << insns_size << ")";
325 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700326
jeffhaobdb76512011-09-07 11:43:16 -0700327 /* Create and initialize register lists. */
jeffhaod1f0fde2011-09-08 17:25:33 -0700328 if (!InitRegisterTable(vdata, &reg_table,
329 generate_register_map ? kTrackRegsGcPoints : kTrackRegsBranches)) {
jeffhaobdb76512011-09-07 11:43:16 -0700330 return false;
331 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700332
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700333 vdata->register_lines_ = reg_table.register_lines_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700334
335 /* Allocate a map to hold the classes of uninitialized instances. */
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700336 vdata->uninit_map_.reset(CreateUninitInstanceMap(vdata));
jeffhaobdb76512011-09-07 11:43:16 -0700337
338 /* Initialize register types of method arguments. */
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700339 if (!SetTypesFromSignature(vdata, reg_table.register_lines_[0].reg_types_.get())) {
jeffhaobdb76512011-09-07 11:43:16 -0700340 LOG(ERROR) << "VFY: bad signature '"
341 << method->GetSignature()->ToModifiedUtf8() << "' for "
342 << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
343 << "." << method->GetName()->ToModifiedUtf8();
344 return false;
345 }
346
347 /* Perform code flow verification. */
348 if (!CodeFlowVerifyMethod(vdata, &reg_table)) {
349 return false;
350 }
351
jeffhaod1f0fde2011-09-08 17:25:33 -0700352 /* Generate a register map. */
353 if (generate_register_map) {
jeffhaoe23d93c2011-09-15 14:48:43 -0700354 UniquePtr<RegisterMap> map(GenerateRegisterMapV(vdata));
jeffhaod1f0fde2011-09-08 17:25:33 -0700355 /*
356 * Tuck the map into the Method. It will either get used directly or, if
357 * we're in dexopt, will be packed up and appended to the DEX file.
358 */
jeffhaoe23d93c2011-09-15 14:48:43 -0700359 ByteArray* header = ByteArray::Alloc(sizeof(RegisterMapHeader));
360 ByteArray* data = ByteArray::Alloc(ComputeRegisterMapSize(map.get()));
361
362 memcpy(header->GetData(), map.get()->header_, sizeof(RegisterMapHeader));
363 memcpy(data->GetData(), map.get()->data_, ComputeRegisterMapSize(map.get()));
364
365 method->SetRegisterMapHeader(header);
366 method->SetRegisterMapData(data);
jeffhaod1f0fde2011-09-08 17:25:33 -0700367 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700368
jeffhaobdb76512011-09-07 11:43:16 -0700369 return true;
370}
371
372bool DexVerifier::ComputeWidthsAndCountOps(VerifierData* vdata) {
373 const uint16_t* insns = vdata->code_item_->insns_;
374 uint32_t insns_size = vdata->code_item_->insns_size_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700375 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700376 const byte* ptr = reinterpret_cast<const byte*>(insns);
377 const Instruction* inst = Instruction::At(ptr);
378 size_t new_instance_count = 0;
379 size_t monitor_enter_count = 0;
380 size_t width = 0;
381
382 while (width < insns_size) {
383 Instruction::Code opcode = inst->Opcode();
384 if (opcode == Instruction::NEW_INSTANCE) {
385 new_instance_count++;
386 } else if (opcode == Instruction::MONITOR_ENTER) {
387 monitor_enter_count++;
388 }
389
390 insn_flags[width] |= inst->Size();
391 width += inst->Size();
392 inst = inst->Next();
393 }
394
395 if (width != insns_size) {
396 LOG(ERROR) << "VFY: code did not end where expected (" << width << " vs. "
397 << insns_size << ")";
398 return false;
399 }
400
401 vdata->new_instance_count_ = new_instance_count;
402 vdata->monitor_enter_count_ = monitor_enter_count;
403 return true;
404}
405
406bool DexVerifier::ScanTryCatchBlocks(VerifierData* vdata) {
407 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700408 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700409 uint32_t insns_size = code_item->insns_size_;
410 uint32_t tries_size = code_item->tries_size_;
411
412 if (tries_size == 0) {
413 return true;
414 }
415
416 const DexFile::TryItem* tries = DexFile::dexGetTryItems(*code_item, 0);
417
418 for (uint32_t idx = 0; idx < tries_size; idx++) {
419 const DexFile::TryItem* try_item = &tries[idx];
420 uint32_t start = try_item->start_addr_;
421 uint32_t end = start + try_item->insn_count_;
422
423 if ((start >= end) || (start >= insns_size) || (end > insns_size)) {
424 LOG(ERROR) << "VFY: bad exception entry: startAddr=" << start
425 << " endAddr=" << end << " (size=" << insns_size << ")";
426 return false;
427 }
428
429 if (InsnGetWidth(insn_flags, start) == 0) {
430 LOG(ERROR) << "VFY: 'try' block starts inside an instruction ("
431 << start << ")";
432 return false;
433 }
434
435 uint32_t addr;
436 for (addr = start; addr < end; addr += InsnGetWidth(insn_flags, addr)) {
437 InsnSetInTry(insn_flags, addr);
438 }
439 }
440
441 /* Iterate over each of the handlers to verify target addresses. */
442 const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item, 0);
443 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
444 for (uint32_t idx = 0; idx < handlers_size; idx++) {
445 DexFile::CatchHandlerIterator iterator(handlers_ptr);
446
447 for (; !iterator.HasNext(); iterator.Next()) {
448 uint32_t addr = iterator.Get().address_;
449 if (InsnGetWidth(insn_flags, addr) == 0) {
450 LOG(ERROR) << "VFY: exception handler starts at bad address ("
451 << addr << ")";
452 return false;
453 }
454
455 InsnSetBranchTarget(insn_flags, addr);
456 }
457
458 handlers_ptr = iterator.GetData();
459 }
460
461 return true;
462}
463
464bool DexVerifier::GetBranchOffset(const DexFile::CodeItem* code_item,
465 const InsnFlags insn_flags[], uint32_t cur_offset, int32_t* pOffset,
jeffhaoba5ebb92011-08-25 17:24:37 -0700466 bool* pConditional, bool* selfOkay) {
467 const uint16_t* insns = code_item->insns_ + cur_offset;
468
469 switch (*insns & 0xff) {
470 case Instruction::GOTO:
471 *pOffset = ((int16_t) *insns) >> 8;
472 *pConditional = false;
473 *selfOkay = false;
474 break;
475 case Instruction::GOTO_32:
476 *pOffset = insns[1] | (((uint32_t) insns[2]) << 16);
477 *pConditional = false;
478 *selfOkay = true;
479 break;
480 case Instruction::GOTO_16:
481 *pOffset = (int16_t) insns[1];
482 *pConditional = false;
483 *selfOkay = false;
484 break;
485 case Instruction::IF_EQ:
486 case Instruction::IF_NE:
487 case Instruction::IF_LT:
488 case Instruction::IF_GE:
489 case Instruction::IF_GT:
490 case Instruction::IF_LE:
491 case Instruction::IF_EQZ:
492 case Instruction::IF_NEZ:
493 case Instruction::IF_LTZ:
494 case Instruction::IF_GEZ:
495 case Instruction::IF_GTZ:
496 case Instruction::IF_LEZ:
497 *pOffset = (int16_t) insns[1];
498 *pConditional = true;
499 *selfOkay = false;
500 break;
501 default:
502 return false;
503 break;
504 }
505
506 return true;
507}
508
jeffhaobdb76512011-09-07 11:43:16 -0700509bool DexVerifier::CheckArrayData(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700510 uint32_t cur_offset) {
511 const uint32_t insn_count = code_item->insns_size_;
512 const uint16_t* insns = code_item->insns_ + cur_offset;
513 const uint16_t* array_data;
514 int32_t array_data_offset;
515
516 assert(cur_offset < insn_count);
517
518 /* make sure the start of the array data table is in range */
519 array_data_offset = insns[1] | (((int32_t) insns[2]) << 16);
520 if ((int32_t) cur_offset + array_data_offset < 0 ||
521 cur_offset + array_data_offset + 2 >= insn_count)
522 {
523 LOG(ERROR) << "VFY: invalid array data start: at " << cur_offset
524 << ", data offset " << array_data_offset << ", count "
525 << insn_count;
526 return false;
527 }
528
529 /* offset to array data table is a relative branch-style offset */
530 array_data = insns + array_data_offset;
531
532 /* make sure the table is 32-bit aligned */
533 if ((((uint32_t) array_data) & 0x03) != 0) {
534 LOG(ERROR) << "VFY: unaligned array data table: at " << cur_offset
535 << ", data offset " << array_data_offset;
536 return false;
537 }
538
539 uint32_t value_width = array_data[1];
540 uint32_t value_count = *(uint32_t*) (&array_data[2]);
541 uint32_t table_size = 4 + (value_width * value_count + 1) / 2;
542
543 /* make sure the end of the switch is in range */
544 if (cur_offset + array_data_offset + table_size > insn_count) {
545 LOG(ERROR) << "VFY: invalid array data end: at " << cur_offset
546 << ", data offset " << array_data_offset << ", end "
547 << cur_offset + array_data_offset + table_size << ", count "
548 << insn_count;
549 return false;
550 }
551
552 return true;
553}
554
jeffhaobdb76512011-09-07 11:43:16 -0700555bool DexVerifier::CheckNewInstance(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700556 if (idx >= dex_file->GetHeader().type_ids_size_) {
557 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
558 << dex_file->GetHeader().type_ids_size_ << ")";
559 return false;
560 }
561
562 const char* descriptor = dex_file->dexStringByTypeIdx(idx);
563 if (descriptor[0] != 'L') {
564 LOG(ERROR) << "VFY: can't call new-instance on type '"
565 << descriptor << "'";
566 return false;
567 }
568
569 return true;
570}
571
jeffhaobdb76512011-09-07 11:43:16 -0700572bool DexVerifier::CheckNewArray(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700573 if (idx >= dex_file->GetHeader().type_ids_size_) {
574 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
575 << dex_file->GetHeader().type_ids_size_ << ")";
576 return false;
577 }
578
579 int bracket_count = 0;
580 const char* descriptor = dex_file->dexStringByTypeIdx(idx);
581 const char* cp = descriptor;
582 while (*cp++ == '[')
583 bracket_count++;
584
585 if (bracket_count == 0) {
586 /* The given class must be an array type. */
587 LOG(ERROR) << "VFY: can't new-array class '" << descriptor
588 << "' (not an array)";
589 return false;
590 } else if (bracket_count > 255) {
591 /* It is illegal to create an array of more than 255 dimensions. */
592 LOG(ERROR) << "VFY: can't new-array class '" << descriptor
593 << "' (exceeds limit)";
594 return false;
595 }
596
597 return true;
598}
599
jeffhaobdb76512011-09-07 11:43:16 -0700600bool DexVerifier::CheckTypeIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700601 if (idx >= dex_file->GetHeader().type_ids_size_) {
602 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
603 << dex_file->GetHeader().type_ids_size_ << ")";
604 return false;
605 }
606 return true;
607}
608
jeffhaobdb76512011-09-07 11:43:16 -0700609bool DexVerifier::CheckFieldIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700610 if (idx >= dex_file->GetHeader().field_ids_size_) {
611 LOG(ERROR) << "VFY: bad field index " << idx << " (max "
612 << dex_file->GetHeader().field_ids_size_ << ")";
613 return false;
614 }
615 return true;
616}
617
jeffhaobdb76512011-09-07 11:43:16 -0700618bool DexVerifier::CheckMethodIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700619 if (idx >= dex_file->GetHeader().method_ids_size_) {
620 LOG(ERROR) << "VFY: bad method index " << idx << " (max "
621 << dex_file->GetHeader().method_ids_size_ << ")";
622 return false;
623 }
624 return true;
625}
626
jeffhaobdb76512011-09-07 11:43:16 -0700627bool DexVerifier::CheckStringIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700628 if (idx >= dex_file->GetHeader().string_ids_size_) {
629 LOG(ERROR) << "VFY: bad string index " << idx << " (max "
630 << dex_file->GetHeader().string_ids_size_ << ")";
631 return false;
632 }
633 return true;
634}
635
jeffhaobdb76512011-09-07 11:43:16 -0700636bool DexVerifier::CheckRegisterIndex(const DexFile::CodeItem* code_item,
637 uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700638 if (idx >= code_item->registers_size_) {
639 LOG(ERROR) << "VFY: register index out of range (" << idx << " >= "
640 << code_item->registers_size_ << ")";
641 return false;
642 }
643 return true;
644}
645
jeffhaobdb76512011-09-07 11:43:16 -0700646bool DexVerifier::CheckWideRegisterIndex(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700647 uint32_t idx) {
648 if (idx + 1 >= code_item->registers_size_) {
649 LOG(ERROR) << "VFY: wide register index out of range (" << idx
650 << "+1 >= " << code_item->registers_size_ << ")";
651 return false;
652 }
653 return true;
654}
655
jeffhaobdb76512011-09-07 11:43:16 -0700656bool DexVerifier::CheckVarArgRegs(const DexFile::CodeItem* code_item,
657 uint32_t vA, uint32_t arg[]) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700658 uint16_t registers_size = code_item->registers_size_;
659 uint32_t idx;
660
661 if (vA > 5) {
662 LOG(ERROR) << "VFY: invalid arg count (" << vA << ") in non-range invoke)";
663 return false;
664 }
665
666 for (idx = 0; idx < vA; idx++) {
667 if (arg[idx] > registers_size) {
668 LOG(ERROR) << "VFY: invalid reg index (" << arg[idx]
669 << ") in non-range invoke (> " << registers_size << ")";
670 return false;
671 }
672 }
673
674 return true;
675}
676
jeffhaobdb76512011-09-07 11:43:16 -0700677bool DexVerifier::CheckVarArgRangeRegs(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700678 uint32_t vA, uint32_t vC) {
679 uint16_t registers_size = code_item->registers_size_;
680
681 /*
682 * vA/vC are unsigned 8-bit/16-bit quantities for /range instructions,
683 * so there's no risk of integer overflow when adding them here.
684 */
685 if (vA + vC > registers_size) {
686 LOG(ERROR) << "VFY: invalid reg index " << vA << "+" << vC
687 << " in range invoke (> " << registers_size << ")";
688 return false;
689 }
690
691 return true;
692}
693
jeffhaobdb76512011-09-07 11:43:16 -0700694bool DexVerifier::CheckSwitchTargets(const DexFile::CodeItem* code_item,
695 InsnFlags insn_flags[], uint32_t cur_offset) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700696 const uint32_t insn_count = code_item->insns_size_;
697 const uint16_t* insns = code_item->insns_ + cur_offset;
698 const uint16_t* switch_insns;
699 uint16_t expected_signature;
700 uint32_t switch_count, table_size;
701 int32_t switch_offset, keys_offset, targets_offset;
702 int32_t offset, abs_offset;
703 uint32_t targ;
704
705 /* make sure the start of the switch is in range */
706 switch_offset = insns[1] | ((int32_t) insns[2]) << 16;
707 if ((int32_t) cur_offset + switch_offset < 0 ||
708 cur_offset + switch_offset + 2 >= insn_count) {
709 LOG(ERROR) << "VFY: invalid switch start: at " << cur_offset
710 << ", switch offset " << switch_offset << ", count "
711 << insn_count;
712 return false;
713 }
714
715 /* offset to switch table is a relative branch-style offset */
716 switch_insns = insns + switch_offset;
717
718 /* make sure the table is 32-bit aligned */
719 if ((((uint32_t) switch_insns) & 0x03) != 0) {
720 LOG(ERROR) << "VFY: unaligned switch table: at " << cur_offset
721 << ", switch offset " << switch_offset;
722 return false;
723 }
724
725 switch_count = switch_insns[1];
726
727 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
728 /* 0=sig, 1=count, 2/3=firstKey */
729 targets_offset = 4;
730 keys_offset = -1;
731 expected_signature = Instruction::kPackedSwitchSignature;
732 } else {
733 /* 0=sig, 1=count, 2..count*2 = keys */
734 keys_offset = 2;
735 targets_offset = 2 + 2 * switch_count;
736 expected_signature = Instruction::kSparseSwitchSignature;
737 }
738 table_size = targets_offset + switch_count * 2;
739
740 if (switch_insns[0] != expected_signature) {
jeffhaobdb76512011-09-07 11:43:16 -0700741 LOG(ERROR) << "VFY: wrong signature for switch table (0x" << std::hex
742 << switch_insns[0] << ", wanted 0x" << expected_signature << ")"
743 << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700744 return false;
745 }
746
747 /* make sure the end of the switch is in range */
748 if (cur_offset + switch_offset + table_size > (uint32_t) insn_count) {
749 LOG(ERROR) << "VFY: invalid switch end: at " << cur_offset
750 << ", switch offset " << switch_offset << ", end "
751 << cur_offset + switch_offset + table_size << ", count "
752 << insn_count;
753 return false;
754 }
755
756 /* for a sparse switch, verify the keys are in ascending order */
757 if (keys_offset > 0 && switch_count > 1) {
758 int32_t last_key;
759
760 last_key = switch_insns[keys_offset] |
761 (switch_insns[keys_offset + 1] << 16);
762 for (targ = 1; targ < switch_count; targ++) {
763 int32_t key = (int32_t) switch_insns[keys_offset + targ * 2] |
764 (int32_t) (switch_insns[keys_offset + targ * 2 + 1] << 16);
765 if (key <= last_key) {
766 LOG(ERROR) << "VFY: invalid packed switch: last key=" << last_key
767 << ", this=" << key;
768 return false;
769 }
770
771 last_key = key;
772 }
773 }
774
775 /* verify each switch target */
776 for (targ = 0; targ < switch_count; targ++) {
777 offset = (int32_t) switch_insns[targets_offset + targ * 2] |
778 (int32_t) (switch_insns[targets_offset + targ * 2 + 1] << 16);
779 abs_offset = cur_offset + offset;
780
781 if (abs_offset < 0 || abs_offset >= (int32_t) insn_count ||
782 !InsnIsOpcode(insn_flags, abs_offset)) {
783 LOG(ERROR) << "VFY: invalid switch target " << offset << " (-> "
jeffhaobdb76512011-09-07 11:43:16 -0700784 << std::hex << abs_offset << ") at " << cur_offset << std::dec
785 << "[" << targ << "]";
jeffhaoba5ebb92011-08-25 17:24:37 -0700786 return false;
787 }
jeffhaobdb76512011-09-07 11:43:16 -0700788 InsnSetBranchTarget(insn_flags, abs_offset);
jeffhaoba5ebb92011-08-25 17:24:37 -0700789 }
790
791 return true;
792}
793
jeffhaobdb76512011-09-07 11:43:16 -0700794bool DexVerifier::CheckBranchTarget(const DexFile::CodeItem* code_item,
795 InsnFlags insn_flags[], uint32_t cur_offset) {
796 const uint32_t insn_count = code_item->insns_size_;
jeffhaoba5ebb92011-08-25 17:24:37 -0700797 int32_t offset, abs_offset;
798 bool isConditional, selfOkay;
799
800 if (!GetBranchOffset(code_item, insn_flags, cur_offset, &offset,
801 &isConditional, &selfOkay))
802 return false;
803
804 if (!selfOkay && offset == 0) {
jeffhaobdb76512011-09-07 11:43:16 -0700805 LOG(ERROR) << "VFY: branch offset of zero not allowed at" << std::hex
806 << cur_offset << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700807 return false;
808 }
809
810 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700811 * Check for 32-bit overflow. This isn't strictly necessary if we can
jeffhaoba5ebb92011-08-25 17:24:37 -0700812 * depend on the VM to have identical "wrap-around" behavior, but
813 * it's unwise to depend on that.
814 */
815 if (((int64_t) cur_offset + (int64_t) offset) !=
jeffhaobdb76512011-09-07 11:43:16 -0700816 (int64_t) (cur_offset + offset)) {
817 LOG(ERROR) << "VFY: branch target overflow " << std::hex << cur_offset
818 << std::dec << " +" << offset;
jeffhaoba5ebb92011-08-25 17:24:37 -0700819 return false;
820 }
821 abs_offset = cur_offset + offset;
jeffhaobdb76512011-09-07 11:43:16 -0700822 if (abs_offset < 0 || (uint32_t) abs_offset >= insn_count ||
jeffhaoba5ebb92011-08-25 17:24:37 -0700823 !InsnIsOpcode(insn_flags, abs_offset))
824 {
825 LOG(ERROR) << "VFY: invalid branch target " << offset << " (-> "
jeffhaobdb76512011-09-07 11:43:16 -0700826 << std::hex << abs_offset << ") at " << cur_offset << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700827 return false;
828 }
jeffhaobdb76512011-09-07 11:43:16 -0700829 InsnSetBranchTarget(insn_flags, abs_offset);
jeffhaoba5ebb92011-08-25 17:24:37 -0700830
831 return true;
832}
833
jeffhaobdb76512011-09-07 11:43:16 -0700834bool DexVerifier::InitRegisterTable(VerifierData* vdata,
835 RegisterTable* reg_table, RegisterTrackingMode track_regs_for) {
836 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700837 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700838 uint16_t registers_size = code_item->registers_size_;
839 uint32_t insns_size = code_item->insns_size_;
840 uint32_t i;
841
842 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700843 * Every address gets a RegisterLine struct. This is wasteful, but
jeffhaobdb76512011-09-07 11:43:16 -0700844 * not so much that it's worth chasing through an extra level of
845 * indirection.
846 */
847 reg_table->insn_reg_count_plus_ = registers_size + kExtraRegs;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700848 reg_table->register_lines_.reset(new RegisterLine[insns_size]());
jeffhaobdb76512011-09-07 11:43:16 -0700849
850 assert(insns_size > 0);
851
852 bool track_monitors;
853 //if (gDvm.monitorVerification) {
854 //track_monitors = (vdata->monitor_enter_count_ != 0);
855 //} else {
856 track_monitors = false;
857 //}
858
859 /*
860 * Allocate entries in the sparse register line table.
861 *
862 * There is a RegisterLine associated with every address, but not
863 * every RegisterLine has non-NULL pointers to storage for its fields.
864 */
865 for (i = 0; i < insns_size; i++) {
866 bool interesting;
867
868 switch (track_regs_for) {
869 case kTrackRegsAll:
870 interesting = InsnIsOpcode(insn_flags, i);
871 break;
872 case kTrackRegsGcPoints:
873 interesting = InsnIsGcPoint(insn_flags, i) ||
874 InsnIsBranchTarget(insn_flags, i);
875 break;
876 case kTrackRegsBranches:
877 interesting = InsnIsBranchTarget(insn_flags, i);
878 break;
879 default:
880 return false;
881 }
882
883 if (interesting) {
884 reg_table->register_lines_[i].Alloc(reg_table->insn_reg_count_plus_,
885 track_monitors);
886 }
887 }
888
889 /*
890 * Allocate space for our "temporary" register lines.
891 */
892 reg_table->work_line_.Alloc(reg_table->insn_reg_count_plus_, track_monitors);
893 reg_table->saved_line_.Alloc(reg_table->insn_reg_count_plus_, track_monitors);
894
895 return true;
896}
897
898DexVerifier::UninitInstanceMap* DexVerifier::CreateUninitInstanceMap(
899 VerifierData* vdata) {
900 Method* method = vdata->method_;
901 const DexFile::CodeItem* code_item = vdata->code_item_;
902 size_t new_instance_count = vdata->new_instance_count_;
903
904 if (IsInitMethod(method)) {
905 new_instance_count++;
906 }
907
908 /*
909 * Allocate the header and map as a single unit.
910 *
911 * TODO: consider having a static instance so we can avoid allocations.
912 * I don't think the verifier is guaranteed to be single-threaded when
913 * running in the VM (rather than dexopt), so that must be taken into
914 * account.
915 */
916 UninitInstanceMap* uninit_map = new UninitInstanceMap(new_instance_count);
917
918 size_t idx = 0;
919 if (IsInitMethod(method)) {
920 uninit_map->map_[idx++].addr_ = kUninitThisArgAddr;
921 }
922
923 /*
924 * Run through and find the new-instance instructions.
925 */
926 uint32_t addr = 0;
927 uint32_t insns_size = code_item->insns_size_;
928 const byte* ptr = reinterpret_cast<const byte*>(code_item->insns_);
jeffhaoba5ebb92011-08-25 17:24:37 -0700929 const Instruction* inst = Instruction::At(ptr);
jeffhaobdb76512011-09-07 11:43:16 -0700930 while (addr < insns_size) {
931 Instruction::Code opcode = inst->Opcode();
932 if (opcode == Instruction::NEW_INSTANCE) {
933 uninit_map->map_[idx++].addr_ = addr;
934 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700935
jeffhaobdb76512011-09-07 11:43:16 -0700936 addr += inst->Size();
jeffhaoba5ebb92011-08-25 17:24:37 -0700937 inst = inst->Next();
938 }
939
jeffhaobdb76512011-09-07 11:43:16 -0700940 assert(idx == new_instance_count);
941 return uninit_map;
942}
943
944bool DexVerifier::IsInitMethod(const Method* method) {
945 return (method->GetName()->Equals("<init>"));
946}
947
948Class* DexVerifier::LookupClassByDescriptor(const Method* method,
949 const char* descriptor, VerifyError* failure) {
950 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700951 * The compiler occasionally puts references to nonexistent classes in
952 * signatures. For example, if you have a non-static inner class with no
953 * constructor, the compiler provides a private <init> for you.
954 * Constructing the class requires <init>(parent), but the outer class can't
955 * call that because the method is private. So the compiler generates a
956 * package-scope <init>(parent,bogus) method that just calls the regular
957 * <init> (the "bogus" part being necessary to distinguish the signature of
958 * the synthetic method). Treating the bogus class as an instance of
959 * java.lang.Object allows the verifier to process the class successfully.
jeffhaobdb76512011-09-07 11:43:16 -0700960 */
961 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
962 const ClassLoader* class_loader =
963 method->GetDeclaringClass()->GetClassLoader();
964 Class* klass = class_linker->FindClass(descriptor, class_loader);
965
966 if (klass == NULL) {
967 Thread::Current()->ClearException();
968 if (strchr(descriptor, '$') != NULL) {
969 LOG(INFO) << "VFY: unable to find class referenced in signature ("
970 << descriptor << ")";
971 } else {
972 LOG(ERROR) << "VFY: unable to find class referenced in signature ("
973 << descriptor << ")";
974 }
975
976 /* Check if the descriptor is an array. */
977 if (descriptor[0] == '[') {
978 /*
979 * There should never be a problem loading primitive arrays.
980 */
981 if (descriptor[1] != 'L' && descriptor[1] != '[') {
982 LOG(ERROR) << "VFY: invalid char in signature in '" << descriptor
983 << "'";
984 *failure = VERIFY_ERROR_GENERIC;
985 }
986
987 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700988 * Try to continue with base array type. This will let us pass basic
989 * stuff (e.g. get array len) that wouldn't fly with an Object. This
990 * is NOT correct if the missing type is a primitive array, but we
991 * should never have a problem loading those. (I'm not convinced this
992 * is correct or even useful. Just use Object here?)
jeffhaobdb76512011-09-07 11:43:16 -0700993 */
994 klass = class_linker->FindClass("[Ljava/lang/Object;", class_loader);
995 } else if (descriptor[0] == 'L') {
996 /*
997 * We are looking at a non-array reference descriptor;
998 * try to continue with base reference type.
999 */
1000 klass = class_linker->FindSystemClass("Ljava/lang/Object;");
1001 } else {
1002 /* We are looking at a primitive type. */
1003 LOG(ERROR) << "VFY: invalid char in signature in '" << descriptor << "'";
1004 *failure = VERIFY_ERROR_GENERIC;
1005 }
1006
1007 if (klass == NULL) {
1008 *failure = VERIFY_ERROR_GENERIC;
1009 }
1010 }
1011
1012 if (klass->IsPrimitive()) {
1013 LOG(ERROR) << "VFY: invalid use of primitive type '" << descriptor << "'";
1014 *failure = VERIFY_ERROR_GENERIC;
1015 klass = NULL;
1016 }
1017
1018 return klass;
1019}
1020
1021Class* DexVerifier::LookupSignatureClass(const Method* method, std::string sig,
1022 VerifyError* failure) {
1023 assert(sig[0] == 'L');
1024 size_t end = sig.find(';');
1025
1026 if (end == std::string::npos) {
1027 LOG(ERROR) << "VFY: bad signature component '" << sig << "' (missing ';')";
1028 *failure = VERIFY_ERROR_GENERIC;
1029 return NULL;
1030 }
1031
1032 return LookupClassByDescriptor(method, sig.substr(0, end + 1).c_str(),
1033 failure);
1034}
1035
1036Class* DexVerifier::LookupSignatureArrayClass(const Method* method,
1037 std::string sig, VerifyError* failure) {
1038 assert(sig[0] == '[');
1039 size_t end = 0;
1040
1041 while (sig[end] == '[')
1042 end++;
1043
1044 if (sig[end] == 'L') {
1045 end = sig.find(';');
1046 if (end == std::string::npos) {
1047 LOG(ERROR) << "VFY: bad signature component '" << sig
1048 << "' (missing ';')";
1049 *failure = VERIFY_ERROR_GENERIC;
1050 return NULL;
1051 }
1052 }
1053
1054 return LookupClassByDescriptor(method, sig.substr(0, end + 1).c_str(),
1055 failure);
1056}
1057
1058bool DexVerifier::SetTypesFromSignature(VerifierData* vdata, RegType* reg_types)
1059{
1060 Method* method = vdata->method_;
1061 const DexFile* dex_file = vdata->dex_file_;
1062 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001063 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001064
1065 int arg_start = code_item->registers_size_ - code_item->ins_size_;
1066 int expected_args = code_item->ins_size_; /* long/double count as two */
1067 int actual_args = 0;
1068
1069 assert(arg_start >= 0); /* should have been verified earlier */
1070
1071 /*
1072 * Include the "this" pointer.
1073 */
1074 if (!method->IsStatic()) {
1075 /*
1076 * If this is a constructor for a class other than java.lang.Object,
jeffhaod1f0fde2011-09-08 17:25:33 -07001077 * mark the first ("this") argument as uninitialized. This restricts
jeffhaobdb76512011-09-07 11:43:16 -07001078 * field access until the superclass constructor is called.
1079 */
1080 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1081 Class* klass_object = class_linker->FindSystemClass("Ljava/lang/Object;");
1082 if (IsInitMethod(method) && method->GetDeclaringClass() != klass_object) {
1083 int idx = SetUninitInstance(uninit_map, kUninitThisArgAddr,
1084 method->GetDeclaringClass());
1085 assert(idx == 0);
1086 reg_types[arg_start + actual_args] = RegTypeFromUninitIndex(idx);
1087 } else {
1088 reg_types[arg_start + actual_args] =
1089 RegTypeFromClass(method->GetDeclaringClass());
1090 }
1091 actual_args++;
1092 }
1093
1094 const DexFile::ProtoId& proto_id =
1095 dex_file->GetProtoId(method->GetProtoIdx());
1096 DexFile::ParameterIterator iterator(*dex_file, proto_id);
1097 VerifyError failure = VERIFY_ERROR_NONE;
1098
1099 for (; iterator.HasNext(); iterator.Next()) {
1100 const char* descriptor = iterator.GetDescriptor();
1101
1102 if (descriptor == NULL) {
1103 break;
1104 }
1105
1106 if (actual_args >= expected_args) {
1107 LOG(ERROR) << "VFY: expected " << expected_args << " args, found more ("
1108 << descriptor << ")";
1109 return false;
1110 }
1111
1112 switch (*descriptor) {
1113 case 'L':
1114 case '[':
1115 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001116 * We assume that reference arguments are initialized. The only way
1117 * it could be otherwise (assuming the caller was verified) is if
1118 * the current method is <init>, but in that case it's effectively
1119 * considered initialized the instant we reach here (in the sense
1120 * that we can return without doing anything or call virtual methods).
jeffhaobdb76512011-09-07 11:43:16 -07001121 */
1122 {
1123 Class* klass =
1124 LookupClassByDescriptor(method, descriptor, &failure);
1125 if (failure != VERIFY_ERROR_NONE)
1126 return false;
1127 reg_types[arg_start + actual_args] = RegTypeFromClass(klass);
1128 }
1129 actual_args++;
1130 break;
1131 case 'Z':
1132 reg_types[arg_start + actual_args] = kRegTypeBoolean;
1133 actual_args++;
1134 break;
1135 case 'C':
1136 reg_types[arg_start + actual_args] = kRegTypeChar;
1137 actual_args++;
1138 break;
1139 case 'B':
1140 reg_types[arg_start + actual_args] = kRegTypeByte;
1141 actual_args++;
1142 break;
1143 case 'I':
1144 reg_types[arg_start + actual_args] = kRegTypeInteger;
1145 actual_args++;
1146 break;
1147 case 'S':
1148 reg_types[arg_start + actual_args] = kRegTypeShort;
1149 actual_args++;
1150 break;
1151 case 'F':
1152 reg_types[arg_start + actual_args] = kRegTypeFloat;
1153 actual_args++;
1154 break;
1155 case 'D':
1156 reg_types[arg_start + actual_args] = kRegTypeDoubleLo;
1157 reg_types[arg_start + actual_args +1] = kRegTypeDoubleHi;
1158 actual_args += 2;
1159 break;
1160 case 'J':
1161 reg_types[arg_start + actual_args] = kRegTypeLongLo;
1162 reg_types[arg_start + actual_args +1] = kRegTypeLongHi;
1163 actual_args += 2;
1164 break;
1165 default:
1166 LOG(ERROR) << "VFY: unexpected signature type char '" << descriptor
1167 << "'";
1168 return false;
1169 }
1170 }
1171
1172 if (actual_args != expected_args) {
1173 LOG(ERROR) << "VFY: expected " << expected_args << " args, found "
1174 << actual_args;
jeffhaoba5ebb92011-08-25 17:24:37 -07001175 return false;
1176 }
1177
jeffhaobdb76512011-09-07 11:43:16 -07001178 const char* descriptor = dex_file->GetReturnTypeDescriptor(proto_id);
1179
1180 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001181 * Validate return type. We don't do the type lookup; just want to make
1182 * sure that it has the right format. Only major difference from the
jeffhaobdb76512011-09-07 11:43:16 -07001183 * method argument format is that 'V' is supported.
1184 */
1185 switch (*descriptor) {
1186 case 'I':
1187 case 'C':
1188 case 'S':
1189 case 'B':
1190 case 'Z':
1191 case 'V':
1192 case 'F':
1193 case 'D':
1194 case 'J':
1195 if (*(descriptor + 1) != '\0')
1196 return false;
1197 break;
1198 case '[':
1199 /* single/multi, object/primitive */
1200 while (*++descriptor == '[')
1201 ;
1202 if (*descriptor == 'L') {
1203 while (*++descriptor != ';' && *descriptor != '\0')
1204 ;
1205 if (*descriptor != ';')
1206 return false;
1207 } else {
1208 if (*(descriptor+1) != '\0')
1209 return false;
1210 }
1211 break;
1212 case 'L':
1213 /* could be more thorough here, but shouldn't be required */
1214 while (*++descriptor != ';' && *descriptor != '\0')
1215 ;
1216 if (*descriptor != ';')
1217 return false;
1218 break;
1219 default:
1220 return false;
1221 }
1222
jeffhaoba5ebb92011-08-25 17:24:37 -07001223 return true;
1224}
1225
jeffhaobdb76512011-09-07 11:43:16 -07001226int DexVerifier::SetUninitInstance(UninitInstanceMap* uninit_map, int addr,
1227 Class* klass) {
1228 int idx;
1229 assert(klass != NULL);
1230
jeffhaod1f0fde2011-09-08 17:25:33 -07001231 /* TODO: binary search when num_entries > 8 */
jeffhaobdb76512011-09-07 11:43:16 -07001232 for (idx = uninit_map->num_entries_ - 1; idx >= 0; idx--) {
1233 if (uninit_map->map_[idx].addr_ == addr) {
1234 if (uninit_map->map_[idx].klass_ != NULL &&
1235 uninit_map->map_[idx].klass_ != klass) {
1236 LOG(ERROR) << "VFY: addr " << addr << " already set to "
1237 << (int) uninit_map->map_[idx].klass_ << ", not setting to "
1238 << (int) klass;
1239 return -1; // already set to something else??
1240 }
1241 uninit_map->map_[idx].klass_ = klass;
1242 return idx;
1243 }
1244 }
1245
1246 LOG(ERROR) << "VFY: addr " << addr << " not found in uninit map";
1247 assert(false); // shouldn't happen
1248 return -1;
1249}
1250
1251bool DexVerifier::CodeFlowVerifyMethod(VerifierData* vdata,
1252 RegisterTable* reg_table) {
1253 const Method* method = vdata->method_;
1254 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001255 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001256 const uint16_t* insns = code_item->insns_;
jeffhaoba5ebb92011-08-25 17:24:37 -07001257 uint32_t insns_size = code_item->insns_size_;
jeffhaobdb76512011-09-07 11:43:16 -07001258 size_t insn_idx, start_guess;
jeffhaoba5ebb92011-08-25 17:24:37 -07001259
jeffhaobdb76512011-09-07 11:43:16 -07001260 /* Begin by marking the first instruction as "changed". */
1261 InsnSetChanged(insn_flags, 0, true);
jeffhaoba5ebb92011-08-25 17:24:37 -07001262
jeffhaobdb76512011-09-07 11:43:16 -07001263 start_guess = 0;
jeffhaoba5ebb92011-08-25 17:24:37 -07001264
jeffhaobdb76512011-09-07 11:43:16 -07001265 /* Continue until no instructions are marked "changed". */
1266 while (true) {
1267 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001268 * Find the first marked one. Use "start_guess" as a way to find
jeffhaobdb76512011-09-07 11:43:16 -07001269 * one quickly.
1270 */
1271 for (insn_idx = start_guess; insn_idx < insns_size; insn_idx++) {
1272 if (InsnIsChanged(insn_flags, insn_idx))
1273 break;
1274 }
jeffhaoba5ebb92011-08-25 17:24:37 -07001275
jeffhaobdb76512011-09-07 11:43:16 -07001276 if (insn_idx == insns_size) {
1277 if (start_guess != 0) {
1278 /* try again, starting from the top */
1279 start_guess = 0;
1280 continue;
1281 } else {
1282 /* all flags are clear */
1283 break;
1284 }
1285 }
1286
1287 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001288 * We carry the working set of registers from instruction to instruction.
1289 * If this address can be the target of a branch (or throw) instruction,
1290 * or if we're skipping around chasing "changed" flags, we need to load
1291 * the set of registers from the table.
jeffhaobdb76512011-09-07 11:43:16 -07001292 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001293 * Because we always prefer to continue on to the next instruction, we
1294 * should never have a situation where we have a stray "changed" flag set
1295 * on an instruction that isn't a branch target.
jeffhaobdb76512011-09-07 11:43:16 -07001296 */
1297 if (InsnIsBranchTarget(insn_flags, insn_idx)) {
1298 RegisterLine* work_line = &reg_table->work_line_;
1299 CopyLineFromTable(work_line, reg_table, insn_idx);
1300 } else {
1301#ifndef NDEBUG
1302 /*
1303 * Sanity check: retrieve the stored register line (assuming
1304 * a full table) and make sure it actually matches.
1305 */
1306 RegisterLine* register_line = GetRegisterLine(reg_table, insn_idx);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001307 if (register_line->reg_types_.get() != NULL && CompareLineToTable(reg_table,
jeffhaobdb76512011-09-07 11:43:16 -07001308 insn_idx, &reg_table->work_line_) != 0) {
1309 Class* klass = method->GetDeclaringClass();
1310 LOG(ERROR) << "HUH? work_line diverged in "
1311 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1312 << method->GetName()->ToModifiedUtf8() << " "
1313 << method->GetSignature()->ToModifiedUtf8();
1314 }
1315#endif
1316 }
1317
1318 if (!CodeFlowVerifyInstruction(vdata, reg_table, insn_idx, &start_guess)) {
1319 Class* klass = method->GetDeclaringClass();
1320 LOG(ERROR) << "VFY: failure to verify "
1321 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1322 << method->GetName()->ToModifiedUtf8() << " "
1323 << method->GetSignature()->ToModifiedUtf8();
jeffhaoba5ebb92011-08-25 17:24:37 -07001324 return false;
1325 }
1326
jeffhaobdb76512011-09-07 11:43:16 -07001327 /* Clear "changed" and mark as visited. */
1328 InsnSetVisited(insn_flags, insn_idx, true);
1329 InsnSetChanged(insn_flags, insn_idx, false);
1330 }
jeffhaoba5ebb92011-08-25 17:24:37 -07001331
jeffhaobdb76512011-09-07 11:43:16 -07001332 if (DEAD_CODE_SCAN && ((method->GetAccessFlags() & kAccWritable) == 0)) {
1333 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001334 * Scan for dead code. There's nothing "evil" about dead code
jeffhaobdb76512011-09-07 11:43:16 -07001335 * (besides the wasted space), but it indicates a flaw somewhere
1336 * down the line, possibly in the verifier.
1337 *
1338 * If we've substituted "always throw" instructions into the stream,
1339 * we are almost certainly going to have some dead code.
1340 */
1341 int dead_start = -1;
1342 for (insn_idx = 0; insn_idx < insns_size;
1343 insn_idx += InsnGetWidth(insn_flags, insn_idx)) {
1344 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001345 * Switch-statement data doesn't get "visited" by scanner. It
jeffhaobdb76512011-09-07 11:43:16 -07001346 * may or may not be preceded by a padding NOP (for alignment).
1347 */
1348 if (insns[insn_idx] == Instruction::kPackedSwitchSignature ||
1349 insns[insn_idx] == Instruction::kSparseSwitchSignature ||
1350 insns[insn_idx] == Instruction::kArrayDataSignature ||
1351 (insns[insn_idx] == Instruction::NOP &&
1352 (insns[insn_idx + 1] == Instruction::kPackedSwitchSignature ||
1353 insns[insn_idx + 1] == Instruction::kSparseSwitchSignature ||
1354 insns[insn_idx + 1] == Instruction::kArrayDataSignature))) {
1355 InsnSetVisited(insn_flags, insn_idx, true);
1356 }
1357
1358 if (!InsnIsVisited(insn_flags, insn_idx)) {
1359 if (dead_start < 0)
1360 dead_start = insn_idx;
1361 } else if (dead_start >= 0) {
1362 Class* klass = method->GetDeclaringClass();
1363 LOG(INFO) << "VFY: dead code 0x" << std::hex << dead_start << "-"
1364 << insn_idx - 1 << std::dec << " in "
1365 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1366 << method->GetName()->ToModifiedUtf8() << " "
1367 << method->GetSignature()->ToModifiedUtf8();
1368 dead_start = -1;
1369 }
1370 }
1371 if (dead_start >= 0) {
1372 Class* klass = method->GetDeclaringClass();
1373 LOG(INFO) << "VFY: dead code 0x" << std::hex << dead_start << "-"
1374 << insn_idx - 1 << std::dec << " in "
1375 << klass->GetDescriptor()->ToModifiedUtf8() << "."
1376 << method->GetName()->ToModifiedUtf8() << " "
1377 << method->GetSignature()->ToModifiedUtf8();
jeffhaoba5ebb92011-08-25 17:24:37 -07001378 }
1379 }
1380
jeffhaobdb76512011-09-07 11:43:16 -07001381 return true;
1382}
1383
1384bool DexVerifier::CodeFlowVerifyInstruction(VerifierData* vdata,
1385 RegisterTable* reg_table, uint32_t insn_idx, size_t* start_guess) {
1386 const Method* method = vdata->method_;
1387 Class* klass = method->GetDeclaringClass();
1388 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001389 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001390 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001391 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001392 const uint16_t* insns = code_item->insns_ + insn_idx;
1393 uint32_t insns_size = code_item->insns_size_;
1394 uint32_t registers_size = code_item->registers_size_;
1395
1396#ifdef VERIFIER_STATS
1397 if (InsnIsVisited(insn_flags, insn_idx)) {
1398 gDvm.verifierStats.instrsReexamined++;
1399 } else {
1400 gDvm.verifierStats.instrsExamined++;
1401 }
1402#endif
1403
1404 /*
1405 * Once we finish decoding the instruction, we need to figure out where
jeffhaod1f0fde2011-09-08 17:25:33 -07001406 * we can go from here. There are three possible ways to transfer
jeffhaobdb76512011-09-07 11:43:16 -07001407 * control to another statement:
1408 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001409 * (1) Continue to the next instruction. Applies to all but
jeffhaobdb76512011-09-07 11:43:16 -07001410 * unconditional branches, method returns, and exception throws.
jeffhaod1f0fde2011-09-08 17:25:33 -07001411 * (2) Branch to one or more possible locations. Applies to branches
jeffhaobdb76512011-09-07 11:43:16 -07001412 * and switch statements.
jeffhaod1f0fde2011-09-08 17:25:33 -07001413 * (3) Exception handlers. Applies to any instruction that can
jeffhaobdb76512011-09-07 11:43:16 -07001414 * throw an exception that is handled by an encompassing "try"
1415 * block.
1416 *
1417 * We can also return, in which case there is no successor instruction
1418 * from this point.
1419 *
1420 * The behavior can be determined from the OpcodeFlags.
1421 */
1422 RegisterLine* work_line = &reg_table->work_line_;
1423 const DexFile* dex_file = vdata->dex_file_;
1424 const byte* ptr = reinterpret_cast<const byte*>(insns);
1425 const Instruction* inst = Instruction::At(ptr);
1426 Instruction::DecodedInstruction dec_insn(inst);
1427 int opcode_flag = inst->Flag();
1428
1429 Class* res_class;
1430 int32_t branch_target = 0;
1431 RegType tmp_type;
1432 bool just_set_result = false;
1433 VerifyError failure = VERIFY_ERROR_NONE;
1434
1435 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001436 * Make a copy of the previous register state. If the instruction
jeffhaobdb76512011-09-07 11:43:16 -07001437 * can throw an exception, we will copy/merge this into the "catch"
1438 * address rather than work_line, because we don't want the result
1439 * from the "successful" code path (e.g. a check-cast that "improves"
1440 * a type) to be visible to the exception handler.
1441 */
1442 if ((opcode_flag & Instruction::kThrow) != 0 &&
1443 InsnIsInTry(insn_flags, insn_idx)) {
1444 CopyRegisterLine(&reg_table->saved_line_, work_line,
1445 reg_table->insn_reg_count_plus_);
1446 } else {
1447#ifndef NDEBUG
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001448 memset(reg_table->saved_line_.reg_types_.get(), 0xdd,
jeffhaobdb76512011-09-07 11:43:16 -07001449 reg_table->insn_reg_count_plus_ * sizeof(RegType));
1450#endif
1451 }
1452
1453 switch (dec_insn.opcode_) {
1454 case Instruction::NOP:
1455 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001456 * A "pure" NOP has no effect on anything. Data tables start with
jeffhaobdb76512011-09-07 11:43:16 -07001457 * a signature that looks like a NOP; if we see one of these in
1458 * the course of executing code then we have a problem.
1459 */
1460 if (dec_insn.vA_ != 0) {
1461 LOG(ERROR) << "VFY: encountered data table in instruction stream";
1462 failure = VERIFY_ERROR_GENERIC;
1463 }
1464 break;
1465
1466 case Instruction::MOVE:
1467 case Instruction::MOVE_FROM16:
1468 case Instruction::MOVE_16:
1469 CopyRegister1(work_line, dec_insn.vA_, dec_insn.vB_, kTypeCategory1nr,
1470 &failure);
1471 break;
1472 case Instruction::MOVE_WIDE:
1473 case Instruction::MOVE_WIDE_FROM16:
1474 case Instruction::MOVE_WIDE_16:
1475 CopyRegister2(work_line, dec_insn.vA_, dec_insn.vB_, &failure);
1476 break;
1477 case Instruction::MOVE_OBJECT:
1478 case Instruction::MOVE_OBJECT_FROM16:
1479 case Instruction::MOVE_OBJECT_16:
1480 CopyRegister1(work_line, dec_insn.vA_, dec_insn.vB_, kTypeCategoryRef,
1481 &failure);
1482 break;
1483
1484 /*
1485 * The move-result instructions copy data out of a "pseudo-register"
jeffhaod1f0fde2011-09-08 17:25:33 -07001486 * with the results from the last method invocation. In practice we
jeffhaobdb76512011-09-07 11:43:16 -07001487 * might want to hold the result in an actual CPU register, so the
1488 * Dalvik spec requires that these only appear immediately after an
1489 * invoke or filled-new-array.
1490 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001491 * These calls invalidate the "result" register. (This is now
jeffhaobdb76512011-09-07 11:43:16 -07001492 * redundant with the reset done below, but it can make the debug info
1493 * easier to read in some cases.)
1494 */
1495 case Instruction::MOVE_RESULT:
1496 CopyResultRegister1(work_line, registers_size, dec_insn.vA_,
1497 kTypeCategory1nr, &failure);
1498 break;
1499 case Instruction::MOVE_RESULT_WIDE:
1500 CopyResultRegister2(work_line, registers_size, dec_insn.vA_, &failure);
1501 break;
1502 case Instruction::MOVE_RESULT_OBJECT:
1503 CopyResultRegister1(work_line, registers_size, dec_insn.vA_,
1504 kTypeCategoryRef, &failure);
1505 break;
1506
1507 case Instruction::MOVE_EXCEPTION:
1508 /*
1509 * This statement can only appear as the first instruction in an
1510 * exception handler (though not all exception handlers need to
jeffhaod1f0fde2011-09-08 17:25:33 -07001511 * have one of these). We verify that as part of extracting the
jeffhaobdb76512011-09-07 11:43:16 -07001512 * exception type from the catch block list.
1513 *
1514 * "res_class" will hold the closest common superclass of all
1515 * exceptions that can be handled here.
1516 */
1517 res_class = GetCaughtExceptionType(vdata, insn_idx, &failure);
1518 if (res_class == NULL) {
1519 assert(failure != VERIFY_ERROR_NONE);
1520 } else {
1521 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1522 }
1523 break;
1524
1525 case Instruction::RETURN_VOID:
1526 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1527 failure = VERIFY_ERROR_GENERIC;
1528 } else if (GetMethodReturnType(dex_file, method) != kRegTypeUnknown) {
1529 LOG(ERROR) << "VFY: return-void not expected";
1530 failure = VERIFY_ERROR_GENERIC;
1531 }
1532 break;
1533 case Instruction::RETURN:
1534 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1535 failure = VERIFY_ERROR_GENERIC;
1536 } else {
1537 /* check the method signature */
1538 RegType return_type = GetMethodReturnType(dex_file, method);
1539 CheckTypeCategory(return_type, kTypeCategory1nr, &failure);
1540 if (failure != VERIFY_ERROR_NONE)
1541 LOG(ERROR) << "VFY: return-1nr not expected";
1542
1543 /*
1544 * compiler may generate synthetic functions that write byte
1545 * values into boolean fields. Also, it may use integer values
1546 * for boolean, byte, short, and character return types.
1547 */
1548 RegType src_type = GetRegisterType(work_line, dec_insn.vA_);
1549 if ((return_type == kRegTypeBoolean && src_type == kRegTypeByte) ||
1550 ((return_type == kRegTypeBoolean || return_type == kRegTypeByte ||
1551 return_type == kRegTypeShort || return_type == kRegTypeChar) &&
1552 src_type == kRegTypeInteger))
1553 return_type = src_type;
1554
1555 /* check the register contents */
1556 VerifyRegisterType(work_line, dec_insn.vA_, return_type, &failure);
1557 if (failure != VERIFY_ERROR_NONE) {
1558 LOG(ERROR) << "VFY: return-1nr on invalid register v" << dec_insn.vA_;
1559 }
1560 }
1561 break;
1562 case Instruction::RETURN_WIDE:
1563 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1564 failure = VERIFY_ERROR_GENERIC;
1565 } else {
1566 RegType return_type;
1567
1568 /* check the method signature */
1569 return_type = GetMethodReturnType(dex_file, method);
1570 CheckTypeCategory(return_type, kTypeCategory2, &failure);
1571 if (failure != VERIFY_ERROR_NONE)
1572 LOG(ERROR) << "VFY: return-wide not expected";
1573
1574 /* check the register contents */
1575 VerifyRegisterType(work_line, dec_insn.vA_, return_type, &failure);
1576 if (failure != VERIFY_ERROR_NONE) {
1577 LOG(ERROR) << "VFY: return-wide on invalid register pair v"
1578 << dec_insn.vA_;
1579 }
1580 }
1581 break;
1582 case Instruction::RETURN_OBJECT:
1583 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1584 failure = VERIFY_ERROR_GENERIC;
1585 } else {
1586 RegType return_type = GetMethodReturnType(dex_file, method);
1587 CheckTypeCategory(return_type, kTypeCategoryRef, &failure);
1588 if (failure != VERIFY_ERROR_NONE) {
1589 LOG(ERROR) << "VFY: return-object not expected";
1590 break;
1591 }
1592
1593 /* return_type is the *expected* return type, not register value */
1594 assert(return_type != kRegTypeZero);
1595 assert(!RegTypeIsUninitReference(return_type));
1596
1597 /*
1598 * Verify that the reference in vAA is an instance of the type
jeffhaod1f0fde2011-09-08 17:25:33 -07001599 * in "return_type". The Zero type is allowed here. If the
jeffhaobdb76512011-09-07 11:43:16 -07001600 * method is declared to return an interface, then any
1601 * initialized reference is acceptable.
1602 *
1603 * Note GetClassFromRegister fails if the register holds an
1604 * uninitialized reference, so we do not allow them to be
1605 * returned.
1606 */
1607 Class* decl_class = RegTypeInitializedReferenceToClass(return_type);
1608 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1609 if (failure != VERIFY_ERROR_NONE)
1610 break;
1611 if (res_class != NULL) {
1612 if (!decl_class->IsInterface() &&
1613 //!res_class->InstanceOf(decl_class)) {
1614 !decl_class->IsAssignableFrom(res_class)) {
1615 LOG(ERROR) << "VFY: returning " << std::hex
1616 << res_class->GetDescriptor()->ToModifiedUtf8()
1617 << " (cl=0x" << (int) res_class->GetClassLoader()
1618 << "), declared "
1619 << decl_class->GetDescriptor()->ToModifiedUtf8()
1620 << " (cl=0x" << (int) decl_class->GetClassLoader()
1621 << ")" << std::dec;
1622 failure = VERIFY_ERROR_GENERIC;
1623 break;
1624 }
1625 }
1626 }
1627 break;
1628
1629 case Instruction::CONST_4:
1630 case Instruction::CONST_16:
1631 case Instruction::CONST:
1632 /* could be boolean, int, float, or a null reference */
1633 SetRegisterType(work_line, dec_insn.vA_,
1634 DetermineCat1Const((int32_t) dec_insn.vB_));
1635 break;
1636 case Instruction::CONST_HIGH16:
1637 /* could be boolean, int, float, or a null reference */
1638 SetRegisterType(work_line, dec_insn.vA_,
1639 DetermineCat1Const((int32_t) dec_insn.vB_ << 16));
1640 break;
1641 case Instruction::CONST_WIDE_16:
1642 case Instruction::CONST_WIDE_32:
1643 case Instruction::CONST_WIDE:
1644 case Instruction::CONST_WIDE_HIGH16:
1645 /* could be long or double; resolved upon use */
1646 SetRegisterType(work_line, dec_insn.vA_, kRegTypeConstLo);
1647 break;
1648 case Instruction::CONST_STRING:
1649 case Instruction::CONST_STRING_JUMBO:
1650 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
1651 class_linker->FindSystemClass("Ljava/lang/String;")));
1652 break;
1653 case Instruction::CONST_CLASS:
1654 /* make sure we can resolve the class; access check is important */
jeffhao98eacac2011-09-14 16:11:53 -07001655 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001656 if (res_class == NULL) {
1657 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1658 LOG(ERROR) << "VFY: unable to resolve const-class " << dec_insn.vB_
1659 << " (" << bad_class_desc << ") in "
1660 << klass->GetDescriptor()->ToModifiedUtf8();
1661 assert(failure != VERIFY_ERROR_GENERIC);
1662 } else {
1663 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
1664 class_linker->FindSystemClass("Ljava/lang/Class;")));
1665 }
1666 break;
1667
1668 case Instruction::MONITOR_ENTER:
1669 HandleMonitorEnter(work_line, dec_insn.vA_, insn_idx, &failure);
1670 break;
1671 case Instruction::MONITOR_EXIT:
1672 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001673 * monitor-exit instructions are odd. They can throw exceptions,
jeffhaobdb76512011-09-07 11:43:16 -07001674 * but when they do they act as if they succeeded and the PC is
jeffhaod1f0fde2011-09-08 17:25:33 -07001675 * pointing to the following instruction. (This behavior goes back
jeffhaobdb76512011-09-07 11:43:16 -07001676 * to the need to handle asynchronous exceptions, a now-deprecated
1677 * feature that Dalvik doesn't support.)
1678 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001679 * In practice we don't need to worry about this. The only
jeffhaobdb76512011-09-07 11:43:16 -07001680 * exceptions that can be thrown from monitor-exit are for a
jeffhaod1f0fde2011-09-08 17:25:33 -07001681 * null reference and -exit without a matching -enter. If the
jeffhaobdb76512011-09-07 11:43:16 -07001682 * structured locking checks are working, the former would have
1683 * failed on the -enter instruction, and the latter is impossible.
1684 *
1685 * This is fortunate, because issue 3221411 prevents us from
1686 * chasing the "can throw" path when monitor verification is
jeffhaod1f0fde2011-09-08 17:25:33 -07001687 * enabled. If we can fully verify the locking we can ignore
jeffhaobdb76512011-09-07 11:43:16 -07001688 * some catch blocks (which will show up as "dead" code when
1689 * we skip them here); if we can't, then the code path could be
1690 * "live" so we still need to check it.
1691 */
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001692 if (work_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07001693 opcode_flag &= ~Instruction::kThrow;
1694 HandleMonitorExit(work_line, dec_insn.vA_, insn_idx, &failure);
1695 break;
1696
1697 case Instruction::CHECK_CAST:
1698 /*
1699 * If this instruction succeeds, we will promote register vA to
jeffhaod1f0fde2011-09-08 17:25:33 -07001700 * the type in vB. (This could be a demotion -- not expected, so
jeffhaobdb76512011-09-07 11:43:16 -07001701 * we don't try to address it.)
1702 *
1703 * If it fails, an exception is thrown, which we deal with later
1704 * by ignoring the update to dec_insn.vA_ when branching to a handler.
1705 */
jeffhao98eacac2011-09-14 16:11:53 -07001706 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001707 if (res_class == NULL) {
1708 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1709 LOG(ERROR) << "VFY: unable to resolve check-cast " << dec_insn.vB_
1710 << " (" << bad_class_desc << ") in "
1711 << klass->GetDescriptor()->ToModifiedUtf8();
1712 assert(failure != VERIFY_ERROR_GENERIC);
1713 } else {
1714 RegType orig_type;
1715
1716 orig_type = GetRegisterType(work_line, dec_insn.vA_);
1717 if (!RegTypeIsReference(orig_type)) {
1718 LOG(ERROR) << "VFY: check-cast on non-reference in v" << dec_insn.vA_;
1719 failure = VERIFY_ERROR_GENERIC;
1720 break;
1721 }
1722 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1723 }
1724 break;
1725 case Instruction::INSTANCE_OF:
1726 /* make sure we're checking a reference type */
1727 tmp_type = GetRegisterType(work_line, dec_insn.vB_);
1728 if (!RegTypeIsReference(tmp_type)) {
1729 LOG(ERROR) << "VFY: vB not a reference (" << tmp_type << ")";
1730 failure = VERIFY_ERROR_GENERIC;
1731 break;
1732 }
1733
1734 /* make sure we can resolve the class; access check is important */
jeffhao98eacac2011-09-14 16:11:53 -07001735 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vC_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001736 if (res_class == NULL) {
1737 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vC_);
1738 LOG(ERROR) << "VFY: unable to resolve instanceof " << dec_insn.vC_
1739 << " (" << bad_class_desc << ") in "
1740 << klass->GetDescriptor()->ToModifiedUtf8();
1741 assert(failure != VERIFY_ERROR_GENERIC);
1742 } else {
1743 /* result is boolean */
1744 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1745 }
1746 break;
1747
1748 case Instruction::ARRAY_LENGTH:
1749 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
1750 if (failure != VERIFY_ERROR_NONE)
1751 break;
1752 if (res_class != NULL && !res_class->IsArrayClass()) {
1753 LOG(ERROR) << "VFY: array-length on non-array";
1754 failure = VERIFY_ERROR_GENERIC;
1755 break;
1756 }
1757 SetRegisterType(work_line, dec_insn.vA_, kRegTypeInteger);
1758 break;
1759
1760 case Instruction::NEW_INSTANCE:
jeffhao98eacac2011-09-14 16:11:53 -07001761 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001762 if (res_class == NULL) {
1763 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1764 LOG(ERROR) << "VFY: unable to resolve new-instance " << dec_insn.vB_
1765 << " (" << bad_class_desc << ") in "
1766 << klass->GetDescriptor()->ToModifiedUtf8();
1767 assert(failure != VERIFY_ERROR_GENERIC);
1768 } else {
1769 RegType uninit_type;
1770
1771 /* can't create an instance of an interface or abstract class */
1772 if (res_class->IsAbstract() || res_class->IsInterface()) {
1773 LOG(ERROR) << "VFY: new-instance on interface or abstract class"
1774 << res_class->GetDescriptor()->ToModifiedUtf8();
1775 failure = VERIFY_ERROR_INSTANTIATION;
1776 break;
1777 }
1778
1779 /* add resolved class to uninit map if not already there */
1780 int uidx = SetUninitInstance(uninit_map, insn_idx, res_class);
1781 assert(uidx >= 0);
1782 uninit_type = RegTypeFromUninitIndex(uidx);
1783
1784 /*
1785 * Any registers holding previous allocations from this address
1786 * that have not yet been initialized must be marked invalid.
1787 */
1788 MarkUninitRefsAsInvalid(work_line, registers_size, uninit_map,
1789 uninit_type);
1790
1791 /* add the new uninitialized reference to the register ste */
1792 SetRegisterType(work_line, dec_insn.vA_, uninit_type);
1793 }
1794 break;
1795 case Instruction::NEW_ARRAY:
jeffhao98eacac2011-09-14 16:11:53 -07001796 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vC_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001797 if (res_class == NULL) {
1798 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vC_);
1799 LOG(ERROR) << "VFY: unable to resolve new-array " << dec_insn.vC_
1800 << " (" << bad_class_desc << ") in "
1801 << klass->GetDescriptor()->ToModifiedUtf8();
1802 assert(failure != VERIFY_ERROR_GENERIC);
1803 } else if (!res_class->IsArrayClass()) {
1804 LOG(ERROR) << "VFY: new-array on non-array class";
1805 failure = VERIFY_ERROR_GENERIC;
1806 } else {
1807 /* make sure "size" register is valid type */
1808 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeInteger, &failure);
1809 /* set register type to array class */
1810 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1811 }
1812 break;
1813 case Instruction::FILLED_NEW_ARRAY:
1814 case Instruction::FILLED_NEW_ARRAY_RANGE:
jeffhao98eacac2011-09-14 16:11:53 -07001815 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001816 if (res_class == NULL) {
1817 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1818 LOG(ERROR) << "VFY: unable to resolve filled-array " << dec_insn.vB_
1819 << " (" << bad_class_desc << ") in "
1820 << klass->GetDescriptor()->ToModifiedUtf8();
1821 assert(failure != VERIFY_ERROR_GENERIC);
1822 } else if (!res_class->IsArrayClass()) {
1823 LOG(ERROR) << "VFY: filled-new-array on non-array class";
1824 failure = VERIFY_ERROR_GENERIC;
1825 } else {
1826 bool is_range = (dec_insn.opcode_ ==
1827 Instruction::FILLED_NEW_ARRAY_RANGE);
1828
1829 /* check the arguments to the instruction */
1830 VerifyFilledNewArrayRegs(method, work_line, &dec_insn, res_class,
1831 is_range, &failure);
1832 /* filled-array result goes into "result" register */
1833 SetResultRegisterType(work_line, registers_size,
1834 RegTypeFromClass(res_class));
1835 just_set_result = true;
1836 }
1837 break;
1838
1839 case Instruction::CMPL_FLOAT:
1840 case Instruction::CMPG_FLOAT:
1841 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeFloat, &failure);
1842 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeFloat, &failure);
1843 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1844 break;
1845 case Instruction::CMPL_DOUBLE:
1846 case Instruction::CMPG_DOUBLE:
1847 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeDoubleLo, &failure);
1848 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeDoubleLo, &failure);
1849 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1850 break;
1851 case Instruction::CMP_LONG:
1852 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeLongLo, &failure);
1853 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeLongLo, &failure);
1854 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1855 break;
1856
1857 case Instruction::THROW:
1858 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1859 if (failure == VERIFY_ERROR_NONE && res_class != NULL) {
1860 Class* throwable_class =
1861 class_linker->FindSystemClass("Ljava/lang/Throwable;");
1862 if (!throwable_class->IsAssignableFrom(res_class)) {
1863 LOG(ERROR) << "VFY: thrown class "
1864 << res_class->GetDescriptor()->ToModifiedUtf8()
1865 << " not instanceof Throwable",
1866 failure = VERIFY_ERROR_GENERIC;
1867 }
1868 }
1869 break;
1870
1871 case Instruction::GOTO:
1872 case Instruction::GOTO_16:
1873 case Instruction::GOTO_32:
1874 /* no effect on or use of registers */
1875 break;
1876
1877 case Instruction::PACKED_SWITCH:
1878 case Instruction::SPARSE_SWITCH:
1879 /* verify that vAA is an integer, or can be converted to one */
1880 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeInteger, &failure);
1881 break;
1882
1883 case Instruction::FILL_ARRAY_DATA:
1884 {
1885 RegType value_type;
1886 const uint16_t *array_data;
1887 uint16_t elem_width;
1888
1889 /* Similar to the verification done for APUT */
1890 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1891 if (failure != VERIFY_ERROR_NONE)
1892 break;
1893
1894 /* res_class can be null if the reg type is Zero */
1895 if (res_class == NULL)
1896 break;
1897
1898 Class::PrimitiveType prim_type =
1899 res_class->GetComponentType()->GetPrimitiveType();
1900 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
1901 prim_type == Class::kPrimNot || prim_type == Class::kPrimVoid) {
1902 LOG(ERROR) << "VFY: invalid fill-array-data on " <<
1903 res_class->GetDescriptor()->ToModifiedUtf8();
1904 failure = VERIFY_ERROR_GENERIC;
1905 break;
1906 }
1907
1908 value_type = PrimitiveTypeToRegType(prim_type);
1909 assert(value_type != kRegTypeUnknown);
1910
1911 /*
1912 * Now verify if the element width in the table matches the element
1913 * width declared in the array
1914 */
1915 array_data = insns + (insns[1] | (((int32_t) insns[2]) << 16));
1916 if (array_data[0] != Instruction::kArrayDataSignature) {
1917 LOG(ERROR) << "VFY: invalid magic for array-data";
1918 failure = VERIFY_ERROR_GENERIC;
1919 break;
1920 }
1921
1922 switch (prim_type) {
1923 case Class::kPrimBoolean:
1924 case Class::kPrimByte:
1925 elem_width = 1;
1926 break;
1927 case Class::kPrimChar:
1928 case Class::kPrimShort:
1929 elem_width = 2;
1930 break;
1931 case Class::kPrimFloat:
1932 case Class::kPrimInt:
1933 elem_width = 4;
1934 break;
1935 case Class::kPrimDouble:
1936 case Class::kPrimLong:
1937 elem_width = 8;
1938 break;
1939 default:
1940 elem_width = 0;
1941 break;
1942 }
1943
1944 /*
1945 * Since we don't compress the data in Dex, expect to see equal
1946 * width of data stored in the table and expected from the array
1947 * class.
1948 */
1949 if (array_data[1] != elem_width) {
1950 LOG(ERROR) << "VFY: array-data size mismatch (" << array_data[1]
1951 << " vs " << elem_width << ")";
1952 failure = VERIFY_ERROR_GENERIC;
1953 }
1954 }
1955 break;
1956
1957 case Instruction::IF_EQ:
1958 case Instruction::IF_NE:
1959 {
1960 RegType type1, type2;
1961
1962 type1 = GetRegisterType(work_line, dec_insn.vA_);
1963 type2 = GetRegisterType(work_line, dec_insn.vB_);
1964
1965 /* both references? */
1966 if (RegTypeIsReference(type1) && RegTypeIsReference(type2))
1967 break;
1968
1969 /* both category-1nr? */
1970 CheckTypeCategory(type1, kTypeCategory1nr, &failure);
1971 CheckTypeCategory(type2, kTypeCategory1nr, &failure);
1972 if (failure != VERIFY_ERROR_NONE) {
1973 LOG(ERROR) << "VFY: args to if-eq/if-ne must both be refs or cat1";
1974 break;
1975 }
1976 }
1977 break;
1978 case Instruction::IF_LT:
1979 case Instruction::IF_GE:
1980 case Instruction::IF_GT:
1981 case Instruction::IF_LE:
1982 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
1983 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1984 if (failure != VERIFY_ERROR_NONE) {
1985 LOG(ERROR) << "VFY: args to 'if' must be cat-1nr";
1986 break;
1987 }
1988 tmp_type = GetRegisterType(work_line, dec_insn.vB_);
1989 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1990 if (failure != VERIFY_ERROR_NONE) {
1991 LOG(ERROR) << "VFY: args to 'if' must be cat-1nr";
1992 break;
1993 }
1994 break;
1995 case Instruction::IF_EQZ:
1996 case Instruction::IF_NEZ:
1997 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
1998 if (RegTypeIsReference(tmp_type))
1999 break;
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 case Instruction::IF_LTZ:
2005 case Instruction::IF_GEZ:
2006 case Instruction::IF_GTZ:
2007 case Instruction::IF_LEZ:
2008 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
2009 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
2010 if (failure != VERIFY_ERROR_NONE)
2011 LOG(ERROR) << "VFY: expected cat-1 arg to if";
2012 break;
2013
2014 case Instruction::AGET:
2015 tmp_type = kRegTypeConstInteger;
2016 goto aget_1nr_common;
2017 case Instruction::AGET_BOOLEAN:
2018 tmp_type = kRegTypeBoolean;
2019 goto aget_1nr_common;
2020 case Instruction::AGET_BYTE:
2021 tmp_type = kRegTypeByte;
2022 goto aget_1nr_common;
2023 case Instruction::AGET_CHAR:
2024 tmp_type = kRegTypeChar;
2025 goto aget_1nr_common;
2026 case Instruction::AGET_SHORT:
2027 tmp_type = kRegTypeShort;
2028 goto aget_1nr_common;
2029aget_1nr_common:
2030 {
2031 RegType src_type, index_type;
2032
2033 index_type = GetRegisterType(work_line, dec_insn.vC_);
2034 CheckArrayIndexType(method, index_type, &failure);
2035 if (failure != VERIFY_ERROR_NONE)
2036 break;
2037
2038 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2039 if (failure != VERIFY_ERROR_NONE)
2040 break;
2041 if (res_class != NULL) {
2042 /* verify the class */
2043 Class::PrimitiveType prim_type =
2044 res_class->GetComponentType()->GetPrimitiveType();
2045 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
2046 prim_type == Class::kPrimNot) {
2047 LOG(ERROR) << "VFY: invalid aget-1nr target "
2048 << res_class->GetDescriptor()->ToModifiedUtf8();
2049 failure = VERIFY_ERROR_GENERIC;
2050 break;
2051 }
2052
2053 /* make sure array type matches instruction */
2054 src_type = PrimitiveTypeToRegType(prim_type);
2055
2056 /* differentiate between float and int */
2057 if (src_type == kRegTypeFloat || src_type == kRegTypeInteger)
2058 tmp_type = src_type;
2059
2060 if (tmp_type != src_type) {
2061 LOG(ERROR) << "VFY: invalid aget-1nr, array type=" << src_type
2062 << " with inst type=" << tmp_type << " (on "
2063 << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
2064 failure = VERIFY_ERROR_GENERIC;
2065 break;
2066 }
2067
2068 }
2069 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2070 }
2071 break;
2072
2073 case Instruction::AGET_WIDE:
2074 {
2075 RegType dst_type, index_type;
2076
2077 index_type = GetRegisterType(work_line, dec_insn.vC_);
2078 CheckArrayIndexType(method, index_type, &failure);
2079 if (failure != VERIFY_ERROR_NONE)
2080 break;
2081
2082 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2083 if (failure != VERIFY_ERROR_NONE)
2084 break;
2085 if (res_class != NULL) {
2086 /* verify the class */
2087 Class::PrimitiveType prim_type =
2088 res_class->GetComponentType()->GetPrimitiveType();
2089 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
2090 prim_type == Class::kPrimNot) {
2091 LOG(ERROR) << "VFY: invalid aget-wide target "
2092 << res_class->GetDescriptor()->ToModifiedUtf8();
2093 failure = VERIFY_ERROR_GENERIC;
2094 break;
2095 }
2096
2097 /* try to refine "dst_type" */
2098 switch (prim_type) {
2099 case Class::kPrimLong:
2100 dst_type = kRegTypeLongLo;
2101 break;
2102 case Class::kPrimDouble:
2103 dst_type = kRegTypeDoubleLo;
2104 break;
2105 default:
2106 LOG(ERROR) << "VFY: invalid aget-wide on "
2107 << res_class->GetDescriptor()->ToModifiedUtf8();
2108 dst_type = kRegTypeUnknown;
2109 failure = VERIFY_ERROR_GENERIC;
2110 break;
2111 }
2112 } else {
2113 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002114 * Null array ref; this code path will fail at runtime. We
jeffhaobdb76512011-09-07 11:43:16 -07002115 * know this is either long or double, so label it const.
2116 */
2117 dst_type = kRegTypeConstLo;
2118 }
2119 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2120 }
2121 break;
2122
2123 case Instruction::AGET_OBJECT:
2124 {
2125 RegType dst_type, index_type;
2126
2127 index_type = GetRegisterType(work_line, dec_insn.vC_);
2128 CheckArrayIndexType(method, index_type, &failure);
2129 if (failure != VERIFY_ERROR_NONE)
2130 break;
2131
2132 /* get the class of the array we're pulling an object from */
2133 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2134 if (failure != VERIFY_ERROR_NONE)
2135 break;
2136 if (res_class != NULL) {
2137 Class* element_class;
2138
2139 assert(res_class != NULL);
2140 if (!res_class->IsArrayClass()) {
2141 LOG(ERROR) << "VFY: aget-object on non-array class";
2142 failure = VERIFY_ERROR_GENERIC;
2143 break;
2144 }
2145 assert(res_class->GetComponentType() != NULL);
2146
2147 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002148 * Find the element class. res_class->GetComponentType() indicates
jeffhaobdb76512011-09-07 11:43:16 -07002149 * the basic type, which won't be what we want for a
2150 * multi-dimensional array.
2151 */
2152 if (res_class->GetDescriptor()->CharAt(1) == '[') {
2153 assert(res_class->GetArrayRank() > 1);
2154 std::string descriptor =
2155 res_class->GetDescriptor()->ToModifiedUtf8();
2156 element_class = class_linker->FindClass(descriptor.c_str() + 1,
2157 res_class->GetClassLoader());
2158 } else if (res_class->GetDescriptor()->CharAt(1) == 'L') {
2159 assert(res_class->GetArrayRank() == 1);
2160 element_class = res_class->GetComponentType();
2161 } else {
2162 LOG(ERROR) << "VFY: aget-object on non-ref array class ("
2163 << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
2164 failure = VERIFY_ERROR_GENERIC;
2165 break;
2166 }
2167
2168 dst_type = RegTypeFromClass(element_class);
2169 } else {
2170 /*
2171 * The array reference is NULL, so the current code path will
jeffhaod1f0fde2011-09-08 17:25:33 -07002172 * throw an exception. For proper merging with later code
jeffhaobdb76512011-09-07 11:43:16 -07002173 * paths, and correct handling of "if-eqz" tests on the
2174 * result of the array get, we want to treat this as a null
2175 * reference.
2176 */
2177 dst_type = kRegTypeZero;
2178 }
2179 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2180 }
2181 break;
2182 case Instruction::APUT:
2183 tmp_type = kRegTypeInteger;
2184 goto aput_1nr_common;
2185 case Instruction::APUT_BOOLEAN:
2186 tmp_type = kRegTypeBoolean;
2187 goto aput_1nr_common;
2188 case Instruction::APUT_BYTE:
2189 tmp_type = kRegTypeByte;
2190 goto aput_1nr_common;
2191 case Instruction::APUT_CHAR:
2192 tmp_type = kRegTypeChar;
2193 goto aput_1nr_common;
2194 case Instruction::APUT_SHORT:
2195 tmp_type = kRegTypeShort;
2196 goto aput_1nr_common;
2197aput_1nr_common:
2198 {
2199 RegType src_type, dst_type, index_type;
2200
2201 index_type = GetRegisterType(work_line, dec_insn.vC_);
2202 CheckArrayIndexType(method, index_type, &failure);
2203 if (failure != VERIFY_ERROR_NONE)
2204 break;
2205
2206 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2207 if (failure != VERIFY_ERROR_NONE)
2208 break;
2209
2210 /* res_class can be null if the reg type is Zero */
2211 if (res_class == NULL)
2212 break;
2213
2214 Class::PrimitiveType prim_type =
2215 res_class->GetComponentType()->GetPrimitiveType();
2216 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
2217 prim_type == Class::kPrimNot) {
2218 LOG(ERROR) << "VFY: invalid aput-1nr on "
2219 << res_class->GetDescriptor()->ToModifiedUtf8();
2220 failure = VERIFY_ERROR_GENERIC;
2221 break;
2222 }
2223
2224 /* verify that instruction matches array */
2225 dst_type = PrimitiveTypeToRegType(prim_type);
2226
2227 /* correct if float */
2228 if (dst_type == kRegTypeFloat)
2229 tmp_type = kRegTypeFloat;
2230
2231 /* make sure the source register has the correct type */
2232 src_type = GetRegisterType(work_line, dec_insn.vA_);
2233 if (!CanConvertTo1nr(src_type, tmp_type)) {
2234 LOG(ERROR) << "VFY: invalid reg type " << src_type
2235 << " on aput instr (need " << tmp_type << ")";
2236 failure = VERIFY_ERROR_GENERIC;
2237 break;
2238 }
2239
2240 VerifyRegisterType(work_line, dec_insn.vA_, dst_type, &failure);
2241
2242 if (failure != VERIFY_ERROR_NONE || dst_type == kRegTypeUnknown ||
2243 tmp_type != dst_type) {
2244 LOG(ERROR) << "VFY: invalid aput-1nr on "
2245 << res_class->GetDescriptor()->ToModifiedUtf8()
2246 << " (inst=" << tmp_type << " dst=" << dst_type << ")";
2247 failure = VERIFY_ERROR_GENERIC;
2248 break;
2249 }
2250 }
2251 break;
2252 case Instruction::APUT_WIDE:
2253 tmp_type = GetRegisterType(work_line, dec_insn.vC_);
2254 CheckArrayIndexType(method, tmp_type, &failure);
2255 if (failure != VERIFY_ERROR_NONE)
2256 break;
2257
2258 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2259 if (failure != VERIFY_ERROR_NONE)
2260 break;
2261 if (res_class != NULL) {
2262 Class::PrimitiveType prim_type =
2263 res_class->GetComponentType()->GetPrimitiveType();
2264 /* verify the class and try to refine "dst_type" */
2265 if (!res_class->IsArrayClass() || res_class->GetArrayRank() != 1 ||
2266 prim_type == Class::kPrimNot)
2267 {
2268 LOG(ERROR) << "VFY: invalid aput-wide on "
2269 << res_class->GetDescriptor()->ToModifiedUtf8();
2270 failure = VERIFY_ERROR_GENERIC;
2271 break;
2272 }
2273
2274 switch (prim_type) {
2275 case Class::kPrimLong:
2276 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo,
2277 &failure);
2278 break;
2279 case Class::kPrimDouble:
2280 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2281 &failure);
2282 break;
2283 default:
2284 LOG(ERROR) << "VFY: invalid aput-wide on "
2285 << res_class->GetDescriptor()->ToModifiedUtf8();
2286 failure = VERIFY_ERROR_GENERIC;
2287 break;
2288 }
2289 }
2290 break;
2291 case Instruction::APUT_OBJECT:
2292 tmp_type = GetRegisterType(work_line, dec_insn.vC_);
2293 CheckArrayIndexType(method, tmp_type, &failure);
2294 if (failure != VERIFY_ERROR_NONE)
2295 break;
2296
2297 /* get the ref we're storing; Zero is okay, Uninit is not */
2298 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
2299 if (failure != VERIFY_ERROR_NONE)
2300 break;
2301 if (res_class != NULL) {
2302 Class* array_class;
2303 Class* element_class;
2304
2305 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002306 * Get the array class. If the array ref is null, we won't
jeffhaobdb76512011-09-07 11:43:16 -07002307 * have type information (and we'll crash at runtime with a
2308 * null pointer exception).
2309 */
2310 array_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2311
2312 if (array_class != NULL) {
2313 /* see if the array holds a compatible type */
2314 if (!array_class->IsArrayClass()) {
2315 LOG(ERROR) << "VFY: invalid aput-object on "
2316 << array_class->GetDescriptor()->ToModifiedUtf8();
2317 failure = VERIFY_ERROR_GENERIC;
2318 break;
2319 }
2320
2321 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002322 * Find the element class. res_class->GetComponentType() indicates
jeffhaobdb76512011-09-07 11:43:16 -07002323 * the basic type, which won't be what we want for a
2324 * multi-dimensional array.
2325 *
2326 * All we want to check here is that the element type is a
jeffhaod1f0fde2011-09-08 17:25:33 -07002327 * reference class. We *don't* check instanceof here, because
jeffhaobdb76512011-09-07 11:43:16 -07002328 * you can still put a String into a String[] after the latter
2329 * has been cast to an Object[].
2330 */
2331 if (array_class->GetDescriptor()->CharAt(1) == '[') {
2332 assert(array_class->GetArrayRank() > 1);
2333 std::string descriptor =
2334 array_class->GetDescriptor()->ToModifiedUtf8();
2335 element_class = class_linker->FindClass(descriptor.c_str() + 1,
2336 array_class->GetClassLoader());
2337 } else {
2338 assert(array_class->GetArrayRank() == 1);
2339 element_class = array_class->GetComponentType();
2340 }
2341 if (element_class->GetPrimitiveType() != Class::kPrimNot) {
2342 LOG(ERROR) << "VFY: invalid aput-object of "
2343 << res_class->GetDescriptor()->ToModifiedUtf8()
2344 << " into "
2345 << array_class->GetDescriptor()->ToModifiedUtf8();
2346 failure = VERIFY_ERROR_GENERIC;
2347 break;
2348 }
2349 }
2350 }
2351 break;
2352
2353 case Instruction::IGET:
2354 tmp_type = kRegTypeInteger;
2355 goto iget_1nr_common;
2356 case Instruction::IGET_BOOLEAN:
2357 tmp_type = kRegTypeBoolean;
2358 goto iget_1nr_common;
2359 case Instruction::IGET_BYTE:
2360 tmp_type = kRegTypeByte;
2361 goto iget_1nr_common;
2362 case Instruction::IGET_CHAR:
2363 tmp_type = kRegTypeChar;
2364 goto iget_1nr_common;
2365 case Instruction::IGET_SHORT:
2366 tmp_type = kRegTypeShort;
2367 goto iget_1nr_common;
2368iget_1nr_common:
2369 {
2370 Field* inst_field;
2371 RegType obj_type, field_type;
2372
2373 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2374 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2375 if (failure != VERIFY_ERROR_NONE)
2376 break;
2377
2378 /* make sure the field's type is compatible with expectation */
2379 field_type =
2380 PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
2381
2382 /* correct if float */
2383 if (field_type == kRegTypeFloat)
2384 tmp_type = kRegTypeFloat;
2385
2386 if (field_type == kRegTypeUnknown || tmp_type != field_type) {
2387 Class* inst_field_class = inst_field->GetDeclaringClass();
2388 LOG(ERROR) << "VFY: invalid iget-1nr of "
2389 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2390 << "." << inst_field->GetName()->ToModifiedUtf8()
2391 << " (inst=" << tmp_type << " field=" << field_type << ")";
2392 failure = VERIFY_ERROR_GENERIC;
2393 break;
2394 }
2395
2396 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2397 }
2398 break;
2399 case Instruction::IGET_WIDE:
2400 {
2401 RegType dst_type;
2402 Field* inst_field;
2403 RegType obj_type;
2404
2405 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2406 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2407 Class* inst_field_class = inst_field->GetDeclaringClass();
2408 if (failure != VERIFY_ERROR_NONE)
2409 break;
2410 /* check the type, which should be prim */
2411 switch (inst_field->GetType()->GetPrimitiveType()) {
2412 case Class::kPrimDouble:
2413 dst_type = kRegTypeDoubleLo;
2414 break;
2415 case Class::kPrimLong:
2416 dst_type = kRegTypeLongLo;
2417 break;
2418 default:
2419 LOG(ERROR) << "VFY: invalid iget-wide of "
2420 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2421 << "." << inst_field->GetName()->ToModifiedUtf8();
2422 dst_type = kRegTypeUnknown;
2423 failure = VERIFY_ERROR_GENERIC;
2424 break;
2425 }
2426 if (failure == VERIFY_ERROR_NONE) {
2427 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2428 }
2429 }
2430 break;
2431 case Instruction::IGET_OBJECT:
2432 {
2433 Class* field_class;
2434 Field* inst_field;
2435 RegType obj_type;
2436
2437 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2438 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2439 if (failure != VERIFY_ERROR_NONE)
2440 break;
2441 field_class = inst_field->GetType();
2442 if (field_class == NULL) {
2443 /* class not found or primitive type */
2444 LOG(ERROR) << "VFY: unable to recover field class from "
2445 << inst_field->GetName()->ToModifiedUtf8();
2446 failure = VERIFY_ERROR_GENERIC;
2447 break;
2448 }
2449 if (failure == VERIFY_ERROR_NONE) {
2450 assert(!field_class->IsPrimitive());
2451 SetRegisterType(work_line, dec_insn.vA_,
2452 RegTypeFromClass(field_class));
2453 }
2454 }
2455 break;
2456 case Instruction::IPUT:
2457 tmp_type = kRegTypeInteger;
2458 goto iput_1nr_common;
2459 case Instruction::IPUT_BOOLEAN:
2460 tmp_type = kRegTypeBoolean;
2461 goto iput_1nr_common;
2462 case Instruction::IPUT_BYTE:
2463 tmp_type = kRegTypeByte;
2464 goto iput_1nr_common;
2465 case Instruction::IPUT_CHAR:
2466 tmp_type = kRegTypeChar;
2467 goto iput_1nr_common;
2468 case Instruction::IPUT_SHORT:
2469 tmp_type = kRegTypeShort;
2470 goto iput_1nr_common;
2471iput_1nr_common:
2472 {
2473 RegType src_type, field_type, obj_type;
2474 Field* inst_field;
2475
2476 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2477 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2478 if (failure != VERIFY_ERROR_NONE)
2479 break;
2480 CheckFinalFieldAccess(method, inst_field, &failure);
2481 if (failure != VERIFY_ERROR_NONE)
2482 break;
2483
2484 /* get type of field we're storing into */
2485 field_type =
2486 PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
2487 src_type = GetRegisterType(work_line, dec_insn.vA_);
2488
2489 /* correct if float */
2490 if (field_type == kRegTypeFloat)
2491 tmp_type = kRegTypeFloat;
2492
2493 /*
2494 * compiler can generate synthetic functions that write byte values
2495 * into boolean fields.
2496 */
2497 if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
2498 tmp_type = kRegTypeByte;
2499 if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
2500 field_type = kRegTypeByte;
2501
2502 /* make sure the source register has the correct type */
2503 if (!CanConvertTo1nr(src_type, tmp_type)) {
2504 LOG(ERROR) << "VFY: invalid reg type " << src_type
2505 << " on iput instr (need " << tmp_type << ")",
2506 failure = VERIFY_ERROR_GENERIC;
2507 break;
2508 }
2509
2510 VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);
2511
2512 if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
2513 tmp_type != field_type) {
2514 Class* inst_field_class = inst_field->GetDeclaringClass();
2515 LOG(ERROR) << "VFY: invalid iput-1nr of "
2516 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2517 << "." << inst_field->GetName()->ToModifiedUtf8()
2518 << " (inst=" << tmp_type << " field=" << field_type << ")";
2519 failure = VERIFY_ERROR_GENERIC;
2520 break;
2521 }
2522 }
2523 break;
2524 case Instruction::IPUT_WIDE:
2525 Field* inst_field;
2526 RegType obj_type;
2527
2528 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2529 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2530 if (failure != VERIFY_ERROR_NONE)
2531 break;
2532 CheckFinalFieldAccess(method, inst_field, &failure);
2533 if (failure != VERIFY_ERROR_NONE)
2534 break;
2535
2536 /* check the type, which should be prim */
2537 switch (inst_field->GetType()->GetPrimitiveType()) {
2538 case Class::kPrimDouble:
2539 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2540 &failure);
2541 break;
2542 case Class::kPrimLong:
2543 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
2544 break;
2545 default:
2546 LOG(ERROR) << "VFY: invalid iput-wide of "
2547 << inst_field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
2548 << "." << inst_field->GetName()->ToModifiedUtf8();
2549 failure = VERIFY_ERROR_GENERIC;
2550 break;
2551 }
2552 break;
2553 case Instruction::IPUT_OBJECT:
2554 {
2555 Class* field_class;
2556 Class* value_class;
2557 Field* inst_field;
2558 RegType obj_type, value_type;
2559
2560 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2561 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2562 if (failure != VERIFY_ERROR_NONE)
2563 break;
2564 CheckFinalFieldAccess(method, inst_field, &failure);
2565 if (failure != VERIFY_ERROR_NONE)
2566 break;
2567
2568 field_class = inst_field->GetType();
2569 if (field_class == NULL) {
2570 LOG(ERROR) << "VFY: unable to recover field class from '"
2571 << inst_field->GetName()->ToModifiedUtf8() << "'";
2572 failure = VERIFY_ERROR_GENERIC;
2573 break;
2574 }
2575
2576 value_type = GetRegisterType(work_line, dec_insn.vA_);
2577 if (!RegTypeIsReference(value_type)) {
2578 LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
2579 << " into ref field '"
2580 << inst_field->GetName()->ToModifiedUtf8() << "' ("
2581 << field_class->GetDescriptor()->ToModifiedUtf8() << ")";
2582 failure = VERIFY_ERROR_GENERIC;
2583 break;
2584 }
2585 if (value_type != kRegTypeZero) {
2586 value_class = RegTypeInitializedReferenceToClass(value_type);
2587 if (value_class == NULL) {
2588 LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
2589 << " into ref field";
2590 failure = VERIFY_ERROR_GENERIC;
2591 break;
2592 }
2593 /* allow if field is any interface or field is base class */
2594 if (!field_class->IsInterface() &&
2595 !field_class->IsAssignableFrom(value_class)) {
2596 Class* inst_field_class = inst_field->GetDeclaringClass();
2597 LOG(ERROR) << "VFY: storing type '"
2598 << value_class->GetDescriptor()->ToModifiedUtf8()
2599 << "' into field type '"
2600 << field_class->GetDescriptor()->ToModifiedUtf8()
2601 << "' ("
2602 << inst_field_class->GetDescriptor()->ToModifiedUtf8()
2603 << "." << inst_field->GetName()->ToModifiedUtf8() << ")";
2604 failure = VERIFY_ERROR_GENERIC;
2605 break;
2606 }
2607 }
2608 }
2609 break;
2610
2611 case Instruction::SGET:
2612 tmp_type = kRegTypeInteger;
2613 goto sget_1nr_common;
2614 case Instruction::SGET_BOOLEAN:
2615 tmp_type = kRegTypeBoolean;
2616 goto sget_1nr_common;
2617 case Instruction::SGET_BYTE:
2618 tmp_type = kRegTypeByte;
2619 goto sget_1nr_common;
2620 case Instruction::SGET_CHAR:
2621 tmp_type = kRegTypeChar;
2622 goto sget_1nr_common;
2623 case Instruction::SGET_SHORT:
2624 tmp_type = kRegTypeShort;
2625 goto sget_1nr_common;
2626sget_1nr_common:
2627 {
2628 Field* static_field;
2629 RegType field_type;
2630
2631 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2632 if (failure != VERIFY_ERROR_NONE)
2633 break;
2634
2635 /*
2636 * Make sure the field's type is compatible with expectation.
2637 * We can get ourselves into trouble if we mix & match loads
2638 * and stores with different widths, so rather than just checking
2639 * "CanConvertTo1nr" we require that the field types have equal
2640 * widths.
2641 */
2642 field_type =
2643 PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
2644
2645 /* correct if float */
2646 if (field_type == kRegTypeFloat)
2647 tmp_type = kRegTypeFloat;
2648
2649 if (tmp_type != field_type) {
2650 Class* static_field_class = static_field->GetDeclaringClass();
2651 LOG(ERROR) << "VFY: invalid sget-1nr of "
2652 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2653 << "." << static_field->GetName()->ToModifiedUtf8()
2654 << " (inst=" << tmp_type << " actual=" << field_type
2655 << ")";
2656 failure = VERIFY_ERROR_GENERIC;
2657 break;
2658 }
2659
2660 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2661 }
2662 break;
2663 case Instruction::SGET_WIDE:
2664 {
2665 Field* static_field;
2666 RegType dst_type;
2667
2668 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2669 Class* static_field_class = static_field->GetDeclaringClass();
2670 if (failure != VERIFY_ERROR_NONE)
2671 break;
2672 /* check the type, which should be prim */
2673 switch (static_field->GetType()->GetPrimitiveType()) {
2674 case Class::kPrimDouble:
2675 dst_type = kRegTypeDoubleLo;
2676 break;
2677 case Class::kPrimLong:
2678 dst_type = kRegTypeLongLo;
2679 break;
2680 default:
2681 LOG(ERROR) << "VFY: invalid sget-wide of "
2682 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2683 << "." << static_field->GetName()->ToModifiedUtf8();
2684 dst_type = kRegTypeUnknown;
2685 failure = VERIFY_ERROR_GENERIC;
2686 break;
2687 }
2688 if (failure == VERIFY_ERROR_NONE) {
2689 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2690 }
2691 }
2692 break;
2693 case Instruction::SGET_OBJECT:
2694 {
2695 Field* static_field;
2696 Class* field_class;
2697
2698 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2699 if (failure != VERIFY_ERROR_NONE)
2700 break;
2701 field_class = static_field->GetType();
2702 if (field_class == NULL) {
2703 LOG(ERROR) << "VFY: unable to recover field class from '"
2704 << static_field->GetName()->ToModifiedUtf8() << "'";
2705 failure = VERIFY_ERROR_GENERIC;
2706 break;
2707 }
2708 if (field_class->IsPrimitive()) {
2709 LOG(ERROR) << "VFY: attempt to get prim field with sget-object";
2710 failure = VERIFY_ERROR_GENERIC;
2711 break;
2712 }
2713 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(field_class));
2714 }
2715 break;
2716 case Instruction::SPUT:
2717 tmp_type = kRegTypeInteger;
2718 goto sput_1nr_common;
2719 case Instruction::SPUT_BOOLEAN:
2720 tmp_type = kRegTypeBoolean;
2721 goto sput_1nr_common;
2722 case Instruction::SPUT_BYTE:
2723 tmp_type = kRegTypeByte;
2724 goto sput_1nr_common;
2725 case Instruction::SPUT_CHAR:
2726 tmp_type = kRegTypeChar;
2727 goto sput_1nr_common;
2728 case Instruction::SPUT_SHORT:
2729 tmp_type = kRegTypeShort;
2730 goto sput_1nr_common;
2731sput_1nr_common:
2732 {
2733 RegType src_type, field_type;
2734 Field* static_field;
2735
2736 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2737 if (failure != VERIFY_ERROR_NONE)
2738 break;
2739 CheckFinalFieldAccess(method, static_field, &failure);
2740 if (failure != VERIFY_ERROR_NONE)
2741 break;
2742
2743 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002744 * Get type of field we're storing into. We know that the
jeffhaobdb76512011-09-07 11:43:16 -07002745 * contents of the register match the instruction, but we also
2746 * need to ensure that the instruction matches the field type.
2747 * Using e.g. sput-short to write into a 32-bit integer field
2748 * can lead to trouble if we do 16-bit writes.
2749 */
2750 field_type =
2751 PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
2752 src_type = GetRegisterType(work_line, dec_insn.vA_);
2753
2754 /* correct if float */
2755 if (field_type == kRegTypeFloat)
2756 tmp_type = kRegTypeFloat;
2757
2758 /*
2759 * compiler can generate synthetic functions that write byte values
2760 * into boolean fields.
2761 */
2762 if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
2763 tmp_type = kRegTypeByte;
2764 if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
2765 field_type = kRegTypeByte;
2766
2767 /* make sure the source register has the correct type */
2768 if (!CanConvertTo1nr(src_type, tmp_type)) {
2769 LOG(ERROR) << "VFY: invalid reg type " << src_type
2770 << " on sput instr (need " << tmp_type << ")";
2771 failure = VERIFY_ERROR_GENERIC;
2772 break;
2773 }
2774
2775 VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);
2776
2777 if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
2778 tmp_type != field_type) {
2779 Class* static_field_class = static_field->GetDeclaringClass();
2780 LOG(ERROR) << "VFY: invalid sput-1nr of "
2781 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2782 << "." << static_field->GetName()->ToModifiedUtf8()
2783 << " (inst=" << tmp_type << " actual=" << field_type
2784 << ")";
2785 failure = VERIFY_ERROR_GENERIC;
2786 break;
2787 }
2788 }
2789 break;
2790 case Instruction::SPUT_WIDE:
2791 Field* static_field;
2792
2793 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2794 if (failure != VERIFY_ERROR_NONE)
2795 break;
2796 CheckFinalFieldAccess(method, static_field, &failure);
2797 if (failure != VERIFY_ERROR_NONE)
2798 break;
2799
2800 /* check the type, which should be prim */
2801 switch (static_field->GetType()->GetPrimitiveType()) {
2802 case Class::kPrimDouble:
2803 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2804 &failure);
2805 break;
2806 case Class::kPrimLong:
2807 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
2808 break;
2809 default:
2810 LOG(ERROR) << "VFY: invalid sput-wide of "
2811 << static_field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
2812 << "." << static_field->GetName()->ToModifiedUtf8();
2813 failure = VERIFY_ERROR_GENERIC;
2814 break;
2815 }
2816 break;
2817 case Instruction::SPUT_OBJECT:
2818 {
2819 Class* field_class;
2820 Class* value_class;
2821 Field* static_field;
2822 RegType value_type;
2823
2824 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2825 if (failure != VERIFY_ERROR_NONE)
2826 break;
2827 CheckFinalFieldAccess(method, static_field, &failure);
2828 if (failure != VERIFY_ERROR_NONE)
2829 break;
2830
2831 field_class = static_field->GetType();
2832 if (field_class == NULL) {
2833 LOG(ERROR) << "VFY: unable to recover field class from '"
2834 << static_field->GetName()->ToModifiedUtf8() << "'";
2835 failure = VERIFY_ERROR_GENERIC;
2836 break;
2837 }
2838
2839 value_type = GetRegisterType(work_line, dec_insn.vA_);
2840 if (!RegTypeIsReference(value_type)) {
2841 LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
2842 << " into ref field '"
2843 << static_field->GetName()->ToModifiedUtf8() << "' ("
2844 << field_class->GetDescriptor()->ToModifiedUtf8() << ")",
2845 failure = VERIFY_ERROR_GENERIC;
2846 break;
2847 }
2848 if (value_type != kRegTypeZero) {
2849 value_class = RegTypeInitializedReferenceToClass(value_type);
2850 if (value_class == NULL) {
2851 LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
2852 << " into ref field";
2853 failure = VERIFY_ERROR_GENERIC;
2854 break;
2855 }
2856 /* allow if field is any interface or field is base class */
2857 if (!field_class->IsInterface() &&
2858 !field_class->IsAssignableFrom(value_class)) {
2859 Class* static_field_class = static_field->GetDeclaringClass();
2860 LOG(ERROR) << "VFY: storing type '"
2861 << value_class->GetDescriptor()->ToModifiedUtf8()
2862 << "' into field type '"
2863 << field_class->GetDescriptor()->ToModifiedUtf8()
2864 << "' ("
2865 << static_field_class->GetDescriptor()->ToModifiedUtf8()
2866 << "." << static_field->GetName()->ToModifiedUtf8()
2867 << ")",
2868 failure = VERIFY_ERROR_GENERIC;
2869 break;
2870 }
2871 }
2872 }
2873 break;
2874
2875 case Instruction::INVOKE_VIRTUAL:
2876 case Instruction::INVOKE_VIRTUAL_RANGE:
2877 case Instruction::INVOKE_SUPER:
2878 case Instruction::INVOKE_SUPER_RANGE:
2879 {
2880 Method* called_method;
2881 RegType return_type;
2882 bool is_range;
2883 bool is_super;
2884
2885 is_range = (dec_insn.opcode_ == Instruction::INVOKE_VIRTUAL_RANGE ||
2886 dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
2887 is_super = (dec_insn.opcode_ == Instruction::INVOKE_SUPER ||
2888 dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
2889
2890 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2891 &dec_insn, METHOD_VIRTUAL, is_range, is_super, &failure);
2892 if (failure != VERIFY_ERROR_NONE)
2893 break;
2894 return_type = GetMethodReturnType(dex_file, called_method);
2895 SetResultRegisterType(work_line, registers_size, return_type);
2896 just_set_result = true;
2897 }
2898 break;
2899 case Instruction::INVOKE_DIRECT:
2900 case Instruction::INVOKE_DIRECT_RANGE:
2901 {
2902 RegType return_type;
2903 Method* called_method;
2904 bool is_range;
2905
2906 is_range = (dec_insn.opcode_ == Instruction::INVOKE_DIRECT_RANGE);
2907 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2908 &dec_insn, METHOD_DIRECT, is_range, false, &failure);
2909 if (failure != VERIFY_ERROR_NONE)
2910 break;
2911
2912 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002913 * Some additional checks when calling <init>. We know from
jeffhaobdb76512011-09-07 11:43:16 -07002914 * the invocation arg check that the "this" argument is an
jeffhaod1f0fde2011-09-08 17:25:33 -07002915 * instance of called_method->klass. Now we further restrict
jeffhaobdb76512011-09-07 11:43:16 -07002916 * that to require that called_method->klass is the same as
2917 * this->klass or this->super, allowing the latter only if
2918 * the "this" argument is the same as the "this" argument to
2919 * this method (which implies that we're in <init> ourselves).
2920 */
2921 if (IsInitMethod(called_method)) {
2922 RegType this_type;
2923 this_type = GetInvocationThis(work_line, &dec_insn, &failure);
2924 if (failure != VERIFY_ERROR_NONE)
2925 break;
2926
2927 /* no null refs allowed (?) */
2928 if (this_type == kRegTypeZero) {
2929 LOG(ERROR) << "VFY: unable to initialize null ref";
2930 failure = VERIFY_ERROR_GENERIC;
2931 break;
2932 }
2933
2934 Class* this_class;
2935
2936 this_class = RegTypeReferenceToClass(this_type, uninit_map);
2937 assert(this_class != NULL);
2938
2939 /* must be in same class or in superclass */
2940 if (called_method->GetDeclaringClass() == this_class->GetSuperClass())
2941 {
2942 if (this_class != method->GetDeclaringClass()) {
2943 LOG(ERROR) << "VFY: invoke-direct <init> on super only "
2944 << "allowed for 'this' in <init>";
2945 failure = VERIFY_ERROR_GENERIC;
2946 break;
2947 }
2948 } else if (called_method->GetDeclaringClass() != this_class) {
2949 LOG(ERROR) << "VFY: invoke-direct <init> must be on current "
2950 << "class or super";
2951 failure = VERIFY_ERROR_GENERIC;
2952 break;
2953 }
2954
2955 /* arg must be an uninitialized reference */
2956 if (!RegTypeIsUninitReference(this_type)) {
2957 LOG(ERROR) << "VFY: can only initialize the uninitialized";
2958 failure = VERIFY_ERROR_GENERIC;
2959 break;
2960 }
2961
2962 /*
2963 * Replace the uninitialized reference with an initialized
jeffhaod1f0fde2011-09-08 17:25:33 -07002964 * one, and clear the entry in the uninit map. We need to
jeffhaobdb76512011-09-07 11:43:16 -07002965 * do this for all registers that have the same object
2966 * instance in them, not just the "this" register.
2967 */
2968 MarkRefsAsInitialized(work_line, registers_size, uninit_map,
2969 this_type, &failure);
2970 if (failure != VERIFY_ERROR_NONE)
2971 break;
2972 }
2973 return_type = GetMethodReturnType(dex_file, called_method);
2974 SetResultRegisterType(work_line, registers_size, return_type);
2975 just_set_result = true;
2976 }
2977 break;
2978 case Instruction::INVOKE_STATIC:
2979 case Instruction::INVOKE_STATIC_RANGE:
2980 {
2981 RegType return_type;
2982 Method* called_method;
2983 bool is_range;
2984
2985 is_range = (dec_insn.opcode_ == Instruction::INVOKE_STATIC_RANGE);
2986 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2987 &dec_insn, METHOD_STATIC, is_range, false, &failure);
2988 if (failure != VERIFY_ERROR_NONE)
2989 break;
2990
2991 return_type = GetMethodReturnType(dex_file, called_method);
2992 SetResultRegisterType(work_line, registers_size, return_type);
2993 just_set_result = true;
2994 }
2995 break;
2996 case Instruction::INVOKE_INTERFACE:
2997 case Instruction::INVOKE_INTERFACE_RANGE:
2998 {
2999 RegType /*this_type,*/ return_type;
3000 Method* abs_method;
3001 bool is_range;
3002
3003 is_range = (dec_insn.opcode_ == Instruction::INVOKE_INTERFACE_RANGE);
3004 abs_method = VerifyInvocationArgs(vdata, work_line, registers_size,
3005 &dec_insn, METHOD_INTERFACE, is_range, false, &failure);
3006 if (failure != VERIFY_ERROR_NONE)
3007 break;
3008
3009#if 0 /* can't do this here, fails on dalvik test 052-verifier-fun */
3010 /*
3011 * Get the type of the "this" arg, which should always be an
jeffhaod1f0fde2011-09-08 17:25:33 -07003012 * interface class. Because we don't do a full merge on
jeffhaobdb76512011-09-07 11:43:16 -07003013 * interface classes, this might have reduced to Object.
3014 */
3015 this_type = GetInvocationThis(work_line, &dec_insn, &failure);
3016 if (failure != VERIFY_ERROR_NONE)
3017 break;
3018
3019 if (this_type == kRegTypeZero) {
3020 /* null pointer always passes (and always fails at runtime) */
3021 } else {
3022 Class* this_class;
3023
3024 this_class = RegTypeInitializedReferenceToClass(this_type);
3025 if (this_class == NULL) {
3026 LOG(ERROR) << "VFY: interface call on uninitialized";
3027 failure = VERIFY_ERROR_GENERIC;
3028 break;
3029 }
3030
3031 /*
3032 * Either "this_class" needs to be the interface class that
3033 * defined abs_method, or abs_method's class needs to be one
jeffhaod1f0fde2011-09-08 17:25:33 -07003034 * of the interfaces implemented by "this_class". (Or, if
jeffhaobdb76512011-09-07 11:43:16 -07003035 * we couldn't complete the merge, this will be Object.)
3036 */
3037 if (this_class != abs_method->GetDeclaringClass() &&
3038 this_class != class_linker->FindSystemClass("Ljava/lang/Object;") &&
3039 !this_class->Implements(abs_method->GetDeclaringClass())) {
3040 LOG(ERROR) << "VFY: unable to match abs_method '"
3041 << abs_method->GetName()->ToModifiedUtf8() << "' with "
3042 << this_class->GetDescriptor()->ToModifiedUtf8()
3043 << " interfaces";
3044 failure = VERIFY_ERROR_GENERIC;
3045 break;
3046 }
3047 }
3048#endif
3049
3050 /*
3051 * We don't have an object instance, so we can't find the
jeffhaod1f0fde2011-09-08 17:25:33 -07003052 * concrete method. However, all of the type information is
jeffhaobdb76512011-09-07 11:43:16 -07003053 * in the abstract method, so we're good.
3054 */
3055 return_type = GetMethodReturnType(dex_file, abs_method);
3056 SetResultRegisterType(work_line, registers_size, return_type);
3057 just_set_result = true;
3058 }
3059 break;
3060
3061 case Instruction::NEG_INT:
3062 case Instruction::NOT_INT:
3063 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3064 &failure);
3065 break;
3066 case Instruction::NEG_LONG:
3067 case Instruction::NOT_LONG:
3068 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo, &failure);
3069 break;
3070 case Instruction::NEG_FLOAT:
3071 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat, &failure);
3072 break;
3073 case Instruction::NEG_DOUBLE:
3074 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3075 &failure);
3076 break;
3077 case Instruction::INT_TO_LONG:
3078 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeInteger,
3079 &failure);
3080 break;
3081 case Instruction::INT_TO_FLOAT:
3082 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeInteger, &failure);
3083 break;
3084 case Instruction::INT_TO_DOUBLE:
3085 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeInteger,
3086 &failure);
3087 break;
3088 case Instruction::LONG_TO_INT:
3089 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeLongLo,
3090 &failure);
3091 break;
3092 case Instruction::LONG_TO_FLOAT:
3093 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeLongLo, &failure);
3094 break;
3095 case Instruction::LONG_TO_DOUBLE:
3096 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeLongLo,
3097 &failure);
3098 break;
3099 case Instruction::FLOAT_TO_INT:
3100 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeFloat, &failure);
3101 break;
3102 case Instruction::FLOAT_TO_LONG:
3103 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeFloat, &failure);
3104 break;
3105 case Instruction::FLOAT_TO_DOUBLE:
3106 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeFloat,
3107 &failure);
3108 break;
3109 case Instruction::DOUBLE_TO_INT:
3110 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeDoubleLo,
3111 &failure);
3112 break;
3113 case Instruction::DOUBLE_TO_LONG:
3114 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeDoubleLo,
3115 &failure);
3116 break;
3117 case Instruction::DOUBLE_TO_FLOAT:
3118 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeDoubleLo,
3119 &failure);
3120 break;
3121 case Instruction::INT_TO_BYTE:
3122 CheckUnop(work_line, &dec_insn, kRegTypeByte, kRegTypeInteger, &failure);
3123 break;
3124 case Instruction::INT_TO_CHAR:
3125 CheckUnop(work_line, &dec_insn, kRegTypeChar, kRegTypeInteger, &failure);
3126 break;
3127 case Instruction::INT_TO_SHORT:
3128 CheckUnop(work_line, &dec_insn, kRegTypeShort, kRegTypeInteger, &failure);
3129 break;
3130
3131 case Instruction::ADD_INT:
3132 case Instruction::SUB_INT:
3133 case Instruction::MUL_INT:
3134 case Instruction::REM_INT:
3135 case Instruction::DIV_INT:
3136 case Instruction::SHL_INT:
3137 case Instruction::SHR_INT:
3138 case Instruction::USHR_INT:
3139 CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3140 kRegTypeInteger, false, &failure);
3141 break;
3142 case Instruction::AND_INT:
3143 case Instruction::OR_INT:
3144 case Instruction::XOR_INT:
3145 CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3146 kRegTypeInteger, true, &failure);
3147 break;
3148 case Instruction::ADD_LONG:
3149 case Instruction::SUB_LONG:
3150 case Instruction::MUL_LONG:
3151 case Instruction::DIV_LONG:
3152 case Instruction::REM_LONG:
3153 case Instruction::AND_LONG:
3154 case Instruction::OR_LONG:
3155 case Instruction::XOR_LONG:
3156 CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3157 kRegTypeLongLo, false, &failure);
3158 break;
3159 case Instruction::SHL_LONG:
3160 case Instruction::SHR_LONG:
3161 case Instruction::USHR_LONG:
3162 /* shift distance is Int, making these different from other binops */
3163 CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3164 kRegTypeInteger, false, &failure);
3165 break;
3166 case Instruction::ADD_FLOAT:
3167 case Instruction::SUB_FLOAT:
3168 case Instruction::MUL_FLOAT:
3169 case Instruction::DIV_FLOAT:
3170 case Instruction::REM_FLOAT:
3171 CheckBinop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
3172 kRegTypeFloat, false, &failure);
3173 break;
3174 case Instruction::ADD_DOUBLE:
3175 case Instruction::SUB_DOUBLE:
3176 case Instruction::MUL_DOUBLE:
3177 case Instruction::DIV_DOUBLE:
3178 case Instruction::REM_DOUBLE:
3179 CheckBinop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3180 kRegTypeDoubleLo, false, &failure);
3181 break;
3182 case Instruction::ADD_INT_2ADDR:
3183 case Instruction::SUB_INT_2ADDR:
3184 case Instruction::MUL_INT_2ADDR:
3185 case Instruction::REM_INT_2ADDR:
3186 case Instruction::SHL_INT_2ADDR:
3187 case Instruction::SHR_INT_2ADDR:
3188 case Instruction::USHR_INT_2ADDR:
3189 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3190 kRegTypeInteger, false, &failure);
3191 break;
3192 case Instruction::AND_INT_2ADDR:
3193 case Instruction::OR_INT_2ADDR:
3194 case Instruction::XOR_INT_2ADDR:
3195 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3196 kRegTypeInteger, true, &failure);
3197 break;
3198 case Instruction::DIV_INT_2ADDR:
3199 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3200 kRegTypeInteger, false, &failure);
3201 break;
3202 case Instruction::ADD_LONG_2ADDR:
3203 case Instruction::SUB_LONG_2ADDR:
3204 case Instruction::MUL_LONG_2ADDR:
3205 case Instruction::DIV_LONG_2ADDR:
3206 case Instruction::REM_LONG_2ADDR:
3207 case Instruction::AND_LONG_2ADDR:
3208 case Instruction::OR_LONG_2ADDR:
3209 case Instruction::XOR_LONG_2ADDR:
3210 CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3211 kRegTypeLongLo, false, &failure);
3212 break;
3213 case Instruction::SHL_LONG_2ADDR:
3214 case Instruction::SHR_LONG_2ADDR:
3215 case Instruction::USHR_LONG_2ADDR:
3216 CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3217 kRegTypeInteger, false, &failure);
3218 break;
3219 case Instruction::ADD_FLOAT_2ADDR:
3220 case Instruction::SUB_FLOAT_2ADDR:
3221 case Instruction::MUL_FLOAT_2ADDR:
3222 case Instruction::DIV_FLOAT_2ADDR:
3223 case Instruction::REM_FLOAT_2ADDR:
3224 CheckBinop2addr(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
3225 kRegTypeFloat, false, &failure);
3226 break;
3227 case Instruction::ADD_DOUBLE_2ADDR:
3228 case Instruction::SUB_DOUBLE_2ADDR:
3229 case Instruction::MUL_DOUBLE_2ADDR:
3230 case Instruction::DIV_DOUBLE_2ADDR:
3231 case Instruction::REM_DOUBLE_2ADDR:
3232 CheckBinop2addr(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3233 kRegTypeDoubleLo, false, &failure);
3234 break;
3235 case Instruction::ADD_INT_LIT16:
3236 case Instruction::RSUB_INT:
3237 case Instruction::MUL_INT_LIT16:
3238 case Instruction::DIV_INT_LIT16:
3239 case Instruction::REM_INT_LIT16:
3240 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
3241 &failure);
3242 break;
3243 case Instruction::AND_INT_LIT16:
3244 case Instruction::OR_INT_LIT16:
3245 case Instruction::XOR_INT_LIT16:
3246 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
3247 &failure);
3248 break;
3249 case Instruction::ADD_INT_LIT8:
3250 case Instruction::RSUB_INT_LIT8:
3251 case Instruction::MUL_INT_LIT8:
3252 case Instruction::DIV_INT_LIT8:
3253 case Instruction::REM_INT_LIT8:
3254 case Instruction::SHL_INT_LIT8:
3255 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
3256 &failure);
3257 break;
3258 case Instruction::SHR_INT_LIT8:
3259 tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
3260 false, &failure);
3261 CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
3262 &failure);
3263 break;
3264 case Instruction::USHR_INT_LIT8:
3265 tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
3266 true, &failure);
3267 CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
3268 &failure);
3269 break;
3270 case Instruction::AND_INT_LIT8:
3271 case Instruction::OR_INT_LIT8:
3272 case Instruction::XOR_INT_LIT8:
3273 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
3274 &failure);
3275 break;
3276
3277 /*
3278 * This falls into the general category of "optimized" instructions,
jeffhaod1f0fde2011-09-08 17:25:33 -07003279 * which don't generally appear during verification. Because it's
jeffhaobdb76512011-09-07 11:43:16 -07003280 * inserted in the course of verification, we can expect to see it here.
3281 */
3282 //case Instruction::THROW_VERIFICATION_ERROR:
3283 case Instruction::UNUSED_ED:
3284 break;
3285
3286 /*
3287 * Verifying "quickened" instructions is tricky, because we have
jeffhaod1f0fde2011-09-08 17:25:33 -07003288 * discarded the original field/method information. The byte offsets
jeffhaobdb76512011-09-07 11:43:16 -07003289 * and vtable indices only have meaning in the context of an object
3290 * instance.
3291 *
3292 * If a piece of code declares a local reference variable, assigns
3293 * null to it, and then issues a virtual method call on it, we
jeffhaod1f0fde2011-09-08 17:25:33 -07003294 * cannot evaluate the method call during verification. This situation
jeffhaobdb76512011-09-07 11:43:16 -07003295 * isn't hard to handle, since we know the call will always result in an
jeffhaod1f0fde2011-09-08 17:25:33 -07003296 * NPE, and the arguments and return value don't matter. Any code that
jeffhaobdb76512011-09-07 11:43:16 -07003297 * depends on the result of the method call is inaccessible, so the
3298 * fact that we can't fully verify anything that comes after the bad
3299 * call is not a problem.
3300 *
3301 * We must also consider the case of multiple code paths, only some of
jeffhaod1f0fde2011-09-08 17:25:33 -07003302 * which involve a null reference. We can completely verify the method
jeffhaobdb76512011-09-07 11:43:16 -07003303 * if we sidestep the results of executing with a null reference.
3304 * For example, if on the first pass through the code we try to do a
3305 * virtual method invocation through a null ref, we have to skip the
3306 * method checks and have the method return a "wildcard" type (which
jeffhaod1f0fde2011-09-08 17:25:33 -07003307 * merges with anything to become that other thing). The move-result
jeffhaobdb76512011-09-07 11:43:16 -07003308 * will tell us if it's a reference, single-word numeric, or double-word
jeffhaod1f0fde2011-09-08 17:25:33 -07003309 * value. We continue to perform the verification, and at the end of
jeffhaobdb76512011-09-07 11:43:16 -07003310 * the function any invocations that were never fully exercised are
3311 * marked as null-only.
3312 *
jeffhaod1f0fde2011-09-08 17:25:33 -07003313 * We would do something similar for the field accesses. The field's
jeffhaobdb76512011-09-07 11:43:16 -07003314 * type, once known, can be used to recover the width of short integers.
3315 * If the object reference was null, the field-get returns the "wildcard"
3316 * type, which is acceptable for any operation.
3317 */
3318 case Instruction::UNUSED_EE:
3319 case Instruction::UNUSED_EF:
3320 case Instruction::UNUSED_F2:
3321 case Instruction::UNUSED_F3:
3322 case Instruction::UNUSED_F4:
3323 case Instruction::UNUSED_F5:
3324 case Instruction::UNUSED_F6:
3325 case Instruction::UNUSED_F7:
3326 case Instruction::UNUSED_F8:
3327 case Instruction::UNUSED_F9:
3328 case Instruction::UNUSED_FA:
3329 case Instruction::UNUSED_FB:
3330 //case Instruction::EXECUTE_INLINE:
3331 //case Instruction::EXECUTE_INLINE_RANGE:
3332 //case Instruction::IGET_QUICK:
3333 //case Instruction::IGET_WIDE_QUICK:
3334 //case Instruction::IGET_OBJECT_QUICK:
3335 //case Instruction::IPUT_QUICK:
3336 //case Instruction::IPUT_WIDE_QUICK:
3337 //case Instruction::IPUT_OBJECT_QUICK:
3338 //case Instruction::INVOKE_VIRTUAL_QUICK:
3339 //case Instruction::INVOKE_VIRTUAL_QUICK_RANGE:
3340 //case Instruction::INVOKE_SUPER_QUICK:
3341 //case Instruction::INVOKE_SUPER_QUICK_RANGE:
3342 /* fall through to failure */
3343
3344 /*
3345 * These instructions are equivalent (from the verifier's point of view)
jeffhaod1f0fde2011-09-08 17:25:33 -07003346 * to the original form. The change was made for correctness rather
jeffhaobdb76512011-09-07 11:43:16 -07003347 * than improved performance (except for invoke-object-init, which
jeffhaod1f0fde2011-09-08 17:25:33 -07003348 * provides both). The substitution takes place after verification
jeffhaobdb76512011-09-07 11:43:16 -07003349 * completes, though, so we don't expect to see them here.
3350 */
3351 case Instruction::UNUSED_F0:
3352 case Instruction::UNUSED_F1:
3353 case Instruction::UNUSED_E3:
3354 case Instruction::UNUSED_E8:
3355 case Instruction::UNUSED_E7:
3356 case Instruction::UNUSED_E4:
3357 case Instruction::UNUSED_E9:
3358 case Instruction::UNUSED_FC:
3359 case Instruction::UNUSED_E5:
3360 case Instruction::UNUSED_EA:
3361 case Instruction::UNUSED_FD:
3362 case Instruction::UNUSED_E6:
3363 case Instruction::UNUSED_EB:
3364 case Instruction::UNUSED_FE:
3365 //case Instruction::INVOKE_OBJECT_INIT_RANGE:
3366 //case Instruction::RETURN_VOID_BARRIER:
3367 //case Instruction::IGET_VOLATILE:
3368 //case Instruction::IGET_WIDE_VOLATILE:
3369 //case Instruction::IGET_OBJECT_VOLATILE:
3370 //case Instruction::IPUT_VOLATILE:
3371 //case Instruction::IPUT_WIDE_VOLATILE:
3372 //case Instruction::IPUT_OBJECT_VOLATILE:
3373 //case Instruction::SGET_VOLATILE:
3374 //case Instruction::SGET_WIDE_VOLATILE:
3375 //case Instruction::SGET_OBJECT_VOLATILE:
3376 //case Instruction::SPUT_VOLATILE:
3377 //case Instruction::SPUT_WIDE_VOLATILE:
3378 //case Instruction::SPUT_OBJECT_VOLATILE:
3379 /* fall through to failure */
3380
3381 /* These should never appear during verification. */
3382 case Instruction::UNUSED_3E:
3383 case Instruction::UNUSED_3F:
3384 case Instruction::UNUSED_40:
3385 case Instruction::UNUSED_41:
3386 case Instruction::UNUSED_42:
3387 case Instruction::UNUSED_43:
3388 case Instruction::UNUSED_73:
3389 case Instruction::UNUSED_79:
3390 case Instruction::UNUSED_7A:
3391 case Instruction::UNUSED_EC:
3392 case Instruction::UNUSED_FF:
3393 //case Instruction::BREAKPOINT:
3394 //case Instruction::DISPATCH_FF:
3395 failure = VERIFY_ERROR_GENERIC;
3396 break;
3397
3398 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003399 * DO NOT add a "default" clause here. Without it the compiler will
jeffhaobdb76512011-09-07 11:43:16 -07003400 * complain if an instruction is missing (which is desirable).
3401 */
3402 }
3403
3404 if (failure != VERIFY_ERROR_NONE) {
jeffhaobdb76512011-09-07 11:43:16 -07003405 if (failure == VERIFY_ERROR_GENERIC) {
3406 /* immediate failure, reject class */
3407 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
3408 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3409 return false;
3410 } else {
jeffhao98eacac2011-09-14 16:11:53 -07003411 // TODO: CHECK IF THIS WILL WORK!
3412 /* ignore the failure and move on */
3413 LOG(ERROR) << "VFY: failing opcode 0x" << std::hex
3414 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3415 failure = VERIFY_ERROR_NONE;
3416#if 0
jeffhaobdb76512011-09-07 11:43:16 -07003417 /* replace opcode and continue on */
3418 LOG(ERROR) << "VFY: replacing opcode 0x" << std::hex
3419 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3420 if (!ReplaceFailingInstruction(code_item, insn_flags, insn_idx, failure))
3421 {
3422 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
3423 << (int) dec_insn.opcode_ << " at 0x" << insn_idx
3424 << std::dec;
3425 return false;
3426 }
3427 /* IMPORTANT: method->insns may have been changed */
3428 insns = code_item->insns_ + insn_idx;
3429
3430 /* continue on as if we just handled a throw-verification-error */
3431 failure = VERIFY_ERROR_NONE;
3432 opcode_flag = Instruction::kThrow;
jeffhao98eacac2011-09-14 16:11:53 -07003433#endif
jeffhaobdb76512011-09-07 11:43:16 -07003434 }
3435 }
3436
3437 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003438 * If we didn't just set the result register, clear it out. This
jeffhaobdb76512011-09-07 11:43:16 -07003439 * ensures that you can only use "move-result" immediately after the
jeffhaod1f0fde2011-09-08 17:25:33 -07003440 * result is set. (We could check this statically, but it's not
jeffhaobdb76512011-09-07 11:43:16 -07003441 * expensive and it makes our debugging output cleaner.)
3442 */
3443 if (!just_set_result) {
3444 int reg = RESULT_REGISTER(registers_size);
3445 SetRegisterType(work_line, reg, kRegTypeUnknown);
3446 SetRegisterType(work_line, reg + 1, kRegTypeUnknown);
3447 }
3448
3449 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003450 * Handle "continue". Tag the next consecutive instruction.
jeffhaobdb76512011-09-07 11:43:16 -07003451 */
3452 if ((opcode_flag & Instruction::kContinue) != 0) {
3453 size_t insn_width = InsnGetWidth(insn_flags, insn_idx);
3454 if (insn_idx + insn_width >= insns_size) {
3455 LOG(ERROR) << "VFY: execution can walk off end of code area (from 0x"
3456 << std::hex << insn_idx << std::dec << ")";
3457 return false;
3458 }
3459
3460 /*
3461 * The only way to get to a move-exception instruction is to get
jeffhaod1f0fde2011-09-08 17:25:33 -07003462 * thrown there. Make sure the next instruction isn't one.
jeffhaobdb76512011-09-07 11:43:16 -07003463 */
3464 if (!CheckMoveException(code_item->insns_, insn_idx + insn_width))
3465 return false;
3466
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003467 if (GetRegisterLine(reg_table, insn_idx + insn_width)->reg_types_.get() != NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003468 /*
3469 * Merge registers into what we have for the next instruction,
3470 * and set the "changed" flag if needed.
3471 */
3472 if (!UpdateRegisters(insn_flags, reg_table, insn_idx + insn_width,
3473 work_line))
3474 return false;
3475 } else {
3476 /*
3477 * We're not recording register data for the next instruction,
jeffhaod1f0fde2011-09-08 17:25:33 -07003478 * so we don't know what the prior state was. We have to
jeffhaobdb76512011-09-07 11:43:16 -07003479 * assume that something has changed and re-evaluate it.
3480 */
3481 InsnSetChanged(insn_flags, insn_idx + insn_width, true);
3482 }
3483 }
3484
3485 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003486 * Handle "branch". Tag the branch target.
jeffhaobdb76512011-09-07 11:43:16 -07003487 *
3488 * NOTE: instructions like Instruction::EQZ provide information about the
jeffhaod1f0fde2011-09-08 17:25:33 -07003489 * state of the register when the branch is taken or not taken. For example,
jeffhaobdb76512011-09-07 11:43:16 -07003490 * somebody could get a reference field, check it for zero, and if the
3491 * branch is taken immediately store that register in a boolean field
jeffhaod1f0fde2011-09-08 17:25:33 -07003492 * since the value is known to be zero. We do not currently account for
jeffhaobdb76512011-09-07 11:43:16 -07003493 * that, and will reject the code.
3494 *
3495 * TODO: avoid re-fetching the branch target
3496 */
3497 if ((opcode_flag & Instruction::kBranch) != 0) {
3498 bool isConditional, selfOkay;
3499
3500 if (!GetBranchOffset(code_item, insn_flags, insn_idx, &branch_target,
3501 &isConditional, &selfOkay)) {
3502 /* should never happen after static verification */
3503 LOG(ERROR) << "VFY: bad branch at 0x" << std::hex << insn_idx << std::dec;
3504 return false;
3505 }
3506 assert(isConditional || (opcode_flag & Instruction::kContinue) == 0);
3507 assert(!isConditional || (opcode_flag & Instruction::kContinue) != 0);
3508
3509 if (!CheckMoveException(code_item->insns_, insn_idx + branch_target))
3510 return false;
3511
3512 /* update branch target, set "changed" if appropriate */
3513 if (!UpdateRegisters(insn_flags, reg_table, insn_idx + branch_target,
3514 work_line))
3515 return false;
3516 }
3517
3518 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003519 * Handle "switch". Tag all possible branch targets.
jeffhaobdb76512011-09-07 11:43:16 -07003520 *
3521 * We've already verified that the table is structurally sound, so we
3522 * just need to walk through and tag the targets.
3523 */
3524 if ((opcode_flag & Instruction::kSwitch) != 0) {
3525 int offset_to_switch = insns[1] | (((int32_t) insns[2]) << 16);
3526 const uint16_t* switch_insns = insns + offset_to_switch;
3527 int switch_count = switch_insns[1];
3528 int offset_to_targets, targ;
3529
3530 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
3531 /* 0 = sig, 1 = count, 2/3 = first key */
3532 offset_to_targets = 4;
3533 } else {
3534 /* 0 = sig, 1 = count, 2..count * 2 = keys */
3535 assert((*insns & 0xff) == Instruction::SPARSE_SWITCH);
3536 offset_to_targets = 2 + 2 * switch_count;
3537 }
3538
3539 /* verify each switch target */
3540 for (targ = 0; targ < switch_count; targ++) {
3541 int offset;
3542 uint32_t abs_offset;
3543
3544 /* offsets are 32-bit, and only partly endian-swapped */
3545 offset = switch_insns[offset_to_targets + targ * 2] |
3546 (((int32_t) switch_insns[offset_to_targets + targ * 2 + 1]) << 16);
3547 abs_offset = insn_idx + offset;
3548
3549 assert(abs_offset < insns_size);
3550
3551 if (!CheckMoveException(code_item->insns_, abs_offset))
3552 return false;
3553
3554 if (!UpdateRegisters(insn_flags, reg_table, abs_offset, work_line))
3555 return false;
3556 }
3557 }
3558
3559 /*
3560 * Handle instructions that can throw and that are sitting in a
jeffhaod1f0fde2011-09-08 17:25:33 -07003561 * "try" block. (If they're not in a "try" block when they throw,
jeffhaobdb76512011-09-07 11:43:16 -07003562 * control transfers out of the method.)
3563 */
3564 if ((opcode_flag & Instruction::kThrow) != 0 &&
3565 InsnIsInTry(insn_flags, insn_idx)) {
3566 bool has_catch_all = false;
3567 DexFile::CatchHandlerIterator iterator = DexFile::dexFindCatchHandler(
3568 *code_item, insn_idx);
3569
3570 for (; !iterator.HasNext(); iterator.Next()) {
3571 if (iterator.Get().type_idx_ == DexFile::kDexNoIndex)
3572 has_catch_all = true;
3573
3574 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003575 * Merge registers into the "catch" block. We want to use the
3576 * "savedRegs" rather than "work_regs", because at runtime the
3577 * exception will be thrown before the instruction modifies any
3578 * registers.
jeffhaobdb76512011-09-07 11:43:16 -07003579 */
3580 if (!UpdateRegisters(insn_flags, reg_table, iterator.Get().address_,
3581 &reg_table->saved_line_))
3582 return false;
3583 }
3584
3585 /*
3586 * If the monitor stack depth is nonzero, there must be a "catch all"
jeffhaod1f0fde2011-09-08 17:25:33 -07003587 * handler for this instruction. This does apply to monitor-exit
jeffhaobdb76512011-09-07 11:43:16 -07003588 * because of async exception handling.
3589 */
3590 if (work_line->monitor_stack_top_ != 0 && !has_catch_all) {
3591 /*
3592 * The state in work_line reflects the post-execution state.
3593 * If the current instruction is a monitor-enter and the monitor
3594 * stack was empty, we don't need a catch-all (if it throws,
3595 * it will do so before grabbing the lock).
3596 */
3597 if (!(dec_insn.opcode_ == Instruction::MONITOR_ENTER &&
3598 work_line->monitor_stack_top_ == 1))
3599 {
3600 LOG(ERROR) << "VFY: no catch-all for instruction at 0x" << std::hex
3601 << insn_idx << std::dec;
3602 return false;
3603 }
3604 }
3605 }
3606
jeffhaod1f0fde2011-09-08 17:25:33 -07003607 /* If we're returning from the method, make sure monitor stack is empty. */
jeffhaobdb76512011-09-07 11:43:16 -07003608 if ((opcode_flag & Instruction::kReturn) != 0 &&
3609 work_line->monitor_stack_top_ != 0) {
3610 LOG(ERROR) << "VFY: return with stack depth="
3611 << work_line->monitor_stack_top_ << " at 0x" << std::hex
3612 << insn_idx << std::dec;
3613 return false;
3614 }
3615
3616 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003617 * Update start_guess. Advance to the next instruction of that's
3618 * possible, otherwise use the branch target if one was found. If
jeffhaobdb76512011-09-07 11:43:16 -07003619 * neither of those exists we're in a return or throw; leave start_guess
3620 * alone and let the caller sort it out.
3621 */
3622 if ((opcode_flag & Instruction::kContinue) != 0) {
3623 *start_guess = insn_idx + InsnGetWidth(insn_flags, insn_idx);
3624 } else if ((opcode_flag & Instruction::kBranch) != 0) {
3625 /* we're still okay if branch_target is zero */
3626 *start_guess = insn_idx + branch_target;
3627 }
3628
3629 assert(*start_guess < insns_size &&
3630 InsnGetWidth(insn_flags, *start_guess) != 0);
3631
3632 return true;
3633}
3634
3635bool DexVerifier::ReplaceFailingInstruction(const DexFile::CodeItem* code_item,
3636 InsnFlags* insn_flags, int insn_idx, VerifyError failure) {
3637 const uint16_t* insns = code_item->insns_ + insn_idx;
3638 const byte* ptr = reinterpret_cast<const byte*>(insns);
3639 const Instruction* inst = Instruction::At(ptr);
3640 Instruction::Code opcode = inst->Opcode();
3641 VerifyErrorRefType ref_type;
3642
3643 /*
3644 * Generate the new instruction out of the old.
3645 *
3646 * First, make sure this is an instruction we're expecting to stomp on.
3647 */
3648 switch (opcode) {
3649 case Instruction::CONST_CLASS: // insn[1] == class ref, 2 bytes
3650 case Instruction::CHECK_CAST:
3651 case Instruction::INSTANCE_OF:
3652 case Instruction::NEW_INSTANCE:
3653 case Instruction::NEW_ARRAY:
3654 case Instruction::FILLED_NEW_ARRAY: // insn[1] == class ref, 3 bytes
3655 case Instruction::FILLED_NEW_ARRAY_RANGE:
3656 ref_type = VERIFY_ERROR_REF_CLASS;
3657 break;
3658
3659 case Instruction::IGET: // insn[1] == field ref, 2 bytes
3660 case Instruction::IGET_BOOLEAN:
3661 case Instruction::IGET_BYTE:
3662 case Instruction::IGET_CHAR:
3663 case Instruction::IGET_SHORT:
3664 case Instruction::IGET_WIDE:
3665 case Instruction::IGET_OBJECT:
3666 case Instruction::IPUT:
3667 case Instruction::IPUT_BOOLEAN:
3668 case Instruction::IPUT_BYTE:
3669 case Instruction::IPUT_CHAR:
3670 case Instruction::IPUT_SHORT:
3671 case Instruction::IPUT_WIDE:
3672 case Instruction::IPUT_OBJECT:
3673 case Instruction::SGET:
3674 case Instruction::SGET_BOOLEAN:
3675 case Instruction::SGET_BYTE:
3676 case Instruction::SGET_CHAR:
3677 case Instruction::SGET_SHORT:
3678 case Instruction::SGET_WIDE:
3679 case Instruction::SGET_OBJECT:
3680 case Instruction::SPUT:
3681 case Instruction::SPUT_BOOLEAN:
3682 case Instruction::SPUT_BYTE:
3683 case Instruction::SPUT_CHAR:
3684 case Instruction::SPUT_SHORT:
3685 case Instruction::SPUT_WIDE:
3686 case Instruction::SPUT_OBJECT:
3687 ref_type = VERIFY_ERROR_REF_FIELD;
3688 break;
3689
3690 case Instruction::INVOKE_VIRTUAL: // insn[1] == method ref, 3 bytes
3691 case Instruction::INVOKE_VIRTUAL_RANGE:
3692 case Instruction::INVOKE_SUPER:
3693 case Instruction::INVOKE_SUPER_RANGE:
3694 case Instruction::INVOKE_DIRECT:
3695 case Instruction::INVOKE_DIRECT_RANGE:
3696 case Instruction::INVOKE_STATIC:
3697 case Instruction::INVOKE_STATIC_RANGE:
3698 case Instruction::INVOKE_INTERFACE:
3699 case Instruction::INVOKE_INTERFACE_RANGE:
3700 ref_type = VERIFY_ERROR_REF_METHOD;
3701 break;
3702
3703 default:
3704 /* could handle this in a generic way, but this is probably safer */
3705 LOG(ERROR) << "GLITCH: verifier asked to replace opcode 0x" << std::hex
3706 << (int) opcode << std::dec;
3707 return false;
3708 }
3709
3710 assert(inst->IsThrow());
3711
3712 /* write a NOP over the third code unit, if necessary */
3713 int width = InsnGetWidth(insn_flags, insn_idx);
3714 switch (width) {
3715 case 2:
3716 /* nothing to do */
3717 break;
3718 case 3:
3719 // TODO: Add this functionality
3720 //UpdateCodeUnit(method, insns + 2, Instruction::NOP);
3721 break;
3722 default:
3723 /* whoops */
3724 LOG(FATAL) << "ERROR: stomped a " << width
3725 << "-unit instruction with a verifier error";
3726 }
3727
3728 /* encode the opcode, with the failure code in the high byte */
3729 // TODO: REPLACE FAILING OPCODES
3730 //assert(width == 2 || width == 3);
3731 //uint16_t new_val = Instruction::THROW_VERIFICATION_ERROR |
jeffhao98eacac2011-09-14 16:11:53 -07003732 //uint16_t new_val = Instruction::UNUSED_ED |
jeffhaobdb76512011-09-07 11:43:16 -07003733 //(failure << 8) | (ref_type << (8 + kVerifyErrorRefTypeShift));
3734 //UpdateCodeUnit(method, insns, new_val);
3735
3736 return true;
3737}
3738
3739/* Handle a monitor-enter instruction. */
3740void DexVerifier::HandleMonitorEnter(RegisterLine* work_line, uint32_t reg_idx,
3741 uint32_t insn_idx, VerifyError* failure) {
3742 if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
3743 LOG(ERROR) << "VFY: monitor-enter on non-object";
3744 *failure = VERIFY_ERROR_GENERIC;
3745 return;
3746 }
3747
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003748 if (work_line->monitor_entries_.get() == NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003749 return;
3750 }
3751
3752 if (work_line->monitor_stack_top_ == kMaxMonitorStackDepth) {
3753 LOG(ERROR) << "VFY: monitor-enter stack overflow (" << kMaxMonitorStackDepth
3754 << ")";
3755 *failure = VERIFY_ERROR_GENERIC;
3756 return;
3757 }
3758
3759 /*
3760 * Push an entry on the stack, and set a bit in the register flags to
3761 * indicate that it's associated with this register.
3762 */
3763 work_line->monitor_entries_[reg_idx] |= 1 << work_line->monitor_stack_top_;
3764 work_line->monitor_stack_[work_line->monitor_stack_top_++] = insn_idx;
3765}
3766
3767/* Handle a monitor-exit instruction. */
3768void DexVerifier::HandleMonitorExit(RegisterLine* work_line, uint32_t reg_idx,
3769 uint32_t insn_idx, VerifyError* failure) {
3770 if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
3771 LOG(ERROR) << "VFY: monitor-exit on non-object";
3772 *failure = VERIFY_ERROR_GENERIC;
3773 return;
3774 }
3775
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003776 if (work_line->monitor_entries_.get() == NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003777 return;
3778 }
3779
3780 if (work_line->monitor_stack_top_ == 0) {
3781 LOG(ERROR) << "VFY: monitor-exit stack underflow";
3782 *failure = VERIFY_ERROR_GENERIC;
3783 return;
3784 }
3785
3786 /*
3787 * Confirm that the entry at the top of the stack is associated with
jeffhaod1f0fde2011-09-08 17:25:33 -07003788 * the register. Pop the top entry off.
jeffhaobdb76512011-09-07 11:43:16 -07003789 */
3790 work_line->monitor_stack_top_--;
3791#ifdef BUG_3215458_FIXED
3792 /*
3793 * TODO: This code can safely be enabled if know we are working on
3794 * a dex file of format version 036 or later. (That is, we'll need to
3795 * add a check for the version number.)
3796 */
3797 if ((work_line->monitor_entries_[reg_idx] &
3798 (1 << work_line->monitor_stack_top_)) == 0) {
3799 LOG(ERROR) << "VFY: monitor-exit bit " << work_line->monitor_stack_top_
3800 << " not set: addr=0x" << std::hex << insn_idx << std::dec
3801 << " (bits[" << reg_idx << "]=" << std::hex
3802 << work_line->monitor_entries_[reg_idx] << std::dec << ")";
3803 *failure = VERIFY_ERROR_GENERIC;
3804 return;
3805 }
3806#endif
3807 work_line->monitor_stack_[work_line->monitor_stack_top_] = 0;
3808
3809 /* Clear the bit from the register flags. */
3810 work_line->monitor_entries_[reg_idx] &= ~(1 << work_line->monitor_stack_top_);
3811}
3812
3813Field* DexVerifier::GetInstField(VerifierData* vdata, RegType obj_type,
3814 int field_idx, VerifyError* failure) {
3815 Method* method = vdata->method_;
3816 const DexFile* dex_file = vdata->dex_file_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003817 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07003818 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3819 DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
3820 const ClassLoader* class_loader =
3821 method->GetDeclaringClass()->GetClassLoader();
3822 Field* field = NULL;
3823 Class* obj_class;
3824 bool must_be_local = false;
3825
3826 if (!RegTypeIsReference(obj_type)) {
3827 LOG(ERROR) << "VFY: attempt to access field in non-reference type "
3828 << obj_type;
3829 *failure = VERIFY_ERROR_GENERIC;
3830 return field;
3831 }
3832
3833 field = class_linker->ResolveField(*dex_file, field_idx, dex_cache,
3834 class_loader, false);
3835 if (field == NULL) {
3836 LOG(ERROR) << "VFY: unable to resolve instance field " << field_idx;
3837 return field;
3838 }
3839
3840 if (obj_type == kRegTypeZero)
3841 return field;
3842
3843 /*
3844 * Access to fields in uninitialized objects is allowed if this is
3845 * the <init> method for the object and the field in question is
3846 * declared by this class.
3847 */
3848 obj_class = RegTypeReferenceToClass(obj_type, uninit_map);
3849 assert(obj_class != NULL);
3850 if (RegTypeIsUninitReference(obj_type)) {
3851 if (!IsInitMethod(method) || method->GetDeclaringClass() != obj_class) {
3852 LOG(ERROR) << "VFY: attempt to access field via uninitialized ref";
3853 *failure = VERIFY_ERROR_GENERIC;
3854 return field;
3855 }
3856 must_be_local = true;
3857 }
3858
jeffhaobdb76512011-09-07 11:43:16 -07003859 if (!field->GetDeclaringClass()->IsAssignableFrom(obj_class)) {
3860 LOG(ERROR) << "VFY: invalid field access (field "
3861 << field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
3862 << "." << field->GetName()->ToModifiedUtf8() << ", through "
3863 << obj_class->GetDescriptor()->ToModifiedUtf8() << " ref)";
3864 *failure = VERIFY_ERROR_NO_FIELD;
3865 return field;
3866 }
3867
3868 if (must_be_local) {
3869 bool found = false;
3870 /* for uninit ref, make sure it's defined by this class, not super */
3871 for (uint32_t i = 0; i < obj_class->NumInstanceFields(); i++) {
3872 found |= (field == obj_class->GetInstanceField(i));
3873 }
3874 if (!found) {
3875 LOG(ERROR) << "VFY: invalid constructor field access (field "
3876 << field->GetName()->ToModifiedUtf8() << " in "
3877 << obj_class->GetDescriptor()->ToModifiedUtf8() << ")";
3878 *failure = VERIFY_ERROR_GENERIC;
3879 return field;
3880 }
3881 }
3882
3883 return field;
3884}
3885
3886Field* DexVerifier::GetStaticField(VerifierData* vdata, int field_idx,
3887 VerifyError* failure) {
3888 Method* method = vdata->method_;
3889 const DexFile* dex_file = vdata->dex_file_;
3890 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3891 DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
3892 const ClassLoader* class_loader =
3893 method->GetDeclaringClass()->GetClassLoader();
3894 Field* field;
3895
3896 field = class_linker->ResolveField(*dex_file, field_idx, dex_cache,
3897 class_loader, true);
3898 if (field == NULL) {
3899 //const DexFile::FieldId field_id = dex_file->GetFieldId(field_idx);
3900
3901 //LOG(ERROR) << "VFY: unable to resolve static field " << field_idx << " ("
3902 //<< dex_file->GetFieldName(field_id) << ") in "
3903 //<< dex_file->GetFieldClassDescriptor(field_id);
3904 LOG(ERROR) << "VFY: unable to resolve static field";
3905 }
3906
3907 return field;
3908}
3909
3910Class* DexVerifier::GetCaughtExceptionType(VerifierData* vdata, int insn_idx,
3911 VerifyError* failure) {
3912 const DexFile* dex_file = vdata->dex_file_;
3913 const DexFile::CodeItem* code_item = vdata->code_item_;
3914 Method* method = vdata->method_;
3915 Class* common_super = NULL;
3916 uint32_t handlers_size;
jeffhaoba5ebb92011-08-25 17:24:37 -07003917 const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item, 0);
jeffhaobdb76512011-09-07 11:43:16 -07003918
3919 if (code_item->tries_size_ != 0) {
3920 handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
3921 } else {
3922 handlers_size = 0;
3923 }
3924
3925 for (uint32_t i = 0; i < handlers_size; i++) {
jeffhaoba5ebb92011-08-25 17:24:37 -07003926 DexFile::CatchHandlerIterator iterator(handlers_ptr);
3927
3928 for (; !iterator.HasNext(); iterator.Next()) {
jeffhaobdb76512011-09-07 11:43:16 -07003929 DexFile::CatchHandlerItem handler = iterator.Get();
3930 if (handler.address_ == (uint32_t) insn_idx) {
3931 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3932 Class* klass;
jeffhaoba5ebb92011-08-25 17:24:37 -07003933
jeffhaobdb76512011-09-07 11:43:16 -07003934 if (handler.type_idx_ == DexFile::kDexNoIndex) {
3935 klass = class_linker->FindSystemClass("Ljava/lang/Throwable;");
3936 } else {
jeffhao98eacac2011-09-14 16:11:53 -07003937 klass = ResolveClassAndCheckAccess(dex_file, handler.type_idx_,
3938 method->GetDeclaringClass(), failure);
jeffhaobdb76512011-09-07 11:43:16 -07003939 }
3940
3941 if (klass == NULL) {
3942 LOG(ERROR) << "VFY: unable to resolve exception class "
3943 << handler.type_idx_ << " ("
3944 << dex_file->dexStringByTypeIdx(handler.type_idx_) << ")";
jeffhaod1f0fde2011-09-08 17:25:33 -07003945 /* TODO: do we want to keep going? If we don't fail this we run
3946 * the risk of having a non-Throwable introduced at runtime.
3947 * However, that won't pass an instanceof test, so is essentially
3948 * harmless.
jeffhaobdb76512011-09-07 11:43:16 -07003949 */
3950 } else {
3951 if (common_super == NULL)
3952 common_super = klass;
3953 else
3954 common_super = FindCommonSuperclass(klass, common_super);
3955 }
3956 }
jeffhaoba5ebb92011-08-25 17:24:37 -07003957 }
3958
3959 handlers_ptr = iterator.GetData();
3960 }
3961
jeffhaobdb76512011-09-07 11:43:16 -07003962 if (common_super == NULL) {
3963 /* no catch blocks, or no catches with classes we can find */
3964 LOG(ERROR) << "VFY: unable to find exception handler at addr 0x" << std::hex
3965 << insn_idx << std::dec;
3966 *failure = VERIFY_ERROR_GENERIC;
3967 }
3968
3969 return common_super;
jeffhaoba5ebb92011-08-25 17:24:37 -07003970}
3971
jeffhaobdb76512011-09-07 11:43:16 -07003972DexVerifier::RegType DexVerifier::GetMethodReturnType(const DexFile* dex_file,
3973 const Method* method) {
3974 Class* klass = method->GetReturnType();
3975 if (klass->IsPrimitive())
3976 return PrimitiveTypeToRegType(klass->GetPrimitiveType());
3977 else
3978 return RegTypeFromClass(klass);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07003979}
3980
jeffhaobdb76512011-09-07 11:43:16 -07003981Class* DexVerifier::GetClassFromRegister(const RegisterLine* register_line,
3982 uint32_t vsrc, VerifyError* failure) {
3983 /* get the element type of the array held in vsrc */
3984 RegType type = GetRegisterType(register_line, vsrc);
jeffhaoba5ebb92011-08-25 17:24:37 -07003985
jeffhaobdb76512011-09-07 11:43:16 -07003986 /* if "always zero", we allow it to fail at runtime */
3987 if (type == kRegTypeZero)
3988 return NULL;
3989
3990 if (!RegTypeIsReference(type)) {
3991 LOG(ERROR) << "VFY: tried to get class from non-ref register v" << vsrc
3992 << " (type=" << type << ")",
3993 *failure = VERIFY_ERROR_GENERIC;
3994 return NULL;
3995 }
3996 if (RegTypeIsUninitReference(type)) {
3997 LOG(ERROR) << "VFY: register " << vsrc << " holds uninitialized reference";
3998 *failure = VERIFY_ERROR_GENERIC;
3999 return NULL;
jeffhaoba5ebb92011-08-25 17:24:37 -07004000 }
4001
jeffhaobdb76512011-09-07 11:43:16 -07004002 return RegTypeInitializedReferenceToClass(type);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07004003}
4004
jeffhaobdb76512011-09-07 11:43:16 -07004005DexVerifier::RegType DexVerifier::GetInvocationThis(
4006 const RegisterLine* register_line,
4007 const Instruction::DecodedInstruction* dec_insn, VerifyError* failure) {
4008 if (dec_insn->vA_ < 1) {
4009 LOG(ERROR) << "VFY: invoke lacks 'this'";
4010 *failure = VERIFY_ERROR_GENERIC;
4011 return kRegTypeUnknown;
jeffhaoba5ebb92011-08-25 17:24:37 -07004012 }
jeffhaobdb76512011-09-07 11:43:16 -07004013
4014 /* get the element type of the array held in vsrc */
4015 RegType this_type = GetRegisterType(register_line, dec_insn->vC_);
4016 if (!RegTypeIsReference(this_type)) {
4017 LOG(ERROR) << "VFY: tried to get class from non-ref register v"
4018 << dec_insn->vC_ << " (type=" << this_type << ")";
4019 *failure = VERIFY_ERROR_GENERIC;
4020 return kRegTypeUnknown;
4021 }
4022
4023 return this_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07004024}
4025
jeffhaobdb76512011-09-07 11:43:16 -07004026void DexVerifier::SetRegisterType(RegisterLine* register_line, uint32_t vdst,
4027 RegType new_type) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004028 RegType* insn_regs = register_line->reg_types_.get();
jeffhaoba5ebb92011-08-25 17:24:37 -07004029
jeffhaobdb76512011-09-07 11:43:16 -07004030 switch (new_type) {
4031 case kRegTypeUnknown:
4032 case kRegTypeBoolean:
4033 case kRegTypeOne:
4034 case kRegTypeConstByte:
4035 case kRegTypeConstPosByte:
4036 case kRegTypeConstShort:
4037 case kRegTypeConstPosShort:
4038 case kRegTypeConstChar:
4039 case kRegTypeConstInteger:
4040 case kRegTypeByte:
4041 case kRegTypePosByte:
4042 case kRegTypeShort:
4043 case kRegTypePosShort:
4044 case kRegTypeChar:
4045 case kRegTypeInteger:
4046 case kRegTypeFloat:
4047 case kRegTypeZero:
4048 case kRegTypeUninit:
4049 insn_regs[vdst] = new_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07004050 break;
jeffhaobdb76512011-09-07 11:43:16 -07004051 case kRegTypeConstLo:
4052 case kRegTypeLongLo:
4053 case kRegTypeDoubleLo:
4054 insn_regs[vdst] = new_type;
4055 insn_regs[vdst + 1] = new_type + 1;
4056 break;
4057 case kRegTypeConstHi:
4058 case kRegTypeLongHi:
4059 case kRegTypeDoubleHi:
4060 /* should never set these explicitly */
4061 LOG(FATAL) << "BUG: explicit set of high register type";
4062 break;
4063
4064 default:
4065 /* can't switch for ref types, so we check explicitly */
4066 if (RegTypeIsReference(new_type)) {
4067 insn_regs[vdst] = new_type;
4068
4069 /*
4070 * In most circumstances we won't see a reference to a primitive
4071 * class here (e.g. "D"), since that would mean the object in the
jeffhaod1f0fde2011-09-08 17:25:33 -07004072 * register is actually a primitive type. It can happen as the
jeffhaobdb76512011-09-07 11:43:16 -07004073 * result of an assumed-successful check-cast instruction in
jeffhaod1f0fde2011-09-08 17:25:33 -07004074 * which the second argument refers to a primitive class. (In
jeffhaobdb76512011-09-07 11:43:16 -07004075 * practice, such an instruction will always throw an exception.)
4076 *
4077 * This is not an issue for instructions like const-class, where
4078 * the object in the register is a java.lang.Class instance.
4079 */
4080 break;
4081 }
4082 /* bad type - fall through */
4083
4084 case kRegTypeConflict: // should only be set during a merge
4085 LOG(FATAL) << "BUG: set register to unknown type " << new_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07004086 break;
4087 }
4088
jeffhaobdb76512011-09-07 11:43:16 -07004089 /*
4090 * Clear the monitor entry bits for this register.
4091 */
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004092 if (register_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07004093 register_line->monitor_entries_[vdst] = 0;
4094}
4095
4096void DexVerifier::VerifyRegisterType(RegisterLine* register_line, uint32_t vsrc,
4097 RegType check_type, VerifyError* failure) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004098 const RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004099 RegType src_type = insn_regs[vsrc];
4100
4101 switch (check_type) {
4102 case kRegTypeFloat:
4103 case kRegTypeBoolean:
4104 case kRegTypePosByte:
4105 case kRegTypeByte:
4106 case kRegTypePosShort:
4107 case kRegTypeShort:
4108 case kRegTypeChar:
4109 case kRegTypeInteger:
4110 if (!CanConvertTo1nr(src_type, check_type)) {
4111 LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
4112 << ", wanted " << check_type;
4113 *failure = VERIFY_ERROR_GENERIC;
4114 }
4115 /* Update type if result is float */
4116 if (check_type == kRegTypeFloat) {
4117 SetRegisterType(register_line, vsrc, check_type);
4118 } else {
4119 /* Update const type to actual type after use */
4120 SetRegisterType(register_line, vsrc, ConstTypeToRegType(src_type));
4121 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004122 break;
jeffhaobdb76512011-09-07 11:43:16 -07004123 case kRegTypeLongLo:
4124 case kRegTypeDoubleLo:
4125 if (insn_regs[vsrc + 1] != src_type + 1) {
4126 LOG(ERROR) << "VFY: register2 v" << vsrc << "-" << vsrc + 1
4127 << " values " << insn_regs[vsrc] << ","
4128 << insn_regs[vsrc + 1];
4129 *failure = VERIFY_ERROR_GENERIC;
4130 } else if (!CanConvertTo2(src_type, check_type)) {
4131 LOG(ERROR) << "VFY: register2 v" << vsrc << " type " << src_type
4132 << ", wanted " << check_type;
4133 *failure = VERIFY_ERROR_GENERIC;
4134 }
4135 /* Update type if source is from const */
4136 if (src_type == kRegTypeConstLo) {
4137 SetRegisterType(register_line, vsrc, check_type);
4138 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004139 break;
jeffhaobdb76512011-09-07 11:43:16 -07004140 case kRegTypeConstLo:
4141 case kRegTypeConstHi:
4142 case kRegTypeLongHi:
4143 case kRegTypeDoubleHi:
4144 case kRegTypeZero:
4145 case kRegTypeOne:
4146 case kRegTypeUnknown:
4147 case kRegTypeConflict:
4148 /* should never be checking for these explicitly */
4149 assert(false);
4150 *failure = VERIFY_ERROR_GENERIC;
4151 return;
4152 case kRegTypeUninit:
4153 default:
4154 /* make sure check_type is initialized reference */
4155 if (!RegTypeIsReference(check_type)) {
4156 LOG(ERROR) << "VFY: unexpected check type " << check_type;
4157 assert(false);
4158 *failure = VERIFY_ERROR_GENERIC;
4159 break;
4160 }
4161 if (RegTypeIsUninitReference(check_type)) {
4162 LOG(ERROR) << "VFY: uninitialized ref not expected as reg check";
4163 *failure = VERIFY_ERROR_GENERIC;
4164 break;
4165 }
4166 /* make sure src_type is initialized reference or always-NULL */
4167 if (!RegTypeIsReference(src_type)) {
4168 LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
4169 << ", wanted ref";
4170 *failure = VERIFY_ERROR_GENERIC;
4171 break;
4172 }
4173 if (RegTypeIsUninitReference(src_type)) {
4174 LOG(ERROR) << "VFY: register1 v" << vsrc << " holds uninitialized ref";
4175 *failure = VERIFY_ERROR_GENERIC;
4176 break;
4177 }
4178 /* if the register isn't Zero, make sure it's an instance of check */
4179 if (src_type != kRegTypeZero) {
4180 Class* src_class = RegTypeInitializedReferenceToClass(src_type);
4181 Class* check_class = RegTypeInitializedReferenceToClass(check_type);
4182 assert(src_class != NULL);
4183 assert(check_class != NULL);
4184
4185 if (!check_class->IsAssignableFrom(src_class)) {
4186 LOG(ERROR) << "VFY: " << src_class->GetDescriptor()->ToModifiedUtf8()
4187 << " is not instance of "
4188 << check_class->GetDescriptor()->ToModifiedUtf8();
4189 *failure = VERIFY_ERROR_GENERIC;
4190 }
4191 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004192 break;
4193 }
jeffhaobdb76512011-09-07 11:43:16 -07004194}
jeffhaoba5ebb92011-08-25 17:24:37 -07004195
jeffhaobdb76512011-09-07 11:43:16 -07004196void DexVerifier::SetResultRegisterType(RegisterLine* register_line,
4197 const int insn_reg_count, RegType new_type) {
4198 SetRegisterType(register_line, RESULT_REGISTER(insn_reg_count), new_type);
4199}
4200
4201void DexVerifier::MarkRefsAsInitialized(RegisterLine* register_line,
4202 int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type,
4203 VerifyError* failure) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004204 RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004205 Class* klass = GetUninitInstance(uninit_map,
4206 RegTypeToUninitIndex(uninit_type));
4207
4208 if (klass == NULL) {
4209 LOG(ERROR) << "VFY: unable to find type=" << std::hex << uninit_type
4210 << std::dec << " (idx=" << RegTypeToUninitIndex(uninit_type)
4211 << ")";
4212 *failure = VERIFY_ERROR_GENERIC;
4213 return;
jeffhaoba5ebb92011-08-25 17:24:37 -07004214 }
4215
jeffhaobdb76512011-09-07 11:43:16 -07004216 RegType init_type = RegTypeFromClass(klass);
4217 int changed = 0;
4218 for (int i = 0; i < insn_reg_count; i++) {
4219 if (insn_regs[i] == uninit_type) {
4220 insn_regs[i] = init_type;
4221 changed++;
4222 }
4223 }
4224 assert(changed > 0);
4225
4226 return;
4227}
4228
4229void DexVerifier::MarkUninitRefsAsInvalid(RegisterLine* register_line,
4230 int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004231 RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004232
4233 for (int i = 0; i < insn_reg_count; i++) {
4234 if (insn_regs[i] == uninit_type) {
4235 insn_regs[i] = kRegTypeConflict;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004236 if (register_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07004237 register_line->monitor_entries_[i] = 0;
4238 }
4239 }
4240}
4241
4242void DexVerifier::CopyRegister1(RegisterLine* register_line, uint32_t vdst,
4243 uint32_t vsrc, TypeCategory cat, VerifyError* failure) {
4244 assert(cat == kTypeCategory1nr || cat == kTypeCategoryRef);
4245 RegType type = GetRegisterType(register_line, vsrc);
4246 CheckTypeCategory(type, cat, failure);
4247 if (*failure != VERIFY_ERROR_NONE) {
4248 LOG(ERROR) << "VFY: copy1 v" << vdst << "<-v" << vsrc << " type=" << type
4249 << " cat=" << (int) cat;
4250 } else {
4251 SetRegisterType(register_line, vdst, type);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004252 if (cat == kTypeCategoryRef && register_line->monitor_entries_.get() != NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07004253 register_line->monitor_entries_[vdst] =
4254 register_line->monitor_entries_[vsrc];
4255 }
4256 }
4257}
4258
4259void DexVerifier::CopyRegister2(RegisterLine* register_line, uint32_t vdst,
4260 uint32_t vsrc, VerifyError* failure) {
4261 RegType type_l = GetRegisterType(register_line, vsrc);
4262 RegType type_h = GetRegisterType(register_line, vsrc + 1);
4263
4264 CheckTypeCategory(type_l, kTypeCategory2, failure);
4265 CheckWidePair(type_l, type_h, failure);
4266 if (*failure != VERIFY_ERROR_NONE) {
4267 LOG(ERROR) << "VFY: copy2 v" << vdst << "<-v" << vsrc << " type=" << type_l
4268 << "/" << type_h;
4269 } else {
4270 SetRegisterType(register_line, vdst, type_l);
4271 }
4272}
4273
4274void DexVerifier::CopyResultRegister1(RegisterLine* register_line,
4275 const int insn_reg_count, uint32_t vdst, TypeCategory cat,
4276 VerifyError* failure) {
4277 assert(vdst < (uint32_t) insn_reg_count);
4278
4279 uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
4280 RegType type = GetRegisterType(register_line, vsrc);
4281 CheckTypeCategory(type, cat, failure);
4282 if (*failure != VERIFY_ERROR_NONE) {
4283 LOG(ERROR) << "VFY: copyRes1 v" << vdst << "<-v" << vsrc << " cat="
4284 << (int) cat << " type=" << type;
4285 } else {
4286 SetRegisterType(register_line, vdst, type);
4287 SetRegisterType(register_line, vsrc, kRegTypeUnknown);
4288 }
4289}
4290
4291/*
jeffhaod1f0fde2011-09-08 17:25:33 -07004292 * Implement "move-result-wide". Copy the category-2 value from the result
jeffhaobdb76512011-09-07 11:43:16 -07004293 * register to another register, and reset the result register.
4294 */
4295void DexVerifier::CopyResultRegister2(RegisterLine* register_line,
4296 const int insn_reg_count, uint32_t vdst, VerifyError* failure) {
4297 assert(vdst < (uint32_t) insn_reg_count);
4298
4299 uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
4300 RegType type_l = GetRegisterType(register_line, vsrc);
4301 RegType type_h = GetRegisterType(register_line, vsrc + 1);
4302 CheckTypeCategory(type_l, kTypeCategory2, failure);
4303 CheckWidePair(type_l, type_h, failure);
4304 if (*failure != VERIFY_ERROR_NONE) {
4305 LOG(ERROR) << "VFY: copyRes2 v" << vdst << "<-v" << vsrc << " type="
4306 << type_l << "/" << type_h;
4307 } else {
4308 SetRegisterType(register_line, vdst, type_l);
4309 SetRegisterType(register_line, vsrc, kRegTypeUnknown);
4310 SetRegisterType(register_line, vsrc + 1, kRegTypeUnknown);
4311 }
4312}
4313
4314int DexVerifier::GetClassDepth(Class* klass) {
4315 int depth = 0;
4316 while (klass->GetSuperClass() != NULL) {
4317 klass = klass->GetSuperClass();
4318 depth++;
4319 }
4320 return depth;
4321}
4322
4323Class* DexVerifier::DigForSuperclass(Class* c1, Class* c2) {
4324 int depth1, depth2;
4325
4326 depth1 = GetClassDepth(c1);
4327 depth2 = GetClassDepth(c2);
4328
4329 /* pull the deepest one up */
4330 if (depth1 > depth2) {
4331 while (depth1 > depth2) {
4332 c1 = c1->GetSuperClass();
4333 depth1--;
4334 }
4335 } else {
4336 while (depth2 > depth1) {
4337 c2 = c2->GetSuperClass();
4338 depth2--;
4339 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004340 }
4341
jeffhaobdb76512011-09-07 11:43:16 -07004342 /* walk up in lock-step */
4343 while (c1 != c2) {
4344 c1 = c1->GetSuperClass();
4345 c2 = c2->GetSuperClass();
4346
4347 assert(c1 != NULL && c2 != NULL);
4348 }
4349
4350 return c1;
4351}
4352
4353Class* DexVerifier::FindCommonArraySuperclass(Class* c1, Class* c2) {
4354 Class* array_class = NULL;
4355 Class* common_elem;
4356 int array_dim1, array_dim2;
4357 int i, num_dims;
4358 bool has_primitive = false;
4359
4360 array_dim1 = c1->GetArrayRank();
4361 array_dim2 = c2->GetArrayRank();
4362 assert(c1->GetArrayRank() > 0);
4363 assert(c2->GetArrayRank() > 0);
4364
4365 if (c1->GetComponentType()->IsPrimitive()) {
4366 array_dim1--;
4367 has_primitive = true;
4368 }
4369 if (c2->GetComponentType()->IsPrimitive()) {
4370 array_dim2--;
4371 has_primitive = true;
4372 }
4373
4374 if (!has_primitive && array_dim1 == array_dim2) {
4375 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004376 * Two arrays of reference types with equal dimensions. Try to
jeffhaobdb76512011-09-07 11:43:16 -07004377 * find a good match.
4378 */
4379 common_elem = FindCommonSuperclass(c1->GetComponentType(),
4380 c2->GetComponentType());
4381 num_dims = array_dim1;
4382 } else {
4383 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004384 * Mismatched array depths and/or array(s) of primitives. We want
jeffhaobdb76512011-09-07 11:43:16 -07004385 * Object, or an Object array with appropriate dimensions.
4386 *
4387 * We initialize array_class to Object here, because it's possible
4388 * for us to set num_dims=0.
4389 */
4390 if (array_dim1 < array_dim2)
4391 num_dims = array_dim1;
4392 else
4393 num_dims = array_dim2;
4394 array_class = common_elem = c1->GetSuperClass(); // == java.lang.Object
4395 }
4396
4397 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004398 * Find an appropriately-dimensioned array class. This is easiest
jeffhaobdb76512011-09-07 11:43:16 -07004399 * to do iteratively, using the array class found by the current round
4400 * as the element type for the next round.
4401 */
4402 for (i = 0; i < num_dims; i++) {
4403 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4404 const ClassLoader* class_loader = c1->GetClassLoader();
4405 std::string descriptor = "[" +
4406 common_elem->GetDescriptor()->ToModifiedUtf8();
4407 array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
4408 common_elem = array_class;
4409 }
4410 assert(array_class != NULL);
4411
4412 return array_class;
4413}
4414
4415Class* DexVerifier::FindCommonSuperclass(Class* c1, Class* c2) {
4416 assert(!c1->IsPrimitive() && !c2->IsPrimitive());
4417
4418 if (c1 == c2)
4419 return c1;
4420
jeffhao5dbddee2011-09-07 16:38:26 -07004421 if (c1->IsInterface() && c1->IsAssignableFrom(c2)) {
jeffhaobdb76512011-09-07 11:43:16 -07004422 return c1;
4423 }
jeffhao5dbddee2011-09-07 16:38:26 -07004424 if (c2->IsInterface() && c2->IsAssignableFrom(c1)) {
jeffhaobdb76512011-09-07 11:43:16 -07004425 return c2;
4426 }
4427 if (c1->IsArrayClass() && c2->IsArrayClass()) {
4428 return FindCommonArraySuperclass(c1, c2);
4429 }
4430
4431 return DigForSuperclass(c1, c2);
4432}
4433
jeffhao98eacac2011-09-14 16:11:53 -07004434Class* DexVerifier::ResolveClassAndCheckAccess(const DexFile* dex_file,
4435 uint32_t class_idx, const Class* referrer, VerifyError* failure) {
4436 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4437 Class* res_class = class_linker->ResolveType(*dex_file, class_idx, referrer);
4438
4439 if (res_class == NULL) {
4440 *failure = VERIFY_ERROR_NO_CLASS;
4441 return NULL;
4442 }
4443
4444 /* Check if access is allowed. */
4445 if (!referrer->CanAccess(res_class)) {
4446 LOG(ERROR) << "VFY: illegal class access: "
4447 << referrer->GetDescriptor()->ToModifiedUtf8() << " -> "
4448 << res_class->GetDescriptor()->ToModifiedUtf8();
4449 *failure = VERIFY_ERROR_ACCESS_CLASS;
4450 return NULL;
4451 }
4452
4453 return res_class;
4454}
4455
jeffhaobdb76512011-09-07 11:43:16 -07004456DexVerifier::RegType DexVerifier::MergeTypes(RegType type1, RegType type2,
4457 bool* changed) {
4458 RegType result;
4459
jeffhao98eacac2011-09-14 16:11:53 -07004460 /* Check for trivial case so we don't have to hit memory. */
jeffhaobdb76512011-09-07 11:43:16 -07004461 if (type1 == type2)
4462 return type1;
4463
4464 /*
4465 * Use the table if we can, and reject any attempts to merge something
4466 * from the table with a reference type.
4467 *
4468 * Uninitialized references are composed of the enum ORed with an
jeffhaod1f0fde2011-09-08 17:25:33 -07004469 * index value. The uninitialized table entry at index zero *will*
4470 * show up as a simple kRegTypeUninit value. Since this cannot be
jeffhaobdb76512011-09-07 11:43:16 -07004471 * merged with anything but itself, the rules do the right thing.
4472 */
4473 if (type1 < kRegTypeMAX) {
4474 if (type2 < kRegTypeMAX) {
4475 result = merge_table_[type1][type2];
4476 } else {
4477 /* simple + reference == conflict, usually */
4478 if (type1 == kRegTypeZero)
4479 result = type2;
4480 else
4481 result = kRegTypeConflict;
4482 }
4483 } else {
4484 if (type2 < kRegTypeMAX) {
4485 /* reference + simple == conflict, usually */
4486 if (type2 == kRegTypeZero)
4487 result = type1;
4488 else
4489 result = kRegTypeConflict;
4490 } else {
4491 /* merging two references */
4492 if (RegTypeIsUninitReference(type1) ||
4493 RegTypeIsUninitReference(type2))
4494 {
4495 /* can't merge uninit with anything but self */
4496 result = kRegTypeConflict;
4497 } else {
4498 Class* klass1 = RegTypeInitializedReferenceToClass(type1);
4499 Class* klass2 = RegTypeInitializedReferenceToClass(type2);
4500 Class* merged_class = FindCommonSuperclass(klass1, klass2);
4501 assert(merged_class != NULL);
4502 result = RegTypeFromClass(merged_class);
4503 }
4504 }
4505 }
4506
4507 if (result != type1)
4508 *changed = true;
jeffhaoba5ebb92011-08-25 17:24:37 -07004509 return result;
jeffhaobdb76512011-09-07 11:43:16 -07004510}
4511
4512DexVerifier::MonitorEntries DexVerifier::MergeMonitorEntries(
4513 MonitorEntries ents1, MonitorEntries ents2, bool* changed) {
4514 MonitorEntries result = ents1 & ents2;
4515 if (result != ents1)
4516 *changed = true;
4517 return result;
4518}
4519
4520bool DexVerifier::UpdateRegisters(InsnFlags* insn_flags,
4521 RegisterTable* reg_table, int next_insn, const RegisterLine* work_line) {
4522 const size_t insn_reg_count_plus = reg_table->insn_reg_count_plus_;
4523 assert(work_line != NULL);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004524 const RegType* work_regs = work_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004525
4526 if (!InsnIsVisitedOrChanged(insn_flags, next_insn)) {
4527 /*
4528 * We haven't processed this instruction before, and we haven't
jeffhaod1f0fde2011-09-08 17:25:33 -07004529 * touched the registers here, so there's nothing to "merge". Copy
4530 * the registers over and mark it as changed. (This is the only
jeffhaobdb76512011-09-07 11:43:16 -07004531 * way a register can transition out of "unknown", so this is not
4532 * just an optimization.)
4533 */
4534 CopyLineToTable(reg_table, next_insn, work_line);
4535 InsnSetChanged(insn_flags, next_insn, true);
4536 } else {
4537 /* Merge registers, set Changed only if different */
4538 RegisterLine* target_line = GetRegisterLine(reg_table, next_insn);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004539 RegType* target_regs = target_line->reg_types_.get();
4540 MonitorEntries* work_mon_ents = work_line->monitor_entries_.get();
4541 MonitorEntries* target_mon_ents = target_line->monitor_entries_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004542 bool changed = false;
4543 unsigned int idx;
4544
4545 assert(target_regs != NULL);
4546 if (target_mon_ents != NULL) {
4547 /* Monitor stacks must be identical. */
4548 if (target_line->monitor_stack_top_ != work_line->monitor_stack_top_) {
4549 LOG(ERROR) << "VFY: mismatched stack depth "
4550 << target_line->monitor_stack_top_ << " vs. "
4551 << work_line->monitor_stack_top_ << " at 0x"
4552 << std::hex << next_insn << std::dec;
4553 return false;
4554 }
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004555 if (memcmp(target_line->monitor_stack_.get(), work_line->monitor_stack_.get(),
jeffhaobdb76512011-09-07 11:43:16 -07004556 target_line->monitor_stack_top_ * sizeof(uint32_t)) != 0) {
4557 LOG(ERROR) << "VFY: mismatched monitor stacks at 0x" << std::hex
4558 << next_insn << std::dec;
4559 return false;
4560 }
4561 }
4562
4563 for (idx = 0; idx < insn_reg_count_plus; idx++) {
4564 target_regs[idx] = MergeTypes(target_regs[idx], work_regs[idx], &changed);
4565
4566 if (target_mon_ents != NULL) {
4567 target_mon_ents[idx] = MergeMonitorEntries(target_mon_ents[idx],
4568 work_mon_ents[idx], &changed);
4569 }
4570 }
4571
4572 if (changed) {
4573 InsnSetChanged(insn_flags, next_insn, true);
4574 }
4575 }
4576
4577 return true;
4578}
4579
4580bool DexVerifier::CanConvertTo1nr(RegType src_type, RegType check_type) {
4581 static const char conv_tab[kRegType1nrEND - kRegType1nrSTART + 1]
4582 [kRegType1nrEND - kRegType1nrSTART + 1] =
4583 {
4584 /* chk: 0 1 Z y Y h H c i b B s S C I F */
4585 { /*0*/ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4586 { /*1*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4587 { /*Z*/ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
4588 { /*y*/ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4589 { /*Y*/ 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1 },
4590 { /*h*/ 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1 },
4591 { /*H*/ 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1 },
4592 { /*c*/ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1 },
4593 { /*i*/ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1 },
4594 { /*b*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0 },
4595 { /*B*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0 },
4596 { /*s*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 },
4597 { /*S*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 },
4598 { /*C*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 },
4599 { /*I*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },
4600 { /*F*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
4601 };
4602
4603 assert(check_type >= kRegType1nrSTART && check_type <= kRegType1nrEND);
4604
4605 if (src_type >= kRegType1nrSTART && src_type <= kRegType1nrEND)
4606 return (bool) conv_tab[src_type - kRegType1nrSTART]
4607 [check_type - kRegType1nrSTART];
4608
4609 return false;
4610}
4611
4612bool DexVerifier::CanConvertTo2(RegType src_type, RegType check_type) {
4613 return ((src_type == kRegTypeConstLo || src_type == check_type) &&
4614 (check_type == kRegTypeLongLo || check_type == kRegTypeDoubleLo));
4615}
4616
4617DexVerifier::RegType DexVerifier::PrimitiveTypeToRegType(
4618 Class::PrimitiveType prim_type) {
4619 switch (prim_type) {
4620 case Class::kPrimBoolean: return kRegTypeBoolean;
4621 case Class::kPrimByte: return kRegTypeByte;
4622 case Class::kPrimShort: return kRegTypeShort;
4623 case Class::kPrimChar: return kRegTypeChar;
4624 case Class::kPrimInt: return kRegTypeInteger;
4625 case Class::kPrimLong: return kRegTypeLongLo;
4626 case Class::kPrimFloat: return kRegTypeFloat;
4627 case Class::kPrimDouble: return kRegTypeDoubleLo;
4628 case Class::kPrimVoid:
4629 default: {
4630 return kRegTypeUnknown;
4631 }
4632 }
4633}
4634
4635DexVerifier::RegType DexVerifier::ConstTypeToRegType(RegType const_type) {
4636 switch (const_type) {
4637 case kRegTypeConstPosByte: return kRegTypePosByte;
4638 case kRegTypeConstByte: return kRegTypeByte;
4639 case kRegTypeConstPosShort: return kRegTypePosShort;
4640 case kRegTypeConstShort: return kRegTypeShort;
4641 case kRegTypeConstChar: return kRegTypeChar;
4642 case kRegTypeConstInteger: return kRegTypeInteger;
4643 default: {
4644 return const_type;
4645 }
4646 }
4647}
4648
4649char DexVerifier::DetermineCat1Const(int32_t value) {
4650 if (value < -32768)
4651 return kRegTypeConstInteger;
4652 else if (value < -128)
4653 return kRegTypeConstShort;
4654 else if (value < 0)
4655 return kRegTypeConstByte;
4656 else if (value == 0)
4657 return kRegTypeZero;
4658 else if (value == 1)
4659 return kRegTypeOne;
4660 else if (value < 128)
4661 return kRegTypeConstPosByte;
4662 else if (value < 32768)
4663 return kRegTypeConstPosShort;
4664 else if (value < 65536)
4665 return kRegTypeConstChar;
4666 else
4667 return kRegTypeConstInteger;
4668}
4669
4670void DexVerifier::CheckFinalFieldAccess(const Method* method,
4671 const Field* field, VerifyError* failure) {
4672 if (!field->IsFinal())
4673 return;
4674
4675 /* make sure we're in the same class */
4676 if (method->GetDeclaringClass() != field->GetDeclaringClass()) {
4677 LOG(ERROR) << "VFY: can't modify final field "
4678 << field->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
4679 << "." << field->GetName()->ToModifiedUtf8();
4680 *failure = VERIFY_ERROR_ACCESS_FIELD;
4681 return;
4682 }
4683}
4684
4685void DexVerifier::CheckArrayIndexType(const Method* method, RegType reg_type,
4686 VerifyError* failure) {
4687 if (*failure == VERIFY_ERROR_NONE) {
4688 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004689 * The 1nr types are interchangeable at this level. We could
jeffhaobdb76512011-09-07 11:43:16 -07004690 * do something special if we can definitively identify it as a
4691 * float, but there's no real value in doing so.
4692 */
4693 CheckTypeCategory(reg_type, kTypeCategory1nr, failure);
4694 if (*failure != VERIFY_ERROR_NONE) {
4695 LOG(ERROR) << "Invalid reg type for array index (" << reg_type << ")";
4696 }
4697 }
4698}
4699
4700bool DexVerifier::CheckConstructorReturn(const Method* method,
4701 const RegisterLine* register_line, const int insn_reg_count) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004702 const RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004703
4704 if (!IsInitMethod(method))
4705 return true;
4706
4707 RegType uninit_this = RegTypeFromUninitIndex(kUninitThisArgSlot);
4708
4709 for (int i = 0; i < insn_reg_count; i++) {
4710 if (insn_regs[i] == uninit_this) {
4711 LOG(ERROR) << "VFY: <init> returning without calling superclass init";
4712 return false;
4713 }
4714 }
4715 return true;
4716}
4717
4718bool DexVerifier::CheckMoveException(const uint16_t* insns, int insn_idx) {
4719 if ((insns[insn_idx] & 0xff) == Instruction::MOVE_EXCEPTION) {
4720 LOG(ERROR) << "VFY: invalid use of move-exception";
4721 return false;
4722 }
4723 return true;
4724}
4725
4726void DexVerifier::CheckTypeCategory(RegType type, TypeCategory cat,
4727 VerifyError* failure) {
4728 switch (cat) {
4729 case kTypeCategory1nr:
4730 switch (type) {
4731 case kRegTypeZero:
4732 case kRegTypeOne:
4733 case kRegTypeBoolean:
4734 case kRegTypeConstPosByte:
4735 case kRegTypeConstByte:
4736 case kRegTypeConstPosShort:
4737 case kRegTypeConstShort:
4738 case kRegTypeConstChar:
4739 case kRegTypeConstInteger:
4740 case kRegTypePosByte:
4741 case kRegTypeByte:
4742 case kRegTypePosShort:
4743 case kRegTypeShort:
4744 case kRegTypeChar:
4745 case kRegTypeInteger:
4746 case kRegTypeFloat:
4747 break;
4748 default:
4749 *failure = VERIFY_ERROR_GENERIC;
4750 break;
4751 }
4752 break;
4753 case kTypeCategory2:
4754 switch (type) {
4755 case kRegTypeConstLo:
4756 case kRegTypeLongLo:
4757 case kRegTypeDoubleLo:
4758 break;
4759 default:
4760 *failure = VERIFY_ERROR_GENERIC;
4761 break;
4762 }
4763 break;
4764 case kTypeCategoryRef:
4765 if (type != kRegTypeZero && !RegTypeIsReference(type))
4766 *failure = VERIFY_ERROR_GENERIC;
4767 break;
4768 default:
4769 assert(false);
4770 *failure = VERIFY_ERROR_GENERIC;
4771 break;
4772 }
4773}
4774
4775void DexVerifier::CheckWidePair(RegType type_l, RegType type_h,
4776 VerifyError* failure) {
4777 if ((type_h != type_l + 1))
4778 *failure = VERIFY_ERROR_GENERIC;
4779}
4780
4781void DexVerifier::CheckUnop(RegisterLine* register_line,
4782 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4783 RegType src_type, VerifyError* failure) {
4784 VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
4785 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4786}
4787
4788bool DexVerifier::UpcastBooleanOp(RegisterLine* register_line, uint32_t reg1,
4789 uint32_t reg2) {
4790 RegType type1, type2;
4791
4792 type1 = GetRegisterType(register_line, reg1);
4793 type2 = GetRegisterType(register_line, reg2);
4794
4795 if ((type1 == kRegTypeBoolean || type1 == kRegTypeZero || type1 == kRegTypeOne) &&
4796 (type2 == kRegTypeBoolean || type2 == kRegTypeZero || type2 == kRegTypeOne)) {
4797 return true;
4798 }
4799 return false;
4800}
4801
4802void DexVerifier::CheckLitop(RegisterLine* register_line,
4803 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4804 RegType src_type, bool check_boolean_op, VerifyError* failure) {
4805 VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
4806
4807 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
4808 assert(dst_type == kRegTypeInteger);
4809
4810 /* check vB with the call, then check the constant manually */
4811 if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vB_)
4812 && (dec_insn->vC_ == 0 || dec_insn->vC_ == 1)) {
4813 dst_type = kRegTypeBoolean;
4814 }
4815 }
4816
4817 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4818}
4819
4820void DexVerifier::CheckBinop(RegisterLine* register_line,
4821 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4822 RegType src_type1, RegType src_type2, bool check_boolean_op,
4823 VerifyError* failure) {
4824 VerifyRegisterType(register_line, dec_insn->vB_, src_type1, failure);
4825 VerifyRegisterType(register_line, dec_insn->vC_, src_type2, failure);
4826
4827 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
4828 assert(dst_type == kRegTypeInteger);
4829 if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vC_))
4830 dst_type = kRegTypeBoolean;
4831 }
4832
4833 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4834}
4835
4836void DexVerifier::CheckBinop2addr(RegisterLine* register_line,
4837 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4838 RegType src_type1, RegType src_type2, bool check_boolean_op,
4839 VerifyError* failure) {
4840 VerifyRegisterType(register_line, dec_insn->vA_, src_type1, failure);
4841 VerifyRegisterType(register_line, dec_insn->vB_, src_type2, failure);
4842
4843 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
4844 assert(dst_type == kRegTypeInteger);
4845 if (UpcastBooleanOp(register_line, dec_insn->vA_, dec_insn->vB_))
4846 dst_type = kRegTypeBoolean;
4847 }
4848
4849 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4850}
4851
4852DexVerifier::RegType DexVerifier::AdjustForRightShift(
4853 RegisterLine* register_line, int reg, unsigned int shift_count,
4854 bool is_unsigned_shift, VerifyError* failure) {
4855 RegType src_type = GetRegisterType(register_line, reg);
4856 RegType new_type;
4857
4858 /* convert const derived types to their actual types */
4859 src_type = ConstTypeToRegType(src_type);
4860
4861 /* no-op */
4862 if (shift_count == 0)
4863 return src_type;
4864
4865 /* safe defaults */
4866 if (is_unsigned_shift)
4867 new_type = kRegTypeInteger;
4868 else
4869 new_type = src_type;
4870
4871 if (shift_count >= 32) {
4872 LOG(ERROR) << "Got unexpectedly large shift count " << shift_count;
4873 /* fail? */
4874 return new_type;
4875 }
4876
4877 switch (src_type) {
4878 case kRegTypeInteger: /* 32-bit signed value */
4879 if (is_unsigned_shift) {
4880 if (shift_count > 24)
4881 new_type = kRegTypePosByte;
4882 else if (shift_count >= 16)
4883 new_type = kRegTypeChar;
4884 } else {
4885 if (shift_count >= 24)
4886 new_type = kRegTypeByte;
4887 else if (shift_count >= 16)
4888 new_type = kRegTypeShort;
4889 }
4890 break;
4891 case kRegTypeShort: /* 16-bit signed value */
4892 if (is_unsigned_shift) {
4893 /* default (kRegTypeInteger) is correct */
4894 } else {
4895 if (shift_count >= 8)
4896 new_type = kRegTypeByte;
4897 }
4898 break;
4899 case kRegTypePosShort: /* 15-bit unsigned value */
4900 if (shift_count >= 8)
4901 new_type = kRegTypePosByte;
4902 break;
4903 case kRegTypeChar: /* 16-bit unsigned value */
4904 if (shift_count > 8)
4905 new_type = kRegTypePosByte;
4906 break;
4907 case kRegTypeByte: /* 8-bit signed value */
4908 /* defaults (u=kRegTypeInteger / s=src_type) are correct */
4909 break;
4910 case kRegTypePosByte: /* 7-bit unsigned value */
4911 /* always use new_type=src_type */
4912 new_type = src_type;
4913 break;
4914 case kRegTypeZero: /* 1-bit unsigned value */
4915 case kRegTypeOne:
4916 case kRegTypeBoolean:
4917 /* unnecessary? */
4918 new_type = kRegTypeZero;
4919 break;
4920 default:
4921 /* long, double, references; shouldn't be here! */
4922 assert(false);
4923 break;
4924 }
4925
4926 return new_type;
4927}
4928
4929void DexVerifier::VerifyFilledNewArrayRegs(const Method* method,
4930 RegisterLine* register_line,
4931 const Instruction::DecodedInstruction* dec_insn, Class* res_class,
4932 bool is_range, VerifyError* failure) {
4933 uint32_t arg_count = dec_insn->vA_;
4934 RegType expected_type;
4935 Class::PrimitiveType elem_type;
4936 unsigned int ui;
4937
4938 assert(res_class->IsArrayClass());
4939 elem_type = res_class->GetComponentType()->GetPrimitiveType();
4940 if (elem_type == Class::kPrimNot) {
4941 expected_type = RegTypeFromClass(res_class->GetComponentType());
4942 } else {
4943 expected_type = PrimitiveTypeToRegType(elem_type);
4944 }
4945
4946 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004947 * Verify each register. If "arg_count" is bad, VerifyRegisterType()
4948 * will run off the end of the list and fail. It's legal, if silly,
jeffhaobdb76512011-09-07 11:43:16 -07004949 * for arg_count to be zero.
4950 */
4951 for (ui = 0; ui < arg_count; ui++) {
4952 uint32_t get_reg;
4953
4954 if (is_range)
4955 get_reg = dec_insn->vC_ + ui;
4956 else
4957 get_reg = dec_insn->arg_[ui];
4958
4959 VerifyRegisterType(register_line, get_reg, expected_type, failure);
4960 if (*failure != VERIFY_ERROR_NONE) {
4961 LOG(ERROR) << "VFY: filled-new-array arg " << ui << "(" << get_reg
4962 << ") not valid";
4963 return;
4964 }
4965 }
4966}
4967
4968bool DexVerifier::IsCorrectInvokeKind(MethodType method_type,
4969 Method* res_method) {
4970 switch (method_type) {
4971 case METHOD_DIRECT:
4972 return res_method->IsDirect();
4973 case METHOD_STATIC:
4974 return res_method->IsStatic();
4975 case METHOD_VIRTUAL:
4976 case METHOD_INTERFACE:
4977 return !res_method->IsDirect();
4978 default:
4979 return false;
4980 }
4981}
4982
4983Method* DexVerifier::VerifyInvocationArgs(VerifierData* vdata,
4984 RegisterLine* register_line, const int insn_reg_count,
4985 const Instruction::DecodedInstruction* dec_insn, MethodType method_type,
4986 bool is_range, bool is_super, VerifyError* failure) {
4987 Method* method = vdata->method_;
4988 const DexFile* dex_file = vdata->dex_file_;
4989 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004990 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004991 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4992 DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
4993 const ClassLoader* class_loader =
4994 method->GetDeclaringClass()->GetClassLoader();
4995
4996 Method* res_method;
4997 std::string sig;
4998 size_t sig_offset;
4999 int expected_args;
5000 int actual_args;
5001
5002 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07005003 * Resolve the method. This could be an abstract or concrete method
jeffhaobdb76512011-09-07 11:43:16 -07005004 * depending on what sort of call we're making.
5005 */
5006 res_method = class_linker->ResolveMethod(*dex_file, dec_insn->vB_, dex_cache,
5007 class_loader, (method_type == METHOD_DIRECT || method_type == METHOD_STATIC));
5008
jeffhaobdb76512011-09-07 11:43:16 -07005009 if (res_method == NULL) {
jeffhao98eacac2011-09-14 16:11:53 -07005010 const DexFile::MethodId& method_id = dex_file->GetMethodId(dec_insn->vB_);
5011 const char* method_name = dex_file->GetMethodName(method_id);
5012 const char* method_proto = dex_file->GetMethodPrototype(method_id);
5013 const char* class_descriptor = dex_file->GetMethodClassDescriptor(method_id);
5014
5015 LOG(ERROR) << "VFY: unable to resolve method " << dec_insn->vB_ << ": "
5016 << class_descriptor << "." << method_name << " " << method_proto;
jeffhaobdb76512011-09-07 11:43:16 -07005017 *failure = VERIFY_ERROR_NO_METHOD;
5018 return NULL;
5019 }
jeffhaobdb76512011-09-07 11:43:16 -07005020
5021 /*
5022 * Only time you can explicitly call a method starting with '<' is when
jeffhaod1f0fde2011-09-08 17:25:33 -07005023 * making a "direct" invocation on "<init>". There are additional
jeffhaobdb76512011-09-07 11:43:16 -07005024 * restrictions but we don't enforce them here.
5025 */
5026 if (res_method->GetName()->Equals("<init>")) {
5027 if (method_type != METHOD_DIRECT || !IsInitMethod(res_method)) {
5028 LOG(ERROR) << "VFY: invalid call to "
jeffhao98eacac2011-09-14 16:11:53 -07005029 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
jeffhaobdb76512011-09-07 11:43:16 -07005030 << "." << res_method->GetName();
5031 goto bad_sig;
5032 }
5033 }
5034
5035 /*
5036 * See if the method type implied by the invoke instruction matches the
5037 * access flags for the target method.
5038 */
5039 if (!IsCorrectInvokeKind(method_type, res_method)) {
5040 LOG(ERROR) << "VFY: invoke type does not match method type of "
jeffhao98eacac2011-09-14 16:11:53 -07005041 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
jeffhaobdb76512011-09-07 11:43:16 -07005042 << "." << res_method->GetName()->ToModifiedUtf8();
5043
5044 *failure = VERIFY_ERROR_GENERIC;
5045 return NULL;
5046 }
5047
5048 /*
5049 * If we're using invoke-super(method), make sure that the executing
5050 * method's class' superclass has a vtable entry for the target method.
5051 */
5052 if (is_super) {
5053 assert(method_type == METHOD_VIRTUAL);
5054 Class* super = method->GetDeclaringClass()->GetSuperClass();
5055 if (super == NULL || res_method->GetMethodIndex() > super->GetVTable()->GetLength()) {
5056 if (super == NULL) {
5057 LOG(ERROR) << "VFY: invalid invoke-super from "
5058 << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5059 << "." << method->GetName()->ToModifiedUtf8() << " to super -."
5060 << res_method->GetName()->ToModifiedUtf8()
5061 << " " << res_method->GetSignature()->ToModifiedUtf8();
5062 } else {
5063 LOG(ERROR) << "VFY: invalid invoke-super from "
5064 << method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5065 << "." << method->GetName()->ToModifiedUtf8() << " to super "
5066 << super->GetDescriptor()->ToModifiedUtf8()
5067 << "." << res_method->GetName()->ToModifiedUtf8()
5068 << " " << res_method->GetSignature()->ToModifiedUtf8();
5069 }
5070 *failure = VERIFY_ERROR_NO_METHOD;
5071 return NULL;
5072 }
5073 }
5074
5075 /*
5076 * We use vAA as our expected arg count, rather than res_method->insSize,
jeffhaod1f0fde2011-09-08 17:25:33 -07005077 * because we need to match the call to the signature. Also, we might
jeffhaobdb76512011-09-07 11:43:16 -07005078 * might be calling through an abstract method definition (which doesn't
5079 * have register count values).
5080 */
5081 expected_args = dec_insn->vA_;
5082 actual_args = 0;
5083
5084 /* caught by static verifier */
5085 assert(is_range || expected_args <= 5);
5086
5087 if (expected_args > code_item->outs_size_) {
5088 LOG(ERROR) << "VFY: invalid arg count (" << expected_args
5089 << ") exceeds outsSize (" << code_item->outs_size_ << ")";
5090 *failure = VERIFY_ERROR_GENERIC;
5091 return NULL;
5092 }
5093
5094 sig = res_method->GetSignature()->ToModifiedUtf8();
5095 if (sig[0] != '(') {
5096 LOG(ERROR) << "VFY: descriptor doesn't start with '(': " << sig;
5097 goto bad_sig;
5098 }
5099
5100 /*
5101 * Check the "this" argument, which must be an instance of the class
jeffhaod1f0fde2011-09-08 17:25:33 -07005102 * that declared the method. For an interface class, we don't do the
jeffhaobdb76512011-09-07 11:43:16 -07005103 * full interface merge, so we can't do a rigorous check here (which
5104 * is okay since we have to do it at runtime).
5105 */
5106 if (!res_method->IsStatic()) {
5107 Class* actual_this_ref;
5108 RegType actual_arg_type;
5109
5110 actual_arg_type = GetInvocationThis(register_line, dec_insn, failure);
5111 if (*failure != VERIFY_ERROR_NONE)
5112 return NULL;
5113
5114 if (RegTypeIsUninitReference(actual_arg_type) &&
5115 !res_method->GetName()->Equals("<init>")) {
5116 LOG(ERROR) << "VFY: 'this' arg must be initialized";
5117 *failure = VERIFY_ERROR_GENERIC;
5118 return NULL;
5119 }
5120 if (method_type != METHOD_INTERFACE && actual_arg_type != kRegTypeZero) {
5121 actual_this_ref = RegTypeReferenceToClass(actual_arg_type, uninit_map);
5122 if (!res_method->GetDeclaringClass()->IsAssignableFrom(actual_this_ref)) {
5123 LOG(ERROR) << "VFY: 'this' arg '"
5124 << actual_this_ref->GetDescriptor()->ToModifiedUtf8()
5125 << "' not instance of '"
5126 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5127 << "'";
5128 *failure = VERIFY_ERROR_GENERIC;
5129 return NULL;
5130 }
5131 }
5132 actual_args++;
5133 }
5134
5135 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07005136 * Process the target method's signature. This signature may or may not
jeffhaobdb76512011-09-07 11:43:16 -07005137 * have been verified, so we can't assume it's properly formed.
5138 */
5139 for (sig_offset = 1; sig_offset < sig.size(); sig_offset++) {
jeffhaobdb76512011-09-07 11:43:16 -07005140 if (sig[sig_offset] == ')')
5141 break;
5142
5143 if (actual_args >= expected_args) {
5144 LOG(ERROR) << "VFY: expected " << expected_args << " args, found more ("
5145 << sig.substr(sig_offset) << ")";
5146 goto bad_sig;
5147 }
5148
5149 uint32_t get_reg;
5150 if (is_range)
5151 get_reg = dec_insn->vC_ + actual_args;
5152 else
5153 get_reg = dec_insn->arg_[actual_args];
5154
5155 switch (sig[sig_offset]) {
5156 case 'L':
5157 {
5158 Class* klass = LookupSignatureClass(method, sig.substr(sig_offset),
5159 failure);
5160 if (*failure != VERIFY_ERROR_NONE)
5161 goto bad_sig;
5162 VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
5163 failure);
5164 if (*failure != VERIFY_ERROR_NONE) {
5165 LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
5166 << klass->GetDescriptor()->ToModifiedUtf8() << ")";
5167 goto bad_sig;
5168 }
5169 sig_offset += sig.substr(sig_offset).find(';');
5170 }
5171 actual_args++;
5172 break;
5173 case '[':
5174 {
5175 Class* klass = LookupSignatureArrayClass(method,
5176 sig.substr(sig_offset), failure);
5177 if (*failure != VERIFY_ERROR_NONE)
5178 goto bad_sig;
5179 VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
5180 failure);
5181 if (*failure != VERIFY_ERROR_NONE) {
5182 LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
5183 << klass->GetDescriptor()->ToModifiedUtf8() << ")";
5184 goto bad_sig;
5185 }
5186 while (sig[sig_offset] == '[')
5187 sig_offset++;
5188 if (sig[sig_offset] == 'L')
5189 sig_offset += sig.substr(sig_offset).find(';');
5190 }
5191 actual_args++;
5192 break;
5193 case 'Z':
5194 VerifyRegisterType(register_line, get_reg, kRegTypeBoolean, failure);
5195 actual_args++;
5196 break;
5197 case 'C':
5198 VerifyRegisterType(register_line, get_reg, kRegTypeChar, failure);
5199 actual_args++;
5200 break;
5201 case 'B':
5202 VerifyRegisterType(register_line, get_reg, kRegTypeByte, failure);
5203 actual_args++;
5204 break;
5205 case 'I':
5206 VerifyRegisterType(register_line, get_reg, kRegTypeInteger, failure);
5207 actual_args++;
5208 break;
5209 case 'S':
5210 VerifyRegisterType(register_line, get_reg, kRegTypeShort, failure);
5211 actual_args++;
5212 break;
5213 case 'F':
5214 VerifyRegisterType(register_line, get_reg, kRegTypeFloat, failure);
5215 actual_args++;
5216 break;
5217 case 'D':
5218 VerifyRegisterType(register_line, get_reg, kRegTypeDoubleLo, failure);
5219 actual_args += 2;
5220 break;
5221 case 'J':
5222 VerifyRegisterType(register_line, get_reg, kRegTypeLongLo, failure);
5223 actual_args += 2;
5224 break;
5225 default:
5226 LOG(ERROR) << "VFY: invocation target: bad signature type char '"
5227 << sig << "'";
5228 goto bad_sig;
5229 }
5230 }
5231 if (sig[sig_offset] != ')') {
5232 LOG(ERROR) << "VFY: invocation target: bad signature '"
5233 << res_method->GetSignature()->ToModifiedUtf8() << "'";
5234 goto bad_sig;
5235 }
5236
5237 if (actual_args != expected_args) {
5238 LOG(ERROR) << "VFY: expected " << expected_args << " args, found "
5239 << actual_args;
5240 goto bad_sig;
5241 }
5242
5243 return res_method;
5244
5245bad_sig:
5246 if (res_method != NULL) {
5247 LOG(ERROR) << "VFY: rejecting call to "
5248 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5249 << "." << res_method->GetName()->ToModifiedUtf8() << " "
5250 << res_method->GetSignature()->ToModifiedUtf8();
5251 }
5252
5253 if (*failure == VERIFY_ERROR_NONE)
5254 *failure = VERIFY_ERROR_GENERIC;
5255 return NULL;
5256}
jeffhaoba5ebb92011-08-25 17:24:37 -07005257
jeffhaod1f0fde2011-09-08 17:25:33 -07005258DexVerifier::RegisterMap* DexVerifier::GenerateRegisterMapV(VerifierData* vdata)
5259{
5260 const DexFile::CodeItem* code_item = vdata->code_item_;
5261 int i, bytes_for_addr, gc_point_count;
5262
5263 if (code_item->registers_size_ >= 2048) {
5264 LOG(ERROR) << "ERROR: register map can't handle "
5265 << code_item->registers_size_ << " registers";
5266 return NULL;
5267 }
5268 uint8_t reg_width = (code_item->registers_size_ + 7) / 8;
5269
5270 /*
5271 * Decide if we need 8 or 16 bits to hold the address. Strictly speaking
5272 * we only need 16 bits if we actually encode an address >= 256 -- if
5273 * the method has a section at the end without GC points (e.g. array
5274 * data) we don't need to count it. The situation is unusual, and
5275 * detecting it requires scanning the entire method, so we don't bother.
5276 */
5277 RegisterMapFormat format;
5278 if (code_item->insns_size_ < 256) {
5279 format = kRegMapFormatCompact8;
5280 bytes_for_addr = 1;
5281 } else {
5282 format = kRegMapFormatCompact16;
5283 bytes_for_addr = 2;
5284 }
5285
5286 /*
5287 * Count up the number of GC point instructions.
5288 *
5289 * NOTE: this does not automatically include the first instruction,
5290 * since we don't count method entry as a GC point.
5291 */
5292 gc_point_count = 0;
5293 for (i = 0; i < (int) code_item->insns_size_; i++) {
5294 if (InsnIsGcPoint(vdata->insn_flags_.get(), i))
5295 gc_point_count++;
5296 }
5297 if (gc_point_count >= 65536) {
5298 /* We could handle this, but in practice we don't get near this. */
5299 LOG(ERROR) << "ERROR: register map can't handle " << gc_point_count
5300 << " gc points in one method";
5301 return NULL;
5302 }
5303
5304 /* Calculate size of buffer to hold the map data. */
5305 uint32_t data_size = gc_point_count * (bytes_for_addr + reg_width);
5306
5307 RegisterMap* map = new RegisterMap(format, reg_width, gc_point_count,
5308 true, data_size);
5309
5310 /* Populate it. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005311 uint8_t* map_data = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005312 for (i = 0; i < (int) vdata->code_item_->insns_size_; i++) {
5313 if (InsnIsGcPoint(vdata->insn_flags_.get(), i)) {
5314 assert(vdata->register_lines_[i].reg_types_.get() != NULL);
5315 if (format == kRegMapFormatCompact8) {
5316 *map_data++ = i;
5317 } else /*kRegMapFormatCompact16*/ {
5318 *map_data++ = i & 0xff;
5319 *map_data++ = i >> 8;
5320 }
5321 OutputTypeVector(vdata->register_lines_[i].reg_types_.get(),
5322 code_item->registers_size_, map_data);
5323 map_data += reg_width;
5324 }
5325 }
5326
jeffhaoe23d93c2011-09-15 14:48:43 -07005327 assert((uint32_t) map_data - (uint32_t) map->data_ == data_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005328
5329 // TODO: Remove this check when it's really running...
5330#if 1
5331 if (!VerifyMap(vdata, map)) {
5332 LOG(ERROR) << "Map failed to verify";
5333 return NULL;
5334 }
5335#endif
5336
5337 /* Try to compress the map. */
5338 RegisterMap* compress_map = CompressMapDifferential(map);
5339 if (compress_map != NULL) {
5340 // TODO: Remove this check when it's really running...
5341#if 1
5342 /*
5343 * Expand the compressed map we just created, and compare it
5344 * to the original. Abort the VM if it doesn't match up.
5345 */
5346 UniquePtr<RegisterMap> uncompressed_map(UncompressMapDifferential(compress_map));
5347 if (uncompressed_map.get() == NULL) {
5348 LOG(ERROR) << "Map failed to uncompress - "
5349 << vdata->method_->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5350 << "." << vdata->method_->GetName()->ToModifiedUtf8();
5351 delete map;
5352 delete compress_map;
5353 /* bad - compression is broken or we're out of memory */
5354 return NULL;
5355 } else {
5356 if (!CompareMaps(map, uncompressed_map.get())) {
5357 LOG(ERROR) << "Map comparison failed - "
5358 << vdata->method_->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5359 << "." << vdata->method_->GetName()->ToModifiedUtf8();
5360 delete map;
5361 delete compress_map;
5362 /* bad - compression is broken */
5363 return NULL;
5364 }
5365 }
5366#endif
5367 delete map;
5368 map = compress_map;
5369 }
5370
5371 return map;
5372}
5373
5374void DexVerifier::OutputTypeVector(const RegType* regs, int insn_reg_count,
5375 uint8_t* data) {
5376 uint8_t val = 0;
5377 int i;
5378
5379 for (i = 0; i < insn_reg_count; i++) {
5380 RegType type = *regs++;
5381 val >>= 1;
5382 if (IsReferenceType(type))
5383 val |= 0x80; /* set hi bit */
5384
5385 if ((i & 0x07) == 7)
5386 *data++ = val;
5387 }
5388 if ((i & 0x07) != 0) {
5389 /* Flush bits from last byte. */
5390 val >>= 8 - (i & 0x07);
5391 *data++ = val;
5392 }
5393}
5394
5395bool DexVerifier::VerifyMap(VerifierData* vdata, const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005396 const uint8_t* raw_map = map->data_;
5397 uint8_t format = map->header_->format_;
5398 const int num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005399 int ent;
5400
jeffhaoe23d93c2011-09-15 14:48:43 -07005401 if ((vdata->code_item_->registers_size_ + 7) / 8 != map->header_->reg_width_) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005402 LOG(ERROR) << "GLITCH: registersSize=" << vdata->code_item_->registers_size_
jeffhaoe23d93c2011-09-15 14:48:43 -07005403 << ", reg_width=" << map->header_->reg_width_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005404 return false;
5405 }
5406
5407 for (ent = 0; ent < num_entries; ent++) {
5408 int addr;
5409
5410 switch (format) {
5411 case kRegMapFormatCompact8:
5412 addr = *raw_map++;
5413 break;
5414 case kRegMapFormatCompact16:
5415 addr = *raw_map++;
5416 addr |= (*raw_map++) << 8;
5417 break;
5418 default:
5419 LOG(FATAL) << "GLITCH: bad format (" << format << ")";
5420 return false;
5421 }
5422
5423 const RegType* regs = vdata->register_lines_[addr].reg_types_.get();
5424 if (regs == NULL) {
5425 LOG(ERROR) << "GLITCH: addr " << addr << " has no data";
5426 return false;
5427 }
5428
5429 uint8_t val = 0;
5430 int i;
5431
5432 for (i = 0; i < vdata->code_item_->registers_size_; i++) {
5433 bool bit_is_ref, reg_is_ref;
5434
5435 val >>= 1;
5436 if ((i & 0x07) == 0) {
5437 /* Load next byte of data. */
5438 val = *raw_map++;
5439 }
5440
5441 bit_is_ref = val & 0x01;
5442
5443 RegType type = regs[i];
5444 reg_is_ref = IsReferenceType(type);
5445
5446 if (bit_is_ref != reg_is_ref) {
5447 LOG(ERROR) << "GLITCH: addr " << addr << " reg " << i << ": bit="
5448 << bit_is_ref << " reg=" << reg_is_ref << "(" << type << ")";
5449 return false;
5450 }
5451 }
5452 /* Raw_map now points to the address field of the next entry. */
5453 }
5454
5455 return true;
5456}
5457
5458bool DexVerifier::CompareMaps(const RegisterMap* map1, const RegisterMap* map2)
5459{
5460 size_t size1, size2;
5461
5462 size1 = ComputeRegisterMapSize(map1);
5463 size2 = ComputeRegisterMapSize(map2);
5464 if (size1 != size2) {
5465 LOG(ERROR) << "CompareMaps: size mismatch (" << size1 << " vs " << size2
5466 << ")";
5467 return false;
5468 }
5469
jeffhaoe23d93c2011-09-15 14:48:43 -07005470 if (map1->header_->format_ != map2->header_->format_ ||
5471 map1->header_->reg_width_ != map2->header_->reg_width_ ||
5472 map1->header_->num_entries_ != map2->header_->num_entries_ ||
5473 map1->header_->format_on_heap_ != map2->header_->format_on_heap_) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005474 LOG(ERROR) << "CompareMaps: fields mismatch";
5475 }
jeffhaoe23d93c2011-09-15 14:48:43 -07005476 if (memcmp(map1->data_, map2->data_, size1) != 0) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005477 LOG(ERROR) << "CompareMaps: data mismatch";
5478 return false;
5479 }
5480
5481 return true;
5482}
5483
5484size_t DexVerifier::ComputeRegisterMapSize(const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005485 uint8_t format = map->header_->format_;
5486 uint16_t num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005487
5488 assert(map != NULL);
5489
5490 switch (format) {
5491 case kRegMapFormatNone:
5492 return 1;
5493 case kRegMapFormatCompact8:
jeffhaoe23d93c2011-09-15 14:48:43 -07005494 return (1 + map->header_->reg_width_) * num_entries;
jeffhaod1f0fde2011-09-08 17:25:33 -07005495 case kRegMapFormatCompact16:
jeffhaoe23d93c2011-09-15 14:48:43 -07005496 return (2 + map->header_->reg_width_) * num_entries;
jeffhaod1f0fde2011-09-08 17:25:33 -07005497 case kRegMapFormatDifferential:
5498 {
5499 /* Decoded ULEB128 length. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005500 const uint8_t* ptr = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005501 return DecodeUnsignedLeb128(&ptr);
5502 }
5503 default:
5504 LOG(FATAL) << "Bad register map format " << format;
5505 return 0;
5506 }
5507}
5508
5509int DexVerifier::ComputeBitDiff(const uint8_t* bits1, const uint8_t* bits2,
5510 int byte_width, int* first_bit_changed_ptr, int* num_bits_changed_ptr,
5511 uint8_t* leb_out_buf) {
5512 int num_bits_changed = 0;
5513 int first_bit_changed = -1;
5514 int leb_size = 0;
5515 int byte_num;
5516
5517 /*
5518 * Run through the vectors, first comparing them at the byte level. This
5519 * will yield a fairly quick result if nothing has changed between them.
5520 */
5521 for (byte_num = 0; byte_num < byte_width; byte_num++) {
5522 uint8_t byte1 = *bits1++;
5523 uint8_t byte2 = *bits2++;
5524 if (byte1 != byte2) {
5525 /* Walk through the byte, identifying the changed bits. */
5526 int bit_num;
5527 for (bit_num = 0; bit_num < 8; bit_num++) {
5528 if (((byte1 >> bit_num) & 0x01) != ((byte2 >> bit_num) & 0x01)) {
5529 int bit_offset = (byte_num << 3) + bit_num;
5530
5531 if (first_bit_changed < 0)
5532 first_bit_changed = bit_offset;
5533 num_bits_changed++;
5534
5535 if (leb_out_buf == NULL) {
5536 leb_size += UnsignedLeb128Size(bit_offset);
5537 } else {
5538 uint8_t* cur_buf = leb_out_buf;
5539 leb_out_buf = WriteUnsignedLeb128(leb_out_buf, bit_offset);
5540 leb_size += leb_out_buf - cur_buf;
5541 }
5542 }
5543 }
5544 }
5545 }
5546
5547 if (num_bits_changed > 0)
5548 assert(first_bit_changed >= 0);
5549
5550 if (first_bit_changed_ptr != NULL)
5551 *first_bit_changed_ptr = first_bit_changed;
5552 if (num_bits_changed_ptr != NULL)
5553 *num_bits_changed_ptr = num_bits_changed;
5554
5555 return leb_size;
5556}
5557
5558DexVerifier::RegisterMap* DexVerifier::CompressMapDifferential(
5559 const RegisterMap* map) {
5560 int orig_size = ComputeRegisterMapSize(map);
5561 uint8_t* tmp_ptr;
5562 int addr_width;
5563
jeffhaoe23d93c2011-09-15 14:48:43 -07005564 uint8_t format = map->header_->format_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005565 switch (format) {
5566 case kRegMapFormatCompact8:
5567 addr_width = 1;
5568 break;
5569 case kRegMapFormatCompact16:
5570 addr_width = 2;
5571 break;
5572 default:
5573 LOG(ERROR) << "ERROR: can't compress map with format=" << format;
5574 return NULL;
5575 }
5576
jeffhaoe23d93c2011-09-15 14:48:43 -07005577 int reg_width = map->header_->reg_width_;
5578 int num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005579
5580 if (num_entries <= 1) {
5581 return NULL;
5582 }
5583
5584 /*
5585 * We don't know how large the compressed data will be. It's possible
5586 * for it to expand and become larger than the original. The header
5587 * itself is variable-sized, so we generate everything into a temporary
5588 * buffer and then copy it to form-fitting storage once we know how big
5589 * it will be (and that it's smaller than the original).
5590 *
5591 * If we use a size that is equal to the size of the input map plus
5592 * a value longer than a single entry can possibly expand to, we need
5593 * only check for overflow at the end of each entry. The worst case
5594 * for a single line is (1 + <ULEB8 address> + <full copy of vector>).
5595 * Addresses are 16 bits, so that's (1 + 3 + reg_width).
5596 *
5597 * The initial address offset and bit vector will take up less than
5598 * or equal to the amount of space required when uncompressed -- large
5599 * initial offsets are rejected.
5600 */
5601 UniquePtr<uint8_t[]> tmp_buf(new uint8_t[orig_size + (1 + 3 + reg_width)]);
5602
5603 tmp_ptr = tmp_buf.get();
5604
jeffhaoe23d93c2011-09-15 14:48:43 -07005605 const uint8_t* map_data = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005606 const uint8_t* prev_bits;
5607 uint16_t addr, prev_addr;
5608
5609 addr = *map_data++;
5610 if (addr_width > 1)
5611 addr |= (*map_data++) << 8;
5612
5613 if (addr >= 128) {
5614 LOG(ERROR) << "Can't compress map with starting address >= 128";
5615 return NULL;
5616 }
5617
5618 /*
5619 * Start by writing the initial address and bit vector data. The high
5620 * bit of the initial address is used to indicate the required address
5621 * width (which the decoder can't otherwise determine without parsing
5622 * the compressed data).
5623 */
5624 *tmp_ptr++ = addr | (addr_width > 1 ? 0x80 : 0x00);
5625 memcpy(tmp_ptr, map_data, reg_width);
5626
5627 prev_bits = map_data;
5628 prev_addr = addr;
5629
5630 tmp_ptr += reg_width;
5631 map_data += reg_width;
5632
5633 /* Loop over all following entries. */
5634 for (int entry = 1; entry < num_entries; entry++) {
5635 int addr_diff;
5636 uint8_t key;
5637
5638 /* Pull out the address and figure out how to encode it. */
5639 addr = *map_data++;
5640 if (addr_width > 1)
5641 addr |= (*map_data++) << 8;
5642
5643 addr_diff = addr - prev_addr;
5644 assert(addr_diff > 0);
5645 if (addr_diff < 8) {
5646 /* Small difference, encode in 3 bits. */
5647 key = addr_diff -1; /* set 00000AAA */
5648 } else {
5649 /* Large difference, output escape code. */
5650 key = 0x07; /* escape code for AAA */
5651 }
5652
5653 int num_bits_changed, first_bit_changed, leb_size;
5654
5655 leb_size = ComputeBitDiff(prev_bits, map_data, reg_width,
5656 &first_bit_changed, &num_bits_changed, NULL);
5657
5658 if (num_bits_changed == 0) {
5659 /* set B to 1 and CCCC to zero to indicate no bits were changed */
5660 key |= 0x08;
5661 } else if (num_bits_changed == 1 && first_bit_changed < 16) {
5662 /* set B to 0 and CCCC to the index of the changed bit */
5663 key |= first_bit_changed << 4;
5664 } else if (num_bits_changed < 15 && leb_size < reg_width) {
5665 /* set B to 1 and CCCC to the number of bits */
5666 key |= 0x08 | (num_bits_changed << 4);
5667 } else {
5668 /* set B to 1 and CCCC to 0x0f so we store the entire vector */
5669 key |= 0x08 | 0xf0;
5670 }
5671
5672 /*
5673 * Encode output. Start with the key, follow with the address
5674 * diff (if it didn't fit in 3 bits), then the changed bit info.
5675 */
5676 *tmp_ptr++ = key;
5677 if ((key & 0x07) == 0x07)
5678 tmp_ptr = WriteUnsignedLeb128(tmp_ptr, addr_diff);
5679
5680 if ((key & 0x08) != 0) {
5681 int bit_count = key >> 4;
5682 if (bit_count == 0) {
5683 /* nothing changed, no additional output required */
5684 } else if (bit_count == 15) {
5685 /* full vector is most compact representation */
5686 memcpy(tmp_ptr, map_data, reg_width);
5687 tmp_ptr += reg_width;
5688 } else {
5689 /* write bit indices in ULEB128 format */
5690 (void) ComputeBitDiff(prev_bits, map_data, reg_width,
5691 NULL, NULL, tmp_ptr);
5692 tmp_ptr += leb_size;
5693 }
5694 } else {
5695 /* single-bit changed, value encoded in key byte */
5696 }
5697
5698 prev_bits = map_data;
5699 prev_addr = addr;
5700 map_data += reg_width;
5701
5702 /* See if we've run past the original size. */
5703 if (tmp_ptr - tmp_buf.get() >= orig_size) {
5704 return NULL;
5705 }
5706 }
5707
5708 /*
5709 * Create a RegisterMap with the contents.
5710 *
5711 * TODO: consider using a threshold other than merely ">=". We would
5712 * get poorer compression but potentially use less native heap space.
5713 */
5714 int new_data_size = tmp_ptr - tmp_buf.get();
5715 int new_map_size = new_data_size + UnsignedLeb128Size(new_data_size);
5716
5717 if (new_map_size >= orig_size) {
5718 return NULL;
5719 }
5720
5721 RegisterMap* new_map = new RegisterMap(kRegMapFormatDifferential, reg_width,
5722 num_entries, true, new_map_size);
5723
jeffhaoe23d93c2011-09-15 14:48:43 -07005724 tmp_ptr = new_map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005725 tmp_ptr = WriteUnsignedLeb128(tmp_ptr, new_data_size);
5726 memcpy(tmp_ptr, tmp_buf.get(), new_data_size);
5727
5728 return new_map;
5729}
5730
5731DexVerifier::RegisterMap* DexVerifier::UncompressMapDifferential(
5732 const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005733 uint8_t format = map->header_->format_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005734 RegisterMapFormat new_format;
5735 int reg_width, num_entries, new_addr_width, new_data_size;
5736
5737 if (format != kRegMapFormatDifferential) {
5738 LOG(ERROR) << "Not differential (" << format << ")";
5739 return NULL;
5740 }
5741
jeffhaoe23d93c2011-09-15 14:48:43 -07005742 reg_width = map->header_->reg_width_;
5743 num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005744
5745 /* Get the data size; we can check this at the end. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005746 const uint8_t* src_ptr = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005747 int expected_src_len = DecodeUnsignedLeb128(&src_ptr);
5748 const uint8_t* src_start = src_ptr;
5749
5750 /* Get the initial address and the 16-bit address flag. */
5751 int addr = *src_ptr & 0x7f;
5752 if ((*src_ptr & 0x80) == 0) {
5753 new_format = kRegMapFormatCompact8;
5754 new_addr_width = 1;
5755 } else {
5756 new_format = kRegMapFormatCompact16;
5757 new_addr_width = 2;
5758 }
5759 src_ptr++;
5760
5761 /* Now we know enough to allocate the new map. */
5762 new_data_size = (new_addr_width + reg_width) * num_entries;
5763 RegisterMap* new_map = new RegisterMap(new_format, reg_width, num_entries,
5764 true, new_data_size);
5765
5766 /* Write the start address and initial bits to the new map. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005767 uint8_t* dst_ptr = new_map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005768
5769 *dst_ptr++ = addr & 0xff;
5770 if (new_addr_width > 1)
5771 *dst_ptr++ = (uint8_t) (addr >> 8);
5772
5773 memcpy(dst_ptr, src_ptr, reg_width);
5774
5775 int prev_addr = addr;
5776 const uint8_t* prev_bits = dst_ptr; /* point at uncompressed data */
5777
5778 dst_ptr += reg_width;
5779 src_ptr += reg_width;
5780
5781 /* Walk through, uncompressing one line at a time. */
5782 int entry;
5783 for (entry = 1; entry < num_entries; entry++) {
5784 int addr_diff;
5785 uint8_t key;
5786
5787 key = *src_ptr++;
5788
5789 /* Get the address. */
5790 if ((key & 0x07) == 7) {
5791 /* Address diff follows in ULEB128. */
5792 addr_diff = DecodeUnsignedLeb128(&src_ptr);
5793 } else {
5794 addr_diff = (key & 0x07) +1;
5795 }
5796
5797 addr = prev_addr + addr_diff;
5798 *dst_ptr++ = addr & 0xff;
5799 if (new_addr_width > 1)
5800 *dst_ptr++ = (uint8_t) (addr >> 8);
5801
5802 /* Unpack the bits. */
5803 if ((key & 0x08) != 0) {
5804 int bit_count = (key >> 4);
5805 if (bit_count == 0) {
5806 /* No bits changed, just copy previous. */
5807 memcpy(dst_ptr, prev_bits, reg_width);
5808 } else if (bit_count == 15) {
5809 /* Full copy of bit vector is present; ignore prev_bits. */
5810 memcpy(dst_ptr, src_ptr, reg_width);
5811 src_ptr += reg_width;
5812 } else {
5813 /* Copy previous bits and modify listed indices. */
5814 memcpy(dst_ptr, prev_bits, reg_width);
5815 while (bit_count--) {
5816 int bit_index = DecodeUnsignedLeb128(&src_ptr);
5817 ToggleBit(dst_ptr, bit_index);
5818 }
5819 }
5820 } else {
5821 /* Copy previous bits and modify the specified one. */
5822 memcpy(dst_ptr, prev_bits, reg_width);
5823
5824 /* One bit, from 0-15 inclusive, was changed. */
5825 ToggleBit(dst_ptr, key >> 4);
5826 }
5827
5828 prev_addr = addr;
5829 prev_bits = dst_ptr;
5830 dst_ptr += reg_width;
5831 }
5832
jeffhaoe23d93c2011-09-15 14:48:43 -07005833 if (dst_ptr - new_map->data_ != new_data_size) {
5834 LOG(ERROR) << "ERROR: output " << dst_ptr - new_map->data_
jeffhaod1f0fde2011-09-08 17:25:33 -07005835 << " bytes, expected " << new_data_size;
5836 free(new_map);
5837 return NULL;
5838 }
5839
5840 if (src_ptr - src_start != expected_src_len) {
5841 LOG(ERROR) << "ERROR: consumed " << src_ptr - src_start
5842 << " bytes, expected " << expected_src_len;
5843 free(new_map);
5844 return NULL;
5845 }
5846
5847 return new_map;
5848}
5849
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07005850} // namespace art