예제 #1
0
    @Override
    public ARGPath getNextPathForInterpolation() {
      ARGState current = sources.remove(0);

      assert current.isTarget() : "current element is not a target";

      ARGPathBuilder errorPathBuilder = ARGPath.reverseBuilder();

      errorPathBuilder.add(
          current, FluentIterable.from(AbstractStates.getOutgoingEdges(current)).first().orNull());

      while (predecessorRelation.get(current) != null) {

        ARGState parent = predecessorRelation.get(current);

        if (stateHasFalseInterpolant(parent)) {
          logger.log(
              Level.FINEST,
              "interpolant on path, namely for state ",
              parent.getStateId(),
              " is already false, so return empty path");
          return EMPTY_PATH;
        }

        if (predecessorRelation.get(parent) != null) {
          errorPathBuilder.add(parent, parent.getEdgeToChild(current));
        }

        current = parent;
      }

      return errorPathBuilder.build(current);
    }
    private void refineRelevantPredicatesComputer(List<ARGState> pPath, ARGReachedSet pReached) {
      UnmodifiableReachedSet reached = pReached.asReachedSet();
      Precision oldPrecision = reached.getPrecision(reached.getLastState());
      PredicatePrecision oldPredicatePrecision =
          Precisions.extractPrecisionByType(oldPrecision, PredicatePrecision.class);

      BlockPartitioning partitioning = predicateCpa.getPartitioning();
      Deque<Block> openBlocks = new ArrayDeque<>();
      openBlocks.push(partitioning.getMainBlock());
      for (ARGState pathElement : pPath) {
        CFANode currentNode = AbstractStates.extractLocation(pathElement);
        Integer currentNodeInstance =
            getPredicateState(pathElement).getAbstractionLocationsOnPath().get(currentNode);
        if (partitioning.isCallNode(currentNode)) {
          openBlocks.push(partitioning.getBlockForCallNode(currentNode));
        }

        Collection<AbstractionPredicate> localPreds =
            oldPredicatePrecision.getPredicates(currentNode, currentNodeInstance);
        for (Block block : openBlocks) {
          for (AbstractionPredicate pred : localPreds) {
            relevantPredicatesComputer.considerPredicateAsRelevant(block, pred);
          }
        }

        while (openBlocks.peek().isReturnNode(currentNode)) {
          openBlocks.pop();
        }
      }
    }
  boolean areAbstractSuccessors(
      AbstractState pElement,
      CFAEdge pCfaEdge,
      Collection<? extends AbstractState> pSuccessors,
      ProofChecker wrappedProofChecker)
      throws CPATransferException, InterruptedException {
    ARGState element = (ARGState) pElement;

    assert Iterables.elementsEqual(element.getChildren(), pSuccessors);

    AbstractState wrappedState = element.getWrappedState();
    Multimap<CFAEdge, AbstractState> wrappedSuccessors = HashMultimap.create();
    for (AbstractState absElement : pSuccessors) {
      ARGState successorElem = (ARGState) absElement;
      wrappedSuccessors.put(element.getEdgeToChild(successorElem), successorElem.getWrappedState());
    }

    if (pCfaEdge != null) {
      return wrappedProofChecker.areAbstractSuccessors(
          wrappedState, pCfaEdge, wrappedSuccessors.get(pCfaEdge));
    }

    CFANode loc = AbstractStates.extractLocation(element);
    for (CFAEdge edge : leavingEdges(loc)) {
      if (!wrappedProofChecker.areAbstractSuccessors(
          wrappedState, edge, wrappedSuccessors.get(edge))) {
        return false;
      }
    }
    return true;
  }
  /**
   * This method chooses a new refinement root, in a bottom-up fashion along the error path. It
   * either picks the next state on the path sharing the same CFA location, or the (only) child of
   * the ARG root, what ever comes first.
   *
   * @param currentRoot the current refinement root
   * @return the relocated refinement root
   */
  private ARGState relocateRepeatedRefinementRoot(final ARGState currentRoot) {
    repeatedRefinements.inc();
    int currentRootNumber = AbstractStates.extractLocation(currentRoot).getNodeNumber();

    ARGPath path = ARGUtils.getOnePathTo(currentRoot);
    for (ARGState currentState : path.asStatesList().reverse()) {
      // skip identity, because a new root has to be found
      if (currentState == currentRoot) {
        continue;
      }

      if (currentRootNumber == AbstractStates.extractLocation(currentState).getNodeNumber()) {
        return currentState;
      }
    }

    return Iterables.getOnlyElement(path.getFirstState().getChildren());
  }
예제 #5
0
  /**
   * This method exports the current representation in dot format to the given file.
   *
   * @param file file the file to write to
   */
  public void exportToDot(PathTemplate file, int refinementCounter) {
    StringBuilder result = new StringBuilder().append("digraph tree {" + "\n");
    for (Map.Entry<ARGState, ARGState> current : successorRelation.entries()) {
      if (interpolants.containsKey(current.getKey())) {
        StringBuilder sb = new StringBuilder();

        sb.append("itp is " + interpolants.get(current.getKey()));

        result.append(
            current.getKey().getStateId()
                + " [label=\""
                + (current.getKey().getStateId()
                    + " / "
                    + AbstractStates.extractLocation(current.getKey()))
                + " has itp "
                + (sb.toString())
                + "\"]"
                + "\n");
        result.append(
            current.getKey().getStateId()
                + " -> "
                + current.getValue().getStateId()
                + "\n"); // + " [label=\"" +
                         // current.getKey().getEdgeToChild(current.getValue()).getRawStatement().replace("\n", "") + "\"]\n");

      } else {
        result.append(
            current.getKey().getStateId()
                + " [label=\""
                + current.getKey().getStateId()
                + " has itp NA\"]"
                + "\n");
        result.append(
            current.getKey().getStateId()
                + " -> "
                + current.getValue().getStateId()
                + "\n"); // + " [label=\"" +
                         // current.getKey().getEdgeToChild(current.getValue()).getRawStatement().replace("\n", "") + "\"]\n");
      }

      if (current.getValue().isTarget()) {
        result.append(
            current.getValue().getStateId() + " [style=filled, fillcolor=\"red\"]" + "\n");
      }

      assert (!current.getKey().isTarget());
    }
    result.append("}");

    try {
      MoreFiles.writeFile(
          file.getPath(refinementCounter, interpolationCounter), Charset.defaultCharset(), result);
    } catch (IOException e) {
      logger.logUserException(Level.WARNING, e, "Could not write interpolation tree to file");
    }
  }
예제 #6
0
  /**
   * This method extracts the precision increment for the given refinement root. It does so by
   * collection all non-trivial interpolants in the subtree of the given refinement root.
   *
   * @return the precision increment for the given refinement root
   */
  public Multimap<CFANode, MemoryLocation> extractPrecisionIncrement(ARGState pRefinementRoot) {
    Multimap<CFANode, MemoryLocation> increment = HashMultimap.create();

    Deque<ARGState> todo =
        new ArrayDeque<>(Collections.singleton(predecessorRelation.get(pRefinementRoot)));

    while (!todo.isEmpty()) {
      final ARGState currentState = todo.removeFirst();

      if (stateHasNonTrivialInterpolant(currentState) && !currentState.isTarget()) {
        I itp = interpolants.get(currentState);
        for (MemoryLocation memoryLocation : itp.getMemoryLocations()) {
          increment.put(AbstractStates.extractLocation(currentState), memoryLocation);
        }
      }

      if (!stateHasFalseInterpolant(currentState)) {
        todo.addAll(successorRelation.get(currentState));
      }
    }

    return increment;
  }
 private boolean noConcreteSuccessorExist(
     final ARGState pPredecessor,
     final CFAEdge pSuccEdge,
     HistoryForwardingReachedSet pForwaredReachedSet) {
   // check if analysis stopped exploration due e.g. time limit
   for (ReachedSet reached : pForwaredReachedSet.getAllReachedSetsUsedAsDelegates()) {
     if (reached.getWaitlist().contains(pPredecessor)) {
       return false;
     }
   }
   // check if analysis stopped exploration due to true state in automaton --> concrete successors
   // may exist
   for (AbstractState state : AbstractStates.asIterable(pPredecessor)) {
     if (state instanceof AutomatonState
         && ((AutomatonState) state).getOwningAutomatonName().equals("AssumptionAutomaton")) {
       if (AutomatonStateARGCombiningHelper.endsInAssumptionTrueState(
           (AutomatonState) state, pSuccEdge)) {
         return false;
       }
     }
   }
   return true;
 }
  @Override
  public AlgorithmStatus run(ReachedSet pReached) throws CPAException, InterruptedException {
    checkArgument(
        pReached instanceof ForwardingReachedSet, "RestartAlgorithm needs ForwardingReachedSet");
    ForwardingReachedSet reached = (ForwardingReachedSet) pReached;

    CFANode mainFunction = AbstractStates.extractLocation(pReached.getFirstState());
    assert mainFunction != null : "Location information needed";

    AlgorithmStatus status = AlgorithmStatus.UNSOUND_AND_PRECISE;

    try {
      ReachedSetFactory reachedSetFactory = new ReachedSetFactory(globalConfig);

      // predicate analysis
      logger.log(Level.FINE, "Creating CPA for PredicateAnalysis");
      Configuration singleConfig1 = getConfigFromFile(configFiles.get(0));
      ConfigurableProgramAnalysis cpa1 = getCPA(reachedSetFactory, singleConfig1);
      Algorithm algorithm1 = getAlgorithm(shutdownNotifier, singleConfig1, logger, cpa1);
      ReachedSet reached1 =
          createInitialReachedSetForRestart(cpa1, mainFunction, singleConfig1, logger);

      reached.setDelegate(reached1);

      stats.noOfAlgorithmsUsed++;
      stats.totalTime.start();

      status = run0(reached1, algorithm1);

      // stats.printIntermediateStatistics(System.out, Result.UNKNOWN, reached); // disabled,
      // because table-generator can not distinguish 1st and 2nd statistics.
      stats.resetSubStatistics();

      // predicate bit-precise analysis
      logger.log(Level.FINE, "Creating CPA for PredicateAnalysis-Bitprecise");
      Configuration singleConfig2 = getConfigFromFile(configFiles.get(1));
      ConfigurableProgramAnalysis cpa2 = getCPA(reachedSetFactory, singleConfig2);

      {
        // this is the important step: re-use the reached-set
        ARGReplayCPA argReplay = CPAs.retrieveCPA(cpa2, ARGReplayCPA.class);
        checkNotNull(argReplay, "ARGReplay-CPA is needed for second analysis");
        argReplay.setARGAndCPA(reached1, cpa1);
      }

      Algorithm algorithm2 = getAlgorithm(shutdownNotifier, singleConfig2, logger, cpa2);
      ReachedSet reached2 =
          createInitialReachedSetForRestart(cpa2, mainFunction, singleConfig2, logger);

      reached.setDelegate(reached2);

      stats.noOfAlgorithmsUsed++;
      stats.totalTime.start();

      status = run0(reached2, algorithm2);

      stats.printIntermediateStatistics(System.out, Result.UNKNOWN, reached);
      stats.resetSubStatistics();

    } catch (InvalidConfigurationException e) {
      logger.logUserException(
          Level.WARNING, e, "Exiting analysis because the configuration file is invalid");
    } catch (IOException e) {
      logger.logUserException(
          Level.WARNING, e, "Exiting analysis because the configuration file could not be read");
    } finally {
      // TODO close CPAs and algorithms
    }

    return status;
  }
  private boolean combineARGs(
      List<ARGState> roots,
      ForwardingReachedSet pReceivedReachedSet,
      HistoryForwardingReachedSet pForwaredReachedSet)
      throws InterruptedException, CPAException {
    Pair<Map<String, Integer>, List<AbstractState>> initStates =
        identifyCompositeStateTypesAndTheirInitialInstances(roots);

    Map<String, Integer> stateToPos = initStates.getFirst();
    List<AbstractState> initialStates = initStates.getSecond();

    try {
      pReceivedReachedSet.setDelegate(new ReachedSetFactory(config, logger).create());
    } catch (InvalidConfigurationException e) {
      logger.log(Level.SEVERE, "Creating reached set which should contain combined ARG fails.");
      return false;
    }

    shutdown.shutdownIfNecessary();

    // combined root
    ARGState combinedRoot = new ARGState(new CompositeState(initialStates), null);

    CFANode locPred;
    ARGState composedState, composedSuccessor;
    Collection<ARGState> components;

    List<List<ARGState>> successorsForEdge = new ArrayList<>(initialStates.size());
    EdgeSuccessor edgeSuccessorIdentifier = new EdgeSuccessor();

    Map<Pair<List<AbstractState>, List<ARGState>>, ARGState> constructedCombinedStates =
        Maps.newHashMap();
    Deque<Pair<List<ARGState>, ARGState>> toVisit = new ArrayDeque<>();
    toVisit.add(Pair.of(roots, combinedRoot));

    // traverse through ARGs and construct combined ARG
    // assume that states in initial states are most general, represent top state (except for
    // automaton CPAs)
    while (!toVisit.isEmpty()) {
      shutdown.shutdownIfNecessary();

      components = toVisit.peek().getFirst();
      composedState = toVisit.poll().getSecond();

      // add composed state to reached set
      pReceivedReachedSet.add(composedState, SingletonPrecision.getInstance());
      pReceivedReachedSet.removeOnlyFromWaitlist(composedState);

      // identify possible successor edges
      locPred = AbstractStates.extractLocation(composedState);
      nextEdge:
      for (CFAEdge succEdge : CFAUtils.allLeavingEdges(locPred)) {
        shutdown.shutdownIfNecessary();

        successorsForEdge.clear();
        edgeSuccessorIdentifier.setCFAEdge(succEdge);

        for (ARGState component : components) {
          // get the successors of ARG state for this edge succEdge
          edgeSuccessorIdentifier.setPredecessor(component);
          successorsForEdge.add(
              Lists.newArrayList(
                  Iterables.filter(component.getChildren(), edgeSuccessorIdentifier)));
          // check if stopped because no concrete successors exists, then do not
          if (successorsForEdge.get(successorsForEdge.size() - 1).isEmpty()
              && noConcreteSuccessorExist(component, succEdge, pForwaredReachedSet)) {
            continue nextEdge;
          }
        }

        // construct successors for each identified combination
        for (Pair<List<AbstractState>, List<ARGState>> combinedSuccessor :
            computeCartesianProduct(successorsForEdge, stateToPos, initialStates)) {
          if (constructedCombinedStates.containsKey(combinedSuccessor)) {
            // handle coverage
            constructedCombinedStates.get(combinedSuccessor).addParent(composedState);
          } else {
            // construct and register composed successor
            composedSuccessor =
                new ARGState(new CompositeState(combinedSuccessor.getFirst()), composedState);
            constructedCombinedStates.put(combinedSuccessor, composedSuccessor);

            // add successor for further exploration
            toVisit.add(Pair.of(combinedSuccessor.getSecond(), composedSuccessor));
          }
        }
      }
    }
    return true;
  }
  @Override
  public AlgorithmStatus run(ReachedSet pReachedSet)
      throws CPAException, InterruptedException, CPAEnabledAnalysisPropertyViolationException {
    checkArgument(
        pReachedSet instanceof ForwardingReachedSet,
        "PartialARGsCombiner needs ForwardingReachedSet");

    HistoryForwardingReachedSet reached = new HistoryForwardingReachedSet(pReachedSet);

    logger.log(Level.INFO, "Start inner algorithm to analyze program(s)");
    AlgorithmStatus status = AlgorithmStatus.UNSOUND_AND_PRECISE;

    stats.analysisTime.start();
    try {
      status = restartAlgorithm.run(reached);
    } finally {
      stats.analysisTime.stop();
    }

    if (status.isSound()) {
      shutdown.shutdownIfNecessary();

      logger.log(Level.INFO, "Program(s) soundly analyzed, start combining ARGs.");

      stats.argCombineTime.start();
      try {
        Collection<ReachedSet> usedReachedSets = reached.getAllReachedSetsUsedAsDelegates();

        if (usedReachedSets.size() <= 1) {
          logger.log(Level.INFO, "Only a single ARG is considered. Do not need to combine ARGs");
          if (usedReachedSets.size() == 1) {
            ((ForwardingReachedSet) pReachedSet).setDelegate(reached.getDelegate());
          }
          return status;
        }

        if (from(reached.getDelegate()).anyMatch((IS_TARGET_STATE))) {
          logger.log(Level.INFO, "Error found, do not combine ARGs.");
          ((ForwardingReachedSet) pReachedSet).setDelegate(reached.getDelegate());
          return status;
        }

        logger.log(Level.FINE, "Extract root nodes of ARGs");
        List<ARGState> rootNodes = new ArrayList<>(usedReachedSets.size());
        for (ReachedSet usedReached : usedReachedSets) {
          checkArgument(
              usedReached.getFirstState() instanceof ARGState,
              "Require that all restart configurations use ARGCPA as top level CPA.");
          checkArgument(
              AbstractStates.extractLocation(usedReached.getFirstState()) != null,
              "Require that all restart configurations consider a location aware state");

          for (AbstractState errorState : from(usedReached).filter((IS_TARGET_STATE))) {
            logger.log(
                Level.INFO,
                "Error state found in reached set ",
                usedReached,
                "but not by last configuration. Error state must be infeasible.");
            logger.log(Level.FINE, "Remove infeasible error state", errorState);
            ((ARGState) errorState).removeFromARG();
          }

          rootNodes.add((ARGState) usedReached.getFirstState());
        }

        shutdown.shutdownIfNecessary();

        if (!combineARGs(rootNodes, (ForwardingReachedSet) pReachedSet, reached)) {
          logger.log(Level.SEVERE, "Combination of ARGs failed.");
          return status.withSound(false);
        }
      } finally {
        stats.argCombineTime.stop();
      }

      logger.log(Level.INFO, "Finished combination of ARGS");

    } else {
      logger.log(
          Level.INFO,
          "Program analysis is already unsound.",
          "Do not continue with combination of unsound results");
      // set reached set to last used by restart algorithm
      if (reached.getDelegate() != pReachedSet) {
        ((ForwardingReachedSet) pReachedSet).setDelegate(reached.getDelegate());
      }
      return status.withSound(false);
    }

    return status.withSound(true);
  }
예제 #11
0
  public void writeCoverageReport(
      final PrintStream pStatisticsOutput, final ReachedSet pReached, final CFA pCfa) {

    if (!enabled) {
      return;
    }

    Multiset<FunctionEntryNode> reachedLocations = getFunctionEntriesFromReached(pReached);

    Map<String, FileCoverageInformation> infosPerFile = new HashMap<>();

    // Add information about existing functions
    for (FunctionEntryNode entryNode : pCfa.getAllFunctionHeads()) {
      final FileLocation loc = entryNode.getFileLocation();
      if (loc.getStartingLineNumber() == 0) {
        // dummy location
        continue;
      }
      final String functionName = entryNode.getFunctionName();
      final FileCoverageInformation infos = getFileInfoTarget(loc, infosPerFile);

      final int startingLine = loc.getStartingLineInOrigin();
      final int endingLine = loc.getEndingLineInOrigin();

      infos.addExistingFunction(functionName, startingLine, endingLine);

      if (reachedLocations.contains(entryNode)) {
        infos.addVisitedFunction(entryNode.getFunctionName(), reachedLocations.count(entryNode));
      }
    }

    // Add information about existing locations
    for (CFANode node : pCfa.getAllNodes()) {
      for (int i = 0; i < node.getNumLeavingEdges(); i++) {
        handleExistedEdge(node.getLeavingEdge(i), infosPerFile);
      }
    }

    Set<CFANode> reachedNodes =
        from(pReached).transform(EXTRACT_LOCATION).filter(notNull()).toSet();
    // Add information about visited locations
    for (AbstractState state : pReached) {
      ARGState argState = AbstractStates.extractStateByType(state, ARGState.class);
      if (argState != null) {
        for (ARGState child : argState.getChildren()) {
          if (!child.isCovered()) {
            List<CFAEdge> edges = argState.getEdgesToChild(child);
            if (edges.size() > 1) {
              for (CFAEdge innerEdge : edges) {
                handleCoveredEdge(innerEdge, infosPerFile);
              }

              // BAM produces paths with no edge connection thus the list will be empty
            } else if (!edges.isEmpty()) {
              handleCoveredEdge(Iterables.getOnlyElement(edges), infosPerFile);
            }
          }
        }
      } else {
        // Simple kind of analysis
        // Cover all edges from reached nodes
        // It is less precise, but without ARG it is impossible to know what path we chose
        CFANode node = AbstractStates.extractLocation(state);
        for (int i = 0; i < node.getNumLeavingEdges(); i++) {
          CFAEdge edge = node.getLeavingEdge(i);
          if (reachedNodes.contains(edge.getSuccessor())) {
            handleCoveredEdge(edge, infosPerFile);
          }
        }
      }
    }

    for (CoverageWriter w : reportWriters) {
      w.write(infosPerFile, pStatisticsOutput);
    }
  }