1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*
18 * Dalvik classfile verification. This file contains the verifier entry
19 * points and the static constraint checks.
20 */
21 #include "Dalvik.h"
22 #include "analysis/CodeVerify.h"
23 #include "libdex/DexCatch.h"
24
25
26 /* fwd */
27 static bool verifyMethod(Method* meth);
28 static bool verifyInstructions(VerifierData* vdata);
29
30
31 /*
32 * Verify a class.
33 *
34 * By the time we get here, the value of gDvm.classVerifyMode should already
35 * have been factored in. If you want to call into the verifier even
36 * though verification is disabled, that's your business.
37 *
38 * Returns "true" on success.
39 */
dvmVerifyClass(ClassObject * clazz)40 bool dvmVerifyClass(ClassObject* clazz)
41 {
42 int i;
43
44 if (dvmIsClassVerified(clazz)) {
45 LOGD("Ignoring duplicate verify attempt on %s", clazz->descriptor);
46 return true;
47 }
48
49 for (i = 0; i < clazz->directMethodCount; i++) {
50 if (!verifyMethod(&clazz->directMethods[i])) {
51 LOG_VFY("Verifier rejected class %s", clazz->descriptor);
52 return false;
53 }
54 }
55 for (i = 0; i < clazz->virtualMethodCount; i++) {
56 if (!verifyMethod(&clazz->virtualMethods[i])) {
57 LOG_VFY("Verifier rejected class %s", clazz->descriptor);
58 return false;
59 }
60 }
61
62 return true;
63 }
64
65
66 /*
67 * Compute the width of the instruction at each address in the instruction
68 * stream, and store it in vdata->insnFlags. Addresses that are in the
69 * middle of an instruction, or that are part of switch table data, are not
70 * touched (so the caller should probably initialize "insnFlags" to zero).
71 *
72 * The "newInstanceCount" and "monitorEnterCount" fields in vdata are
73 * also set.
74 *
75 * Performs some static checks, notably:
76 * - opcode of first instruction begins at index 0
77 * - only documented instructions may appear
78 * - each instruction follows the last
79 * - last byte of last instruction is at (code_length-1)
80 *
81 * Logs an error and returns "false" on failure.
82 */
computeWidthsAndCountOps(VerifierData * vdata)83 static bool computeWidthsAndCountOps(VerifierData* vdata)
84 {
85 const Method* meth = vdata->method;
86 InsnFlags* insnFlags = vdata->insnFlags;
87 size_t insnCount = vdata->insnsSize;
88 const u2* insns = meth->insns;
89 bool result = false;
90 int newInstanceCount = 0;
91 int monitorEnterCount = 0;
92 int i;
93
94 for (i = 0; i < (int) insnCount; /**/) {
95 size_t width = dexGetWidthFromInstruction(insns);
96 if (width == 0) {
97 LOG_VFY_METH(meth, "VFY: invalid instruction (0x%04x)", *insns);
98 goto bail;
99 } else if (width > 65535) {
100 LOG_VFY_METH(meth,
101 "VFY: warning: unusually large instr width (%d)", width);
102 }
103
104 Opcode opcode = dexOpcodeFromCodeUnit(*insns);
105 if (opcode == OP_NEW_INSTANCE || opcode == OP_NEW_INSTANCE_JUMBO)
106 newInstanceCount++;
107 if (opcode == OP_MONITOR_ENTER)
108 monitorEnterCount++;
109
110 insnFlags[i] |= width;
111 i += width;
112 insns += width;
113 }
114 if (i != (int) vdata->insnsSize) {
115 LOG_VFY_METH(meth, "VFY: code did not end where expected (%d vs. %d)",
116 i, dvmGetMethodInsnsSize(meth));
117 goto bail;
118 }
119
120 result = true;
121 vdata->newInstanceCount = newInstanceCount;
122 vdata->monitorEnterCount = monitorEnterCount;
123
124 bail:
125 return result;
126 }
127
128 /*
129 * Set the "in try" flags for all instructions protected by "try" statements.
130 * Also sets the "branch target" flags for exception handlers.
131 *
132 * Call this after widths have been set in "insnFlags".
133 *
134 * Returns "false" if something in the exception table looks fishy, but
135 * we're expecting the exception table to be somewhat sane.
136 */
scanTryCatchBlocks(const Method * meth,InsnFlags * insnFlags)137 static bool scanTryCatchBlocks(const Method* meth, InsnFlags* insnFlags)
138 {
139 u4 insnsSize = dvmGetMethodInsnsSize(meth);
140 const DexCode* pCode = dvmGetMethodCode(meth);
141 u4 triesSize = pCode->triesSize;
142 const DexTry* pTries;
143 u4 idx;
144
145 if (triesSize == 0) {
146 return true;
147 }
148
149 pTries = dexGetTries(pCode);
150
151 for (idx = 0; idx < triesSize; idx++) {
152 const DexTry* pTry = &pTries[idx];
153 u4 start = pTry->startAddr;
154 u4 end = start + pTry->insnCount;
155 u4 addr;
156
157 if ((start >= end) || (start >= insnsSize) || (end > insnsSize)) {
158 LOG_VFY_METH(meth,
159 "VFY: bad exception entry: startAddr=%d endAddr=%d (size=%d)",
160 start, end, insnsSize);
161 return false;
162 }
163
164 if (dvmInsnGetWidth(insnFlags, start) == 0) {
165 LOG_VFY_METH(meth,
166 "VFY: 'try' block starts inside an instruction (%d)",
167 start);
168 return false;
169 }
170
171 for (addr = start; addr < end;
172 addr += dvmInsnGetWidth(insnFlags, addr))
173 {
174 assert(dvmInsnGetWidth(insnFlags, addr) != 0);
175 dvmInsnSetInTry(insnFlags, addr, true);
176 }
177 }
178
179 /* Iterate over each of the handlers to verify target addresses. */
180 u4 handlersSize = dexGetHandlersSize(pCode);
181 u4 offset = dexGetFirstHandlerOffset(pCode);
182 for (idx = 0; idx < handlersSize; idx++) {
183 DexCatchIterator iterator;
184 dexCatchIteratorInit(&iterator, pCode, offset);
185
186 for (;;) {
187 DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
188 u4 addr;
189
190 if (handler == NULL) {
191 break;
192 }
193
194 addr = handler->address;
195 if (dvmInsnGetWidth(insnFlags, addr) == 0) {
196 LOG_VFY_METH(meth,
197 "VFY: exception handler starts at bad address (%d)",
198 addr);
199 return false;
200 }
201
202 dvmInsnSetBranchTarget(insnFlags, addr, true);
203 }
204
205 offset = dexCatchIteratorGetEndOffset(&iterator, pCode);
206 }
207
208 return true;
209 }
210
211 /*
212 * Perform verification on a single method.
213 *
214 * We do this in three passes:
215 * (1) Walk through all code units, determining instruction locations,
216 * widths, and other characteristics.
217 * (2) Walk through all code units, performing static checks on
218 * operands.
219 * (3) Iterate through the method, checking type safety and looking
220 * for code flow problems.
221 *
222 * Some checks may be bypassed depending on the verification mode. We can't
223 * turn this stuff off completely if we want to do "exact" GC.
224 *
225 * TODO: cite source?
226 * Confirmed here:
227 * - code array must not be empty
228 * - (N/A) code_length must be less than 65536
229 * Confirmed by computeWidthsAndCountOps():
230 * - opcode of first instruction begins at index 0
231 * - only documented instructions may appear
232 * - each instruction follows the last
233 * - last byte of last instruction is at (code_length-1)
234 */
verifyMethod(Method * meth)235 static bool verifyMethod(Method* meth)
236 {
237 bool result = false;
238
239 /*
240 * Verifier state blob. Various values will be cached here so we
241 * can avoid expensive lookups and pass fewer arguments around.
242 */
243 VerifierData vdata;
244 #if 1 // ndef NDEBUG
245 memset(&vdata, 0x99, sizeof(vdata));
246 #endif
247
248 vdata.method = meth;
249 vdata.insnsSize = dvmGetMethodInsnsSize(meth);
250 vdata.insnRegCount = meth->registersSize;
251 vdata.insnFlags = NULL;
252 vdata.uninitMap = NULL;
253 vdata.basicBlocks = NULL;
254
255 /*
256 * If there aren't any instructions, make sure that's expected, then
257 * exit successfully. Note: for native methods, meth->insns gets set
258 * to a native function pointer on first call, so don't use that as
259 * an indicator.
260 */
261 if (vdata.insnsSize == 0) {
262 if (!dvmIsNativeMethod(meth) && !dvmIsAbstractMethod(meth)) {
263 LOG_VFY_METH(meth,
264 "VFY: zero-length code in concrete non-native method");
265 goto bail;
266 }
267
268 goto success;
269 }
270
271 /*
272 * Sanity-check the register counts. ins + locals = registers, so make
273 * sure that ins <= registers.
274 */
275 if (meth->insSize > meth->registersSize) {
276 LOG_VFY_METH(meth, "VFY: bad register counts (ins=%d regs=%d)",
277 meth->insSize, meth->registersSize);
278 goto bail;
279 }
280
281 /*
282 * Allocate and populate an array to hold instruction data.
283 *
284 * TODO: Consider keeping a reusable pre-allocated array sitting
285 * around for smaller methods.
286 */
287 vdata.insnFlags = (InsnFlags*) calloc(vdata.insnsSize, sizeof(InsnFlags));
288 if (vdata.insnFlags == NULL)
289 goto bail;
290
291 /*
292 * Compute the width of each instruction and store the result in insnFlags.
293 * Count up the #of occurrences of certain opcodes while we're at it.
294 */
295 if (!computeWidthsAndCountOps(&vdata))
296 goto bail;
297
298 /*
299 * Allocate a map to hold the classes of uninitialized instances.
300 */
301 vdata.uninitMap = dvmCreateUninitInstanceMap(meth, vdata.insnFlags,
302 vdata.newInstanceCount);
303 if (vdata.uninitMap == NULL)
304 goto bail;
305
306 /*
307 * Set the "in try" flags for all instructions guarded by a "try" block.
308 * Also sets the "branch target" flag on exception handlers.
309 */
310 if (!scanTryCatchBlocks(meth, vdata.insnFlags))
311 goto bail;
312
313 /*
314 * Perform static instruction verification. Also sets the "branch
315 * target" flags.
316 */
317 if (!verifyInstructions(&vdata))
318 goto bail;
319
320 /*
321 * Do code-flow analysis.
322 *
323 * We could probably skip this for a method with no registers, but
324 * that's so rare that there's little point in checking.
325 */
326 if (!dvmVerifyCodeFlow(&vdata)) {
327 //LOGD("+++ %s failed code flow", meth->name);
328 goto bail;
329 }
330
331 success:
332 result = true;
333
334 bail:
335 dvmFreeVfyBasicBlocks(&vdata);
336 dvmFreeUninitInstanceMap(vdata.uninitMap);
337 free(vdata.insnFlags);
338 return result;
339 }
340
341
342 /*
343 * Verify an array data table. "curOffset" is the offset of the
344 * fill-array-data instruction.
345 */
checkArrayData(const Method * meth,u4 curOffset)346 static bool checkArrayData(const Method* meth, u4 curOffset)
347 {
348 const u4 insnCount = dvmGetMethodInsnsSize(meth);
349 const u2* insns = meth->insns + curOffset;
350 const u2* arrayData;
351 u4 valueCount, valueWidth, tableSize;
352 s4 offsetToArrayData;
353
354 assert(curOffset < insnCount);
355
356 /* make sure the start of the array data table is in range */
357 offsetToArrayData = insns[1] | (((s4)insns[2]) << 16);
358 if ((s4)curOffset + offsetToArrayData < 0 ||
359 curOffset + offsetToArrayData + 2 >= insnCount)
360 {
361 LOG_VFY("VFY: invalid array data start: at %d, data offset %d, "
362 "count %d",
363 curOffset, offsetToArrayData, insnCount);
364 return false;
365 }
366
367 /* offset to array data table is a relative branch-style offset */
368 arrayData = insns + offsetToArrayData;
369
370 /* make sure the table is 32-bit aligned */
371 if ((((u4) arrayData) & 0x03) != 0) {
372 LOG_VFY("VFY: unaligned array data table: at %d, data offset %d",
373 curOffset, offsetToArrayData);
374 return false;
375 }
376
377 valueWidth = arrayData[1];
378 valueCount = *(u4*)(&arrayData[2]);
379
380 tableSize = 4 + (valueWidth * valueCount + 1) / 2;
381
382 /* make sure the end of the switch is in range */
383 if (curOffset + offsetToArrayData + tableSize > insnCount) {
384 LOG_VFY("VFY: invalid array data end: at %d, data offset %d, end %d, "
385 "count %d",
386 curOffset, offsetToArrayData,
387 curOffset + offsetToArrayData + tableSize, insnCount);
388 return false;
389 }
390
391 return true;
392 }
393
394 /*
395 * Perform static checks on a "new-instance" instruction. Specifically,
396 * make sure the class reference isn't for an array class.
397 *
398 * We don't need the actual class, just a pointer to the class name.
399 */
checkNewInstance(const DvmDex * pDvmDex,u4 idx)400 static bool checkNewInstance(const DvmDex* pDvmDex, u4 idx)
401 {
402 const char* classDescriptor;
403
404 if (idx >= pDvmDex->pHeader->typeIdsSize) {
405 LOG_VFY("VFY: bad type index %d (max %d)",
406 idx, pDvmDex->pHeader->typeIdsSize);
407 return false;
408 }
409
410 classDescriptor = dexStringByTypeIdx(pDvmDex->pDexFile, idx);
411 if (classDescriptor[0] != 'L') {
412 LOG_VFY("VFY: can't call new-instance on type '%s'",
413 classDescriptor);
414 return false;
415 }
416
417 return true;
418 }
419
420 /*
421 * Perform static checks on a "new-array" instruction. Specifically, make
422 * sure they aren't creating an array of arrays that causes the number of
423 * dimensions to exceed 255.
424 */
checkNewArray(const DvmDex * pDvmDex,u4 idx)425 static bool checkNewArray(const DvmDex* pDvmDex, u4 idx)
426 {
427 const char* classDescriptor;
428
429 if (idx >= pDvmDex->pHeader->typeIdsSize) {
430 LOG_VFY("VFY: bad type index %d (max %d)",
431 idx, pDvmDex->pHeader->typeIdsSize);
432 return false;
433 }
434
435 classDescriptor = dexStringByTypeIdx(pDvmDex->pDexFile, idx);
436
437 int bracketCount = 0;
438 const char* cp = classDescriptor;
439 while (*cp++ == '[')
440 bracketCount++;
441
442 if (bracketCount == 0) {
443 /* The given class must be an array type. */
444 LOG_VFY("VFY: can't new-array class '%s' (not an array)",
445 classDescriptor);
446 return false;
447 } else if (bracketCount > 255) {
448 /* It is illegal to create an array of more than 255 dimensions. */
449 LOG_VFY("VFY: can't new-array class '%s' (exceeds limit)",
450 classDescriptor);
451 return false;
452 }
453
454 return true;
455 }
456
457 /*
458 * Perform static checks on an instruction that takes a class constant.
459 * Ensure that the class index is in the valid range.
460 */
checkTypeIndex(const DvmDex * pDvmDex,u4 idx)461 static bool checkTypeIndex(const DvmDex* pDvmDex, u4 idx)
462 {
463 if (idx >= pDvmDex->pHeader->typeIdsSize) {
464 LOG_VFY("VFY: bad type index %d (max %d)",
465 idx, pDvmDex->pHeader->typeIdsSize);
466 return false;
467 }
468 return true;
469 }
470
471 /*
472 * Perform static checks on a field get or set instruction. All we do
473 * here is ensure that the field index is in the valid range.
474 */
checkFieldIndex(const DvmDex * pDvmDex,u4 idx)475 static bool checkFieldIndex(const DvmDex* pDvmDex, u4 idx)
476 {
477 if (idx >= pDvmDex->pHeader->fieldIdsSize) {
478 LOG_VFY("VFY: bad field index %d (max %d)",
479 idx, pDvmDex->pHeader->fieldIdsSize);
480 return false;
481 }
482 return true;
483 }
484
485 /*
486 * Perform static checks on a method invocation instruction. All we do
487 * here is ensure that the method index is in the valid range.
488 */
checkMethodIndex(const DvmDex * pDvmDex,u4 idx)489 static bool checkMethodIndex(const DvmDex* pDvmDex, u4 idx)
490 {
491 if (idx >= pDvmDex->pHeader->methodIdsSize) {
492 LOG_VFY("VFY: bad method index %d (max %d)",
493 idx, pDvmDex->pHeader->methodIdsSize);
494 return false;
495 }
496 return true;
497 }
498
499 /*
500 * Ensure that the string index is in the valid range.
501 */
checkStringIndex(const DvmDex * pDvmDex,u4 idx)502 static bool checkStringIndex(const DvmDex* pDvmDex, u4 idx)
503 {
504 if (idx >= pDvmDex->pHeader->stringIdsSize) {
505 LOG_VFY("VFY: bad string index %d (max %d)",
506 idx, pDvmDex->pHeader->stringIdsSize);
507 return false;
508 }
509 return true;
510 }
511
512 /*
513 * Ensure that the register index is valid for this method.
514 */
checkRegisterIndex(const Method * meth,u4 idx)515 static bool checkRegisterIndex(const Method* meth, u4 idx)
516 {
517 if (idx >= meth->registersSize) {
518 LOG_VFY("VFY: register index out of range (%d >= %d)",
519 idx, meth->registersSize);
520 return false;
521 }
522 return true;
523 }
524
525 /*
526 * Ensure that the wide register index is valid for this method.
527 */
checkWideRegisterIndex(const Method * meth,u4 idx)528 static bool checkWideRegisterIndex(const Method* meth, u4 idx)
529 {
530 if (idx+1 >= meth->registersSize) {
531 LOG_VFY("VFY: wide register index out of range (%d+1 >= %d)",
532 idx, meth->registersSize);
533 return false;
534 }
535 return true;
536 }
537
538 /*
539 * Check the register indices used in a "vararg" instruction, such as
540 * invoke-virtual or filled-new-array.
541 *
542 * vA holds word count (0-5), args[] have values.
543 *
544 * There are some tests we don't do here, e.g. we don't try to verify
545 * that invoking a method that takes a double is done with consecutive
546 * registers. This requires parsing the target method signature, which
547 * we will be doing later on during the code flow analysis.
548 */
checkVarargRegs(const Method * meth,const DecodedInstruction * pDecInsn)549 static bool checkVarargRegs(const Method* meth,
550 const DecodedInstruction* pDecInsn)
551 {
552 u2 registersSize = meth->registersSize;
553 unsigned int idx;
554
555 if (pDecInsn->vA > 5) {
556 LOG_VFY("VFY: invalid arg count (%d) in non-range invoke)",
557 pDecInsn->vA);
558 return false;
559 }
560
561 for (idx = 0; idx < pDecInsn->vA; idx++) {
562 if (pDecInsn->arg[idx] > registersSize) {
563 LOG_VFY("VFY: invalid reg index (%d) in non-range invoke (> %d)",
564 pDecInsn->arg[idx], registersSize);
565 return false;
566 }
567 }
568
569 return true;
570 }
571
572 /*
573 * Check the register indices used in a "vararg/range" instruction, such as
574 * invoke-virtual/range or filled-new-array/range.
575 *
576 * vA holds word count, vC holds index of first reg.
577 */
checkVarargRangeRegs(const Method * meth,const DecodedInstruction * pDecInsn)578 static bool checkVarargRangeRegs(const Method* meth,
579 const DecodedInstruction* pDecInsn)
580 {
581 u2 registersSize = meth->registersSize;
582
583 /*
584 * vA/vC are unsigned 8-bit/16-bit quantities for /range instructions,
585 * so there's no risk of integer overflow when adding them here.
586 */
587 if (pDecInsn->vA + pDecInsn->vC > registersSize) {
588 LOG_VFY("VFY: invalid reg index %d+%d in range invoke (> %d)",
589 pDecInsn->vA, pDecInsn->vC, registersSize);
590 return false;
591 }
592
593 return true;
594 }
595
596 /*
597 * Verify a switch table. "curOffset" is the offset of the switch
598 * instruction.
599 *
600 * Updates "insnFlags", setting the "branch target" flag.
601 */
checkSwitchTargets(const Method * meth,InsnFlags * insnFlags,u4 curOffset)602 static bool checkSwitchTargets(const Method* meth, InsnFlags* insnFlags,
603 u4 curOffset)
604 {
605 const u4 insnCount = dvmGetMethodInsnsSize(meth);
606 const u2* insns = meth->insns + curOffset;
607 const u2* switchInsns;
608 u2 expectedSignature;
609 u4 switchCount, tableSize;
610 s4 offsetToSwitch, offsetToKeys, offsetToTargets;
611 s4 offset, absOffset;
612 u4 targ;
613
614 assert(curOffset < insnCount);
615
616 /* make sure the start of the switch is in range */
617 offsetToSwitch = insns[1] | ((s4) insns[2]) << 16;
618 if ((s4) curOffset + offsetToSwitch < 0 ||
619 curOffset + offsetToSwitch + 2 >= insnCount)
620 {
621 LOG_VFY("VFY: invalid switch start: at %d, switch offset %d, "
622 "count %d",
623 curOffset, offsetToSwitch, insnCount);
624 return false;
625 }
626
627 /* offset to switch table is a relative branch-style offset */
628 switchInsns = insns + offsetToSwitch;
629
630 /* make sure the table is 32-bit aligned */
631 if ((((u4) switchInsns) & 0x03) != 0) {
632 LOG_VFY("VFY: unaligned switch table: at %d, switch offset %d",
633 curOffset, offsetToSwitch);
634 return false;
635 }
636
637 switchCount = switchInsns[1];
638
639 if ((*insns & 0xff) == OP_PACKED_SWITCH) {
640 /* 0=sig, 1=count, 2/3=firstKey */
641 offsetToTargets = 4;
642 offsetToKeys = -1;
643 expectedSignature = kPackedSwitchSignature;
644 } else {
645 /* 0=sig, 1=count, 2..count*2 = keys */
646 offsetToKeys = 2;
647 offsetToTargets = 2 + 2*switchCount;
648 expectedSignature = kSparseSwitchSignature;
649 }
650 tableSize = offsetToTargets + switchCount*2;
651
652 if (switchInsns[0] != expectedSignature) {
653 LOG_VFY("VFY: wrong signature for switch table (0x%04x, wanted 0x%04x)",
654 switchInsns[0], expectedSignature);
655 return false;
656 }
657
658 /* make sure the end of the switch is in range */
659 if (curOffset + offsetToSwitch + tableSize > (u4) insnCount) {
660 LOG_VFY("VFY: invalid switch end: at %d, switch offset %d, end %d, "
661 "count %d",
662 curOffset, offsetToSwitch, curOffset + offsetToSwitch + tableSize,
663 insnCount);
664 return false;
665 }
666
667 /* for a sparse switch, verify the keys are in ascending order */
668 if (offsetToKeys > 0 && switchCount > 1) {
669 s4 lastKey;
670
671 lastKey = switchInsns[offsetToKeys] |
672 (switchInsns[offsetToKeys+1] << 16);
673 for (targ = 1; targ < switchCount; targ++) {
674 s4 key = (s4) switchInsns[offsetToKeys + targ*2] |
675 (s4) (switchInsns[offsetToKeys + targ*2 +1] << 16);
676 if (key <= lastKey) {
677 LOG_VFY("VFY: invalid packed switch: last key=%d, this=%d",
678 lastKey, key);
679 return false;
680 }
681
682 lastKey = key;
683 }
684 }
685
686 /* verify each switch target */
687 for (targ = 0; targ < switchCount; targ++) {
688 offset = (s4) switchInsns[offsetToTargets + targ*2] |
689 (s4) (switchInsns[offsetToTargets + targ*2 +1] << 16);
690 absOffset = curOffset + offset;
691
692 if (absOffset < 0 || absOffset >= (s4)insnCount ||
693 !dvmInsnIsOpcode(insnFlags, absOffset))
694 {
695 LOG_VFY("VFY: invalid switch target %d (-> %#x) at %#x[%d]",
696 offset, absOffset, curOffset, targ);
697 return false;
698 }
699 dvmInsnSetBranchTarget(insnFlags, absOffset, true);
700 }
701
702 return true;
703 }
704
705 /*
706 * Verify that the target of a branch instruction is valid.
707 *
708 * We don't expect code to jump directly into an exception handler, but
709 * it's valid to do so as long as the target isn't a "move-exception"
710 * instruction. We verify that in a later stage.
711 *
712 * The VM spec doesn't forbid an instruction from branching to itself,
713 * but the Dalvik spec declares that only certain instructions can do so.
714 *
715 * Updates "insnFlags", setting the "branch target" flag.
716 */
checkBranchTarget(const Method * meth,InsnFlags * insnFlags,int curOffset,bool selfOkay)717 static bool checkBranchTarget(const Method* meth, InsnFlags* insnFlags,
718 int curOffset, bool selfOkay)
719 {
720 const int insnCount = dvmGetMethodInsnsSize(meth);
721 s4 offset, absOffset;
722 bool isConditional;
723
724 if (!dvmGetBranchOffset(meth, insnFlags, curOffset, &offset,
725 &isConditional))
726 return false;
727
728 if (!selfOkay && offset == 0) {
729 LOG_VFY_METH(meth, "VFY: branch offset of zero not allowed at %#x",
730 curOffset);
731 return false;
732 }
733
734 /*
735 * Check for 32-bit overflow. This isn't strictly necessary if we can
736 * depend on the VM to have identical "wrap-around" behavior, but
737 * it's unwise to depend on that.
738 */
739 if (((s8) curOffset + (s8) offset) != (s8)(curOffset + offset)) {
740 LOG_VFY_METH(meth, "VFY: branch target overflow %#x +%d",
741 curOffset, offset);
742 return false;
743 }
744 absOffset = curOffset + offset;
745 if (absOffset < 0 || absOffset >= insnCount ||
746 !dvmInsnIsOpcode(insnFlags, absOffset))
747 {
748 LOG_VFY_METH(meth,
749 "VFY: invalid branch target %d (-> %#x) at %#x",
750 offset, absOffset, curOffset);
751 return false;
752 }
753 dvmInsnSetBranchTarget(insnFlags, absOffset, true);
754
755 return true;
756 }
757
758
759 /*
760 * Perform static verification on instructions.
761 *
762 * As a side effect, this sets the "branch target" flags in InsnFlags.
763 *
764 * "(CF)" items are handled during code-flow analysis.
765 *
766 * v3 4.10.1
767 * - target of each jump and branch instruction must be valid
768 * - targets of switch statements must be valid
769 * - operands referencing constant pool entries must be valid
770 * - (CF) operands of getfield, putfield, getstatic, putstatic must be valid
771 * - (new) verify operands of "quick" field ops
772 * - (CF) operands of method invocation instructions must be valid
773 * - (new) verify operands of "quick" method invoke ops
774 * - (CF) only invoke-direct can call a method starting with '<'
775 * - (CF) <clinit> must never be called explicitly
776 * - operands of instanceof, checkcast, new (and variants) must be valid
777 * - new-array[-type] limited to 255 dimensions
778 * - can't use "new" on an array class
779 * - (?) limit dimensions in multi-array creation
780 * - local variable load/store register values must be in valid range
781 *
782 * v3 4.11.1.2
783 * - branches must be within the bounds of the code array
784 * - targets of all control-flow instructions are the start of an instruction
785 * - register accesses fall within range of allocated registers
786 * - (N/A) access to constant pool must be of appropriate type
787 * - code does not end in the middle of an instruction
788 * - execution cannot fall off the end of the code
789 * - (earlier) for each exception handler, the "try" area must begin and
790 * end at the start of an instruction (end can be at the end of the code)
791 * - (earlier) for each exception handler, the handler must start at a valid
792 * instruction
793 */
verifyInstructions(VerifierData * vdata)794 static bool verifyInstructions(VerifierData* vdata)
795 {
796 const Method* meth = vdata->method;
797 const DvmDex* pDvmDex = meth->clazz->pDvmDex;
798 InsnFlags* insnFlags = vdata->insnFlags;
799 const u2* insns = meth->insns;
800 unsigned int codeOffset;
801
802 /* the start of the method is a "branch target" */
803 dvmInsnSetBranchTarget(insnFlags, 0, true);
804
805 for (codeOffset = 0; codeOffset < vdata->insnsSize; /**/) {
806 /*
807 * Pull the instruction apart.
808 */
809 int width = dvmInsnGetWidth(insnFlags, codeOffset);
810 DecodedInstruction decInsn;
811 bool okay = true;
812
813 dexDecodeInstruction(meth->insns + codeOffset, &decInsn);
814
815 /*
816 * Check register, type, class, field, method, and string indices
817 * for out-of-range values. Do additional checks on branch targets
818 * and some special cases like new-instance and new-array.
819 */
820 switch (decInsn.opcode) {
821 case OP_NOP:
822 case OP_RETURN_VOID:
823 /* nothing to check */
824 break;
825 case OP_MOVE_RESULT:
826 case OP_MOVE_RESULT_OBJECT:
827 case OP_MOVE_EXCEPTION:
828 case OP_RETURN:
829 case OP_RETURN_OBJECT:
830 case OP_CONST_4:
831 case OP_CONST_16:
832 case OP_CONST:
833 case OP_CONST_HIGH16:
834 case OP_MONITOR_ENTER:
835 case OP_MONITOR_EXIT:
836 case OP_THROW:
837 okay &= checkRegisterIndex(meth, decInsn.vA);
838 break;
839 case OP_MOVE_RESULT_WIDE:
840 case OP_RETURN_WIDE:
841 case OP_CONST_WIDE_16:
842 case OP_CONST_WIDE_32:
843 case OP_CONST_WIDE:
844 case OP_CONST_WIDE_HIGH16:
845 okay &= checkWideRegisterIndex(meth, decInsn.vA);
846 break;
847 case OP_GOTO:
848 case OP_GOTO_16:
849 okay &= checkBranchTarget(meth, insnFlags, codeOffset, false);
850 break;
851 case OP_GOTO_32:
852 okay &= checkBranchTarget(meth, insnFlags, codeOffset, true);
853 break;
854 case OP_MOVE:
855 case OP_MOVE_FROM16:
856 case OP_MOVE_16:
857 case OP_MOVE_OBJECT:
858 case OP_MOVE_OBJECT_FROM16:
859 case OP_MOVE_OBJECT_16:
860 case OP_ARRAY_LENGTH:
861 case OP_NEG_INT:
862 case OP_NOT_INT:
863 case OP_NEG_FLOAT:
864 case OP_INT_TO_FLOAT:
865 case OP_FLOAT_TO_INT:
866 case OP_INT_TO_BYTE:
867 case OP_INT_TO_CHAR:
868 case OP_INT_TO_SHORT:
869 case OP_ADD_INT_2ADDR:
870 case OP_SUB_INT_2ADDR:
871 case OP_MUL_INT_2ADDR:
872 case OP_DIV_INT_2ADDR:
873 case OP_REM_INT_2ADDR:
874 case OP_AND_INT_2ADDR:
875 case OP_OR_INT_2ADDR:
876 case OP_XOR_INT_2ADDR:
877 case OP_SHL_INT_2ADDR:
878 case OP_SHR_INT_2ADDR:
879 case OP_USHR_INT_2ADDR:
880 case OP_ADD_FLOAT_2ADDR:
881 case OP_SUB_FLOAT_2ADDR:
882 case OP_MUL_FLOAT_2ADDR:
883 case OP_DIV_FLOAT_2ADDR:
884 case OP_REM_FLOAT_2ADDR:
885 case OP_ADD_INT_LIT16:
886 case OP_RSUB_INT:
887 case OP_MUL_INT_LIT16:
888 case OP_DIV_INT_LIT16:
889 case OP_REM_INT_LIT16:
890 case OP_AND_INT_LIT16:
891 case OP_OR_INT_LIT16:
892 case OP_XOR_INT_LIT16:
893 case OP_ADD_INT_LIT8:
894 case OP_RSUB_INT_LIT8:
895 case OP_MUL_INT_LIT8:
896 case OP_DIV_INT_LIT8:
897 case OP_REM_INT_LIT8:
898 case OP_AND_INT_LIT8:
899 case OP_OR_INT_LIT8:
900 case OP_XOR_INT_LIT8:
901 case OP_SHL_INT_LIT8:
902 case OP_SHR_INT_LIT8:
903 case OP_USHR_INT_LIT8:
904 okay &= checkRegisterIndex(meth, decInsn.vA);
905 okay &= checkRegisterIndex(meth, decInsn.vB);
906 break;
907 case OP_INT_TO_LONG:
908 case OP_INT_TO_DOUBLE:
909 case OP_FLOAT_TO_LONG:
910 case OP_FLOAT_TO_DOUBLE:
911 case OP_SHL_LONG_2ADDR:
912 case OP_SHR_LONG_2ADDR:
913 case OP_USHR_LONG_2ADDR:
914 okay &= checkWideRegisterIndex(meth, decInsn.vA);
915 okay &= checkRegisterIndex(meth, decInsn.vB);
916 break;
917 case OP_LONG_TO_INT:
918 case OP_LONG_TO_FLOAT:
919 case OP_DOUBLE_TO_INT:
920 case OP_DOUBLE_TO_FLOAT:
921 okay &= checkRegisterIndex(meth, decInsn.vA);
922 okay &= checkWideRegisterIndex(meth, decInsn.vB);
923 break;
924 case OP_MOVE_WIDE:
925 case OP_MOVE_WIDE_FROM16:
926 case OP_MOVE_WIDE_16:
927 case OP_DOUBLE_TO_LONG:
928 case OP_LONG_TO_DOUBLE:
929 case OP_NEG_DOUBLE:
930 case OP_NEG_LONG:
931 case OP_NOT_LONG:
932 case OP_ADD_LONG_2ADDR:
933 case OP_SUB_LONG_2ADDR:
934 case OP_MUL_LONG_2ADDR:
935 case OP_DIV_LONG_2ADDR:
936 case OP_REM_LONG_2ADDR:
937 case OP_AND_LONG_2ADDR:
938 case OP_OR_LONG_2ADDR:
939 case OP_XOR_LONG_2ADDR:
940 case OP_ADD_DOUBLE_2ADDR:
941 case OP_SUB_DOUBLE_2ADDR:
942 case OP_MUL_DOUBLE_2ADDR:
943 case OP_DIV_DOUBLE_2ADDR:
944 case OP_REM_DOUBLE_2ADDR:
945 okay &= checkWideRegisterIndex(meth, decInsn.vA);
946 okay &= checkWideRegisterIndex(meth, decInsn.vB);
947 break;
948 case OP_CONST_STRING:
949 case OP_CONST_STRING_JUMBO:
950 okay &= checkRegisterIndex(meth, decInsn.vA);
951 okay &= checkStringIndex(pDvmDex, decInsn.vB);
952 break;
953 case OP_CONST_CLASS:
954 case OP_CONST_CLASS_JUMBO:
955 case OP_CHECK_CAST:
956 case OP_CHECK_CAST_JUMBO:
957 okay &= checkRegisterIndex(meth, decInsn.vA);
958 okay &= checkTypeIndex(pDvmDex, decInsn.vB);
959 break;
960 case OP_INSTANCE_OF:
961 case OP_INSTANCE_OF_JUMBO:
962 okay &= checkRegisterIndex(meth, decInsn.vA);
963 okay &= checkRegisterIndex(meth, decInsn.vB);
964 okay &= checkTypeIndex(pDvmDex, decInsn.vC);
965 break;
966 case OP_NEW_INSTANCE:
967 case OP_NEW_INSTANCE_JUMBO:
968 okay &= checkRegisterIndex(meth, decInsn.vA);
969 okay &= checkNewInstance(pDvmDex, decInsn.vB);
970 break;
971 case OP_NEW_ARRAY:
972 case OP_NEW_ARRAY_JUMBO:
973 okay &= checkRegisterIndex(meth, decInsn.vA);
974 okay &= checkRegisterIndex(meth, decInsn.vB);
975 okay &= checkNewArray(pDvmDex, decInsn.vC);
976 break;
977 case OP_FILL_ARRAY_DATA:
978 okay &= checkRegisterIndex(meth, decInsn.vA);
979 okay &= checkArrayData(meth, codeOffset);
980 break;
981 case OP_PACKED_SWITCH:
982 okay &= checkRegisterIndex(meth, decInsn.vA);
983 okay &= checkSwitchTargets(meth, insnFlags, codeOffset);
984 break;
985 case OP_SPARSE_SWITCH:
986 okay &= checkRegisterIndex(meth, decInsn.vA);
987 okay &= checkSwitchTargets(meth, insnFlags, codeOffset);
988 break;
989 case OP_CMPL_FLOAT:
990 case OP_CMPG_FLOAT:
991 case OP_AGET:
992 case OP_AGET_OBJECT:
993 case OP_AGET_BOOLEAN:
994 case OP_AGET_BYTE:
995 case OP_AGET_CHAR:
996 case OP_AGET_SHORT:
997 case OP_APUT:
998 case OP_APUT_OBJECT:
999 case OP_APUT_BOOLEAN:
1000 case OP_APUT_BYTE:
1001 case OP_APUT_CHAR:
1002 case OP_APUT_SHORT:
1003 case OP_ADD_INT:
1004 case OP_SUB_INT:
1005 case OP_MUL_INT:
1006 case OP_DIV_INT:
1007 case OP_REM_INT:
1008 case OP_AND_INT:
1009 case OP_OR_INT:
1010 case OP_XOR_INT:
1011 case OP_SHL_INT:
1012 case OP_SHR_INT:
1013 case OP_USHR_INT:
1014 case OP_ADD_FLOAT:
1015 case OP_SUB_FLOAT:
1016 case OP_MUL_FLOAT:
1017 case OP_DIV_FLOAT:
1018 case OP_REM_FLOAT:
1019 okay &= checkRegisterIndex(meth, decInsn.vA);
1020 okay &= checkRegisterIndex(meth, decInsn.vB);
1021 okay &= checkRegisterIndex(meth, decInsn.vC);
1022 break;
1023 case OP_AGET_WIDE:
1024 case OP_APUT_WIDE:
1025 okay &= checkWideRegisterIndex(meth, decInsn.vA);
1026 okay &= checkRegisterIndex(meth, decInsn.vB);
1027 okay &= checkRegisterIndex(meth, decInsn.vC);
1028 break;
1029 case OP_CMPL_DOUBLE:
1030 case OP_CMPG_DOUBLE:
1031 case OP_CMP_LONG:
1032 okay &= checkRegisterIndex(meth, decInsn.vA);
1033 okay &= checkWideRegisterIndex(meth, decInsn.vB);
1034 okay &= checkWideRegisterIndex(meth, decInsn.vC);
1035 break;
1036 case OP_ADD_DOUBLE:
1037 case OP_SUB_DOUBLE:
1038 case OP_MUL_DOUBLE:
1039 case OP_DIV_DOUBLE:
1040 case OP_REM_DOUBLE:
1041 case OP_ADD_LONG:
1042 case OP_SUB_LONG:
1043 case OP_MUL_LONG:
1044 case OP_DIV_LONG:
1045 case OP_REM_LONG:
1046 case OP_AND_LONG:
1047 case OP_OR_LONG:
1048 case OP_XOR_LONG:
1049 okay &= checkWideRegisterIndex(meth, decInsn.vA);
1050 okay &= checkWideRegisterIndex(meth, decInsn.vB);
1051 okay &= checkWideRegisterIndex(meth, decInsn.vC);
1052 break;
1053 case OP_SHL_LONG:
1054 case OP_SHR_LONG:
1055 case OP_USHR_LONG:
1056 okay &= checkWideRegisterIndex(meth, decInsn.vA);
1057 okay &= checkWideRegisterIndex(meth, decInsn.vB);
1058 okay &= checkRegisterIndex(meth, decInsn.vC);
1059 break;
1060 case OP_IF_EQ:
1061 case OP_IF_NE:
1062 case OP_IF_LT:
1063 case OP_IF_GE:
1064 case OP_IF_GT:
1065 case OP_IF_LE:
1066 okay &= checkRegisterIndex(meth, decInsn.vA);
1067 okay &= checkRegisterIndex(meth, decInsn.vB);
1068 okay &= checkBranchTarget(meth, insnFlags, codeOffset, false);
1069 break;
1070 case OP_IF_EQZ:
1071 case OP_IF_NEZ:
1072 case OP_IF_LTZ:
1073 case OP_IF_GEZ:
1074 case OP_IF_GTZ:
1075 case OP_IF_LEZ:
1076 okay &= checkRegisterIndex(meth, decInsn.vA);
1077 okay &= checkBranchTarget(meth, insnFlags, codeOffset, false);
1078 break;
1079 case OP_IGET:
1080 case OP_IGET_JUMBO:
1081 case OP_IGET_OBJECT:
1082 case OP_IGET_OBJECT_JUMBO:
1083 case OP_IGET_BOOLEAN:
1084 case OP_IGET_BOOLEAN_JUMBO:
1085 case OP_IGET_BYTE:
1086 case OP_IGET_BYTE_JUMBO:
1087 case OP_IGET_CHAR:
1088 case OP_IGET_CHAR_JUMBO:
1089 case OP_IGET_SHORT:
1090 case OP_IGET_SHORT_JUMBO:
1091 case OP_IPUT:
1092 case OP_IPUT_JUMBO:
1093 case OP_IPUT_OBJECT:
1094 case OP_IPUT_OBJECT_JUMBO:
1095 case OP_IPUT_BOOLEAN:
1096 case OP_IPUT_BOOLEAN_JUMBO:
1097 case OP_IPUT_BYTE:
1098 case OP_IPUT_BYTE_JUMBO:
1099 case OP_IPUT_CHAR:
1100 case OP_IPUT_CHAR_JUMBO:
1101 case OP_IPUT_SHORT:
1102 case OP_IPUT_SHORT_JUMBO:
1103 okay &= checkRegisterIndex(meth, decInsn.vA);
1104 okay &= checkRegisterIndex(meth, decInsn.vB);
1105 okay &= checkFieldIndex(pDvmDex, decInsn.vC);
1106 break;
1107 case OP_IGET_WIDE:
1108 case OP_IGET_WIDE_JUMBO:
1109 case OP_IPUT_WIDE:
1110 case OP_IPUT_WIDE_JUMBO:
1111 okay &= checkWideRegisterIndex(meth, decInsn.vA);
1112 okay &= checkRegisterIndex(meth, decInsn.vB);
1113 okay &= checkFieldIndex(pDvmDex, decInsn.vC);
1114 break;
1115 case OP_SGET:
1116 case OP_SGET_JUMBO:
1117 case OP_SGET_OBJECT:
1118 case OP_SGET_OBJECT_JUMBO:
1119 case OP_SGET_BOOLEAN:
1120 case OP_SGET_BOOLEAN_JUMBO:
1121 case OP_SGET_BYTE:
1122 case OP_SGET_BYTE_JUMBO:
1123 case OP_SGET_CHAR:
1124 case OP_SGET_CHAR_JUMBO:
1125 case OP_SGET_SHORT:
1126 case OP_SGET_SHORT_JUMBO:
1127 case OP_SPUT:
1128 case OP_SPUT_JUMBO:
1129 case OP_SPUT_OBJECT:
1130 case OP_SPUT_OBJECT_JUMBO:
1131 case OP_SPUT_BOOLEAN:
1132 case OP_SPUT_BOOLEAN_JUMBO:
1133 case OP_SPUT_BYTE:
1134 case OP_SPUT_BYTE_JUMBO:
1135 case OP_SPUT_CHAR:
1136 case OP_SPUT_CHAR_JUMBO:
1137 case OP_SPUT_SHORT:
1138 case OP_SPUT_SHORT_JUMBO:
1139 okay &= checkRegisterIndex(meth, decInsn.vA);
1140 okay &= checkFieldIndex(pDvmDex, decInsn.vB);
1141 break;
1142 case OP_SGET_WIDE:
1143 case OP_SGET_WIDE_JUMBO:
1144 case OP_SPUT_WIDE:
1145 case OP_SPUT_WIDE_JUMBO:
1146 okay &= checkWideRegisterIndex(meth, decInsn.vA);
1147 okay &= checkFieldIndex(pDvmDex, decInsn.vB);
1148 break;
1149 case OP_FILLED_NEW_ARRAY:
1150 /* decoder uses B, not C, for type ref */
1151 okay &= checkTypeIndex(pDvmDex, decInsn.vB);
1152 okay &= checkVarargRegs(meth, &decInsn);
1153 break;
1154 case OP_FILLED_NEW_ARRAY_RANGE:
1155 case OP_FILLED_NEW_ARRAY_JUMBO:
1156 okay &= checkTypeIndex(pDvmDex, decInsn.vB);
1157 okay &= checkVarargRangeRegs(meth, &decInsn);
1158 break;
1159 case OP_INVOKE_VIRTUAL:
1160 case OP_INVOKE_SUPER:
1161 case OP_INVOKE_DIRECT:
1162 case OP_INVOKE_STATIC:
1163 case OP_INVOKE_INTERFACE:
1164 /* decoder uses B, not C, for type ref */
1165 okay &= checkMethodIndex(pDvmDex, decInsn.vB);
1166 okay &= checkVarargRegs(meth, &decInsn);
1167 break;
1168 case OP_INVOKE_VIRTUAL_RANGE:
1169 case OP_INVOKE_VIRTUAL_JUMBO:
1170 case OP_INVOKE_SUPER_RANGE:
1171 case OP_INVOKE_SUPER_JUMBO:
1172 case OP_INVOKE_DIRECT_RANGE:
1173 case OP_INVOKE_DIRECT_JUMBO:
1174 case OP_INVOKE_STATIC_RANGE:
1175 case OP_INVOKE_STATIC_JUMBO:
1176 case OP_INVOKE_INTERFACE_RANGE:
1177 case OP_INVOKE_INTERFACE_JUMBO:
1178 okay &= checkMethodIndex(pDvmDex, decInsn.vB);
1179 okay &= checkVarargRangeRegs(meth, &decInsn);
1180 break;
1181
1182 /* verifier/optimizer output; we should never see these */
1183 case OP_IGET_VOLATILE:
1184 case OP_IPUT_VOLATILE:
1185 case OP_SGET_VOLATILE:
1186 case OP_SPUT_VOLATILE:
1187 case OP_IGET_OBJECT_VOLATILE:
1188 case OP_IPUT_OBJECT_VOLATILE:
1189 case OP_SGET_OBJECT_VOLATILE:
1190 case OP_SPUT_OBJECT_VOLATILE:
1191 case OP_IGET_WIDE_VOLATILE:
1192 case OP_IPUT_WIDE_VOLATILE:
1193 case OP_SGET_WIDE_VOLATILE:
1194 case OP_SPUT_WIDE_VOLATILE:
1195 case OP_IGET_VOLATILE_JUMBO:
1196 case OP_IPUT_VOLATILE_JUMBO:
1197 case OP_SGET_VOLATILE_JUMBO:
1198 case OP_SPUT_VOLATILE_JUMBO:
1199 case OP_IGET_OBJECT_VOLATILE_JUMBO:
1200 case OP_IPUT_OBJECT_VOLATILE_JUMBO:
1201 case OP_SGET_OBJECT_VOLATILE_JUMBO:
1202 case OP_SPUT_OBJECT_VOLATILE_JUMBO:
1203 case OP_IGET_WIDE_VOLATILE_JUMBO:
1204 case OP_IPUT_WIDE_VOLATILE_JUMBO:
1205 case OP_SGET_WIDE_VOLATILE_JUMBO:
1206 case OP_SPUT_WIDE_VOLATILE_JUMBO:
1207 case OP_BREAKPOINT:
1208 case OP_THROW_VERIFICATION_ERROR:
1209 case OP_THROW_VERIFICATION_ERROR_JUMBO:
1210 case OP_EXECUTE_INLINE:
1211 case OP_EXECUTE_INLINE_RANGE:
1212 case OP_INVOKE_OBJECT_INIT_RANGE:
1213 case OP_INVOKE_OBJECT_INIT_JUMBO:
1214 case OP_RETURN_VOID_BARRIER:
1215 case OP_IGET_QUICK:
1216 case OP_IGET_WIDE_QUICK:
1217 case OP_IGET_OBJECT_QUICK:
1218 case OP_IPUT_QUICK:
1219 case OP_IPUT_WIDE_QUICK:
1220 case OP_IPUT_OBJECT_QUICK:
1221 case OP_INVOKE_VIRTUAL_QUICK:
1222 case OP_INVOKE_VIRTUAL_QUICK_RANGE:
1223 case OP_INVOKE_SUPER_QUICK:
1224 case OP_INVOKE_SUPER_QUICK_RANGE:
1225 case OP_UNUSED_3E:
1226 case OP_UNUSED_3F:
1227 case OP_UNUSED_40:
1228 case OP_UNUSED_41:
1229 case OP_UNUSED_42:
1230 case OP_UNUSED_43:
1231 case OP_UNUSED_73:
1232 case OP_UNUSED_79:
1233 case OP_UNUSED_7A:
1234 case OP_DISPATCH_FF:
1235 case OP_UNUSED_27FF:
1236 case OP_UNUSED_28FF:
1237 case OP_UNUSED_29FF:
1238 case OP_UNUSED_2AFF:
1239 case OP_UNUSED_2BFF:
1240 case OP_UNUSED_2CFF:
1241 case OP_UNUSED_2DFF:
1242 case OP_UNUSED_2EFF:
1243 case OP_UNUSED_2FFF:
1244 case OP_UNUSED_30FF:
1245 case OP_UNUSED_31FF:
1246 case OP_UNUSED_32FF:
1247 case OP_UNUSED_33FF:
1248 case OP_UNUSED_34FF:
1249 case OP_UNUSED_35FF:
1250 case OP_UNUSED_36FF:
1251 case OP_UNUSED_37FF:
1252 case OP_UNUSED_38FF:
1253 case OP_UNUSED_39FF:
1254 case OP_UNUSED_3AFF:
1255 case OP_UNUSED_3BFF:
1256 case OP_UNUSED_3CFF:
1257 case OP_UNUSED_3DFF:
1258 case OP_UNUSED_3EFF:
1259 case OP_UNUSED_3FFF:
1260 case OP_UNUSED_40FF:
1261 case OP_UNUSED_41FF:
1262 case OP_UNUSED_42FF:
1263 case OP_UNUSED_43FF:
1264 case OP_UNUSED_44FF:
1265 case OP_UNUSED_45FF:
1266 case OP_UNUSED_46FF:
1267 case OP_UNUSED_47FF:
1268 case OP_UNUSED_48FF:
1269 case OP_UNUSED_49FF:
1270 case OP_UNUSED_4AFF:
1271 case OP_UNUSED_4BFF:
1272 case OP_UNUSED_4CFF:
1273 case OP_UNUSED_4DFF:
1274 case OP_UNUSED_4EFF:
1275 case OP_UNUSED_4FFF:
1276 case OP_UNUSED_50FF:
1277 case OP_UNUSED_51FF:
1278 case OP_UNUSED_52FF:
1279 case OP_UNUSED_53FF:
1280 case OP_UNUSED_54FF:
1281 case OP_UNUSED_55FF:
1282 case OP_UNUSED_56FF:
1283 case OP_UNUSED_57FF:
1284 case OP_UNUSED_58FF:
1285 case OP_UNUSED_59FF:
1286 case OP_UNUSED_5AFF:
1287 case OP_UNUSED_5BFF:
1288 case OP_UNUSED_5CFF:
1289 case OP_UNUSED_5DFF:
1290 case OP_UNUSED_5EFF:
1291 case OP_UNUSED_5FFF:
1292 case OP_UNUSED_60FF:
1293 case OP_UNUSED_61FF:
1294 case OP_UNUSED_62FF:
1295 case OP_UNUSED_63FF:
1296 case OP_UNUSED_64FF:
1297 case OP_UNUSED_65FF:
1298 case OP_UNUSED_66FF:
1299 case OP_UNUSED_67FF:
1300 case OP_UNUSED_68FF:
1301 case OP_UNUSED_69FF:
1302 case OP_UNUSED_6AFF:
1303 case OP_UNUSED_6BFF:
1304 case OP_UNUSED_6CFF:
1305 case OP_UNUSED_6DFF:
1306 case OP_UNUSED_6EFF:
1307 case OP_UNUSED_6FFF:
1308 case OP_UNUSED_70FF:
1309 case OP_UNUSED_71FF:
1310 case OP_UNUSED_72FF:
1311 case OP_UNUSED_73FF:
1312 case OP_UNUSED_74FF:
1313 case OP_UNUSED_75FF:
1314 case OP_UNUSED_76FF:
1315 case OP_UNUSED_77FF:
1316 case OP_UNUSED_78FF:
1317 case OP_UNUSED_79FF:
1318 case OP_UNUSED_7AFF:
1319 case OP_UNUSED_7BFF:
1320 case OP_UNUSED_7CFF:
1321 case OP_UNUSED_7DFF:
1322 case OP_UNUSED_7EFF:
1323 case OP_UNUSED_7FFF:
1324 case OP_UNUSED_80FF:
1325 case OP_UNUSED_81FF:
1326 case OP_UNUSED_82FF:
1327 case OP_UNUSED_83FF:
1328 case OP_UNUSED_84FF:
1329 case OP_UNUSED_85FF:
1330 case OP_UNUSED_86FF:
1331 case OP_UNUSED_87FF:
1332 case OP_UNUSED_88FF:
1333 case OP_UNUSED_89FF:
1334 case OP_UNUSED_8AFF:
1335 case OP_UNUSED_8BFF:
1336 case OP_UNUSED_8CFF:
1337 case OP_UNUSED_8DFF:
1338 case OP_UNUSED_8EFF:
1339 case OP_UNUSED_8FFF:
1340 case OP_UNUSED_90FF:
1341 case OP_UNUSED_91FF:
1342 case OP_UNUSED_92FF:
1343 case OP_UNUSED_93FF:
1344 case OP_UNUSED_94FF:
1345 case OP_UNUSED_95FF:
1346 case OP_UNUSED_96FF:
1347 case OP_UNUSED_97FF:
1348 case OP_UNUSED_98FF:
1349 case OP_UNUSED_99FF:
1350 case OP_UNUSED_9AFF:
1351 case OP_UNUSED_9BFF:
1352 case OP_UNUSED_9CFF:
1353 case OP_UNUSED_9DFF:
1354 case OP_UNUSED_9EFF:
1355 case OP_UNUSED_9FFF:
1356 case OP_UNUSED_A0FF:
1357 case OP_UNUSED_A1FF:
1358 case OP_UNUSED_A2FF:
1359 case OP_UNUSED_A3FF:
1360 case OP_UNUSED_A4FF:
1361 case OP_UNUSED_A5FF:
1362 case OP_UNUSED_A6FF:
1363 case OP_UNUSED_A7FF:
1364 case OP_UNUSED_A8FF:
1365 case OP_UNUSED_A9FF:
1366 case OP_UNUSED_AAFF:
1367 case OP_UNUSED_ABFF:
1368 case OP_UNUSED_ACFF:
1369 case OP_UNUSED_ADFF:
1370 case OP_UNUSED_AEFF:
1371 case OP_UNUSED_AFFF:
1372 case OP_UNUSED_B0FF:
1373 case OP_UNUSED_B1FF:
1374 case OP_UNUSED_B2FF:
1375 case OP_UNUSED_B3FF:
1376 case OP_UNUSED_B4FF:
1377 case OP_UNUSED_B5FF:
1378 case OP_UNUSED_B6FF:
1379 case OP_UNUSED_B7FF:
1380 case OP_UNUSED_B8FF:
1381 case OP_UNUSED_B9FF:
1382 case OP_UNUSED_BAFF:
1383 case OP_UNUSED_BBFF:
1384 case OP_UNUSED_BCFF:
1385 case OP_UNUSED_BDFF:
1386 case OP_UNUSED_BEFF:
1387 case OP_UNUSED_BFFF:
1388 case OP_UNUSED_C0FF:
1389 case OP_UNUSED_C1FF:
1390 case OP_UNUSED_C2FF:
1391 case OP_UNUSED_C3FF:
1392 case OP_UNUSED_C4FF:
1393 case OP_UNUSED_C5FF:
1394 case OP_UNUSED_C6FF:
1395 case OP_UNUSED_C7FF:
1396 case OP_UNUSED_C8FF:
1397 case OP_UNUSED_C9FF:
1398 case OP_UNUSED_CAFF:
1399 case OP_UNUSED_CBFF:
1400 case OP_UNUSED_CCFF:
1401 case OP_UNUSED_CDFF:
1402 case OP_UNUSED_CEFF:
1403 case OP_UNUSED_CFFF:
1404 case OP_UNUSED_D0FF:
1405 case OP_UNUSED_D1FF:
1406 case OP_UNUSED_D2FF:
1407 case OP_UNUSED_D3FF:
1408 case OP_UNUSED_D4FF:
1409 case OP_UNUSED_D5FF:
1410 case OP_UNUSED_D6FF:
1411 case OP_UNUSED_D7FF:
1412 case OP_UNUSED_D8FF:
1413 case OP_UNUSED_D9FF:
1414 case OP_UNUSED_DAFF:
1415 case OP_UNUSED_DBFF:
1416 case OP_UNUSED_DCFF:
1417 case OP_UNUSED_DDFF:
1418 case OP_UNUSED_DEFF:
1419 case OP_UNUSED_DFFF:
1420 case OP_UNUSED_E0FF:
1421 case OP_UNUSED_E1FF:
1422 case OP_UNUSED_E2FF:
1423 case OP_UNUSED_E3FF:
1424 case OP_UNUSED_E4FF:
1425 case OP_UNUSED_E5FF:
1426 case OP_UNUSED_E6FF:
1427 case OP_UNUSED_E7FF:
1428 case OP_UNUSED_E8FF:
1429 case OP_UNUSED_E9FF:
1430 case OP_UNUSED_EAFF:
1431 case OP_UNUSED_EBFF:
1432 case OP_UNUSED_ECFF:
1433 case OP_UNUSED_EDFF:
1434 case OP_UNUSED_EEFF:
1435 case OP_UNUSED_EFFF:
1436 case OP_UNUSED_F0FF:
1437 case OP_UNUSED_F1FF:
1438 LOGE("VFY: unexpected opcode %04x", decInsn.opcode);
1439 okay = false;
1440 break;
1441
1442 /*
1443 * DO NOT add a "default" clause here. Without it the compiler will
1444 * complain if an instruction is missing (which is desirable).
1445 */
1446 }
1447
1448 if (!okay) {
1449 LOG_VFY_METH(meth, "VFY: rejecting opcode 0x%02x at 0x%04x",
1450 decInsn.opcode, codeOffset);
1451 return false;
1452 }
1453
1454 OpcodeFlags opFlags = dexGetFlagsFromOpcode(decInsn.opcode);
1455 if ((opFlags & VERIFY_GC_INST_MASK) != 0) {
1456 /*
1457 * This instruction is a GC point. If space is a concern,
1458 * the set of GC points could be reduced by eliminating
1459 * foward branches.
1460 *
1461 * TODO: we could also scan the targets of a "switch" statement,
1462 * and if none of them branch backward we could ignore that
1463 * instruction as well.
1464 */
1465 dvmInsnSetGcPoint(insnFlags, codeOffset, true);
1466 }
1467
1468 assert(width > 0);
1469 codeOffset += width;
1470 insns += width;
1471 }
1472
1473 /* make sure the last instruction ends at the end of the insn area */
1474 if (codeOffset != vdata->insnsSize) {
1475 LOG_VFY_METH(meth,
1476 "VFY: code did not end when expected (end at %d, count %d)",
1477 codeOffset, vdata->insnsSize);
1478 return false;
1479 }
1480
1481 return true;
1482 }
1483