Beispiel #1
0
// read a binary tag value from the specified buffer and get whatever
// hash object it represents from the buffer, returning a reference
// on that object. we will just match against the types of values that
// can appear at the top level of a database entry.
HashObject* ReadSingleValue(Buffer *buf)
{
  switch (PeekOpenTag(buf)) {

  case TAG_BlockCFG:         return BlockCFG::Read(buf);
  case TAG_CompositeCSU:     return CompositeCSU::Read(buf);
  case TAG_EscapeEdgeSet:    return EscapeEdgeSet::Read(buf);
  case TAG_EscapeAccessSet:  return EscapeAccessSet::Read(buf);
  case TAG_CallEdgeSet:      return CallEdgeSet::Read(buf);
  case TAG_BlockModset:      return BlockModset::Read(buf);
  case TAG_BlockSummary:     return BlockSummary::Read(buf);

  // special case: get the CFG too.
  case TAG_BlockMemory: {
    BlockMemory *mcfg = BlockMemory::Read(buf);
    BlockCFG *cfg = GetBlockCFG(mcfg->GetId());
    if (cfg)
      mcfg->SetCFG(cfg);
    return mcfg;
  }

  default:
    logout << "ERROR: Unknown top-level tag in entry: "
           << PeekOpenTag(buf) << endl;
    Assert(false);
  }
}
Beispiel #2
0
// returns whether the error condition is satisfiable within frame.
bool TestErrorSatisfiable(CheckerState *state, CheckerFrame *frame, Bit *bit)
{
  BlockMemory *mcfg = frame->Memory();
  Solver *solver = state->GetSolver();

  if (!solver->IsSatisfiable()) {
    if (checker_verbose.IsSpecified())
      logout << "CHECK: " << frame << ": Guard unsatisfiable: " << bit
             << " [" << bit->Hash() << "]" << endl;
    return false;
  }

  state->PushContext();
  state->AssertBaseBits();

  if (!solver->IsSatisfiable()) {
    if (checker_verbose.IsSpecified())
      logout << "CHECK: " << frame << ": Error unsatisfiable: " << bit
             << " [" << bit->Hash() << "]" << endl;
    state->PopContext();
    return false;
  }

  if (!frame->m_checked_assertions) {
    frame->m_checked_assertions = true;

    // check to see if the error is contradicted by previous assertions
    // in this frame. assert the previous assertions, but don't keep
    // them around past this function to avoid polluting the solver
    // with worthless extra checks.

    BlockSummary *sum = GetBlockSummary(mcfg->GetId());

    const Vector<AssertInfo> *asserts = sum->GetAsserts();
    size_t assert_count = VectorSize<AssertInfo>(asserts);

    for (size_t ind = 0; ind < assert_count; ind++) {
      const AssertInfo &info = asserts->At(ind);

      // only use the same kind of assertion to check for redundancy.
      if (info.kind != state->GetAssertKind())
        continue;

      if (info.cls != ASC_Check)
        continue;

      if (info.point < frame->EndPoint()) {
        // get the asserted condition relative to block entry.

        Bit *assert_value;
        mcfg->TranslateBit(TRK_Point, info.point, info.bit, &assert_value);
        assert_value->MoveRef(&assert_value, NULL);

        Bit *point_guard = mcfg->GetGuard(info.point);
        point_guard->IncRef();

        Bit *imply_assert =
          Bit::MakeImply(point_guard, assert_value);

        solver->AddConstraint(frame->Id(), imply_assert);
      }
    }

    sum->DecRef();

    if (!solver->IsSatisfiable()) {
      if (checker_verbose.IsSpecified())
        logout << "CHECK: " << frame
               << ": Unsatisfiable from assertions" << endl;

      state->PopContext();
      return false;
    }
  }

  state->PopContext();
  return true;
}
  void MultiMap(Exp *exp, Vector<Exp*> *res)
  {
    // follow possible equalities for lvalues and non-arithmetic binops
    // appearing in the input formula.
    bool handle_exp = false;

    if (exp->IsLvalue() || exp->IsBound() || exp->IsTerminate())
      handle_exp = true;
    else if (ExpBinop *nexp = exp->IfBinop()) {
      switch (nexp->GetBinopKind()) {
      case B_Mod:
      case B_BitwiseAnd:
      case B_BitwiseOr:
      case B_BitwiseXOr:
      case B_Min:
      case B_Max:
        handle_exp = true;
      default:
        break;
      }
    }

    /*
    // special cased constant substitution. if we see an 'n < val'
    // or 'n+1 <= val' and a comparison 'n+1 ~ oval', try substituting
    // 'oval <= val'.

    if (ExpBinop *nexp = exp->IfBinop()) {
      long left_value, right_value;
      BinopKind kind = nexp->GetBinopKind();
      Exp *left = nexp->GetLeftOperand();
      Exp *right = nexp->GetRightOperand();

      if ((kind == B_LessThan || kind == B_LessEqual) &&
          left->IsInt() && left->AsInt()->GetInt(&left_value)) {
        for (size_t ind = 0; ind < equalities.Size(); ind++) {
          const BaseCompare &equality = equalities[ind];
          if (equality.target->IsInt() &&
              equality.target->AsInt()->GetInt(&right_value) &&
              right_value == left_value + (kind == B_LessThan ? 1 : 0)) {
            Exp *new_exp = Exp::MakeBinop(B_LessEqual, equality.source, right);
            ExpAddResult(new_exp, res);
          }
        }
      }
    }
    */

    if (!handle_exp) {
      ExpAddResult(exp, res);
      return;
    }

    bool is_loop = (mcfg->GetId()->Kind() == B_Loop);

    // for loops, only follow equalities for terms which change with
    // each iteration.
    if (is_loop && mcfg->IsExpPreserved(exp)) {
      ExpAddResult(exp, res);
      return;
    }

    ExpAddResult(exp, res);

    // try to substitute the expression for anything it might share
    // an ==/<=/>= relationship with.

    for (size_t ind = 0; ind < equalities.Size(); ind++) {
      const BaseCompare &equality = equalities[ind];

      // watch for recursion when following compares.
      if (expand_stack.Contains(equality.test))
        continue;

      // check if there is a match between the exp and equality source.
      Exp *new_target = MatchEquality(exp, equality);

      if (new_target) {
        // keep track of the tests we use during recursive mapping.
        expand_stack.PushBack(equality.test);

        // list to hold result of mapping this substitution.
        Vector<Exp*> sub_res;

        EqualityMapper sub_mapper(mcfg, verbose, equalities, expand_stack);
        new_target->DoMultiMap(&sub_mapper, &sub_res);

        expand_stack.PopBack();

        // for functions, filter out substitutions which resulted in an
        // increase in the number of leaf terms in the expression. this both
        // gets rid of results we don't care about and prevents exponential
        // blowup. we don't need to worry about this for loops because
        // we only follow substitutions for values which change in each
        // iteration, a similar (and less crude) filtering.
        size_t base_term_count = exp->TermCount();

        if (verbose)
          logout << "SUFFICIENT: Substituted: " << exp
                 << " [" << sub_res.Size() << "]" << endl;

        for (size_t rind = 0; rind < sub_res.Size(); rind++) {
          Exp *res_exp = sub_res[rind];

          if (is_loop || res_exp->TermCount() <= base_term_count) {
            if (verbose)
              logout << "  Added: " << res_exp << endl;
            ExpAddResult(res_exp, res);
          }
          else {
            if (verbose)
              logout << "  Dropped: " << res_exp << endl;
          }
        }
      }
    }
  }