|
|
@ -91,7 +91,7 @@ public class CodeVerifier implements Opcodes { |
|
|
|
|
|
|
|
|
|
|
|
public final void need(int count) throws VerifyException { |
|
|
|
public final void need(int count) throws VerifyException { |
|
|
|
if (stackHeight < count) |
|
|
|
if (stackHeight < count) |
|
|
|
throw new VerifyException("stack overflow"); |
|
|
|
throw new VerifyException("stack underflow"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public final void push(Type type) throws VerifyException { |
|
|
|
public final void push(Type type) throws VerifyException { |
|
|
@ -412,9 +412,12 @@ public class CodeVerifier implements Opcodes { |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
case opc_pop: case opc_pop2: |
|
|
|
case opc_pop: case opc_pop2: { |
|
|
|
result.stackHeight -= instr.opcode - (opc_pop-1); |
|
|
|
int count = instr.opcode - (opc_pop-1); |
|
|
|
|
|
|
|
result.need(count); |
|
|
|
|
|
|
|
result.stackHeight -= count; |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
case opc_dup: case opc_dup_x1: case opc_dup_x2: { |
|
|
|
case opc_dup: case opc_dup_x1: case opc_dup_x2: { |
|
|
|
int depth = instr.opcode - opc_dup; |
|
|
|
int depth = instr.opcode - opc_dup; |
|
|
|
result.reserve(1); |
|
|
|
result.reserve(1); |
|
|
@ -672,7 +675,7 @@ public class CodeVerifier implements Opcodes { |
|
|
|
} |
|
|
|
} |
|
|
|
case opc_getfield: { |
|
|
|
case opc_getfield: { |
|
|
|
Reference ref = (Reference) instr.objData; |
|
|
|
Reference ref = (Reference) instr.objData; |
|
|
|
Type classType = Type.tClass(ref.getClazz()); |
|
|
|
Type classType = Type.tType(ref.getClazz()); |
|
|
|
if (!isOfType(result.pop(), classType)) |
|
|
|
if (!isOfType(result.pop(), classType)) |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
Type type = Type.tType(ref.getType()); |
|
|
|
Type type = Type.tType(ref.getType()); |
|
|
@ -699,7 +702,7 @@ public class CodeVerifier implements Opcodes { |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
if (!isOfType(result.pop(), type)) |
|
|
|
if (!isOfType(result.pop(), type)) |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
Type classType = Type.tClass(ref.getClazz()); |
|
|
|
Type classType = Type.tType(ref.getClazz()); |
|
|
|
if (!isOfType(result.pop(), classType)) |
|
|
|
if (!isOfType(result.pop(), classType)) |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
break; |
|
|
|
break; |
|
|
@ -724,10 +727,14 @@ public class CodeVerifier implements Opcodes { |
|
|
|
if (!(clazz instanceof UninitializedClassType)) |
|
|
|
if (!(clazz instanceof UninitializedClassType)) |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
UninitializedClassType uct = (UninitializedClassType) clazz; |
|
|
|
UninitializedClassType uct = (UninitializedClassType) clazz; |
|
|
|
ClassInfo refCi = ClassInfo.forName(ref.getClazz()); |
|
|
|
String refClazz = ref.getClazz(); |
|
|
|
if (refCi != uct.classType |
|
|
|
if (refClazz.charAt(0) != 'L') |
|
|
|
&& (!uct.maySuper |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
|| refCi != uct.classType.getSuperclass())) |
|
|
|
refClazz = refClazz.substring(1, refClazz.length()-1) |
|
|
|
|
|
|
|
.replace('/','.'); |
|
|
|
|
|
|
|
if (!uct.classType.getName().equals(refClazz) |
|
|
|
|
|
|
|
&& (!uct.maySuper || !(uct.classType.getSuperclass() |
|
|
|
|
|
|
|
.getName().equals(refClazz)))) |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
Type newType = Type.tClass(uct.classType); |
|
|
|
Type newType = Type.tClass(uct.classType); |
|
|
|
for (int i=0; i< result.stackHeight; i++) |
|
|
|
for (int i=0; i< result.stackHeight; i++) |
|
|
@ -737,7 +744,7 @@ public class CodeVerifier implements Opcodes { |
|
|
|
if (result.locals[i] == clazz) |
|
|
|
if (result.locals[i] == clazz) |
|
|
|
result.locals[i] = newType; |
|
|
|
result.locals[i] = newType; |
|
|
|
} else if (instr.opcode != opc_invokestatic) { |
|
|
|
} else if (instr.opcode != opc_invokestatic) { |
|
|
|
Type classType = Type.tClass(ref.getClazz()); |
|
|
|
Type classType = Type.tType(ref.getClazz()); |
|
|
|
if (!isOfType(result.pop(), classType)) |
|
|
|
if (!isOfType(result.pop(), classType)) |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
} |
|
|
|
} |
|
|
@ -750,7 +757,9 @@ public class CodeVerifier implements Opcodes { |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
case opc_new: { |
|
|
|
case opc_new: { |
|
|
|
ClassInfo ci = ClassInfo.forName((String) instr.objData); |
|
|
|
String clName = (String) instr.objData; |
|
|
|
|
|
|
|
ClassInfo ci = ClassInfo.forName |
|
|
|
|
|
|
|
(clName.substring(1, clName.length()-1).replace('/','.')); |
|
|
|
result.stack[result.stackHeight++] = |
|
|
|
result.stack[result.stackHeight++] = |
|
|
|
new UninitializedClassType(ci, false); |
|
|
|
new UninitializedClassType(ci, false); |
|
|
|
break; |
|
|
|
break; |
|
|
@ -769,7 +778,7 @@ public class CodeVerifier implements Opcodes { |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
case opc_checkcast: { |
|
|
|
case opc_checkcast: { |
|
|
|
Type classType = Type.tClassOrArray((String) instr.objData); |
|
|
|
Type classType = Type.tType((String) instr.objData); |
|
|
|
if (!isOfType(result.pop(), Type.tUObject)) |
|
|
|
if (!isOfType(result.pop(), Type.tUObject)) |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
throw new VerifyException(instr.getDescription()); |
|
|
|
result.push(classType); |
|
|
|
result.push(classType); |
|
|
|