Search in sources :

Example 1 with TypedConstraint

use of org.sonar.java.se.constraint.TypedConstraint in project sonar-java by SonarSource.

the class BytecodeEGWalkerExecuteTest method method_returning_new_should_have_not_null_result.

@Test
public void method_returning_new_should_have_not_null_result() {
    MethodBehavior mb = walker.getMethodBehavior(BytecodeEGWalkerExecuteTest.class.getCanonicalName() + "#newObject()Ljava/lang/Object;", squidClassLoader);
    List<MethodYield> yields = mb.yields();
    assertThat(yields).hasSize(1);
    MethodYield yield = yields.get(0);
    assertThat(yield).isInstanceOf(HappyPathYield.class);
    ConstraintsByDomain resultConstraint = ((HappyPathYield) yield).resultConstraint();
    assertThat(resultConstraint).isNotNull();
    assertThat(resultConstraint.get(ObjectConstraint.class)).isEqualTo(ObjectConstraint.NOT_NULL);
    TypedConstraint typeConstraint = (TypedConstraint) resultConstraint.get(TypedConstraint.class);
    assertThat(typeConstraint.type.equals("java.lang.String")).isTrue();
}
Also used : ConstraintsByDomain(org.sonar.java.se.constraint.ConstraintsByDomain) HappyPathYield(org.sonar.java.se.xproc.HappyPathYield) MethodYield(org.sonar.java.se.xproc.MethodYield) MethodBehavior(org.sonar.java.se.xproc.MethodBehavior) TypedConstraint(org.sonar.java.se.constraint.TypedConstraint) Test(org.junit.Test)

Example 2 with TypedConstraint

use of org.sonar.java.se.constraint.TypedConstraint in project sonar-java by SonarSource.

the class BytecodeEGWalkerExecuteTest method test_new.

@Test
public void test_new() throws Exception {
    ProgramState programState = execute(new Instruction(Opcodes.NEW, "java.lang.Object"));
    assertStack(programState, new Constraint[][] { { ObjectConstraint.NOT_NULL, new TypedConstraint("java.lang.Object") } });
}
Also used : ProgramState(org.sonar.java.se.ProgramState) Instruction(org.sonar.java.bytecode.cfg.Instruction) TypedConstraint(org.sonar.java.se.constraint.TypedConstraint) Test(org.junit.Test)

Example 3 with TypedConstraint

use of org.sonar.java.se.constraint.TypedConstraint in project sonar-java by SonarSource.

the class BytecodeEGWalkerExecuteTest method test_athrow.

@Test
public void test_athrow() throws Exception {
    SymbolicValue sv = new SymbolicValue();
    Type exceptionType = semanticModel.getClassType("java.lang.RuntimeException");
    ProgramState initialState = ProgramState.EMPTY_STATE.stackValue(sv).addConstraint(sv, new TypedConstraint("java.lang.RuntimeException"));
    ProgramState programState = execute(new Instruction(Opcodes.ATHROW), initialState);
    SymbolicValue exception = programState.peekValue();
    assertThat(exception).isInstanceOf(SymbolicValue.ExceptionalSymbolicValue.class);
    assertThat(((SymbolicValue.ExceptionalSymbolicValue) exception).exceptionType()).isEqualTo(exceptionType);
    assertThat(programState.exitValue()).isEqualTo(exception);
}
Also used : Type(org.sonar.plugins.java.api.semantic.Type) ProgramState(org.sonar.java.se.ProgramState) TypedConstraint(org.sonar.java.se.constraint.TypedConstraint) Instruction(org.sonar.java.bytecode.cfg.Instruction) BinarySymbolicValue(org.sonar.java.se.symbolicvalues.BinarySymbolicValue) SymbolicValue(org.sonar.java.se.symbolicvalues.SymbolicValue) RelationalSymbolicValue(org.sonar.java.se.symbolicvalues.RelationalSymbolicValue) Test(org.junit.Test)

Example 4 with TypedConstraint

use of org.sonar.java.se.constraint.TypedConstraint in project sonar-java by SonarSource.

the class BytecodeEGWalker method startingStates.

@VisibleForTesting
Iterable<ProgramState> startingStates(String signature, ProgramState currentState, boolean isStaticMethod) {
    // TODO : deal with parameter annotations, equals methods etc.
    int parameterIdx = 0;
    ProgramState state = currentState;
    if (!isStaticMethod) {
        // Add a sv for "this"
        SymbolicValue thisSV = constraintManager.createSymbolicValue((Instruction) null);
        state = currentState.addConstraint(thisSV, ObjectConstraint.NOT_NULL).addConstraint(thisSV, new TypedConstraint(signature.substring(0, signature.indexOf('#')))).put(0, thisSV);
        parameterIdx = 1;
    }
    org.objectweb.asm.Type[] argumentTypes = org.objectweb.asm.Type.getArgumentTypes(signature.substring(signature.indexOf('(')));
    for (org.objectweb.asm.Type argumentType : argumentTypes) {
        SymbolicValue sv = constraintManager.createSymbolicValue((Instruction) null);
        methodBehavior.addParameter(sv);
        state = state.put(parameterIdx, sv);
        state = setDoubleOrLong(state, sv, argumentType.getSize() == 2);
        parameterIdx += argumentType.getSize();
    }
    return Collections.singletonList(state);
}
Also used : Type(org.sonar.plugins.java.api.semantic.Type) ProgramState(org.sonar.java.se.ProgramState) TypedConstraint(org.sonar.java.se.constraint.TypedConstraint) 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) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 5 with TypedConstraint

use of org.sonar.java.se.constraint.TypedConstraint 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

TypedConstraint (org.sonar.java.se.constraint.TypedConstraint)5 ProgramState (org.sonar.java.se.ProgramState)4 Test (org.junit.Test)3 Instruction (org.sonar.java.bytecode.cfg.Instruction)3 RelationalSymbolicValue (org.sonar.java.se.symbolicvalues.RelationalSymbolicValue)3 SymbolicValue (org.sonar.java.se.symbolicvalues.SymbolicValue)3 Type (org.sonar.plugins.java.api.semantic.Type)3 VisibleForTesting (com.google.common.annotations.VisibleForTesting)2 ProgramPoint (org.sonar.java.se.ProgramPoint)2 BooleanConstraint (org.sonar.java.se.constraint.BooleanConstraint)2 Constraint (org.sonar.java.se.constraint.Constraint)2 ObjectConstraint (org.sonar.java.se.constraint.ObjectConstraint)2 ConstraintsByDomain (org.sonar.java.se.constraint.ConstraintsByDomain)1 BinarySymbolicValue (org.sonar.java.se.symbolicvalues.BinarySymbolicValue)1 HappyPathYield (org.sonar.java.se.xproc.HappyPathYield)1 MethodBehavior (org.sonar.java.se.xproc.MethodBehavior)1 MethodYield (org.sonar.java.se.xproc.MethodYield)1