public override SourceValue UnaryOperation(AbstractInsnNode insn, SourceValue value ) { int size; switch (insn.GetOpcode()) { case OpcodesConstants.Lneg: case OpcodesConstants.Dneg: case OpcodesConstants.I2l: case OpcodesConstants.I2d: case OpcodesConstants.L2d: case OpcodesConstants.F2l: case OpcodesConstants.F2d: case OpcodesConstants.D2l: { size = 2; break; } case OpcodesConstants.Getfield: { size = Type.GetType(((FieldInsnNode)insn).desc).GetSize(); break; } default: { size = 1; break; } } return(new SourceValue(size, insn)); }
/// <exception cref="AnalyzerException" /> private void ExecuteInvokeInsn(AbstractInsnNode insn, string methodDescriptor, Interpreter <V> interpreter) { var valueList = new List <V>(); for (var i = Type.GetArgumentTypes(methodDescriptor).Length; i > 0; --i) { valueList.Add(0, Pop()); } if (insn.GetOpcode() != OpcodesConstants.Invokestatic && insn.GetOpcode() != OpcodesConstants .Invokedynamic) { valueList.Add(0, Pop()); } if (Type.GetReturnType(methodDescriptor) == Type.Void_Type) { interpreter.NaryOperation(insn, valueList); } else { Push(interpreter.NaryOperation(insn, valueList)); } }
/// <exception cref="AnalyzerException" /> public override BasicValue NaryOperation <_T0>(AbstractInsnNode insn, IList <_T0> values ) { var opcode = insn.GetOpcode(); if (opcode == OpcodesConstants.Multianewarray) { return(NewValue(Type.GetType(((MultiANewArrayInsnNode)insn).desc))); } if (opcode == OpcodesConstants.Invokedynamic) { return(NewValue(Type.GetReturnType(((InvokeDynamicInsnNode)insn).desc))); } return(NewValue(Type.GetReturnType(((MethodInsnNode)insn).desc))); }
/// <exception cref="AnalyzerException" /> public override BasicValue NaryOperation <_T0>(AbstractInsnNode insn, IList <_T0> values ) { var opcode = insn.GetOpcode(); if (opcode == OpcodesConstants.Multianewarray) { foreach (var value in values) { if (!BasicValue.Int_Value.Equals(value)) { throw new AnalyzerException(insn, null, BasicValue.Int_Value, value); } } } else { var i = 0; var j = 0; if (opcode != OpcodesConstants.Invokestatic && opcode != OpcodesConstants.Invokedynamic) { var owner = Type.GetObjectType(((MethodInsnNode)insn).owner); if (!IsSubTypeOf(values[i++], NewValue(owner))) { throw new AnalyzerException(insn, "Method owner", NewValue(owner), values[0]); } } var methodDescriptor = opcode == OpcodesConstants.Invokedynamic ? ((InvokeDynamicInsnNode )insn).desc : ((MethodInsnNode)insn).desc; var args = Type.GetArgumentTypes(methodDescriptor); while (i < values.Count) { var expected = NewValue(args[j++]); var actual = values[i++]; if (!IsSubTypeOf(actual, expected)) { throw new AnalyzerException(insn, "Argument " + j, expected, actual); } } } return(base.NaryOperation(insn, values)); }
public override SourceValue NaryOperation <_T0>(AbstractInsnNode insn, IList <_T0> values) { int size; var opcode = insn.GetOpcode(); if (opcode == OpcodesConstants.Multianewarray) { size = 1; } else if (opcode == OpcodesConstants.Invokedynamic) { size = Type.GetReturnType(((InvokeDynamicInsnNode)insn).desc).GetSize(); } else { size = Type.GetReturnType(((MethodInsnNode)insn).desc).GetSize(); } return(new SourceValue(size, insn)); }
public override SourceValue BinaryOperation(AbstractInsnNode insn, SourceValue value1 , SourceValue value2) { int size; switch (insn.GetOpcode()) { case OpcodesConstants.Laload: case OpcodesConstants.Daload: case OpcodesConstants.Ladd: case OpcodesConstants.Dadd: case OpcodesConstants.Lsub: case OpcodesConstants.Dsub: case OpcodesConstants.Lmul: case OpcodesConstants.Dmul: case OpcodesConstants.Ldiv: case OpcodesConstants.Ddiv: case OpcodesConstants.Lrem: case OpcodesConstants.Drem: case OpcodesConstants.Lshl: case OpcodesConstants.Lshr: case OpcodesConstants.Lushr: case OpcodesConstants.Land: case OpcodesConstants.Lor: case OpcodesConstants.Lxor: { size = 2; break; } default: { size = 1; break; } } return(new SourceValue(size, insn)); }
public override SourceValue NewOperation(AbstractInsnNode insn) { int size; switch (insn.GetOpcode()) { case OpcodesConstants.Lconst_0: case OpcodesConstants.Lconst_1: case OpcodesConstants.Dconst_0: case OpcodesConstants.Dconst_1: { size = 2; break; } case OpcodesConstants.Ldc: { var value = ((LdcInsnNode)insn).cst; size = value is long || value is double? 2 : 1; break; } case OpcodesConstants.Getstatic: { size = Type.GetType(((FieldInsnNode)insn).desc).GetSize(); break; } default: { size = 1; break; } } return(new SourceValue(size, insn)); }
/// <summary> /// Simulates the execution of the given instruction on this execution stack frame. /// </summary> /// <param name="insn">the instruction to execute.</param> /// <param name="interpreter"> /// the interpreter to use to compute values from other values. /// </param> /// <exception cref="AnalyzerException"> /// if the instruction cannot be executed on this execution frame (e.g. a /// POP on an empty operand stack). /// </exception> /// <exception cref="AnalyzerException" /> public virtual void Execute(AbstractInsnNode insn, Interpreter <V> interpreter) { V value1; V value2; V value3; V value4; int var; switch (insn.GetOpcode()) { case OpcodesConstants.Nop: { break; } case OpcodesConstants.Aconst_Null: case OpcodesConstants.Iconst_M1: case OpcodesConstants.Iconst_0: case OpcodesConstants.Iconst_1: case OpcodesConstants.Iconst_2: case OpcodesConstants.Iconst_3: case OpcodesConstants.Iconst_4: case OpcodesConstants.Iconst_5: case OpcodesConstants.Lconst_0: case OpcodesConstants.Lconst_1: case OpcodesConstants.Fconst_0: case OpcodesConstants.Fconst_1: case OpcodesConstants.Fconst_2: case OpcodesConstants.Dconst_0: case OpcodesConstants.Dconst_1: case OpcodesConstants.Bipush: case OpcodesConstants.Sipush: case OpcodesConstants.Ldc: { Push(interpreter.NewOperation(insn)); break; } case OpcodesConstants.Iload: case OpcodesConstants.Lload: case OpcodesConstants.Fload: case OpcodesConstants.Dload: case OpcodesConstants.Aload: { Push(interpreter.CopyOperation(insn, GetLocal(((VarInsnNode)insn).var))); break; } case OpcodesConstants.Istore: case OpcodesConstants.Lstore: case OpcodesConstants.Fstore: case OpcodesConstants.Dstore: case OpcodesConstants.Astore: { value1 = interpreter.CopyOperation(insn, Pop()); var = ((VarInsnNode)insn).var; SetLocal(var, value1); if (value1.GetSize() == 2) { SetLocal(var + 1, interpreter.NewEmptyValue(var + 1)); } if (var > 0) { Value local = GetLocal(var - 1); if (local != null && local.GetSize() == 2) { SetLocal(var - 1, interpreter.NewEmptyValue(var - 1)); } } break; } case OpcodesConstants.Iastore: case OpcodesConstants.Lastore: case OpcodesConstants.Fastore: case OpcodesConstants.Dastore: case OpcodesConstants.Aastore: case OpcodesConstants.Bastore: case OpcodesConstants.Castore: case OpcodesConstants.Sastore: { value3 = Pop(); value2 = Pop(); value1 = Pop(); interpreter.TernaryOperation(insn, value1, value2, value3); break; } case OpcodesConstants.Pop: { if (Pop().GetSize() == 2) { throw new AnalyzerException(insn, "Illegal use of POP"); } break; } case OpcodesConstants.Pop2: { if (Pop().GetSize() == 1 && Pop().GetSize() != 1) { throw new AnalyzerException(insn, "Illegal use of POP2"); } break; } case OpcodesConstants.Dup: { value1 = Pop(); if (value1.GetSize() != 1) { throw new AnalyzerException(insn, "Illegal use of DUP"); } Push(value1); Push(interpreter.CopyOperation(insn, value1)); break; } case OpcodesConstants.Dup_X1: { value1 = Pop(); value2 = Pop(); if (value1.GetSize() != 1 || value2.GetSize() != 1) { throw new AnalyzerException(insn, "Illegal use of DUP_X1"); } Push(interpreter.CopyOperation(insn, value1)); Push(value2); Push(value1); break; } case OpcodesConstants.Dup_X2: { value1 = Pop(); if (value1.GetSize() == 1 && ExecuteDupX2(insn, value1, interpreter)) { break; } throw new AnalyzerException(insn, "Illegal use of DUP_X2"); } case OpcodesConstants.Dup2: { value1 = Pop(); if (value1.GetSize() == 1) { value2 = Pop(); if (value2.GetSize() == 1) { Push(value2); Push(value1); Push(interpreter.CopyOperation(insn, value2)); Push(interpreter.CopyOperation(insn, value1)); break; } } else { Push(value1); Push(interpreter.CopyOperation(insn, value1)); break; } throw new AnalyzerException(insn, "Illegal use of DUP2"); } case OpcodesConstants.Dup2_X1: { value1 = Pop(); if (value1.GetSize() == 1) { value2 = Pop(); if (value2.GetSize() == 1) { value3 = Pop(); if (value3.GetSize() == 1) { Push(interpreter.CopyOperation(insn, value2)); Push(interpreter.CopyOperation(insn, value1)); Push(value3); Push(value2); Push(value1); break; } } } else { value2 = Pop(); if (value2.GetSize() == 1) { Push(interpreter.CopyOperation(insn, value1)); Push(value2); Push(value1); break; } } throw new AnalyzerException(insn, "Illegal use of DUP2_X1"); } case OpcodesConstants.Dup2_X2: { value1 = Pop(); if (value1.GetSize() == 1) { value2 = Pop(); if (value2.GetSize() == 1) { value3 = Pop(); if (value3.GetSize() == 1) { value4 = Pop(); if (value4.GetSize() == 1) { Push(interpreter.CopyOperation(insn, value2)); Push(interpreter.CopyOperation(insn, value1)); Push(value4); Push(value3); Push(value2); Push(value1); break; } } else { Push(interpreter.CopyOperation(insn, value2)); Push(interpreter.CopyOperation(insn, value1)); Push(value3); Push(value2); Push(value1); break; } } } else if (ExecuteDupX2(insn, value1, interpreter)) { break; } throw new AnalyzerException(insn, "Illegal use of DUP2_X2"); } case OpcodesConstants.Swap: { value2 = Pop(); value1 = Pop(); if (value1.GetSize() != 1 || value2.GetSize() != 1) { throw new AnalyzerException(insn, "Illegal use of SWAP"); } Push(interpreter.CopyOperation(insn, value2)); Push(interpreter.CopyOperation(insn, value1)); break; } case OpcodesConstants.Iaload: case OpcodesConstants.Laload: case OpcodesConstants.Faload: case OpcodesConstants.Daload: case OpcodesConstants.Aaload: case OpcodesConstants.Baload: case OpcodesConstants.Caload: case OpcodesConstants.Saload: case OpcodesConstants.Iadd: case OpcodesConstants.Ladd: case OpcodesConstants.Fadd: case OpcodesConstants.Dadd: case OpcodesConstants.Isub: case OpcodesConstants.Lsub: case OpcodesConstants.Fsub: case OpcodesConstants.Dsub: case OpcodesConstants.Imul: case OpcodesConstants.Lmul: case OpcodesConstants.Fmul: case OpcodesConstants.Dmul: case OpcodesConstants.Idiv: case OpcodesConstants.Ldiv: case OpcodesConstants.Fdiv: case OpcodesConstants.Ddiv: case OpcodesConstants.Irem: case OpcodesConstants.Lrem: case OpcodesConstants.Frem: case OpcodesConstants.Drem: case OpcodesConstants.Ishl: case OpcodesConstants.Lshl: case OpcodesConstants.Ishr: case OpcodesConstants.Lshr: case OpcodesConstants.Iushr: case OpcodesConstants.Lushr: case OpcodesConstants.Iand: case OpcodesConstants.Land: case OpcodesConstants.Ior: case OpcodesConstants.Lor: case OpcodesConstants.Ixor: case OpcodesConstants.Lxor: case OpcodesConstants.Lcmp: case OpcodesConstants.Fcmpl: case OpcodesConstants.Fcmpg: case OpcodesConstants.Dcmpl: case OpcodesConstants.Dcmpg: { value2 = Pop(); value1 = Pop(); Push(interpreter.BinaryOperation(insn, value1, value2)); break; } case OpcodesConstants.Ineg: case OpcodesConstants.Lneg: case OpcodesConstants.Fneg: case OpcodesConstants.Dneg: { Push(interpreter.UnaryOperation(insn, Pop())); break; } case OpcodesConstants.Iinc: { var = ((IincInsnNode)insn).var; SetLocal(var, interpreter.UnaryOperation(insn, GetLocal(var))); break; } case OpcodesConstants.I2l: case OpcodesConstants.I2f: case OpcodesConstants.I2d: case OpcodesConstants.L2i: case OpcodesConstants.L2f: case OpcodesConstants.L2d: case OpcodesConstants.F2i: case OpcodesConstants.F2l: case OpcodesConstants.F2d: case OpcodesConstants.D2i: case OpcodesConstants.D2l: case OpcodesConstants.D2f: case OpcodesConstants.I2b: case OpcodesConstants.I2c: case OpcodesConstants.I2s: { Push(interpreter.UnaryOperation(insn, Pop())); break; } case OpcodesConstants.Ifeq: case OpcodesConstants.Ifne: case OpcodesConstants.Iflt: case OpcodesConstants.Ifge: case OpcodesConstants.Ifgt: case OpcodesConstants.Ifle: { interpreter.UnaryOperation(insn, Pop()); break; } case OpcodesConstants.If_Icmpeq: case OpcodesConstants.If_Icmpne: case OpcodesConstants.If_Icmplt: case OpcodesConstants.If_Icmpge: case OpcodesConstants.If_Icmpgt: case OpcodesConstants.If_Icmple: case OpcodesConstants.If_Acmpeq: case OpcodesConstants.If_Acmpne: case OpcodesConstants.Putfield: { value2 = Pop(); value1 = Pop(); interpreter.BinaryOperation(insn, value1, value2); break; } case OpcodesConstants.Goto: { break; } case OpcodesConstants.Jsr: { Push(interpreter.NewOperation(insn)); break; } case OpcodesConstants.Ret: { break; } case OpcodesConstants.Tableswitch: case OpcodesConstants.Lookupswitch: { interpreter.UnaryOperation(insn, Pop()); break; } case OpcodesConstants.Ireturn: case OpcodesConstants.Lreturn: case OpcodesConstants.Freturn: case OpcodesConstants.Dreturn: case OpcodesConstants.Areturn: { value1 = Pop(); interpreter.UnaryOperation(insn, value1); interpreter.ReturnOperation(insn, value1, returnValue); break; } case OpcodesConstants.Return: { if (returnValue != null) { throw new AnalyzerException(insn, "Incompatible return type"); } break; } case OpcodesConstants.Getstatic: { Push(interpreter.NewOperation(insn)); break; } case OpcodesConstants.Putstatic: { interpreter.UnaryOperation(insn, Pop()); break; } case OpcodesConstants.Getfield: { Push(interpreter.UnaryOperation(insn, Pop())); break; } case OpcodesConstants.Invokevirtual: case OpcodesConstants.Invokespecial: case OpcodesConstants.Invokestatic: case OpcodesConstants.Invokeinterface: { ExecuteInvokeInsn(insn, ((MethodInsnNode)insn).desc, interpreter); break; } case OpcodesConstants.Invokedynamic: { ExecuteInvokeInsn(insn, ((InvokeDynamicInsnNode)insn).desc, interpreter); break; } case OpcodesConstants.New: { Push(interpreter.NewOperation(insn)); break; } case OpcodesConstants.Newarray: case OpcodesConstants.Anewarray: case OpcodesConstants.Arraylength: { Push(interpreter.UnaryOperation(insn, Pop())); break; } case OpcodesConstants.Athrow: { interpreter.UnaryOperation(insn, Pop()); break; } case OpcodesConstants.Checkcast: case OpcodesConstants.Instanceof: { Push(interpreter.UnaryOperation(insn, Pop())); break; } case OpcodesConstants.Monitorenter: case OpcodesConstants.Monitorexit: { interpreter.UnaryOperation(insn, Pop()); break; } case OpcodesConstants.Multianewarray: { IList <V> valueList = new List <V>(); for (var i = ((MultiANewArrayInsnNode)insn).dims; i > 0; --i) { valueList.Add(0, Pop()); } Push(interpreter.NaryOperation(insn, valueList)); break; } case OpcodesConstants.Ifnull: case OpcodesConstants.Ifnonnull: { interpreter.UnaryOperation(insn, Pop()); break; } default: { throw new AnalyzerException(insn, "Illegal opcode " + insn.GetOpcode()); } } }
/// <summary>Analyzes the given method.</summary> /// <param name="owner">the internal name of the class to which 'method' belongs.</param> /// <param name="method">the method to be analyzed.</param> /// <returns> /// the symbolic state of the execution stack frame at each bytecode instruction of the /// method. The size of the returned array is equal to the number of instructions (and labels) /// of the method. A given frame is /// <literal>null</literal> /// if and only if the corresponding /// instruction cannot be reached (dead code). /// </returns> /// <exception cref="AnalyzerException">if a problem occurs during the analysis.</exception> /// <exception cref="AnalyzerException" /> public virtual Frame <V>[] Analyze(string owner, MethodNode method) { if ((method.access & (AccessFlags.Abstract | AccessFlags.Native )) != 0) { frames = new Frame <V> [0]; return(frames); } insnList = method.instructions; insnListSize = insnList.Size(); handlers = (IList <TryCatchBlockNode>[]) new IList <object> [insnListSize]; frames = new Frame <V> [insnListSize]; subroutines = new Subroutine[insnListSize]; inInstructionsToProcess = new bool[insnListSize]; instructionsToProcess = new int[insnListSize]; numInstructionsToProcess = 0; // For each exception handler, and each instruction within its range, record in 'handlers' the // fact that execution can flow from this instruction to the exception handler. for (var i = 0; i < method.tryCatchBlocks.Count; ++i) { var tryCatchBlock = method.tryCatchBlocks[i]; var startIndex = insnList.IndexOf(tryCatchBlock.start); var endIndex = insnList.IndexOf(tryCatchBlock.end); for (var j = startIndex; j < endIndex; ++j) { var insnHandlers = handlers[j]; if (insnHandlers == null) { insnHandlers = new List <TryCatchBlockNode>(); handlers[j] = insnHandlers; } insnHandlers.Add(tryCatchBlock); } } // For each instruction, compute the subroutine to which it belongs. // Follow the main 'subroutine', and collect the jsr instructions to nested subroutines. var main = new Subroutine(null, method.maxLocals, null); IList <AbstractInsnNode> jsrInsns = new List <AbstractInsnNode>(); FindSubroutine(0, main, jsrInsns); // Follow the nested subroutines, and collect their own nested subroutines, until all // subroutines are found. IDictionary <LabelNode, Subroutine> jsrSubroutines = new Dictionary <LabelNode, Subroutine >(); while (!(jsrInsns.Count == 0)) { var jsrInsn = (JumpInsnNode)jsrInsns.RemoveAtReturningValue(0); var subroutine = jsrSubroutines.GetOrNull(jsrInsn.label); if (subroutine == null) { subroutine = new Subroutine(jsrInsn.label, method.maxLocals, jsrInsn); Collections.Put(jsrSubroutines, jsrInsn.label, subroutine); FindSubroutine(insnList.IndexOf(jsrInsn.label), subroutine, jsrInsns); } else { subroutine.callers.Add(jsrInsn); } } // Clear the main 'subroutine', which is not a real subroutine (and was used only as an // intermediate step above to find the real ones). for (var i = 0; i < insnListSize; ++i) { if (subroutines[i] != null && subroutines[i].start == null) { subroutines[i] = null; } } // Initializes the data structures for the control flow analysis. var currentFrame = ComputeInitialFrame(owner, method); Merge(0, currentFrame, null); Init(owner, method); // Control flow analysis. while (numInstructionsToProcess > 0) { // Get and remove one instruction from the list of instructions to process. var insnIndex = instructionsToProcess[--numInstructionsToProcess]; var oldFrame = frames[insnIndex]; var subroutine = subroutines[insnIndex]; inInstructionsToProcess[insnIndex] = false; // Simulate the execution of this instruction. AbstractInsnNode insnNode = null; try { insnNode = method.instructions.Get(insnIndex); var insnOpcode = insnNode.GetOpcode(); var insnType = insnNode.GetType(); if (insnType == AbstractInsnNode.Label || insnType == AbstractInsnNode.Line || insnType == AbstractInsnNode.Frame) { Merge(insnIndex + 1, oldFrame, subroutine); NewControlFlowEdge(insnIndex, insnIndex + 1); } else { currentFrame.Init(oldFrame).Execute(insnNode, interpreter); subroutine = subroutine == null ? null : new Subroutine(subroutine); if (insnNode is JumpInsnNode) { var jumpInsn = (JumpInsnNode)insnNode; if (insnOpcode != OpcodesConstants.Goto && insnOpcode != OpcodesConstants.Jsr) { currentFrame.InitJumpTarget(insnOpcode, null); /* target = */ Merge(insnIndex + 1, currentFrame, subroutine); NewControlFlowEdge(insnIndex, insnIndex + 1); } var jumpInsnIndex = insnList.IndexOf(jumpInsn.label); currentFrame.InitJumpTarget(insnOpcode, jumpInsn.label); if (insnOpcode == OpcodesConstants.Jsr) { Merge(jumpInsnIndex, currentFrame, new Subroutine(jumpInsn.label, method.maxLocals , jumpInsn)); } else { Merge(jumpInsnIndex, currentFrame, subroutine); } NewControlFlowEdge(insnIndex, jumpInsnIndex); } else if (insnNode is LookupSwitchInsnNode) { var lookupSwitchInsn = (LookupSwitchInsnNode)insnNode; var targetInsnIndex = insnList.IndexOf(lookupSwitchInsn.dflt); currentFrame.InitJumpTarget(insnOpcode, lookupSwitchInsn.dflt); Merge(targetInsnIndex, currentFrame, subroutine); NewControlFlowEdge(insnIndex, targetInsnIndex); for (var i = 0; i < lookupSwitchInsn.labels.Count; ++i) { var label = lookupSwitchInsn.labels[i]; targetInsnIndex = insnList.IndexOf(label); currentFrame.InitJumpTarget(insnOpcode, label); Merge(targetInsnIndex, currentFrame, subroutine); NewControlFlowEdge(insnIndex, targetInsnIndex); } } else if (insnNode is TableSwitchInsnNode) { var tableSwitchInsn = (TableSwitchInsnNode)insnNode; var targetInsnIndex = insnList.IndexOf(tableSwitchInsn.dflt); currentFrame.InitJumpTarget(insnOpcode, tableSwitchInsn.dflt); Merge(targetInsnIndex, currentFrame, subroutine); NewControlFlowEdge(insnIndex, targetInsnIndex); for (var i = 0; i < tableSwitchInsn.labels.Count; ++i) { var label = tableSwitchInsn.labels[i]; currentFrame.InitJumpTarget(insnOpcode, label); targetInsnIndex = insnList.IndexOf(label); Merge(targetInsnIndex, currentFrame, subroutine); NewControlFlowEdge(insnIndex, targetInsnIndex); } } else if (insnOpcode == OpcodesConstants.Ret) { if (subroutine == null) { throw new AnalyzerException(insnNode, "RET instruction outside of a subroutine"); } for (var i = 0; i < subroutine.callers.Count; ++i) { var caller = subroutine.callers[i]; var jsrInsnIndex = insnList.IndexOf(caller); if (frames[jsrInsnIndex] != null) { Merge(jsrInsnIndex + 1, frames[jsrInsnIndex], currentFrame, subroutines[jsrInsnIndex ], subroutine.localsUsed); NewControlFlowEdge(insnIndex, jsrInsnIndex + 1); } } } else if (insnOpcode != OpcodesConstants.Athrow && (insnOpcode < OpcodesConstants.Ireturn || insnOpcode > OpcodesConstants.Return)) { if (subroutine != null) { if (insnNode is VarInsnNode) { var var = ((VarInsnNode)insnNode).var; subroutine.localsUsed[var] = true; if (insnOpcode == OpcodesConstants.Lload || insnOpcode == OpcodesConstants.Dload || insnOpcode == OpcodesConstants.Lstore || insnOpcode == OpcodesConstants.Dstore) { subroutine.localsUsed[var + 1] = true; } } else if (insnNode is IincInsnNode) { var var = ((IincInsnNode)insnNode).var; subroutine.localsUsed[var] = true; } } Merge(insnIndex + 1, currentFrame, subroutine); NewControlFlowEdge(insnIndex, insnIndex + 1); } } var insnHandlers = handlers[insnIndex]; if (insnHandlers != null) { foreach (var tryCatchBlock in insnHandlers) { Type catchType; if (tryCatchBlock.type == null) { catchType = Type.GetObjectType("java/lang/Throwable"); } else { catchType = Type.GetObjectType(tryCatchBlock.type); } if (NewControlFlowExceptionEdge(insnIndex, tryCatchBlock)) { var handler = NewFrame(oldFrame); handler.ClearStack(); handler.Push(interpreter.NewExceptionValue(tryCatchBlock, handler, catchType)); Merge(insnList.IndexOf(tryCatchBlock.handler), handler, subroutine); } } } } catch (AnalyzerException e) { throw new AnalyzerException(e.node, "Error at instruction " + insnIndex + ": " + e.Message, e); } catch (Exception e) { // DontCheck(IllegalCatch): can't be fixed, for backward compatibility. throw new AnalyzerException(insnNode, "Error at instruction " + insnIndex + ": " + e.Message, e); } } return(frames); }
/// <exception cref="AnalyzerException" /> public override BasicValue BinaryOperation(AbstractInsnNode insn, BasicValue value1 , BasicValue value2) { switch (insn.GetOpcode()) { case OpcodesConstants.Iaload: case OpcodesConstants.Baload: case OpcodesConstants.Caload: case OpcodesConstants.Saload: case OpcodesConstants.Iadd: case OpcodesConstants.Isub: case OpcodesConstants.Imul: case OpcodesConstants.Idiv: case OpcodesConstants.Irem: case OpcodesConstants.Ishl: case OpcodesConstants.Ishr: case OpcodesConstants.Iushr: case OpcodesConstants.Iand: case OpcodesConstants.Ior: case OpcodesConstants.Ixor: { return(BasicValue.Int_Value); } case OpcodesConstants.Faload: case OpcodesConstants.Fadd: case OpcodesConstants.Fsub: case OpcodesConstants.Fmul: case OpcodesConstants.Fdiv: case OpcodesConstants.Frem: { return(BasicValue.Float_Value); } case OpcodesConstants.Laload: case OpcodesConstants.Ladd: case OpcodesConstants.Lsub: case OpcodesConstants.Lmul: case OpcodesConstants.Ldiv: case OpcodesConstants.Lrem: case OpcodesConstants.Lshl: case OpcodesConstants.Lshr: case OpcodesConstants.Lushr: case OpcodesConstants.Land: case OpcodesConstants.Lor: case OpcodesConstants.Lxor: { return(BasicValue.Long_Value); } case OpcodesConstants.Daload: case OpcodesConstants.Dadd: case OpcodesConstants.Dsub: case OpcodesConstants.Dmul: case OpcodesConstants.Ddiv: case OpcodesConstants.Drem: { return(BasicValue.Double_Value); } case OpcodesConstants.Aaload: { return(BasicValue.Reference_Value); } case OpcodesConstants.Lcmp: case OpcodesConstants.Fcmpl: case OpcodesConstants.Fcmpg: case OpcodesConstants.Dcmpl: case OpcodesConstants.Dcmpg: { return(BasicValue.Int_Value); } case OpcodesConstants.If_Icmpeq: case OpcodesConstants.If_Icmpne: case OpcodesConstants.If_Icmplt: case OpcodesConstants.If_Icmpge: case OpcodesConstants.If_Icmpgt: case OpcodesConstants.If_Icmple: case OpcodesConstants.If_Acmpeq: case OpcodesConstants.If_Acmpne: case OpcodesConstants.Putfield: { return(null); } default: { throw new AssertionError(); } } }
/// <exception cref="AnalyzerException" /> public override BasicValue UnaryOperation(AbstractInsnNode insn, BasicValue value ) { switch (insn.GetOpcode()) { case OpcodesConstants.Ineg: case OpcodesConstants.Iinc: case OpcodesConstants.L2i: case OpcodesConstants.F2i: case OpcodesConstants.D2i: case OpcodesConstants.I2b: case OpcodesConstants.I2c: case OpcodesConstants.I2s: { return(BasicValue.Int_Value); } case OpcodesConstants.Fneg: case OpcodesConstants.I2f: case OpcodesConstants.L2f: case OpcodesConstants.D2f: { return(BasicValue.Float_Value); } case OpcodesConstants.Lneg: case OpcodesConstants.I2l: case OpcodesConstants.F2l: case OpcodesConstants.D2l: { return(BasicValue.Long_Value); } case OpcodesConstants.Dneg: case OpcodesConstants.I2d: case OpcodesConstants.L2d: case OpcodesConstants.F2d: { return(BasicValue.Double_Value); } case OpcodesConstants.Ifeq: case OpcodesConstants.Ifne: case OpcodesConstants.Iflt: case OpcodesConstants.Ifge: case OpcodesConstants.Ifgt: case OpcodesConstants.Ifle: case OpcodesConstants.Tableswitch: case OpcodesConstants.Lookupswitch: case OpcodesConstants.Ireturn: case OpcodesConstants.Lreturn: case OpcodesConstants.Freturn: case OpcodesConstants.Dreturn: case OpcodesConstants.Areturn: case OpcodesConstants.Putstatic: { return(null); } case OpcodesConstants.Getfield: { return(NewValue(Type.GetType(((FieldInsnNode)insn).desc))); } case OpcodesConstants.Newarray: { switch (((IntInsnNode)insn).operand) { case OpcodesConstants.T_Boolean: { return(NewValue(Type.GetType("[Z"))); } case OpcodesConstants.T_Char: { return(NewValue(Type.GetType("[C"))); } case OpcodesConstants.T_Byte: { return(NewValue(Type.GetType("[B"))); } case OpcodesConstants.T_Short: { return(NewValue(Type.GetType("[S"))); } case OpcodesConstants.T_Int: { return(NewValue(Type.GetType("[I"))); } case OpcodesConstants.T_Float: { return(NewValue(Type.GetType("[F"))); } case OpcodesConstants.T_Double: { return(NewValue(Type.GetType("[D"))); } case OpcodesConstants.T_Long: { return(NewValue(Type.GetType("[J"))); } } throw new AnalyzerException(insn, "Invalid array type"); } case OpcodesConstants.Anewarray: { return(NewValue(Type.GetType("[" + Type.GetObjectType(((TypeInsnNode)insn).desc)) )); } case OpcodesConstants.Arraylength: { return(BasicValue.Int_Value); } case OpcodesConstants.Athrow: { return(null); } case OpcodesConstants.Checkcast: { return(NewValue(Type.GetObjectType(((TypeInsnNode)insn).desc))); } case OpcodesConstants.Instanceof: { return(BasicValue.Int_Value); } case OpcodesConstants.Monitorenter: case OpcodesConstants.Monitorexit: case OpcodesConstants.Ifnull: case OpcodesConstants.Ifnonnull: { return(null); } default: { throw new AssertionError(); } } }
/// <exception cref="AnalyzerException" /> public override BasicValue NewOperation(AbstractInsnNode insn) { switch (insn.GetOpcode()) { case OpcodesConstants.Aconst_Null: { return(NewValue(Null_Type)); } case OpcodesConstants.Iconst_M1: case OpcodesConstants.Iconst_0: case OpcodesConstants.Iconst_1: case OpcodesConstants.Iconst_2: case OpcodesConstants.Iconst_3: case OpcodesConstants.Iconst_4: case OpcodesConstants.Iconst_5: { return(BasicValue.Int_Value); } case OpcodesConstants.Lconst_0: case OpcodesConstants.Lconst_1: { return(BasicValue.Long_Value); } case OpcodesConstants.Fconst_0: case OpcodesConstants.Fconst_1: case OpcodesConstants.Fconst_2: { return(BasicValue.Float_Value); } case OpcodesConstants.Dconst_0: case OpcodesConstants.Dconst_1: { return(BasicValue.Double_Value); } case OpcodesConstants.Bipush: case OpcodesConstants.Sipush: { return(BasicValue.Int_Value); } case OpcodesConstants.Ldc: { var value = ((LdcInsnNode)insn).cst; if (value is int) { return(BasicValue.Int_Value); } if (value is float) { return(BasicValue.Float_Value); } if (value is long) { return(BasicValue.Long_Value); } if (value is double) { return(BasicValue.Double_Value); } if (value is string) { return(NewValue(Type.GetObjectType("java/lang/String"))); } if (value is Type) { var sort = ((Type)value).GetSort(); if (sort == Type.Object || sort == Type.Array) { return(NewValue(Type.GetObjectType("java/lang/Class"))); } if (sort == Type.Method) { return(NewValue(Type.GetObjectType("java/lang/invoke/MethodType"))); } throw new AnalyzerException(insn, "Illegal LDC value " + value); } if (value is Handle) { return(NewValue(Type.GetObjectType("java/lang/invoke/MethodHandle"))); } if (value is ConstantDynamic) { return(NewValue(Type.GetType(((ConstantDynamic)value).GetDescriptor()))); } throw new AnalyzerException(insn, "Illegal LDC value " + value); goto case OpcodesConstants.Jsr; } case OpcodesConstants.Jsr: { return(BasicValue.Returnaddress_Value); } case OpcodesConstants.Getstatic: { return(NewValue(Type.GetType(((FieldInsnNode)insn).desc))); } case OpcodesConstants.New: { return(NewValue(Type.GetObjectType(((TypeInsnNode)insn).desc))); } default: { throw new AssertionError(); } } }
/// <exception cref="AnalyzerException" /> public override BasicValue CopyOperation(AbstractInsnNode insn, BasicValue value) { Value expected; switch (insn.GetOpcode()) { case OpcodesConstants.Iload: case OpcodesConstants.Istore: { expected = BasicValue.Int_Value; break; } case OpcodesConstants.Fload: case OpcodesConstants.Fstore: { expected = BasicValue.Float_Value; break; } case OpcodesConstants.Lload: case OpcodesConstants.Lstore: { expected = BasicValue.Long_Value; break; } case OpcodesConstants.Dload: case OpcodesConstants.Dstore: { expected = BasicValue.Double_Value; break; } case OpcodesConstants.Aload: { if (!value.IsReference()) { throw new AnalyzerException(insn, null, "an object reference", value); } return(value); } case OpcodesConstants.Astore: { if (!value.IsReference() && !BasicValue.Returnaddress_Value.Equals(value)) { throw new AnalyzerException(insn, null, "an object reference or a return address" , value); } return(value); } default: { return(value); } } if (!expected.Equals(value)) { throw new AnalyzerException(insn, null, expected, value); } return(value); }
/// <exception cref="AnalyzerException" /> public override BasicValue TernaryOperation(AbstractInsnNode insn, BasicValue value1 , BasicValue value2, BasicValue value3) { BasicValue expected1; BasicValue expected3; switch (insn.GetOpcode()) { case OpcodesConstants.Iastore: { expected1 = NewValue(Type.GetType("[I")); expected3 = BasicValue.Int_Value; break; } case OpcodesConstants.Bastore: { if (IsSubTypeOf(value1, NewValue(Type.GetType("[Z")))) { expected1 = NewValue(Type.GetType("[Z")); } else { expected1 = NewValue(Type.GetType("[B")); } expected3 = BasicValue.Int_Value; break; } case OpcodesConstants.Castore: { expected1 = NewValue(Type.GetType("[C")); expected3 = BasicValue.Int_Value; break; } case OpcodesConstants.Sastore: { expected1 = NewValue(Type.GetType("[S")); expected3 = BasicValue.Int_Value; break; } case OpcodesConstants.Lastore: { expected1 = NewValue(Type.GetType("[J")); expected3 = BasicValue.Long_Value; break; } case OpcodesConstants.Fastore: { expected1 = NewValue(Type.GetType("[F")); expected3 = BasicValue.Float_Value; break; } case OpcodesConstants.Dastore: { expected1 = NewValue(Type.GetType("[D")); expected3 = BasicValue.Double_Value; break; } case OpcodesConstants.Aastore: { expected1 = value1; expected3 = BasicValue.Reference_Value; break; } default: { throw new AssertionError(); } } if (!IsSubTypeOf(value1, expected1)) { throw new AnalyzerException(insn, "First argument", "a " + expected1 + " array reference" , value1); } if (!BasicValue.Int_Value.Equals(value2)) { throw new AnalyzerException(insn, "Second argument", BasicValue.Int_Value, value2 ); } if (!IsSubTypeOf(value3, expected3)) { throw new AnalyzerException(insn, "Third argument", expected3, value3); } return(null); }
/// <exception cref="AnalyzerException" /> public override BasicValue BinaryOperation(AbstractInsnNode insn, BasicValue value1 , BasicValue value2) { BasicValue expected1; BasicValue expected2; switch (insn.GetOpcode()) { case OpcodesConstants.Iaload: { expected1 = NewValue(Type.GetType("[I")); expected2 = BasicValue.Int_Value; break; } case OpcodesConstants.Baload: { if (IsSubTypeOf(value1, NewValue(Type.GetType("[Z")))) { expected1 = NewValue(Type.GetType("[Z")); } else { expected1 = NewValue(Type.GetType("[B")); } expected2 = BasicValue.Int_Value; break; } case OpcodesConstants.Caload: { expected1 = NewValue(Type.GetType("[C")); expected2 = BasicValue.Int_Value; break; } case OpcodesConstants.Saload: { expected1 = NewValue(Type.GetType("[S")); expected2 = BasicValue.Int_Value; break; } case OpcodesConstants.Laload: { expected1 = NewValue(Type.GetType("[J")); expected2 = BasicValue.Int_Value; break; } case OpcodesConstants.Faload: { expected1 = NewValue(Type.GetType("[F")); expected2 = BasicValue.Int_Value; break; } case OpcodesConstants.Daload: { expected1 = NewValue(Type.GetType("[D")); expected2 = BasicValue.Int_Value; break; } case OpcodesConstants.Aaload: { expected1 = NewValue(Type.GetType("[Ljava/lang/Object;")); expected2 = BasicValue.Int_Value; break; } case OpcodesConstants.Iadd: case OpcodesConstants.Isub: case OpcodesConstants.Imul: case OpcodesConstants.Idiv: case OpcodesConstants.Irem: case OpcodesConstants.Ishl: case OpcodesConstants.Ishr: case OpcodesConstants.Iushr: case OpcodesConstants.Iand: case OpcodesConstants.Ior: case OpcodesConstants.Ixor: case OpcodesConstants.If_Icmpeq: case OpcodesConstants.If_Icmpne: case OpcodesConstants.If_Icmplt: case OpcodesConstants.If_Icmpge: case OpcodesConstants.If_Icmpgt: case OpcodesConstants.If_Icmple: { expected1 = BasicValue.Int_Value; expected2 = BasicValue.Int_Value; break; } case OpcodesConstants.Fadd: case OpcodesConstants.Fsub: case OpcodesConstants.Fmul: case OpcodesConstants.Fdiv: case OpcodesConstants.Frem: case OpcodesConstants.Fcmpl: case OpcodesConstants.Fcmpg: { expected1 = BasicValue.Float_Value; expected2 = BasicValue.Float_Value; break; } case OpcodesConstants.Ladd: case OpcodesConstants.Lsub: case OpcodesConstants.Lmul: case OpcodesConstants.Ldiv: case OpcodesConstants.Lrem: case OpcodesConstants.Land: case OpcodesConstants.Lor: case OpcodesConstants.Lxor: case OpcodesConstants.Lcmp: { expected1 = BasicValue.Long_Value; expected2 = BasicValue.Long_Value; break; } case OpcodesConstants.Lshl: case OpcodesConstants.Lshr: case OpcodesConstants.Lushr: { expected1 = BasicValue.Long_Value; expected2 = BasicValue.Int_Value; break; } case OpcodesConstants.Dadd: case OpcodesConstants.Dsub: case OpcodesConstants.Dmul: case OpcodesConstants.Ddiv: case OpcodesConstants.Drem: case OpcodesConstants.Dcmpl: case OpcodesConstants.Dcmpg: { expected1 = BasicValue.Double_Value; expected2 = BasicValue.Double_Value; break; } case OpcodesConstants.If_Acmpeq: case OpcodesConstants.If_Acmpne: { expected1 = BasicValue.Reference_Value; expected2 = BasicValue.Reference_Value; break; } case OpcodesConstants.Putfield: { var fieldInsn = (FieldInsnNode)insn; expected1 = NewValue(Type.GetObjectType(fieldInsn.owner)); expected2 = NewValue(Type.GetType(fieldInsn.desc)); break; } default: { throw new AssertionError(); } } if (!IsSubTypeOf(value1, expected1)) { throw new AnalyzerException(insn, "First argument", expected1, value1); } if (!IsSubTypeOf(value2, expected2)) { throw new AnalyzerException(insn, "Second argument", expected2, value2); } if (insn.GetOpcode() == OpcodesConstants.Aaload) { return(GetElementValue(value1)); } return(base.BinaryOperation(insn, value1, value2)); }
/// <exception cref="AnalyzerException" /> public override BasicValue UnaryOperation(AbstractInsnNode insn, BasicValue value ) { BasicValue expected; switch (insn.GetOpcode()) { case OpcodesConstants.Ineg: case OpcodesConstants.Iinc: case OpcodesConstants.I2f: case OpcodesConstants.I2l: case OpcodesConstants.I2d: case OpcodesConstants.I2b: case OpcodesConstants.I2c: case OpcodesConstants.I2s: case OpcodesConstants.Ifeq: case OpcodesConstants.Ifne: case OpcodesConstants.Iflt: case OpcodesConstants.Ifge: case OpcodesConstants.Ifgt: case OpcodesConstants.Ifle: case OpcodesConstants.Tableswitch: case OpcodesConstants.Lookupswitch: case OpcodesConstants.Ireturn: case OpcodesConstants.Newarray: case OpcodesConstants.Anewarray: { expected = BasicValue.Int_Value; break; } case OpcodesConstants.Fneg: case OpcodesConstants.F2i: case OpcodesConstants.F2l: case OpcodesConstants.F2d: case OpcodesConstants.Freturn: { expected = BasicValue.Float_Value; break; } case OpcodesConstants.Lneg: case OpcodesConstants.L2i: case OpcodesConstants.L2f: case OpcodesConstants.L2d: case OpcodesConstants.Lreturn: { expected = BasicValue.Long_Value; break; } case OpcodesConstants.Dneg: case OpcodesConstants.D2i: case OpcodesConstants.D2f: case OpcodesConstants.D2l: case OpcodesConstants.Dreturn: { expected = BasicValue.Double_Value; break; } case OpcodesConstants.Getfield: { expected = NewValue(Type.GetObjectType(((FieldInsnNode)insn).owner)); break; } case OpcodesConstants.Arraylength: { if (!IsArrayValue(value)) { throw new AnalyzerException(insn, null, "an array reference", value); } return(base.UnaryOperation(insn, value)); } case OpcodesConstants.Checkcast: case OpcodesConstants.Areturn: case OpcodesConstants.Athrow: case OpcodesConstants.Instanceof: case OpcodesConstants.Monitorenter: case OpcodesConstants.Monitorexit: case OpcodesConstants.Ifnull: case OpcodesConstants.Ifnonnull: { if (!value.IsReference()) { throw new AnalyzerException(insn, null, "an object reference", value); } return(base.UnaryOperation(insn, value)); } case OpcodesConstants.Putstatic: { expected = NewValue(Type.GetType(((FieldInsnNode)insn).desc)); break; } default: { throw new AssertionError(); } } if (!IsSubTypeOf(value, expected)) { throw new AnalyzerException(insn, null, expected, value); } return(base.UnaryOperation(insn, value)); }