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() pop = programState.unstackValue(1); symbolicValueSymbols = ImmutableList.of( new ProgramState.SymbolicValueSymbol(SymbolicValue.NULL_LITERAL, null), pop.valuesAndSymbols.get(0)); ps = pop.state;
private static Set<Flow> flowsForMethodArguments(ExplodedGraph.Node node, MethodInvocationTree mit, int parameterCausingExceptionIndex) { ProgramState programState = node.programState; List<ProgramState.SymbolicValueSymbol> arguments = Lists.reverse(programState.peekValuesAndSymbols(mit.arguments().size())); SymbolicValue parameterCausingExceptionSV = arguments.get(parameterCausingExceptionIndex).symbolicValue(); Set<SymbolicValue> argSymbolicValues = new LinkedHashSet<>(); Set<Symbol> argSymbols = new LinkedHashSet<>(); arguments.stream() .filter(svs -> parameterCausingExceptionSV == svs.symbolicValue() || hasConstraintOtherThanNonNull(svs, programState)) .forEach(svs -> { argSymbolicValues.add(svs.symbolicValue()); Symbol symbol = svs.symbol(); if (symbol != null) { argSymbols.add(symbol); } }); List<Class<? extends Constraint>> domains = domainsFromArguments(programState, argSymbolicValues); return FlowComputation.flow(node, argSymbolicValues, c -> true, c -> false, domains, argSymbols); }
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() pop = programState.unstackValue(1); symbolicValueSymbols = ImmutableList.of( new ProgramState.SymbolicValueSymbol(SymbolicValue.NULL_LITERAL, null), pop.valuesAndSymbols.get(0)); ps = pop.state;
@Override public void visitNewClass(NewClassTree syntaxNode) { if (isOpeningResource(syntaxNode)) { List<ProgramState.SymbolicValueSymbol> arguments = Lists.reverse(programState.peekValuesAndSymbols(syntaxNode.arguments().size())); Iterator<ProgramState.SymbolicValueSymbol> iterator = arguments.iterator(); for (ExpressionTree argumentTree : syntaxNode.arguments()) { if (!iterator.hasNext()) { throw new IllegalStateException("Mismatch between declared constructor arguments and argument values!"); } ProgramState.SymbolicValueSymbol argument = iterator.next(); if (shouldWrapArgument(argument, argumentTree)) { constraintManager.setValueFactory(new WrappedValueFactory(argument.symbolicValue())); break; } if (shouldCloseArgument(argument)){ closeResource(argument.symbolicValue()); } } } else { closeArguments(syntaxNode.arguments()); } }
@Override public void visitNewClass(NewClassTree syntaxNode) { if (isOpeningResource(syntaxNode)) { List<ProgramState.SymbolicValueSymbol> arguments = Lists.reverse(programState.peekValuesAndSymbols(syntaxNode.arguments().size())); Iterator<ProgramState.SymbolicValueSymbol> iterator = arguments.iterator(); for (ExpressionTree argumentTree : syntaxNode.arguments()) { if (!iterator.hasNext()) { throw new IllegalStateException("Mismatch between declared constructor arguments and argument values!"); } ProgramState.SymbolicValueSymbol argument = iterator.next(); if (shouldWrapArgument(argument, argumentTree)) { constraintManager.setValueFactory(new WrappedValueFactory(argument.symbolicValue())); break; } if (shouldCloseArgument(argument)){ closeResource(argument.symbolicValue()); } } } else { closeArguments(syntaxNode.arguments()); } }
@Override public void visitAssignmentExpression(AssignmentExpressionTree tree) { SymbolicValue var; SymbolicValue expr; Symbol symbol; if (ExpressionUtils.isSimpleAssignment(tree)) { symbol = ExpressionUtils.extractIdentifier(tree).symbol(); var = programState.getValue(symbol); expr = programState.peekValue(); } else { ProgramState.Pop unstackValue = programState.unstackValue(2); var = unstackValue.values.get(1); expr = unstackValue.values.get(0); symbol = unstackValue.valuesAndSymbols.get(0).symbol(); } checkExpression(tree, var, expr, symbol); }
private void handleAssignment(CheckerContext context, AssignmentExpressionTree assignmentExpressionTree) { SymbolicValueSymbol assignedVariable = context.getState().peekValueSymbol(); Symbol assignedSymbol = assignedVariable.symbol(); if (assignedSymbol == null // Rule S3959 returns the same SV after each intermediate operations, // meaning that 'stream = stream.map(...);' would be detected as redundant assignment if not explicitly excluded || STREAM_TYPES.stream().anyMatch(assignedSymbol.type()::is)) { return; } ExplodedGraph.Node node = context.getNode(); ProgramState previousState = node.programState; SymbolicValue oldValue = previousState.getValue(assignedSymbol); SymbolicValue newValue = assignedVariable.symbolicValue(); Symbol fromSymbol = previousState.peekValueSymbol().symbol(); assignmentsByMethod.peek().put(assignmentExpressionTree, new AssignmentDataHolder(assignedSymbol, oldValue, newValue, fromSymbol, node)); }
private static Set<Flow> flowsForMethodArguments(ExplodedGraph.Node node, MethodInvocationTree mit, int parameterCausingExceptionIndex) { ProgramState programState = node.programState; List<ProgramState.SymbolicValueSymbol> arguments = Lists.reverse(programState.peekValuesAndSymbols(mit.arguments().size())); SymbolicValue parameterCausingExceptionSV = arguments.get(parameterCausingExceptionIndex).symbolicValue(); Set<SymbolicValue> argSymbolicValues = new LinkedHashSet<>(); Set<Symbol> argSymbols = new LinkedHashSet<>(); arguments.stream() .filter(svs -> parameterCausingExceptionSV == svs.symbolicValue() || hasConstraintOtherThanNonNull(svs, programState)) .forEach(svs -> { argSymbolicValues.add(svs.symbolicValue()); Symbol symbol = svs.symbol(); if (symbol != null) { argSymbols.add(symbol); } }); List<Class<? extends Constraint>> domains = domainsFromArguments(programState, argSymbolicValues); return FlowComputation.flow(node, argSymbolicValues, c -> true, c -> false, domains, argSymbols); }
@Override public void visitBinaryExpression(BinaryExpressionTree tree) { switch (tree.kind()) { case MULTIPLY: case PLUS: case MINUS: case DIVIDE: case REMAINDER: ProgramState.Pop unstackValue = programState.unstackValue(2); checkExpression(tree, unstackValue.values.get(1), unstackValue.values.get(0), unstackValue.valuesAndSymbols.get(0).symbol()); break; default: // do nothing } }
@Override public void visitAssignmentExpression(AssignmentExpressionTree tree) { SymbolicValue var; SymbolicValue expr; Symbol symbol; if (ExpressionUtils.isSimpleAssignment(tree)) { symbol = ExpressionUtils.extractIdentifier(tree).symbol(); var = programState.getValue(symbol); expr = programState.peekValue(); } else { ProgramState.Pop unstackValue = programState.unstackValue(2); var = unstackValue.values.get(1); expr = unstackValue.values.get(0); symbol = unstackValue.valuesAndSymbols.get(0).symbol(); } checkExpression(tree, var, expr, symbol); }
private void handleAssignment(CheckerContext context, AssignmentExpressionTree assignmentExpressionTree) { SymbolicValueSymbol assignedVariable = context.getState().peekValueSymbol(); Symbol assignedSymbol = assignedVariable.symbol(); if (assignedSymbol == null // Rule S3959 returns the same SV after each intermediate operations, // meaning that 'stream = stream.map(...);' would be detected as redundant assignment if not explicitly excluded || STREAM_TYPES.stream().anyMatch(assignedSymbol.type()::is)) { return; } ExplodedGraph.Node node = context.getNode(); ProgramState previousState = node.programState; SymbolicValue oldValue = previousState.getValue(assignedSymbol); SymbolicValue newValue = assignedVariable.symbolicValue(); Symbol fromSymbol = previousState.peekValueSymbol().symbol(); assignmentsByMethod.peek().put(assignmentExpressionTree, new AssignmentDataHolder(assignedSymbol, oldValue, newValue, fromSymbol, node)); }
public ProgramState stackValue(SymbolicValue sv) { return new ProgramState(this, stack.push(new SymbolicValueSymbol(sv, null))); }
public ProgramState stackValue(SymbolicValue sv, @Nullable Symbol symbol) { return new ProgramState(this, stack.push(new SymbolicValueSymbol(sv, symbol))); }
public ProgramState stackValue(SymbolicValue sv) { return new ProgramState(this, stack.push(new SymbolicValueSymbol(sv, null))); }
@Override public void visitBinaryExpression(BinaryExpressionTree tree) { switch (tree.kind()) { case MULTIPLY: case PLUS: case MINUS: case DIVIDE: case REMAINDER: ProgramState.Pop unstackValue = programState.unstackValue(2); checkExpression(tree, unstackValue.values.get(1), unstackValue.values.get(0), unstackValue.valuesAndSymbols.get(0).symbol()); break; default: // do nothing } }
private boolean shouldCloseArgument(ProgramState.SymbolicValueSymbol argument) { ResourceConstraint argConstraint = programState.getConstraint(argument.symbolicValue(), ResourceConstraint.class); return argConstraint == OPEN; }
private boolean shouldCloseArgument(ProgramState.SymbolicValueSymbol argument) { ResourceConstraint argConstraint = programState.getConstraint(argument.symbolicValue(), ResourceConstraint.class); return argConstraint == OPEN; }
private static boolean hasConstraintOtherThanNonNull(ProgramState.SymbolicValueSymbol svs, ProgramState ps) { SymbolicValue sv = svs.symbolicValue(); ConstraintsByDomain constraints = ps.getConstraints(sv); return constraints != null && !hasOnlyNonNullConstraint(constraints); }
public ProgramState stackValue(SymbolicValue sv, @Nullable Symbol symbol) { return new ProgramState(this, stack.push(new SymbolicValueSymbol(sv, symbol))); }
private Set<Symbol> getReturnSymbolAsTrackedSymbols(List<Integer> parameterIndices) { if (parameterIndices.contains(-1) && node.programState.peekValue() == node.programState.exitValue()) { Symbol symbol = node.programState.peekValueSymbol().symbol(); if (symbol != null) { return Collections.singleton(symbol); } } return Collections.emptySet(); }