예제 #1
0
 private List<ARGState> chooseIfArbitrary(
     ARGState parent, List<ARGState> pRelevantChildrenOfElement) {
   if (pRelevantChildrenOfElement.size() <= 1) {
     return pRelevantChildrenOfElement;
   }
   List<ARGState> result = new ArrayList<>(2);
   for (ARGState candidate : pRelevantChildrenOfElement) {
     boolean valid = true;
     if (!result.isEmpty()) {
       Set<ARGState> candidateParents = ImmutableSet.copyOf(candidate.getParents());
       Set<ARGState> candidateChildren = ImmutableSet.copyOf(candidate.getChildren());
       for (ARGState chosen : result) {
         if (parent.getEdgesToChild(chosen).equals(parent.getEdgesToChild(candidate))) {
           Set<ARGState> chosenParents = ImmutableSet.copyOf(chosen.getParents());
           Set<ARGState> chosenChildren = ImmutableSet.copyOf(chosen.getChildren());
           if (candidateParents.equals(chosenParents)
               && candidateChildren.equals(chosenChildren)) {
             valid = false;
             break;
           }
         }
       }
     }
     if (valid) {
       result.add(candidate);
     }
   }
   return result;
 }
  private boolean checkAndAddSuccessors(
      final ARGState pPredecessor,
      final ReachedSet pReachedSet,
      final Precision pPrecision,
      @Nullable List<ARGState> pIncompleteStates)
      throws InterruptedException, CPAException {
    stats.getTransferTimer().start();
    Collection<ARGState> successors = pPredecessor.getChildren();
    logger.log(Level.FINER, "Checking abstract successors", successors);
    if (!checkSuccessors(pPredecessor, successors, pPrecision)) {
      stats.getTransferTimer().stop();
      if (pIncompleteStates != null) {
        pIncompleteStates.add(pPredecessor);
        logger.log(
            Level.FINER,
            "State",
            pPredecessor,
            "is explored incompletely, will be recorded in the assumption automaton.");
        return true;
      }
      logger.log(Level.WARNING, "State", pPredecessor, "has other successors than", successors);
      return false;
    }
    stats.getTransferTimer().stop();

    if (!addSuccessors(successors, pReachedSet, pPrecision)) {
      return false;
    }
    return true;
  }
예제 #3
0
  private Collection<Edge> getRelevantChildrenOfState(
      ARGState currentElement, Stack<FunctionBody> functionStack, Set<ARGState> elementsOnPath) {
    // find the next elements to add to the waitlist

    List<ARGState> relevantChildrenOfElement =
        from(currentElement.getChildren()).filter(in(elementsOnPath)).toList();
    relevantChildrenOfElement = chooseIfArbitrary(currentElement, relevantChildrenOfElement);

    // if there is only one child on the path
    if (relevantChildrenOfElement.size() == 1) {
      // get the next ARG state, create a new edge using the same stack and add it to the waitlist
      ARGState elem = Iterables.getOnlyElement(relevantChildrenOfElement);
      CFAEdge e = currentElement.getEdgeToChild(elem);
      Edge newEdge = new Edge(elem, currentElement, e, functionStack);
      return Collections.singleton(newEdge);

    } else if (relevantChildrenOfElement.size() > 1) {
      // if there are more than one relevant child, then this is a condition
      // we need to update the stack
      assert relevantChildrenOfElement.size() == 2;
      Collection<Edge> result = new ArrayList<>(2);
      int ind = 0;
      for (ARGState elem : relevantChildrenOfElement) {
        Stack<FunctionBody> newStack = cloneStack(functionStack);
        CFAEdge e = currentElement.getEdgeToChild(elem);
        FunctionBody currentFunction = newStack.peek();
        assert e instanceof CAssumeEdge;
        CAssumeEdge assumeEdge = (CAssumeEdge) e;
        boolean truthAssumption = assumeEdge.getTruthAssumption();

        String cond = "";

        if (ind == 0) {
          cond = "if ";
        } else if (ind == 1) {
          cond = "else if ";
        } else {
          throw new AssertionError();
        }
        ind++;

        if (truthAssumption) {
          cond += "(" + assumeEdge.getExpression().toASTString() + ")";
        } else {
          cond += "(!(" + assumeEdge.getExpression().toASTString() + "))";
        }

        // create a new block starting with this condition
        currentFunction.enterBlock(currentElement.getStateId(), assumeEdge, cond);

        Edge newEdge = new Edge(elem, currentElement, e, newStack);
        result.add(newEdge);
      }
      return result;
    }
    return Collections.emptyList();
  }
  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;
  }
    private List<BooleanFormula> computeBlockFormulas(final ARGState pRoot)
        throws CPATransferException, InterruptedException {

      final Map<ARGState, ARGState> callStacks =
          new HashMap<>(); // contains states and their next higher callstate
      final Map<ARGState, PathFormula> finishedFormulas = new HashMap<>();
      final List<BooleanFormula> abstractionFormulas = new ArrayList<>();
      final Deque<ARGState> waitlist = new ArrayDeque<>();

      // initialize
      assert pRoot.getParents().isEmpty() : "rootState must be the first state of the program";
      callStacks.put(pRoot, null); // main-start has no callstack
      finishedFormulas.put(pRoot, pfmgr.makeEmptyPathFormula());
      waitlist.addAll(pRoot.getChildren());

      // iterate over all elements in the ARG with BFS
      while (!waitlist.isEmpty()) {
        final ARGState currentState = waitlist.pollFirst();
        if (finishedFormulas.containsKey(currentState)) {
          continue; // already handled
        }

        if (!finishedFormulas.keySet().containsAll(currentState.getParents())) {
          // parent not handled yet, re-queue current element and wait for all parents
          waitlist.addLast(currentState);
          continue;
        }

        // collect formulas for current location
        final List<PathFormula> currentFormulas = new ArrayList<>(currentState.getParents().size());
        final List<ARGState> currentStacks = new ArrayList<>(currentState.getParents().size());
        for (ARGState parentElement : currentState.getParents()) {
          PathFormula parentFormula = finishedFormulas.get(parentElement);
          final CFAEdge edge = parentElement.getEdgeToChild(currentState);
          assert edge != null : "ARG is invalid: parent has no edge to child";

          final ARGState prevCallState;
          // we enter a function, so lets add the previous state to the stack
          if (edge.getEdgeType() == CFAEdgeType.FunctionCallEdge) {
            prevCallState = parentElement;

          } else if (edge.getEdgeType() == CFAEdgeType.FunctionReturnEdge) {
            // we leave a function, so rebuild return-state before assigning the return-value.
            // rebuild states with info from previous state
            assert callStacks.containsKey(parentElement);
            final ARGState callState = callStacks.get(parentElement);

            assert extractLocation(callState).getLeavingSummaryEdge().getSuccessor()
                    == extractLocation(currentState)
                : "callstack does not match entry of current function-exit.";
            assert callState != null || currentState.getChildren().isEmpty()
                : "returning from empty callstack is only possible at program-exit";

            prevCallState = callStacks.get(callState);
            parentFormula =
                rebuildStateAfterFunctionCall(
                    parentFormula,
                    finishedFormulas.get(callState),
                    (FunctionExitNode) extractLocation(parentElement));

          } else {
            assert callStacks.containsKey(parentElement); // check for null is not enough
            prevCallState = callStacks.get(parentElement);
          }

          final PathFormula currentFormula = pfmgr.makeAnd(parentFormula, edge);
          currentFormulas.add(currentFormula);
          currentStacks.add(prevCallState);
        }

        assert currentFormulas.size() >= 1 : "each state except root must have parents";
        assert currentStacks.size() == currentFormulas.size()
            : "number of callstacks must match predecessors";

        // merging after functioncall with different callstates is ugly.
        // this is also guaranteed by the abstraction-locations at function-entries
        // (--> no merge of states with different latest abstractions).
        assert Sets.newHashSet(currentStacks).size() <= 1
            : "function with multiple entry-states not supported";

        callStacks.put(currentState, currentStacks.get(0));

        PathFormula currentFormula;
        final PredicateAbstractState predicateElement =
            extractStateByType(currentState, PredicateAbstractState.class);
        if (predicateElement.isAbstractionState()) {
          // abstraction element is the start of a new part of the ARG

          assert waitlist.isEmpty() : "todo should be empty, because of the special ARG structure";
          assert currentState.getParents().size() == 1
              : "there should be only one parent, because of the special ARG structure";

          // finishedFormulas.clear(); // free some memory
          // TODO disabled, we need to keep callStates for later usage

          // start new block with empty formula
          currentFormula = getOnlyElement(currentFormulas);
          abstractionFormulas.add(currentFormula.getFormula());
          currentFormula = pfmgr.makeEmptyPathFormula(currentFormula);

        } else {
          // merge the formulas
          Iterator<PathFormula> it = currentFormulas.iterator();
          currentFormula = it.next();
          while (it.hasNext()) {
            currentFormula = pfmgr.makeOr(currentFormula, it.next());
          }
        }

        assert !finishedFormulas.containsKey(currentState) : "a state should only be finished once";
        finishedFormulas.put(currentState, currentFormula);
        waitlist.addAll(currentState.getChildren());
      }
      return abstractionFormulas;
    }
예제 #6
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);
    }
  }