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();
}
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") } });
}
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);
}
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);
}
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);
}
Aggregations