/// <exception cref="AnalyzerException" /> public override void ReturnOperation(AbstractInsnNode insn, BasicValue value, BasicValue expected) { if (!IsSubTypeOf(value, expected)) { throw new AnalyzerException(insn, "Incompatible return type", expected, value); } }
public override BasicValue Merge(BasicValue value1, BasicValue value2) { if (!value1.Equals(value2)) { var type1 = value1.GetType(); var type2 = value2.GetType(); if (type1 != null && (type1.GetSort() == Type.Object || type1.GetSort() == Type.Array ) && type2 != null && (type2.GetSort() == Type.Object || type2.GetSort() == Type .Array)) { if (type1.Equals(Null_Type)) { return(value2); } if (type2.Equals(Null_Type)) { return(value1); } if (IsAssignableFrom(type1, type2)) { return(value1); } if (IsAssignableFrom(type2, type1)) { return(value2); } var numDimensions = 0; if (type1.GetSort() == Type.Array && type2.GetSort() == Type.Array && type1.GetDimensions () == type2.GetDimensions() && type1.GetElementType().GetSort() == Type.Object && type2.GetElementType().GetSort() == Type.Object) { numDimensions = type1.GetDimensions(); type1 = type1.GetElementType(); type2 = type2.GetElementType(); } while (true) { if (type1 == null || IsInterface(type1)) { return(NewArrayValue(Type.GetObjectType("java/lang/Object"), numDimensions)); } type1 = GetSuperClass(type1); if (IsAssignableFrom(type1, type2)) { return(NewArrayValue(type1, numDimensions)); } } } return(BasicValue.Uninitialized_Value); } return(value1); }
protected internal override bool IsSubTypeOf(BasicValue value, BasicValue expected ) { var expectedType = expected.GetType(); var type = value.GetType(); switch (expectedType.GetSort()) { case Type.Int: case Type.Float: case Type.Long: case Type.Double: { return(type.Equals(expectedType)); } case Type.Array: case Type.Object: { if (type.Equals(Null_Type)) { return(true); } if (type.GetSort() == Type.Object || type.GetSort() == Type.Array) { if (IsAssignableFrom(expectedType, type)) { return(true); } if (GetClass(expectedType).IsInterface) { // The merge of class or interface types can only yield class types (because it is not // possible in general to find an unambiguous common super interface, due to multiple // inheritance). Because of this limitation, we need to relax the subtyping check here // if 'value' is an interface. return(Runtime.IsAssignableFrom(typeof(object), GetClass(type))); } return(false); } return(false); } default: { throw new AssertionError(); } } }
public override BasicValue NewValue(Type type) { if (type == null) { return(BasicValue.Uninitialized_Value); } var isArray = type.GetSort() == Type.Array; if (isArray) { switch (type.GetElementType().GetSort()) { case Type.Boolean: case Type.Char: case Type.Byte: case Type.Short: { return(new BasicValue(type)); } } } var value = base.NewValue(type); if (BasicValue.Reference_Value.Equals(value)) { if (isArray) { value = NewValue(type.GetElementType()); var descriptor = new StringBuilder(); for (var i = 0; i < type.GetDimensions(); ++i) { descriptor.Append('['); } descriptor.Append(value.GetType().GetDescriptor()); value = new BasicValue(Type.GetType(descriptor.ToString())); } else { value = new BasicValue(type); } } return(value); }
/// <exception cref="AnalyzerException" /> protected internal override BasicValue GetElementValue(BasicValue objectArrayValue ) { var arrayType = objectArrayValue.GetType(); if (arrayType != null) { if (arrayType.GetSort() == Type.Array) { return(NewValue(Type.GetType(Runtime.Substring(arrayType.GetDescriptor(), 1)))); } if (arrayType.Equals(Null_Type)) { return(objectArrayValue); } } throw new AssertionError(); }
protected internal override bool IsArrayValue(BasicValue value) { var type = value.GetType(); return(type != null && (type.GetSort() == Type.Array || type.Equals(Null_Type))); }
/// <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); }
/// <summary> /// Returns whether the type corresponding to the first argument is a subtype of the type /// corresponding to the second argument. /// </summary> /// <param name="value">a value.</param> /// <param name="expected">another value.</param> /// <returns> /// whether the type corresponding to 'value' is a subtype of the type corresponding to /// 'expected'. /// </returns> protected internal virtual bool IsSubTypeOf(BasicValue value, BasicValue expected ) { return(value.Equals(expected)); }
/// <summary> /// Returns the value corresponding to the type of the elements of the given array reference value. /// </summary> /// <param name="objectArrayValue"> /// a value corresponding to array of object (or array) references. /// </param> /// <returns> /// the value corresponding to the type of the elements of 'objectArrayValue'. /// </returns> /// <exception cref="AnalyzerException"> /// if objectArrayValue does not correspond to an array type. /// </exception> /// <exception cref="AnalyzerException" /> protected internal virtual BasicValue GetElementValue(BasicValue objectArrayValue ) { return(BasicValue.Reference_Value); }
/// <summary>Returns whether the given value corresponds to an array reference.</summary> /// <param name="value">a value.</param> /// <returns>whether 'value' corresponds to an array reference.</returns> protected internal virtual bool IsArrayValue(BasicValue value) { return(value.IsReference()); }
/// <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)); }