Ejemplo n.º 1
0
 @Override
 public ResultValue<Integer> eval(AutomatonExpressionArguments pArgs) {
   if (TRANSITION_VARS_PATTERN.matcher(varId).matches()) { // $1  AutomatonTransitionVariables
     // no exception here (would have come in the constructor)
     int key = Integer.parseInt(varId.substring(1));
     String val = pArgs.getTransitionVariable(key);
     if (val == null) {
       pArgs
           .getLogger()
           .log(Level.WARNING, "could not find the transition variable $" + key + ".");
       return new ResultValue<>(
           "could not find the transition variable $" + key + ".", "AutomatonIntExpr.VarAccess");
     }
     try {
       int value = Integer.parseInt(val);
       return new ResultValue<>(Integer.valueOf(value));
     } catch (NumberFormatException e) {
       pArgs
           .getLogger()
           .log(
               Level.WARNING,
               "could not parse the contents of transition variable $"
                   + key
                   + "=\""
                   + val
                   + "\".");
       return new ResultValue<>(
           "could not parse the contents of transition variable $" + key + "=\"" + val + "\".",
           "AutomatonIntExpr.VarAccess");
     }
   } else if (varId.equals("$line")) { // $line  line number in sourcecode
     return new ResultValue<>(Integer.valueOf(pArgs.getCfaEdge().getLineNumber()));
   } else {
     AutomatonVariable variable = pArgs.getAutomatonVariables().get(varId);
     if (variable != null) {
       return new ResultValue<>(Integer.valueOf(variable.getValue()));
     } else {
       pArgs
           .getLogger()
           .log(Level.WARNING, "could not find the automaton variable " + varId + ".");
       return new ResultValue<>(
           "could not find the automaton variable " + varId + ".", "AutomatonIntExpr.VarAccess");
     }
   }
 }
Ejemplo n.º 2
0
    @Override
    public ResultValue<Integer> eval(AutomatonExpressionArguments pArgs) {
      // replace transition variables
      String modifiedQueryString = pArgs.replaceVariables(queryString);
      if (modifiedQueryString == null) {
        return new ResultValue<>(
            "Failed to modify queryString \"" + queryString + "\"", "AutomatonIntExpr.CPAQuery");
      }

      for (AbstractState ae : pArgs.getAbstractStates()) {
        if (ae instanceof AbstractQueryableState) {
          AbstractQueryableState aqe = (AbstractQueryableState) ae;
          if (aqe.getCPAName().equals(cpaName)) {
            try {
              Object result = aqe.evaluateProperty(modifiedQueryString);
              if (result instanceof NumericValue) {
                result = ((NumericValue) result).getNumber();
              }
              if (result instanceof Integer) {
                String message =
                    "CPA-Check succeeded: ModifiedCheckString: \""
                        + modifiedQueryString
                        + "\" CPAElement: ("
                        + aqe.getCPAName()
                        + ") \""
                        + aqe.toString()
                        + "\"";
                pArgs.getLogger().log(Level.FINER, message);
                return new ResultValue<>((Integer) result);
              } else if (result instanceof Long) {
                String message =
                    "CPA-Check succeeded: ModifiedCheckString: \""
                        + modifiedQueryString
                        + "\" CPAElement: ("
                        + aqe.getCPAName()
                        + ") \""
                        + aqe.toString()
                        + "\"";
                pArgs.getLogger().log(Level.FINER, message);
                return new ResultValue<>(((Long) result).intValue());
              } else {
                pArgs
                    .getLogger()
                    .log(
                        Level.WARNING,
                        "Automaton got a non-Numeric value during Query of the "
                            + cpaName
                            + " CPA on Edge "
                            + pArgs.getCfaEdge().getDescription()
                            + ".");
                return new ResultValue<>(
                    "Automaton got a non-Numeric value during Query of the "
                        + cpaName
                        + " CPA on Edge "
                        + pArgs.getCfaEdge().getDescription()
                        + ".",
                    "AutomatonIntExpr.CPAQuery");
              }
            } catch (InvalidQueryException e) {
              pArgs
                  .getLogger()
                  .logException(
                      Level.WARNING,
                      e,
                      "Automaton encountered an Exception during Query of the "
                          + cpaName
                          + " CPA on Edge "
                          + pArgs.getCfaEdge().getDescription()
                          + ".");
              return new ResultValue<>(
                  "Automaton encountered an Exception during Query of the "
                      + cpaName
                      + " CPA on Edge "
                      + pArgs.getCfaEdge().getDescription()
                      + ".",
                  "AutomatonIntExpr.CPAQuery");
            }
          }
        }
      }
      pArgs
          .getLogger()
          .log(
              Level.WARNING,
              "Did not find the CPA to be queried "
                  + cpaName
                  + " CPA on Edge "
                  + pArgs.getCfaEdge().getDescription()
                  + ".");
      return new ResultValue<>(
          "Did not find the CPA to be queried "
              + cpaName
              + " CPA on Edge "
              + pArgs.getCfaEdge().getDescription()
              + ".",
          "AutomatonIntExpr.CPAQuery");
    }
  /**
   * Returns the <code>AutomatonStates</code> that follow this State in the ControlAutomatonCPA. If
   * the passed <code>AutomatonExpressionArguments</code> are not sufficient to determine the
   * following state this method returns a <code>AutomatonUnknownState</code> that contains this as
   * previous State. The strengthen method of the <code>AutomatonUnknownState</code> should be used
   * once enough Information is available to determine the correct following State.
   *
   * <p>If the state is a NonDet-State multiple following states may be returned. If the only
   * following state is BOTTOM an empty set is returned.
   *
   * @throws CPATransferException
   */
  private Collection<AutomatonState> getFollowStates(
      AutomatonState state,
      List<AbstractState> otherElements,
      CFAEdge edge,
      boolean failOnUnknownMatch)
      throws CPATransferException {
    Preconditions.checkArgument(!(state instanceof AutomatonUnknownState));
    if (state == cpa.getBottomState()) {
      return Collections.emptySet();
    }

    if (collectTokenInformation) {
      SourceLocationMapper.getKnownToEdge(edge);
    }

    if (state.getInternalState().getTransitions().isEmpty()) {
      // shortcut
      return Collections.singleton(state);
    }

    Collection<AutomatonState> lSuccessors = Sets.newHashSetWithExpectedSize(2);
    AutomatonExpressionArguments exprArgs =
        new AutomatonExpressionArguments(state, state.getVars(), otherElements, edge, logger);
    boolean edgeMatched = false;
    int failedMatches = 0;
    boolean nonDetState = state.getInternalState().isNonDetState();

    // these transitions cannot be evaluated until last, because they might have sideeffects on
    // other CPAs (dont want to execute them twice)
    // the transitionVariables have to be cached (produced during the match operation)
    // the list holds a Transition and the TransitionVariables generated during its match
    List<Pair<AutomatonTransition, Map<Integer, String>>> transitionsToBeTaken = new ArrayList<>(2);

    for (AutomatonTransition t : state.getInternalState().getTransitions()) {
      exprArgs.clearTransitionVariables();

      matchTime.start();
      ResultValue<Boolean> match = t.match(exprArgs);
      matchTime.stop();

      //      System.out.println("----------------------");
      //      System.out.println(t.getTrigger());
      //      System.out.println(t.getFollowState().getName());
      //      System.out.println(edge.getPredecessor().getNodeNumber());
      //      System.out.println(edge.getCode());
      //      System.out.println(match.getValue());

      if (match.canNotEvaluate()) {
        if (failOnUnknownMatch) {
          throw new CPATransferException(
              "Automaton transition condition could not be evaluated: "
                  + match.getFailureMessage());
        }
        // if one transition cannot be evaluated the evaluation must be postponed until enough
        // information is available
        return Collections.<AutomatonState>singleton(new AutomatonUnknownState(state));
      } else {
        if (match.getValue()) {
          edgeMatched = true;
          assertionsTime.start();
          ResultValue<Boolean> assertionsHold = t.assertionsHold(exprArgs);
          assertionsTime.stop();

          if (assertionsHold.canNotEvaluate()) {
            if (failOnUnknownMatch) {
              throw new CPATransferException(
                  "Automaton transition assertions could not be evaluated: "
                      + assertionsHold.getFailureMessage());
            }
            // cannot yet be evaluated
            return Collections.<AutomatonState>singleton(new AutomatonUnknownState(state));

          } else if (assertionsHold.getValue()) {
            if (!t.canExecuteActionsOn(exprArgs)) {
              if (failOnUnknownMatch) {
                throw new CPATransferException("Automaton transition action could not be executed");
              }
              // cannot yet execute, goto UnknownState
              return Collections.<AutomatonState>singleton(new AutomatonUnknownState(state));
            }

            // delay execution as described above
            Map<Integer, String> transitionVariables =
                ImmutableMap.copyOf(exprArgs.getTransitionVariables());
            transitionsToBeTaken.add(Pair.of(t, transitionVariables));

          } else {
            // matching transitions, but unfulfilled assertions: goto error state
            AutomatonState errorState =
                AutomatonState.automatonStateFactory(
                    Collections.<String, AutomatonVariable>emptyMap(),
                    AutomatonInternalState.ERROR,
                    cpa,
                    0,
                    0,
                    "");
            logger.log(
                Level.INFO,
                "Automaton going to ErrorState on edge \"" + edge.getDescription() + "\"");
            lSuccessors.add(errorState);
          }

          if (!nonDetState) {
            // not a nondet State, break on the first matching edge
            break;
          }
        } else {
          // do nothing if the edge did not match
          failedMatches++;
        }
      }
    }

    if (edgeMatched) {
      // execute Transitions
      for (Pair<AutomatonTransition, Map<Integer, String>> pair : transitionsToBeTaken) {
        // this transition will be taken. copy the variables
        AutomatonTransition t = pair.getFirst();
        Map<Integer, String> transitionVariables = pair.getSecond();
        actionTime.start();
        Map<String, AutomatonVariable> newVars = deepCloneVars(state.getVars());
        exprArgs.setAutomatonVariables(newVars);
        exprArgs.putTransitionVariables(transitionVariables);
        t.executeActions(exprArgs);
        actionTime.stop();
        String violatedPropertyDescription = null;
        if (t.getFollowState().isTarget()) {
          violatedPropertyDescription = t.getViolatedPropertyDescription(exprArgs);
        }
        AutomatonState lSuccessor =
            AutomatonState.automatonStateFactory(
                newVars,
                t.getFollowState(),
                cpa,
                t.getAssumptions(),
                state.getMatches() + 1,
                state.getFailedMatches(),
                violatedPropertyDescription);
        if (!(lSuccessor instanceof AutomatonState.BOTTOM)) {
          lSuccessors.add(lSuccessor);
        } else {
          // add nothing
        }
      }
      return lSuccessors;
    } else {
      // stay in same state, no transitions to be executed here (no transition matched)
      AutomatonState stateNewCounters =
          AutomatonState.automatonStateFactory(
              state.getVars(),
              state.getInternalState(),
              cpa,
              state.getMatches(),
              state.getFailedMatches() + failedMatches,
              null);
      if (collectTokenInformation) {
        stateNewCounters.addNoMatchTokens(state.getTokensSinceLastMatch());
        if (edge.getEdgeType() != CFAEdgeType.DeclarationEdge) {
          stateNewCounters.addNoMatchTokens(
              SourceLocationMapper.getAbsoluteTokensFromCFAEdge(edge, true));
        }
      }
      return Collections.singleton(stateNewCounters);
    }
  }