Пример #1
0
  void Visit(Exp *exp)
  {
    if (ExpFld *nexp = exp->IfFld()) {
      // pick up any type invariants from the host type.
      String *csu_name = nexp->GetField()->GetCSUType()->GetCSUName();
      Vector<BlockCFG*> *annot_list = CompAnnotCache.Lookup(csu_name);

      for (size_t ind = 0; annot_list && ind < annot_list->Size(); ind++) {
        BlockCFG *annot_cfg = annot_list->At(ind);
        Assert(annot_cfg->GetAnnotationKind() == AK_Invariant ||
               annot_cfg->GetAnnotationKind() == AK_InvariantAssume);
        BlockId *id = annot_cfg->GetId();

        Bit *bit = BlockMemory::GetAnnotationBit(annot_cfg);
        if (!bit) continue;

        // get the *this expression. we'll replace this with the actual CSU
        // lvalue to get the assumed bit.
        id->IncRef();
        Variable *this_var = Variable::Make(id, VK_This, NULL, 0, NULL);
        Exp *this_exp = Exp::MakeVar(this_var);
        Exp *this_drf = Exp::MakeDrf(this_exp);
        Exp *target = nexp->GetTarget();

        GuardExpVector lval_res;
        if (mcfg) {
          mcfg->TranslateExp(TRK_Point, point, target, &lval_res);
        }
        else {
          target->IncRef();
          lval_res.PushBack(GuardExp(target, Bit::MakeConstant(true)));
        }

        for (size_t lind = 0; lind < lval_res.Size(); lind++) {
          // ignore the guard component of the result here. this means that
          // accessing a field of a value means related invariants hold for
          // the value along all paths. which is normally right, except when
          // the value is the result of a cast, and could have a different type
          // along other paths. TODO: sort this out.
          const GuardExp &gs = lval_res[lind];
          Bit *new_bit = BitReplaceExp(bit, this_drf, gs.exp);

          new_bit->MoveRef(NULL, assume_list);
          annot_cfg->IncRef(assume_list);

          AssumeInfo info;
          info.annot = annot_cfg;
          info.point = 0;
          info.bit = new_bit;
          assume_list->PushBack(info);
        }

        this_drf->DecRef();
      }

      CompAnnotCache.Release(csu_name);
    }

    if (ExpVar *nexp = exp->IfVar()) {
      if (nexp->GetVariable()->Kind() == VK_Glob) {
        String *var_name = nexp->GetVariable()->GetName();
        Vector<BlockCFG*> *annot_list = InitAnnotCache.Lookup(var_name);

        for (size_t ind = 0; annot_list && ind < annot_list->Size(); ind++) {
          BlockCFG *annot_cfg = annot_list->At(ind);
          Assert(annot_cfg->GetAnnotationKind() == AK_Invariant ||
                 annot_cfg->GetAnnotationKind() == AK_InvariantAssume);

          Bit *bit = BlockMemory::GetAnnotationBit(annot_cfg);
          if (!bit) continue;

          bit->IncRef(assume_list);
          annot_cfg->IncRef(assume_list);

          AssumeInfo info;
          info.annot = annot_cfg;
          info.point = 0;
          info.bit = bit;
          assume_list->PushBack(info);
        }

        InitAnnotCache.Release(var_name);
      }
    }
  }
Пример #2
0
void FillBakedSummary(BlockSummary *sum)
{
  Variable *name = sum->GetId()->BaseVar();

  // primitive memory allocator.

  Exp *object;
  Exp *size;

  if (GetAllocationFunction(name, &object, &size)) {
    Exp *bound = GetByteUpperBound(object);

    // the upper bound is greater or equal to zero.
    bound->IncRef();
    Exp *zero = Exp::MakeInt(0);
    Bit *bound_nonneg = Exp::MakeCompareBit(B_GreaterEqual, bound, zero);
    sum->AddAssume(bound_nonneg);

    // the upper bound of the object is exactly equal to size.
    Bit *bound_equal = Exp::MakeCompareBit(B_Equal, bound, size);
    sum->AddAssume(bound_equal);

    // TODO: it would be nice to assert the offset is exactly equal
    // to zero for the UI; however, this can lead to spurious contradiction
    // if unaligned pointers are in use.
  }

  // return value bears some relation with an argument.

  ReturnCompareFunctionInfo *cur_return = g_return_compare_functions;
  while (cur_return->name) {
    if (TextNameMatch(name, cur_return->name)) {
      Exp *ret_exp = GetReturnedValue();
      Exp *arg_exp = GetArgumentValue(cur_return->compare_arg);

      Type *type = NULL;
      if (IsPointerBinop(cur_return->binop))
        type = Type::MakeInt(1, true);

      Bit *bit = Exp::MakeCompareBit(cur_return->binop,
                                     ret_exp, arg_exp, type);
      sum->AddAssume(bit);
    }

    cur_return++;
  }

  // return value is NULL terminated.

  const char **cur_ret_term = g_return_terminated_functions;
  while (*cur_ret_term) {
    if (TextNameMatch(name, *cur_ret_term)) {
      Exp *ret_exp = GetReturnedValue();
      Exp *terminate = GetNullTerminate(ret_exp);
      Exp *zero = Exp::MakeInt(0);

      Bit *bit = Exp::MakeCompareBit(B_GreaterEqual, terminate, zero);
      sum->AddAssume(bit);
    }

    cur_ret_term++;
  }

  // an argument is NULL terminated.

  TerminateFunctionInfo *cur_term = g_terminate_functions;
  while (cur_term->name) {
    if (TextNameMatch(name, cur_term->name) && cur_term->terminates) {
      Exp *arg_exp = GetArgumentValue(cur_term->terminate_arg);
      Exp *kind = GetNullTerminate(NULL);
      Exp *exit_term = Exp::MakeExit(arg_exp, kind);
      Exp *zero = Exp::MakeInt(0);

      Bit *bit = Exp::MakeCompareBit(B_GreaterEqual, exit_term, zero);
      sum->AddAssume(bit);
    }

    cur_term++;
  }

  // strchr constraint: char_arg != 0 => zterm(ret) > 0.

  StrchrFunctionInfo *cur_strchr = g_strchr_functions;
  while (cur_strchr->name) {
    if (TextNameMatch(name, cur_strchr->name)) {
      Exp *arg_exp = GetArgumentValue(cur_strchr->char_arg);
      Exp *ret_exp = GetReturnedValue();
      Exp *terminate = GetNullTerminate(ret_exp);

      Exp *zero = Exp::MakeInt(0);
      zero->IncRef();

      Bit *left = Exp::MakeCompareBit(B_NotEqual, arg_exp, zero);
      Bit *right = Exp::MakeCompareBit(B_GreaterThan, terminate, zero);
      Bit *bit = Bit::MakeImply(left, right);
      sum->AddAssume(bit);
    }

    cur_strchr++;
  }

  // strlen constraint: ret >= 0 && ret == zterm(arg)

  StrlenFunctionInfo *cur_strlen = g_strlen_functions;
  while (cur_strlen->name) {
    if (TextNameMatch(name, cur_strlen->name)) {
      Exp *arg_exp = GetArgumentValue(cur_strlen->string_arg);
      Exp *retval = GetReturnedValue();

      Exp *terminate = GetNullTerminate(arg_exp);

      retval->IncRef();
      Exp *zero = Exp::MakeInt(0);
      Bit *ge_zero = Exp::MakeCompareBit(B_GreaterEqual, retval, zero);
      sum->AddAssume(ge_zero);

      Bit *eq_term = Exp::MakeCompareBit(B_Equal, retval, terminate);
      sum->AddAssume(eq_term);
    }

    cur_strlen++;
  }

  // strcmp constraint: ret == 0 ==> zterm(arg_one) == zterm(arg_two)

  StrcmpFunctionInfo *cur_strcmp = g_strcmp_functions;
  while (cur_strcmp->name) {
    if (TextNameMatch(name, cur_strcmp->name)) {
      Exp *arg_one_exp = GetArgumentValue(cur_strcmp->string_arg_one);
      Exp *arg_two_exp = GetArgumentValue(cur_strcmp->string_arg_two);
      Exp *retval = GetReturnedValue();

      Exp *terminate_one = GetNullTerminate(arg_one_exp);
      Exp *terminate_two = GetNullTerminate(arg_two_exp);

      Exp *zero = Exp::MakeInt(0);

      Bit *left = Exp::MakeCompareBit(B_Equal, retval, zero);
      Bit *right = Exp::MakeCompareBit(B_Equal, terminate_one, terminate_two);
      Bit *bit = Bit::MakeImply(left, right);
      sum->AddAssume(bit);
    }

    cur_strcmp++;
  }

  // strncmp constraint: ret == 0 ==> (zterm(arg_one) == zterm(arg_two)
  //                                || (zterm(arg_one) >= length_arg &&
  //                                    zterm(arg_two) >= length_arg))

  StrncmpFunctionInfo *cur_strncmp = g_strncmp_functions;
  while (cur_strncmp->name) {
    if (TextNameMatch(name, cur_strncmp->name)) {
      Exp *arg_one_exp = GetArgumentValue(cur_strncmp->string_arg_one);
      Exp *arg_two_exp = GetArgumentValue(cur_strncmp->string_arg_two);
      Exp *length_exp = GetArgumentValue(cur_strncmp->length_arg);
      Exp *retval = GetReturnedValue();

      Exp *terminate_one = GetNullTerminate(arg_one_exp);
      Exp *terminate_two = GetNullTerminate(arg_two_exp);

      Exp *zero = Exp::MakeInt(0);
      terminate_one->IncRef();
      terminate_two->IncRef();
      length_exp->IncRef();

      Bit *left = Exp::MakeCompareBit(B_Equal, retval, zero);
      Bit *term_eq = Exp::MakeCompareBit(B_Equal, terminate_one, terminate_two);
      Bit *ge_one = Exp::MakeCompareBit(B_GreaterEqual, terminate_one, length_exp);
      Bit *ge_two = Exp::MakeCompareBit(B_GreaterEqual, terminate_two, length_exp);
      Bit *ge_both = Bit::MakeAnd(ge_one, ge_two);
      Bit *right = Bit::MakeOr(term_eq, ge_both);
      Bit *bit = Bit::MakeImply(left, right);
      sum->AddAssume(bit);
    }

    cur_strncmp++;
  }
}