Search in sources :

Example 61 with Instruction

use of org.sonar.java.bytecode.cfg.Instruction in project sonar-java by SonarSource.

the class BytecodeEGWalker method handleMethodInvocation.

private boolean handleMethodInvocation(Instruction instruction) {
    boolean isStatic = instruction.opcode == Opcodes.INVOKESTATIC;
    int arity = isStatic ? instruction.arity() : (instruction.arity() + 1);
    ProgramState.Pop pop = programState.unstackValue(arity);
    Preconditions.checkState(pop.values.size() == arity, "Arguments mismatch for INVOKE");
    // TODO use constraintManager.createMethodSymbolicValue to create relational SV for equals
    programState = pop.state;
    SymbolicValue returnSV = instruction.hasReturnValue() ? constraintManager.createSymbolicValue(instruction) : null;
    String signature = instruction.fieldOrMethod.completeSignature();
    MethodBehavior methodInvokedBehavior = behaviorCache.get(signature);
    enqueueUncheckedExceptions();
    // FIXME : empty yields here should not happen, for now act as if behavior was not resolved.
    if (methodInvokedBehavior != null && methodInvokedBehavior.isComplete() && !methodInvokedBehavior.yields().isEmpty()) {
        List<SymbolicValue> stack = Lists.reverse(pop.values);
        if (!isStatic) {
            // remove "thisSV" from stack before trying to apply any yield, as it should not match with arguments
            stack = stack.subList(1, stack.size());
        }
        List<SymbolicValue> arguments = stack;
        methodInvokedBehavior.happyPathYields().forEach(yield -> yield.statesAfterInvocation(arguments, Collections.emptyList(), programState, () -> returnSV).forEach(ps -> {
            checkerDispatcher.methodYield = yield;
            if (ps.peekValue() != null) {
                ps = setDoubleOrLong(ps, ps.peekValue(), instruction.isLongOrDoubleValue());
            }
            checkerDispatcher.addTransition(ps);
            checkerDispatcher.methodYield = null;
        }));
        methodInvokedBehavior.exceptionalPathYields().forEach(yield -> {
            Type exceptionType = yield.exceptionType(semanticModel);
            yield.statesAfterInvocation(arguments, Collections.emptyList(), programState, () -> constraintManager.createExceptionalSymbolicValue(exceptionType)).forEach(ps -> {
                ps.storeExitValue();
                enqueueExceptionHandlers(exceptionType, ps);
            });
        });
        return true;
    }
    if (methodInvokedBehavior != null) {
        methodInvokedBehavior.getDeclaredExceptions().forEach(exception -> {
            Type exceptionType = semanticModel.getClassType(exception);
            ProgramState ps = programState.stackValue(constraintManager.createExceptionalSymbolicValue(exceptionType));
            enqueueExceptionHandlers(exceptionType, ps);
        });
    }
    if (instruction.hasReturnValue()) {
        programState = programState.stackValue(returnSV);
        programState = setDoubleOrLong(returnSV, instruction.isLongOrDoubleValue());
    }
    return false;
}
Also used : ASTORE(org.objectweb.asm.Opcodes.ASTORE) ATHROW(org.objectweb.asm.Opcodes.ATHROW) DMUL(org.objectweb.asm.Opcodes.DMUL) F2D(org.objectweb.asm.Opcodes.F2D) LSHR(org.objectweb.asm.Opcodes.LSHR) IF_ICMPEQ(org.objectweb.asm.Opcodes.IF_ICMPEQ) F2I(org.objectweb.asm.Opcodes.F2I) IINC(org.objectweb.asm.Opcodes.IINC) IFGT(org.objectweb.asm.Opcodes.IFGT) LSHL(org.objectweb.asm.Opcodes.LSHL) IAND(org.objectweb.asm.Opcodes.IAND) DCMPL(org.objectweb.asm.Opcodes.DCMPL) LSTORE(org.objectweb.asm.Opcodes.LSTORE) TypedConstraint(org.sonar.java.se.constraint.TypedConstraint) DCMPG(org.objectweb.asm.Opcodes.DCMPG) IFNULL(org.objectweb.asm.Opcodes.IFNULL) FLOAD(org.objectweb.asm.Opcodes.FLOAD) INSTANCEOF(org.objectweb.asm.Opcodes.INSTANCEOF) IALOAD(org.objectweb.asm.Opcodes.IALOAD) DUP2_X2(org.objectweb.asm.Opcodes.DUP2_X2) DUP2_X1(org.objectweb.asm.Opcodes.DUP2_X1) PUTFIELD(org.objectweb.asm.Opcodes.PUTFIELD) IFEQ(org.objectweb.asm.Opcodes.IFEQ) Lists(com.google.common.collect.Lists) INVOKESTATIC(org.objectweb.asm.Opcodes.INVOKESTATIC) ACONST_NULL(org.objectweb.asm.Opcodes.ACONST_NULL) MethodBehavior(org.sonar.java.se.xproc.MethodBehavior) DALOAD(org.objectweb.asm.Opcodes.DALOAD) INEG(org.objectweb.asm.Opcodes.INEG) MONITORENTER(org.objectweb.asm.Opcodes.MONITORENTER) TABLESWITCH(org.objectweb.asm.Opcodes.TABLESWITCH) ICONST_5(org.objectweb.asm.Opcodes.ICONST_5) IMUL(org.objectweb.asm.Opcodes.IMUL) LOR(org.objectweb.asm.Opcodes.LOR) DASTORE(org.objectweb.asm.Opcodes.DASTORE) ICONST_4(org.objectweb.asm.Opcodes.ICONST_4) Opcodes(org.objectweb.asm.Opcodes) ICONST_3(org.objectweb.asm.Opcodes.ICONST_3) ICONST_2(org.objectweb.asm.Opcodes.ICONST_2) IFGE(org.objectweb.asm.Opcodes.IFGE) ICONST_1(org.objectweb.asm.Opcodes.ICONST_1) ICONST_0(org.objectweb.asm.Opcodes.ICONST_0) LADD(org.objectweb.asm.Opcodes.LADD) F2L(org.objectweb.asm.Opcodes.F2L) Printer(org.objectweb.asm.util.Printer) LREM(org.objectweb.asm.Opcodes.LREM) Preconditions(com.google.common.base.Preconditions) INVOKESPECIAL(org.objectweb.asm.Opcodes.INVOKESPECIAL) DNEG(org.objectweb.asm.Opcodes.DNEG) LDIV(org.objectweb.asm.Opcodes.LDIV) LLOAD(org.objectweb.asm.Opcodes.LLOAD) LCMP(org.objectweb.asm.Opcodes.LCMP) IXOR(org.objectweb.asm.Opcodes.IXOR) DSUB(org.objectweb.asm.Opcodes.DSUB) IFLE(org.objectweb.asm.Opcodes.IFLE) Loggers(org.sonar.api.utils.log.Loggers) LASTORE(org.objectweb.asm.Opcodes.LASTORE) FSTORE(org.objectweb.asm.Opcodes.FSTORE) INVOKEVIRTUAL(org.objectweb.asm.Opcodes.INVOKEVIRTUAL) Collectors(java.util.stream.Collectors) GETFIELD(org.objectweb.asm.Opcodes.GETFIELD) FNEG(org.objectweb.asm.Opcodes.FNEG) I2L(org.objectweb.asm.Opcodes.I2L) CASTORE(org.objectweb.asm.Opcodes.CASTORE) Instruction(org.sonar.java.bytecode.cfg.Instruction) GOTO(org.objectweb.asm.Opcodes.GOTO) I2S(org.objectweb.asm.Opcodes.I2S) Constraint(org.sonar.java.se.constraint.Constraint) ARETURN(org.objectweb.asm.Opcodes.ARETURN) IFLT(org.objectweb.asm.Opcodes.IFLT) IUSHR(org.objectweb.asm.Opcodes.IUSHR) Symbols(org.sonar.java.resolve.Symbols) IF_ACMPEQ(org.objectweb.asm.Opcodes.IF_ACMPEQ) LRETURN(org.objectweb.asm.Opcodes.LRETURN) DivisionByZeroCheck(org.sonar.java.se.checks.DivisionByZeroCheck) ConstraintManager(org.sonar.java.se.constraint.ConstraintManager) ImmutableList(com.google.common.collect.ImmutableList) SymbolicValue(org.sonar.java.se.symbolicvalues.SymbolicValue) LinkedList(java.util.LinkedList) BytecodeCFG(org.sonar.java.bytecode.cfg.BytecodeCFG) NOP(org.objectweb.asm.Opcodes.NOP) SquidClassLoader(org.sonar.java.bytecode.loader.SquidClassLoader) MONITOREXIT(org.objectweb.asm.Opcodes.MONITOREXIT) Type(org.sonar.plugins.java.api.semantic.Type) ISUB(org.objectweb.asm.Opcodes.ISUB) ARRAYLENGTH(org.objectweb.asm.Opcodes.ARRAYLENGTH) DUP_X2(org.objectweb.asm.Opcodes.DUP_X2) DUP_X1(org.objectweb.asm.Opcodes.DUP_X1) AASTORE(org.objectweb.asm.Opcodes.AASTORE) SemanticModel(org.sonar.java.resolve.SemanticModel) BALOAD(org.objectweb.asm.Opcodes.BALOAD) PUTSTATIC(org.objectweb.asm.Opcodes.PUTSTATIC) ProgramPoint(org.sonar.java.se.ProgramPoint) CheckForNull(javax.annotation.CheckForNull) LMUL(org.objectweb.asm.Opcodes.LMUL) INVOKEINTERFACE(org.objectweb.asm.Opcodes.INVOKEINTERFACE) BASTORE(org.objectweb.asm.Opcodes.BASTORE) IF_ICMPNE(org.objectweb.asm.Opcodes.IF_ICMPNE) AALOAD(org.objectweb.asm.Opcodes.AALOAD) BooleanConstraint(org.sonar.java.se.constraint.BooleanConstraint) ExceptionUtils(org.sonar.java.se.ExceptionUtils) FCONST_0(org.objectweb.asm.Opcodes.FCONST_0) FCONST_1(org.objectweb.asm.Opcodes.FCONST_1) FCONST_2(org.objectweb.asm.Opcodes.FCONST_2) DCONST_0(org.objectweb.asm.Opcodes.DCONST_0) SIPUSH(org.objectweb.asm.Opcodes.SIPUSH) Set(java.util.Set) IF_ICMPLT(org.objectweb.asm.Opcodes.IF_ICMPLT) DLOAD(org.objectweb.asm.Opcodes.DLOAD) DUP(org.objectweb.asm.Opcodes.DUP) FCMPG(org.objectweb.asm.Opcodes.FCMPG) LAND(org.objectweb.asm.Opcodes.LAND) FCMPL(org.objectweb.asm.Opcodes.FCMPL) LCONST_0(org.objectweb.asm.Opcodes.LCONST_0) SASTORE(org.objectweb.asm.Opcodes.SASTORE) LALOAD(org.objectweb.asm.Opcodes.LALOAD) DCONST_1(org.objectweb.asm.Opcodes.DCONST_1) LCONST_1(org.objectweb.asm.Opcodes.LCONST_1) IOR(org.objectweb.asm.Opcodes.IOR) ObjectConstraint(org.sonar.java.se.constraint.ObjectConstraint) DSTORE(org.objectweb.asm.Opcodes.DSTORE) CALOAD(org.objectweb.asm.Opcodes.CALOAD) FMUL(org.objectweb.asm.Opcodes.FMUL) LONG_OR_DOUBLE(org.sonar.java.bytecode.se.BytecodeEGWalker.StackValueCategoryConstraint.LONG_OR_DOUBLE) I2B(org.objectweb.asm.Opcodes.I2B) IFNE(org.objectweb.asm.Opcodes.IFNE) IREM(org.objectweb.asm.Opcodes.IREM) I2C(org.objectweb.asm.Opcodes.I2C) I2D(org.objectweb.asm.Opcodes.I2D) SWAP(org.objectweb.asm.Opcodes.SWAP) I2F(org.objectweb.asm.Opcodes.I2F) IADD(org.objectweb.asm.Opcodes.IADD) ISTORE(org.objectweb.asm.Opcodes.ISTORE) Pair(org.sonar.java.se.Pair) LOOKUPSWITCH(org.objectweb.asm.Opcodes.LOOKUPSWITCH) IF_ICMPLE(org.objectweb.asm.Opcodes.IF_ICMPLE) INVOKEDYNAMIC(org.objectweb.asm.Opcodes.INVOKEDYNAMIC) LinkedHashSet(java.util.LinkedHashSet) Nullable(javax.annotation.Nullable) Logger(org.sonar.api.utils.log.Logger) IDIV(org.objectweb.asm.Opcodes.IDIV) DREM(org.objectweb.asm.Opcodes.DREM) POP(org.objectweb.asm.Opcodes.POP) SALOAD(org.objectweb.asm.Opcodes.SALOAD) ISHR(org.objectweb.asm.Opcodes.ISHR) NEWARRAY(org.objectweb.asm.Opcodes.NEWARRAY) DADD(org.objectweb.asm.Opcodes.DADD) RelationalSymbolicValue(org.sonar.java.se.symbolicvalues.RelationalSymbolicValue) ICONST_M1(org.objectweb.asm.Opcodes.ICONST_M1) ISHL(org.objectweb.asm.Opcodes.ISHL) BehaviorCache(org.sonar.java.se.xproc.BehaviorCache) LNEG(org.objectweb.asm.Opcodes.LNEG) IRETURN(org.objectweb.asm.Opcodes.IRETURN) DDIV(org.objectweb.asm.Opcodes.DDIV) ALOAD(org.objectweb.asm.Opcodes.ALOAD) FALOAD(org.objectweb.asm.Opcodes.FALOAD) GETSTATIC(org.objectweb.asm.Opcodes.GETSTATIC) LSUB(org.objectweb.asm.Opcodes.LSUB) D2F(org.objectweb.asm.Opcodes.D2F) D2I(org.objectweb.asm.Opcodes.D2I) D2L(org.objectweb.asm.Opcodes.D2L) L2D(org.objectweb.asm.Opcodes.L2D) NEW(org.objectweb.asm.Opcodes.NEW) BytecodeCFGMethodVisitor(org.sonar.java.bytecode.cfg.BytecodeCFGMethodVisitor) MULTIANEWARRAY(org.objectweb.asm.Opcodes.MULTIANEWARRAY) FADD(org.objectweb.asm.Opcodes.FADD) BIPUSH(org.objectweb.asm.Opcodes.BIPUSH) IASTORE(org.objectweb.asm.Opcodes.IASTORE) FREM(org.objectweb.asm.Opcodes.FREM) List(java.util.List) FDIV(org.objectweb.asm.Opcodes.FDIV) DRETURN(org.objectweb.asm.Opcodes.DRETURN) LXOR(org.objectweb.asm.Opcodes.LXOR) FASTORE(org.objectweb.asm.Opcodes.FASTORE) IFNONNULL(org.objectweb.asm.Opcodes.IFNONNULL) FSUB(org.objectweb.asm.Opcodes.FSUB) LUSHR(org.objectweb.asm.Opcodes.LUSHR) IF_ACMPNE(org.objectweb.asm.Opcodes.IF_ACMPNE) ProgramState(org.sonar.java.se.ProgramState) Deque(java.util.Deque) IF_ICMPGT(org.objectweb.asm.Opcodes.IF_ICMPGT) ExplodedGraphWalker(org.sonar.java.se.ExplodedGraphWalker) LDC(org.objectweb.asm.Opcodes.LDC) CHECKCAST(org.objectweb.asm.Opcodes.CHECKCAST) DUP2(org.objectweb.asm.Opcodes.DUP2) ExplodedGraph(org.sonar.java.se.ExplodedGraph) L2F(org.objectweb.asm.Opcodes.L2F) ANEWARRAY(org.objectweb.asm.Opcodes.ANEWARRAY) L2I(org.objectweb.asm.Opcodes.L2I) RETURN(org.objectweb.asm.Opcodes.RETURN) ILOAD(org.objectweb.asm.Opcodes.ILOAD) FRETURN(org.objectweb.asm.Opcodes.FRETURN) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Collections(java.util.Collections) POP2(org.objectweb.asm.Opcodes.POP2) IF_ICMPGE(org.objectweb.asm.Opcodes.IF_ICMPGE) Type(org.sonar.plugins.java.api.semantic.Type) MethodBehavior(org.sonar.java.se.xproc.MethodBehavior) ProgramState(org.sonar.java.se.ProgramState) SymbolicValue(org.sonar.java.se.symbolicvalues.SymbolicValue) RelationalSymbolicValue(org.sonar.java.se.symbolicvalues.RelationalSymbolicValue) TypedConstraint(org.sonar.java.se.constraint.TypedConstraint) Constraint(org.sonar.java.se.constraint.Constraint) ProgramPoint(org.sonar.java.se.ProgramPoint) BooleanConstraint(org.sonar.java.se.constraint.BooleanConstraint) ObjectConstraint(org.sonar.java.se.constraint.ObjectConstraint)

Example 62 with Instruction

use of org.sonar.java.bytecode.cfg.Instruction in project sonar-java by SonarSource.

the class BytecodeEGWalker method executeInstruction.

@VisibleForTesting
void executeInstruction(Instruction instruction) {
    if (!checkerDispatcher.executeCheckPreStatement(instruction)) {
        return;
    }
    ProgramState.Pop pop;
    SymbolicValue sv;
    switch(instruction.opcode) {
        case NOP:
            break;
        case ACONST_NULL:
            programState = programState.stackValue(SymbolicValue.NULL_LITERAL);
            break;
        case ICONST_M1:
        case ICONST_0:
        case ICONST_1:
        case ICONST_2:
        case ICONST_3:
        case ICONST_4:
        case ICONST_5:
        case LCONST_0:
        case LCONST_1:
        case FCONST_0:
        case FCONST_1:
        case FCONST_2:
        case DCONST_0:
        case DCONST_1:
            sv = constraintManager.createSymbolicValue(instruction);
            programState = setDoubleOrLong(sv, instruction.isLongOrDoubleValue());
            programState = programState.stackValue(sv).addConstraint(sv, ObjectConstraint.NOT_NULL);
            if (instruction.opcode == ICONST_1 || instruction.opcode == LCONST_1 || instruction.opcode == FCONST_1 || instruction.opcode == DCONST_1) {
                programState = programState.addConstraint(sv, BooleanConstraint.TRUE);
            }
            if (instruction.opcode == ICONST_0 || instruction.opcode == LCONST_0 || instruction.opcode == FCONST_0 || instruction.opcode == DCONST_0) {
                programState = programState.addConstraint(sv, BooleanConstraint.FALSE).addConstraint(sv, DivisionByZeroCheck.ZeroConstraint.ZERO);
            } else {
                programState = programState.addConstraint(sv, DivisionByZeroCheck.ZeroConstraint.NON_ZERO);
            }
            break;
        case BIPUSH:
        case SIPUSH:
            sv = constraintManager.createSymbolicValue(instruction);
            programState = programState.stackValue(sv).addConstraint(sv, ObjectConstraint.NOT_NULL).addConstraint(sv, DivisionByZeroCheck.ZeroConstraint.NON_ZERO);
            if (instruction.operand == 0) {
                programState = programState.addConstraint(sv, BooleanConstraint.FALSE).addConstraint(sv, DivisionByZeroCheck.ZeroConstraint.ZERO);
            } else if (instruction.operand == 1) {
                programState = programState.addConstraint(sv, BooleanConstraint.TRUE);
            }
            break;
        case LDC:
            sv = constraintManager.createSymbolicValue(instruction);
            programState = programState.stackValue(sv).addConstraint(sv, ObjectConstraint.NOT_NULL);
            programState = setDoubleOrLong(sv, instruction.isLongOrDoubleValue());
            break;
        case ILOAD:
        case LLOAD:
        case FLOAD:
        case DLOAD:
        case ALOAD:
            SymbolicValue value = programState.getValue(instruction.operand);
            Preconditions.checkNotNull(value, "Loading a symbolic value unindexed");
            programState = programState.stackValue(value);
            break;
        case IALOAD:
        case LALOAD:
        case FALOAD:
        case DALOAD:
        case AALOAD:
        case BALOAD:
        case CALOAD:
        case SALOAD:
            sv = constraintManager.createSymbolicValue(instruction);
            programState = programState.unstackValue(2).state.stackValue(sv);
            if (instruction.opcode != AALOAD) {
                programState = programState.addConstraint(sv, ObjectConstraint.NOT_NULL);
            }
            programState = setDoubleOrLong(sv, instruction.isLongOrDoubleValue());
            break;
        case ISTORE:
        case LSTORE:
        case FSTORE:
        case DSTORE:
        case ASTORE:
            pop = popStack(1, instruction.opcode);
            programState = pop.state.put(instruction.operand, pop.values.get(0));
            break;
        case IASTORE:
        case LASTORE:
        case FASTORE:
        case DASTORE:
        case AASTORE:
        case BASTORE:
        case CASTORE:
        case SASTORE:
            programState = programState.unstackValue(3).state;
            break;
        case POP:
            programState = programState.unstackValue(1).state;
            break;
        case POP2:
            sv = programState.peekValue();
            Preconditions.checkNotNull(sv, "POP2 on empty stack");
            pop = isDoubleOrLong(sv) ? popStack(1, instruction.opcode) : popStack(2, instruction.opcode);
            programState = pop.state;
            break;
        case DUP:
            sv = programState.peekValue();
            Preconditions.checkNotNull(sv, "DUP on empty stack");
            programState = programState.stackValue(sv);
            break;
        case DUP_X1:
            pop = popStack(2, instruction.opcode);
            programState = stackValues(pop, 0, 1, 0);
            break;
        case DUP_X2:
            sv = programState.peekValue(1);
            if (isDoubleOrLong(sv)) {
                pop = popStack(2, instruction.opcode);
                programState = stackValues(pop, 0, 1, 0);
            } else {
                pop = popStack(3, instruction.opcode);
                programState = stackValues(pop, 0, 2, 1, 0);
            }
            break;
        case DUP2:
            sv = programState.peekValue();
            Preconditions.checkNotNull(sv, "DUP2 needs at least 1 value on stack");
            if (isDoubleOrLong(sv)) {
                pop = popStack(1, instruction.opcode);
                programState = stackValues(pop, 0, 0);
            } else {
                pop = popStack(2, instruction.opcode);
                programState = stackValues(pop, 1, 0, 1, 0);
            }
            break;
        case DUP2_X1:
            sv = programState.peekValue();
            Preconditions.checkNotNull(sv, "DUP2_X1 needs at least 1 value on stack");
            if (isDoubleOrLong(sv)) {
                pop = popStack(2, instruction.opcode);
                programState = stackValues(pop, 0, 1, 0);
            } else {
                pop = popStack(3, instruction.opcode);
                programState = stackValues(pop, 1, 0, 2, 1, 0);
            }
            break;
        case DUP2_X2:
            if (isDoubleOrLong(programState.peekValue()) && isDoubleOrLong(programState.peekValue(1))) {
                pop = popStack(2, instruction.opcode);
                programState = stackValues(pop, 0, 1, 0);
            } else if (isDoubleOrLong(programState.peekValue(2))) {
                pop = popStack(3, instruction.opcode);
                programState = stackValues(pop, 1, 0, 2, 1, 0);
            } else if (isDoubleOrLong(programState.peekValue())) {
                pop = popStack(3, instruction.opcode);
                programState = stackValues(pop, 0, 2, 1, 0);
            } else {
                pop = popStack(4, instruction.opcode);
                programState = stackValues(pop, 1, 0, 3, 2, 1, 0);
            }
            break;
        case SWAP:
            pop = popStack(2, instruction.opcode);
            programState = pop.state.stackValue(pop.values.get(0)).stackValue(pop.values.get(1));
            break;
        case IADD:
        case LADD:
        case FADD:
        case DADD:
        case ISUB:
        case LSUB:
        case FSUB:
        case DSUB:
        case IMUL:
        case LMUL:
        case FMUL:
        case DMUL:
        case IDIV:
        case LDIV:
        case FDIV:
        case DDIV:
        case IREM:
        case LREM:
        case FREM:
        case DREM:
        case ISHL:
        case LSHL:
        case ISHR:
        case LSHR:
        case IUSHR:
        case LUSHR:
            pop = popStack(2, instruction.opcode);
            sv = constraintManager.createSymbolicValue(instruction);
            programState = pop.state.stackValue(sv).addConstraint(sv, ObjectConstraint.NOT_NULL);
            programState = setDoubleOrLong(sv, instruction.isLongOrDoubleValue());
            break;
        case INEG:
        case LNEG:
        case FNEG:
        case DNEG:
            pop = popStack(1, instruction.opcode);
            sv = constraintManager.createSymbolicValue(instruction);
            programState = pop.state.stackValue(sv).addConstraint(sv, ObjectConstraint.NOT_NULL);
            programState = setDoubleOrLong(sv, instruction.isLongOrDoubleValue());
            break;
        case IAND:
        case LAND:
        case IOR:
        case LOR:
        case IXOR:
        case LXOR:
            pop = popStack(2, instruction.opcode);
            sv = constraintManager.createBinarySymbolicValue(instruction, pop.valuesAndSymbols);
            programState = pop.state.stackValue(sv).addConstraint(sv, ObjectConstraint.NOT_NULL);
            programState = setDoubleOrLong(sv, instruction.isLongOrDoubleValue());
            break;
        case IINC:
            int index = instruction.operand;
            SymbolicValue existing = programState.getValue(index);
            Preconditions.checkNotNull(existing, "Local variable " + index + " not found");
            sv = constraintManager.createSymbolicValue(instruction);
            programState = programState.put(index, sv).addConstraint(sv, ObjectConstraint.NOT_NULL);
            break;
        case I2L:
        case I2D:
        case F2L:
        case F2D:
            sv = programState.peekValue();
            Preconditions.checkNotNull(sv, "%s needs value on stack", instruction);
            programState = setDoubleOrLong(sv, true);
            break;
        case L2I:
        case L2F:
        case D2I:
        case D2F:
            sv = programState.peekValue();
            Preconditions.checkNotNull(sv, "%s needs value on stack", instruction);
            programState = setDoubleOrLong(sv, false);
            break;
        case D2L:
        case I2F:
        case L2D:
        case F2I:
        case I2B:
        case I2C:
        case I2S:
            break;
        case LCMP:
        case FCMPL:
        case FCMPG:
        case DCMPL:
        case DCMPG:
            pop = popStack(2, instruction.opcode);
            sv = constraintManager.createSymbolicValue(instruction);
            programState = pop.state.stackValue(sv).addConstraint(sv, ObjectConstraint.NOT_NULL);
            break;
        case IRETURN:
        case LRETURN:
        case FRETURN:
        case DRETURN:
        case ARETURN:
            programState.storeExitValue();
            programState = programState.unstackValue(1).state;
            break;
        case RETURN:
            // do nothing
            break;
        case GETSTATIC:
            // TODO SONARJAVA-2510 associated symbolic value with symbol
            sv = constraintManager.createSymbolicValue(instruction);
            programState = programState.stackValue(sv);
            programState = setDoubleOrLong(sv, instruction.isLongOrDoubleValue());
            break;
        case PUTSTATIC:
            pop = programState.unstackValue(1);
            programState = pop.state;
            break;
        case GETFIELD:
            pop = popStack(1, instruction.opcode);
            sv = constraintManager.createSymbolicValue(instruction);
            programState = pop.state.stackValue(sv);
            programState = setDoubleOrLong(sv, instruction.isLongOrDoubleValue());
            break;
        case PUTFIELD:
            pop = popStack(2, instruction.opcode);
            programState = pop.state;
            break;
        case INVOKEVIRTUAL:
        case INVOKESPECIAL:
        case INVOKESTATIC:
        case INVOKEINTERFACE:
            if (handleMethodInvocation(instruction)) {
                // when yields are available, do not execute post check on this node
                return;
            }
            break;
        case INVOKEDYNAMIC:
            pop = popStack(instruction.arity(), instruction.opcode);
            Preconditions.checkState(instruction.hasReturnValue(), "Lambda should always evaluate to target functional interface");
            SymbolicValue lambdaTargetInterface = new SymbolicValue();
            programState = pop.state.stackValue(lambdaTargetInterface).addConstraint(lambdaTargetInterface, ObjectConstraint.NOT_NULL);
            break;
        case NEW:
            sv = constraintManager.createSymbolicValue(instruction);
            programState = programState.stackValue(sv).addConstraint(sv, ObjectConstraint.NOT_NULL).addConstraint(sv, new TypedConstraint(instruction.className));
            break;
        case ARRAYLENGTH:
            pop = popStack(1, instruction.opcode);
            sv = constraintManager.createSymbolicValue(instruction);
            programState = pop.state.stackValue(sv);
            break;
        case NEWARRAY:
        case ANEWARRAY:
            pop = popStack(1, instruction.opcode);
            sv = constraintManager.createSymbolicValue(instruction);
            programState = pop.state.stackValue(sv).addConstraint(sv, ObjectConstraint.NOT_NULL);
            break;
        case ATHROW:
            if (!(programState.peekValue() instanceof SymbolicValue.ExceptionalSymbolicValue)) {
                // create exceptional SV if not already on top of the stack (e.g. throw new MyException(); )
                pop = popStack(1, instruction.opcode);
                sv = pop.values.get(0);
                TypedConstraint typedConstraint = programState.getConstraint(sv, TypedConstraint.class);
                Type type = typedConstraint != null ? typedConstraint.getType(semanticModel) : Symbols.unknownType;
                programState = pop.state.stackValue(constraintManager.createExceptionalSymbolicValue(type));
            }
            programState.storeExitValue();
            break;
        case CHECKCAST:
            Preconditions.checkState(programState.peekValue() != null, "CHECKCAST needs 1 value on stack");
            break;
        case INSTANCEOF:
            pop = popStack(1, instruction.opcode);
            SymbolicValue.InstanceOfSymbolicValue instanceOf = new SymbolicValue.InstanceOfSymbolicValue();
            instanceOf.computedFrom(pop.valuesAndSymbols);
            programState = pop.state.stackValue(instanceOf);
            break;
        case MONITORENTER:
        case MONITOREXIT:
            pop = popStack(1, instruction.opcode);
            programState = pop.state;
            break;
        case MULTIANEWARRAY:
            Instruction.MultiANewArrayInsn multiANewArrayInsn = (Instruction.MultiANewArrayInsn) instruction;
            pop = popStack(multiANewArrayInsn.dim, instruction.opcode);
            SymbolicValue arrayRef = new SymbolicValue();
            programState = pop.state.stackValue(arrayRef).addConstraint(arrayRef, ObjectConstraint.NOT_NULL);
            break;
        default:
            throw new IllegalStateException("Instruction not handled. " + instruction);
    }
    checkerDispatcher.executeCheckPostStatement(instruction);
}
Also used : ProgramState(org.sonar.java.se.ProgramState) TypedConstraint(org.sonar.java.se.constraint.TypedConstraint) Instruction(org.sonar.java.bytecode.cfg.Instruction) TypedConstraint(org.sonar.java.se.constraint.TypedConstraint) Constraint(org.sonar.java.se.constraint.Constraint) ProgramPoint(org.sonar.java.se.ProgramPoint) BooleanConstraint(org.sonar.java.se.constraint.BooleanConstraint) ObjectConstraint(org.sonar.java.se.constraint.ObjectConstraint) Type(org.sonar.plugins.java.api.semantic.Type) SymbolicValue(org.sonar.java.se.symbolicvalues.SymbolicValue) RelationalSymbolicValue(org.sonar.java.se.symbolicvalues.RelationalSymbolicValue) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Aggregations

Instruction (org.sonar.java.bytecode.cfg.Instruction)62 ProgramState (org.sonar.java.se.ProgramState)58 Test (org.junit.Test)55 SymbolicValue (org.sonar.java.se.symbolicvalues.SymbolicValue)48 RelationalSymbolicValue (org.sonar.java.se.symbolicvalues.RelationalSymbolicValue)43 BinarySymbolicValue (org.sonar.java.se.symbolicvalues.BinarySymbolicValue)40 ProgramPoint (org.sonar.java.se.ProgramPoint)26 BooleanConstraint (org.sonar.java.se.constraint.BooleanConstraint)23 TypedConstraint (org.sonar.java.se.constraint.TypedConstraint)20 Constraint (org.sonar.java.se.constraint.Constraint)18 ObjectConstraint (org.sonar.java.se.constraint.ObjectConstraint)18 BytecodeCFG (org.sonar.java.bytecode.cfg.BytecodeCFG)6 ZeroConstraint (org.sonar.java.se.checks.DivisionByZeroCheck.ZeroConstraint)5 ConstraintsByDomain (org.sonar.java.se.constraint.ConstraintsByDomain)5 VisibleForTesting (com.google.common.annotations.VisibleForTesting)4 Type (org.sonar.plugins.java.api.semantic.Type)4 BehaviorCache (org.sonar.java.se.xproc.BehaviorCache)3 MethodBehavior (org.sonar.java.se.xproc.MethodBehavior)3 Preconditions (com.google.common.base.Preconditions)2 ImmutableList (com.google.common.collect.ImmutableList)2