📄 verifier.c
字号:
#endif /* IMPLEMENTS_FLOAT */ case IF_ICMPEQ: case IF_ICMPNE: case IF_ICMPLT: case IF_ICMPGE: case IF_ICMPGT: case IF_ICMPLE: { Vfy_pop(ITEM_Integer); Vfy_pop(ITEM_Integer); Vfy_checkJumpTarget(ip, (IPINDEX)(ip + Vfy_getShort(ip + 1))); ip += 3; break; } case IFEQ: case IFNE: case IFLT: case IFGE: case IFGT: case IFLE: { Vfy_pop(ITEM_Integer); Vfy_checkJumpTarget(ip, (IPINDEX)(ip + Vfy_getShort(ip + 1))); ip += 3; break; } case IF_ACMPEQ: case IF_ACMPNE: { Vfy_pop(ITEM_Reference); Vfy_pop(ITEM_Reference); Vfy_checkJumpTarget(ip, (IPINDEX)(ip + Vfy_getShort(ip + 1))); ip += 3; break; } case IFNULL: case IFNONNULL: Vfy_pop(ITEM_Reference); Vfy_checkJumpTarget(ip, (IPINDEX)(ip + Vfy_getShort(ip + 1))); ip += 3; break; case GOTO: { Vfy_checkJumpTarget(ip, (IPINDEX)(ip + Vfy_getShort(ip + 1))); ip += 3; noControlFlow = TRUE; break; } case GOTO_W: { Vfy_checkJumpTarget(ip, (IPINDEX)(ip + Vfy_getCell(ip + 1))); ip += 5; noControlFlow = TRUE; break; } case TABLESWITCH: case LOOKUPSWITCH: { IPINDEX lpc = ((ip + 1) + 3) & ~3; /* Advance one byte and align to the next word boundary */ IPINDEX lptr; int keys; int k, delta; /* * Pop the switch argument */ Vfy_pop(ITEM_Integer); /* * Get the number of keys and the delta between each entry */ if (opcode == TABLESWITCH) { keys = Vfy_getCell(lpc + 8) - Vfy_getCell(lpc + 4) + 1; delta = 4; } else { keys = Vfy_getCell(lpc + 4); delta = 8; /* * Make sure that the tableswitch items are sorted */ for (k = keys - 1, lptr = lpc + 8 ; --k >= 0 ; lptr += 8) { long this_key = Vfy_getCell(lptr); long next_key = Vfy_getCell(lptr + 8); if (this_key >= next_key) { Vfy_throw(VE_BAD_LOOKUPSWITCH); } } } /* * Check the default case */ Vfy_checkJumpTarget(ip, (IPINDEX)(ip + Vfy_getCell(lpc))); /* * Check all the other cases */ for (k = keys, lptr = lpc + 12 ; --k >= 0; lptr += delta) { Vfy_checkJumpTarget(ip, (IPINDEX)(ip + Vfy_getCell(lptr))); } /* * Advance the virtual ip to the next instruction */ ip = lptr - delta + 4; noControlFlow = TRUE; break; } case IRETURN: { Vfy_popReturn(ITEM_Integer); ip++; noControlFlow = TRUE; break; } case LRETURN: { Vfy_pop(ITEM_Long_2); Vfy_popReturn(ITEM_Long); ip++; noControlFlow = TRUE; break; }#if IMPLEMENTS_FLOAT case FRETURN: { Vfy_popReturn(ITEM_Float); ip++; noControlFlow = TRUE; break; } case DRETURN: { Vfy_pop(ITEM_Double_2); Vfy_popReturn(ITEM_Double); ip++; noControlFlow = TRUE; break; }#endif /* IMPLEMENTS_FLOAT */ case ARETURN: { Vfy_popReturn(Vfy_getObjectVerifierType()); ip++; noControlFlow = TRUE; break; } case RETURN: { Vfy_returnVoid(); ip++; noControlFlow = TRUE; break; } case GETSTATIC: case PUTSTATIC: case GETFIELD: case PUTFIELD: { POOLINDEX fieldNameAndTypeIndex; CLASSKEY fieldTypeKey; /* * Get the index into the constant pool where the field is defined */ POOLINDEX fieldIndex = Vfy_getUShort(ip + 1); /* * Check that the tag is correct */ Pol_checkTagIs(vPool, fieldIndex, CONSTANT_Fieldref, VE_EXPECT_FIELDREF); /* * Get the index to the name-and-type entry */ fieldNameAndTypeIndex = Pol_getNameAndTypeIndex(vPool, fieldIndex); /* * Get the field type key ("I", "J, "Ljava.lang.Foobar" etc) */ fieldTypeKey = Pol_getTypeKey(vPool, fieldNameAndTypeIndex); if (opcode == GETFIELD || opcode == PUTFIELD) { /* * Get the index to the class of the field */ POOLINDEX fieldClassIndex = Pol_getClassIndex(vPool, fieldIndex); /* * Verification of access to protected fields is done here because * the superclass must be loaded at this time (other checks are * done at runtime in order to implement lazy class loading.) * * In order for the access to a protected field to be legal the * class of this method must be a direct descendant of the class * who's field is being accessed. By placing the method's class * in place of the class specified in the constant pool this * will be checked. */ VERIFIERTYPE targetVerifierType; if (Vfy_isProtectedField(vClass, fieldIndex)) { targetVerifierType = Vfy_toVerifierType(Cls_getKey(vClass)); } else { targetVerifierType = Vfy_toVerifierType(Pol_getClassKey(vPool, fieldClassIndex)); } /* * GETFIELD / PUTFIELD */ if (opcode == GETFIELD) { Vfy_pop(targetVerifierType); Vfy_pushClassKey(fieldTypeKey); } else { VERIFIERTYPE obj_type; Vfy_popClassKey(fieldTypeKey); /* 2nd edition JVM allows field initializations * before the super class initializer if the * field is defined within the current class. */ obj_type = Vfy_popCategory1(); if (obj_type == ITEM_InitObject) { /* special case for uninitialized objects */ NameTypeKey nameTypeKey = Pol_getNameTypeKey(vPool, fieldNameAndTypeIndex); INSTANCE_CLASS clazz = (INSTANCE_CLASS) Pol_getClass(vPool, fieldClassIndex); FIELD thisField = Cls_lookupField((INSTANCE_CLASS) clazz, nameTypeKey); if (thisField == NULL || thisField->ofClass != clazz) { Vfy_throw(VE_EXPECTING_OBJ_OR_ARR_ON_STK); } } else { Vfy_push(obj_type); Vfy_pop(targetVerifierType); } } } else { /* * GETSTATIC / PUTSTATIC */ if (opcode == GETSTATIC) { Vfy_pushClassKey(fieldTypeKey); } else { Vfy_popClassKey(fieldTypeKey); } } ip += 3; break; } case INVOKEVIRTUAL: case INVOKESPECIAL: case INVOKESTATIC: case INVOKEINTERFACE: { POOLINDEX methodNameAndTypeIndex; POOLINDEX methodClassIndex; METHODNAMEKEY methodNameKey; METHODTYPEKEY methodTypeKey; int nwords; /* * Get the index into the constant pool where the method is defined */ POOLINDEX methodIndex = Vfy_getUShort(ip + 1); /* * Check that the tag is correct */ Pol_checkTag2Is(vPool, methodIndex, CONSTANT_Methodref, /* this or...*/ CONSTANT_InterfaceMethodref, /* this */ VE_EXPECT_METHODREF); /* * Get the index to the class of the method */ methodClassIndex = Pol_getClassIndex(vPool, methodIndex);; /* * Get the index to the name-and-type entry */ methodNameAndTypeIndex = Pol_getNameAndTypeIndex(vPool, methodIndex); /* * Get the method type key ("(I)J", "(III)D", "(Ljava.lang.Foobar)V" etc.) */ methodTypeKey = Pol_getTypeKey(vPool, methodNameAndTypeIndex); /* * Get the method name */ methodNameKey = Pol_getDescriptorKey(vPool, methodNameAndTypeIndex); /* * Setup the callee context */ Vfy_setupCalleeContext(methodTypeKey); /* * Pop the arguments from the stack */ nwords = Vfy_popInvokeArguments(); /* * Check that the only method called that starts with "<" is <init> * and that it is only called via an INVOKESPECIAL */ if (Vfy_MethodNameStartsWithLeftAngleBracket(methodNameKey)) { if (opcode != INVOKESPECIAL || !Vfy_MethodNameIsInit(methodNameKey)) { Vfy_throw(VE_EXPECT_INVOKESPECIAL); } } /* * Receiver type processing */ if (opcode != INVOKESTATIC) { CLASSKEY methodClassKey = Pol_getClassKey(vPool, methodClassIndex); CLASSKEY targetClassKey; /* * Special processing for calls to <init> */ if (Vfy_MethodNameIsInit(methodNameKey)) { /* * Pop the receiver type */ VERIFIERTYPE receiverType = Vfy_popCategory1(); if (Vfy_isVerifierTypeForNew(receiverType)) { /* * This for is a call to <init> that is made to an object that has just been * created with a NEW bytecode. The address of the new was encoded * as a VERIFIERTYPE by the NEW bytecode using a function called * Vfy_createVerifierTypeForNewAt(). This is converted back into * an IP address and is used to lookup the receiver CLASSKEY */ POOLINDEX newIndex; /* * receiverType is a special encoding of the ip offset into the * method where a NEW instruction should be. Get the index * and check this out. */ IPINDEX newIP = Vfy_retrieveIpForNew(receiverType); if (newIP > codeLength - 3 || Vfy_getOpcode(newIP) != NEW) { Vfy_throw(VE_EXPECT_NEW); } /* * Get the pool index after the NEW bytecode and check that * is a CONSTANT_class */ newIndex = Vfy_getUShort(newIP + 1); Pol_checkTagIsClass(vPool, newIndex); /* * Get the CLASSKEY for is entry */ targetClassKey = Pol_getClassKey(vPool, newIndex); /* * The method must be an <init> method of the indicated class */ if (targetClassKey != methodClassKey) { Vfy_throw(VE_BAD_INIT_CALL); } } else if (receiverType == ITEM_InitObject) { int i; /* * This for is a call to <init> that is made as a result of * a constructor calling another constructor (e.g. this() or super()) * The receiver CLASSKEY must be the same as the one for the class * of the method being verified or its superclass */ targetClassKey = Cls_getKey(vClass); /* * Check that it is this() or super() */ if (methodClassKey != targetClassKey && methodClassKey != Cls_getKey(vSuperClass) || !vNeedInitialization) { Vfy_throw(VE_BAD_INIT_CALL); } /* Make sure that the current opcode is not * inside any exception handlers. */ for (i = 0 ; i < handlerCount ; i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -