use of org.sonar.java.se.ProgramState in project sonar-java by SonarSource.
the class BytecodeEGWalker method enqueue.
void enqueue(ProgramPoint pp, ProgramState programState) {
int nbOfExecution = programState.numberOfTimeVisited(pp);
if (nbOfExecution > MAX_EXEC_PROGRAM_POINT) {
return;
}
ProgramState ps = programState.visitedPoint(pp, nbOfExecution + 1);
ExplodedGraph.Node cachedNode = explodedGraph.node(pp, ps);
cachedNode.addParent(node, null);
if (cachedNode.isNew()) {
workList.addFirst(cachedNode);
}
}
use of org.sonar.java.se.ProgramState in project sonar-java by SonarSource.
the class BytecodeEGWalker method branchingState.
@VisibleForTesting
ProgramState branchingState(Instruction terminator, ProgramState programState) {
ProgramState.Pop pop;
ProgramState ps;
List<ProgramState.SymbolicValueSymbol> symbolicValueSymbols;
switch(terminator.opcode) {
case IFEQ:
case IFNE:
case IFLT:
case IFGE:
case IFGT:
case IFLE:
pop = programState.unstackValue(1);
SymbolicValue svZero = new SymbolicValue();
symbolicValueSymbols = ImmutableList.of(new ProgramState.SymbolicValueSymbol(svZero, null), pop.valuesAndSymbols.get(0));
List<ProgramState> programStates = svZero.setConstraint(pop.state, DivisionByZeroCheck.ZeroConstraint.ZERO).stream().flatMap(s -> svZero.setConstraint(s, BooleanConstraint.FALSE).stream()).collect(Collectors.toList());
Preconditions.checkState(programStates.size() == 1);
ps = programStates.get(0);
break;
case IF_ICMPEQ:
case IF_ICMPNE:
case IF_ICMPLT:
case IF_ICMPGE:
case IF_ICMPGT:
case IF_ICMPLE:
case IF_ACMPEQ:
case IF_ACMPNE:
pop = programState.unstackValue(2);
symbolicValueSymbols = pop.valuesAndSymbols;
ps = pop.state;
break;
case IFNULL:
case IFNONNULL:
pop = programState.unstackValue(1);
symbolicValueSymbols = ImmutableList.of(new ProgramState.SymbolicValueSymbol(SymbolicValue.NULL_LITERAL, null), pop.valuesAndSymbols.get(0));
ps = pop.state;
break;
default:
throw new IllegalStateException("Unexpected terminator " + terminator);
}
return ps.stackValue(constraintManager.createBinarySymbolicValue(terminator, symbolicValueSymbols));
}
use of org.sonar.java.se.ProgramState 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;
}
use of org.sonar.java.se.ProgramState 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.ProgramState in project sonar-java by SonarSource.
the class BytecodeEGWalker method enqueueExceptionHandlers.
private void enqueueExceptionHandlers(Type exceptionType, ProgramState ps) {
List<BytecodeCFG.Block> blocksCatchingException = programPosition.block.successors().stream().map(b -> (BytecodeCFG.Block) b).filter(BytecodeCFG.Block::isCatchBlock).filter(b -> isExceptionHandledByBlock(exceptionType, b)).collect(Collectors.toList());
if (!blocksCatchingException.isEmpty()) {
blocksCatchingException.forEach(b -> enqueue(new ProgramPoint(b), ps));
if (isCatchExhaustive(exceptionType, blocksCatchingException)) {
return;
}
}
// exception was not handled or was handled only partially, enqueue exit block with exceptional SV
Preconditions.checkState(ps.peekValue() instanceof SymbolicValue.ExceptionalSymbolicValue, "Exception shall be on top of the stack");
ps.storeExitValue();
enqueue(new ProgramPoint(exitBlock), ps);
}
Aggregations