コード例 #1
0
/// add axioms stating that if two strings are equal then their hash codes are
/// equals
/// \par parameters: function application with a string argument
/// \return a integer expression corresponding to the hash code of the string
exprt string_constraint_generatort::add_axioms_for_hash_code(
  const function_application_exprt &f)
{
  string_exprt str=add_axioms_for_string_expr(args(f, 1)[0]);
  typet return_type=f.type();
  typet index_type=str.length().type();

  // initialisation of the missing pool variable
  std::map<irep_idt, string_exprt>::iterator it;
  for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++)
    if(hash.find(it->second)==hash.end())
      hash[it->second]=fresh_symbol("hash", return_type);

  // for each string s. either:
  //   c1: hash(str)=hash(s)
  //   c2: |str|!=|s|
  //   c3: (|str|==|s| &&exists i<|s|. s[i]!=str[i])

  // WARNING: the specification may be incomplete
  for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++)
  {
    symbol_exprt i=fresh_exist_index("index_hash", index_type);
    equal_exprt c1(hash[it->second], hash[str]);
    not_exprt c2(equal_exprt(it->second.length(), str.length()));
    and_exprt c3(
      equal_exprt(it->second.length(), str.length()),
      and_exprt(
        not_exprt(equal_exprt(str[i], it->second[i])),
        and_exprt(
          str.axiom_for_is_strictly_longer_than(i),
          axiom_for_is_positive_index(i))));
    axioms.push_back(or_exprt(c1, or_exprt(c2, c3)));
  }
  return hash[str];
}
コード例 #2
0
ファイル: equality_domain.cpp プロジェクト: diffblue/2ls
void equality_domaint::project_on_vars(
  valuet &value,
  const var_sett &vars,
  exprt &result)
{
#if 0
  if(templ.size()==0)
    return domaint::project_on_vars(value, vars, result);
#endif

  equ_valuet &v=static_cast<equ_valuet &>(value);

  exprt::operandst c;
  for(unsigned index=0; index<templ.size(); index++)
  {
    const var_pairt &vv=templ[index].var_pair;

#if 0
    std::cout << vv.second << std::endl;
#endif
    if(vars.find(vv.first)==vars.end() ||
       (vars.find(vv.second)==vars.end() &&
        !(vv.second.id()==ID_constant &&
          to_constant_expr(vv.second).get_value()=="NULL")))
      continue;

    if(v.equs.same_set(vv.first, vv.second))
    {
      if(templ[index].kind==LOOP)
        c.push_back(
          implies_exprt(
            templ[index].pre_guard,
            equal_exprt(vv.first, vv.second)));
      else
        c.push_back(equal_exprt(vv.first, vv.second));
    }
  }

  for(index_sett::const_iterator it=v.disequs.begin();
      it!=v.disequs.end(); it++)
  {
    const var_pairt &vv=templ[*it].var_pair;

    if(vars.find(vv.first)==vars.end() ||
       (vars.find(vv.second)==vars.end() &&
        !(vv.second.id()==ID_constant &&
          to_constant_expr(vv.second).get_value()=="NULL")))
      continue;

    if(templ[*it].kind==LOOP)
      c.push_back(
        implies_exprt(
          templ[*it].pre_guard,
          notequal_exprt(vv.first, vv.second)));
    else
      c.push_back(notequal_exprt(vv.first, vv.second));
  }
  result=conjunction(c);
}
コード例 #3
0
exprt string_constraint_generatort::add_axioms_for_last_index_of(
  const string_exprt &str, const exprt &c, const exprt &from_index)
{
  const refined_string_typet &ref_type=to_refined_string_type(str.type());
  const typet &index_type=ref_type.get_index_type();
  symbol_exprt index=fresh_exist_index("last_index_of", index_type);
  symbol_exprt contains=fresh_boolean("contains_in_last_index_of");

  // We add axioms:
  // a1 : -1 <= i <= from_index
  // a2 : (i=-1 <=> !contains)
  // a3 : (contains => i <= from_index &&s[i]=c)
  // a4 : forall n. i+1 <= n < from_index +1 &&contains => s[n]!=c
  // a5 : forall m. 0 <= m < from_index +1 &&!contains => s[m]!=c

  exprt index1=from_integer(1, index_type);
  exprt minus1=from_integer(-1, index_type);
  exprt from_index_plus_one=plus_exprt(from_index, index1);
  and_exprt a1(
    binary_relation_exprt(index, ID_ge, minus1),
    binary_relation_exprt(index, ID_lt, from_index_plus_one));
  axioms.push_back(a1);

  equal_exprt a2(not_exprt(contains), equal_exprt(index, minus1));
  axioms.push_back(a2);

  implies_exprt a3(
    contains,
    and_exprt(
      binary_relation_exprt(from_index, ID_ge, index),
      equal_exprt(str[index], c)));
  axioms.push_back(a3);

  symbol_exprt n=fresh_univ_index("QA_last_index_of", index_type);
  string_constraintt a4(
    n,
    plus_exprt(index, index1),
    from_index_plus_one,
    contains,
    not_exprt(equal_exprt(str[n], c)));
  axioms.push_back(a4);

  symbol_exprt m=fresh_univ_index("QA_last_index_of", index_type);
  string_constraintt a5(
    m,
    from_index_plus_one,
    not_exprt(contains),
    not_exprt(equal_exprt(str[m], c)));
  axioms.push_back(a5);

  return index;
}
コード例 #4
0
ファイル: equality_domain.cpp プロジェクト: diffblue/2ls
void equality_domaint::make_not_post_constraints(
  valuet &_value,
  exprt::operandst &cond_exprs)
{
  assert(*e_it<templ.size());
  cond_exprs.resize(1);
  if(check_dis)
  {
    cond_exprs[0]=get_post_not_disequ_constraint(*e_it);
    return;
  }
  const template_rowt &templ_row=templ[*e_it];
  if(templ_row.kind==IN)
  {
    cond_exprs[0]=true_exprt();
    return;
  }

  const var_pairt &vv=templ_row.var_pair;
  exprt c=
    and_exprt(
      templ_row.aux_expr,
      not_exprt(
        implies_exprt(
          templ_row.post_guard,
          equal_exprt(vv.first, vv.second))));
  rename(c);
  cond_exprs[0]=c;
}
コード例 #5
0
exprt ssa_alias_guard(
  const exprt &e1,
  const exprt &e2,
  const namespacet &ns)
{
  exprt a1=address_canonizer(address_of_exprt(e1), ns);
  exprt a2=address_canonizer(address_of_exprt(e2), ns);
  
  // in some cases, we can use plain address equality,
  // as we assume well-aligned-ness
  mp_integer size1=pointer_offset_size(e1.type(), ns);
  mp_integer size2=pointer_offset_size(e2.type(), ns);
  
  if(size1>=size2)
  {
    exprt lhs=a1;
    exprt rhs=a2;
    if(ns.follow(rhs.type())!=ns.follow(lhs.type()))
      rhs=typecast_exprt(rhs, lhs.type());
  
    return equal_exprt(lhs, rhs);
  }
  
  return same_object(a1, a2);
}
コード例 #6
0
void symex_target_equationt::assignment(
  const exprt &guard,
  const ssa_exprt &ssa_lhs,
  const exprt &ssa_full_lhs,
  const exprt &original_full_lhs,
  const exprt &ssa_rhs,
  const sourcet &source,
  assignment_typet assignment_type)
{
  assert(ssa_lhs.is_not_nil());
  
  SSA_steps.push_back(SSA_stept());
  SSA_stept &SSA_step=SSA_steps.back();
  
  SSA_step.guard=guard;
  SSA_step.ssa_lhs=ssa_lhs;
  SSA_step.ssa_full_lhs=ssa_full_lhs;
  SSA_step.original_full_lhs=original_full_lhs;
  SSA_step.ssa_rhs=ssa_rhs;
  SSA_step.assignment_type=assignment_type;

  SSA_step.cond_expr=equal_exprt(SSA_step.ssa_lhs, SSA_step.ssa_rhs);
  SSA_step.type=goto_trace_stept::ASSIGNMENT;
  SSA_step.hidden=(assignment_type!=STATE &&
                   assignment_type!=VISIBLE_ACTUAL_PARAMETER);
  SSA_step.source=source;

  merge_ireps(SSA_step);
}
コード例 #7
0
void symex_target_equationt::decl(
  const exprt &guard,
  const ssa_exprt &ssa_lhs,
  const sourcet &source,
  assignment_typet assignment_type)
{
  assert(ssa_lhs.is_not_nil());
  
  SSA_steps.push_back(SSA_stept());
  SSA_stept &SSA_step=SSA_steps.back();
  
  SSA_step.guard=guard;
  SSA_step.ssa_lhs=ssa_lhs;
  SSA_step.ssa_full_lhs=ssa_lhs;
  SSA_step.original_full_lhs=ssa_lhs.get_original_expr();
  SSA_step.type=goto_trace_stept::DECL;
  SSA_step.source=source;
  SSA_step.hidden=(assignment_type!=STATE);

  // the condition is trivially true, and only
  // there so we see the symbols
  SSA_step.cond_expr=equal_exprt(SSA_step.ssa_lhs, SSA_step.ssa_lhs);

  merge_ireps(SSA_step);
}
コード例 #8
0
ファイル: functions.cpp プロジェクト: dcattaruzza/cbmc
exprt functionst::arguments_equal(const exprt::operandst &o1,
                                  const exprt::operandst &o2)
{
  assert(o1.size()==o2.size());

  if(o1.empty())
    return true_exprt();

  and_exprt and_expr;
  and_exprt::operandst &conjuncts=and_expr.operands();
  conjuncts.resize(o1.size());

  for(std::size_t i=0; i<o1.size(); i++)
  {
    exprt lhs=o1[i];
    exprt rhs=o2[i];

    if(lhs.type()!=rhs.type())
      rhs.make_typecast(lhs.type());

    conjuncts[i]=equal_exprt(lhs, rhs);
  }

  return and_expr;
}
コード例 #9
0
ファイル: functions.cpp プロジェクト: dcattaruzza/cbmc
void functionst::add_function_constraints(const function_infot &info)
{
  // Do Ackermann's function reduction.
  // This is quadratic, slow, and needs to be modernized.

  for(std::set<function_application_exprt>::const_iterator
      it1=info.applications.begin();
      it1!=info.applications.end();
      it1++)
  {
    for(std::set<function_application_exprt>::const_iterator
        it2=info.applications.begin();
        it2!=it1;
        it2++)
    {
      exprt arguments_equal_expr=
        arguments_equal(it1->arguments(), it2->arguments());

      implies_exprt implication(arguments_equal_expr,
                                equal_exprt(*it1, *it2));

      prop_conv.set_to_true(implication);
    }
  }
}
コード例 #10
0
void symex_target_equationt::convert_io(
  decision_proceduret &dec_proc)
{
  unsigned io_count=0;

  for(SSA_stepst::iterator it=SSA_steps.begin();
      it!=SSA_steps.end(); it++)
    if(!it->ignore)
    {
      for(std::list<exprt>::const_iterator
          o_it=it->io_args.begin();
          o_it!=it->io_args.end();
          o_it++)
      {
        exprt tmp=*o_it;
        
        if(tmp.is_constant() ||
           tmp.id()==ID_string_constant)
          it->converted_io_args.push_back(tmp);
        else
        {
          symbol_exprt symbol;
          symbol.type()=tmp.type();
          symbol.set_identifier("symex::io::"+i2string(io_count++));
          dec_proc.set_to(equal_exprt(tmp, symbol), true);
          it->converted_io_args.push_back(symbol);
        }
      }
    }
}
コード例 #11
0
void symex_target_equationt::assignment(
  const guardt &guard,
  const symbol_exprt &ssa_lhs,
  const symbol_exprt &original_lhs_object,
  const exprt &ssa_full_lhs,
  const exprt &original_full_lhs,
  const exprt &ssa_rhs,
  const sourcet &source,
  assignment_typet assignment_type)
{
  assert(ssa_lhs.is_not_nil());
  
  SSA_steps.push_back(SSA_stept());
  SSA_stept &SSA_step=SSA_steps.back();
  
  SSA_step.guard_expr=guard.as_expr();
  SSA_step.ssa_lhs=ssa_lhs;
  SSA_step.original_lhs_object=original_lhs_object;
  SSA_step.ssa_full_lhs=ssa_full_lhs;
  SSA_step.original_full_lhs=original_full_lhs;
  SSA_step.ssa_rhs=ssa_rhs;
  SSA_step.assignment_type=assignment_type;

  SSA_step.cond_expr=equal_exprt(SSA_step.ssa_lhs, SSA_step.ssa_rhs);
  SSA_step.type=goto_trace_stept::ASSIGNMENT;
  SSA_step.source=source;
}
コード例 #12
0
ファイル: ssa_dereference.cpp プロジェクト: diffblue/2ls
exprt ssa_alias_guard(
  const exprt &e1,
  const exprt &e2,
  const namespacet &ns)
{
  exprt a1=address_canonizer(address_of_exprt(e1), ns);
  // TODO: We should compare 'base' pointers here because
  // we have a higher chance that there was no pointer arithmetic
  // on the base pointer than that the result of the pointer
  // arithmetic points to a base pointer.
  // The following hack does that:
  if(a1.id()==ID_plus)
    a1=a1.op0();

  exprt a2=address_canonizer(address_of_exprt(e2), ns);

  // in some cases, we can use plain address equality,
  // as we assume well-aligned-ness
  mp_integer size1=pointer_offset_size(e1.type(), ns);
  mp_integer size2=pointer_offset_size(e2.type(), ns);

  if(size1>=size2)
  {
    exprt lhs=a1;
    exprt rhs=a2;
    if(ns.follow(rhs.type())!=ns.follow(lhs.type()))
      rhs=typecast_exprt(rhs, lhs.type());

    return equal_exprt(lhs, rhs);
  }

  return same_object(a1, a2);
}
コード例 #13
0
ファイル: boolbv_with.cpp プロジェクト: lihaol/cbmc
void boolbvt::convert_with_bv(
  const typet &type,
  const exprt &op1,
  const exprt &op2,
  const bvt &prev_bv,
  bvt &next_bv)
{
  literalt l=convert(op2);

  mp_integer op1_value;
  if(!to_integer(op1, op1_value))
  {
    next_bv=prev_bv;

    if(op1_value<next_bv.size())
      next_bv[integer2size_t(op1_value)]=l;

    return;
  }

  typet counter_type=op1.type();

  for(std::size_t i=0; i<prev_bv.size(); i++)
  {
    exprt counter=from_integer(i, counter_type);

    literalt eq_lit=convert(equal_exprt(op1, counter));

    next_bv[i]=prop.lselect(eq_lit, l, prev_bv[i]);
  }
}
コード例 #14
0
exprt string_constraint_generatort::add_axioms_for_last_index_of_string(
  const string_exprt &str,
  const string_exprt &substring,
  const exprt &from_index)
{
  const typet &index_type=str.length().type();
  symbol_exprt offset=fresh_exist_index("index_of", index_type);
  symbol_exprt contains=fresh_boolean("contains_substring");

  // We add axioms:
  // a1 : contains => |substring| >= length &&offset <= from_index
  // a2 : !contains => offset=-1
  // a3 : forall 0 <= witness<substring.length,
  //        contains => str[witness+offset]=substring[witness]

  implies_exprt a1(
    contains,
    and_exprt(
      str.axiom_for_is_longer_than(plus_exprt(substring.length(), offset)),
      binary_relation_exprt(offset, ID_le, from_index)));
  axioms.push_back(a1);

  implies_exprt a2(
    not_exprt(contains),
    equal_exprt(offset, from_integer(-1, index_type)));
  axioms.push_back(a2);

  symbol_exprt qvar=fresh_univ_index("QA_index_of_string", index_type);
  equal_exprt constr3(str[plus_exprt(qvar, offset)], substring[qvar]);
  string_constraintt a3(qvar, substring.length(), contains, constr3);
  axioms.push_back(a3);

  return offset;
}
コード例 #15
0
exprt string_constraint_generatort::add_axioms_for_index_of(
  const string_exprt &str, const exprt &c, const exprt &from_index)
{
  const typet &index_type=str.length().type();
  symbol_exprt index=fresh_exist_index("index_of", index_type);
  symbol_exprt contains=fresh_boolean("contains_in_index_of");

  // We add axioms:
  // a1 : -1 <= index<|str|
  // a2 : !contains <=> index=-1
  // a3 : contains => from_index<=index&&str[index]=c
  // a4 : forall n, from_index<=n<index. contains => str[n]!=c
  // a5 : forall m, from_index<=n<|str|. !contains => str[m]!=c

  exprt minus1=from_integer(-1, index_type);
  and_exprt a1(
    binary_relation_exprt(index, ID_ge, minus1),
    binary_relation_exprt(index, ID_lt, str.length()));
  axioms.push_back(a1);

  equal_exprt a2(not_exprt(contains), equal_exprt(index, minus1));
  axioms.push_back(a2);

  implies_exprt a3(
    contains,
    and_exprt(
      binary_relation_exprt(from_index, ID_le, index),
      equal_exprt(str[index], c)));
  axioms.push_back(a3);

  symbol_exprt n=fresh_univ_index("QA_index_of", index_type);
  string_constraintt a4(
    n, from_index, index, contains, not_exprt(equal_exprt(str[n], c)));
  axioms.push_back(a4);

  symbol_exprt m=fresh_univ_index("QA_index_of", index_type);
  string_constraintt a5(
    m,
    from_index,
    str.length(),
    not_exprt(contains),
    not_exprt(equal_exprt(str[m], c)));
  axioms.push_back(a5);

  return index;
}
コード例 #16
0
ファイル: path_symex_history.cpp プロジェクト: Dthird/CBMC
void path_symex_stept::convert(decision_proceduret &dest) const
{
  if(ssa_rhs.is_not_nil())
    dest << equal_exprt(ssa_lhs, ssa_rhs);

  if(guard.is_not_nil())
    dest << guard;
}
コード例 #17
0
/// add axioms stating that the return value for two equal string should be the
/// same
/// \par parameters: function application with one string argument
/// \return a string expression
symbol_exprt string_constraint_generatort::add_axioms_for_intern(
  const function_application_exprt &f)
{
  string_exprt str=add_axioms_for_string_expr(args(f, 1)[0]);
  const typet &return_type=f.type();
  typet index_type=str.length().type();

  // initialisation of the missing pool variable
  std::map<irep_idt, string_exprt>::iterator it;
  for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++)
    if(pool.find(it->second)==pool.end())
      pool[it->second]=fresh_symbol("pool", return_type);

  // intern(str)=s_0 || s_1 || ...
  // for each string s.
  //    intern(str)=intern(s) || |str|!=|s|
  //    || (|str|==|s| &&exists i<|s|. s[i]!=str[i])

  exprt disj=false_exprt();
  for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++)
    disj=or_exprt(
      disj, equal_exprt(pool[str], symbol_exprt(it->first, return_type)));

  axioms.push_back(disj);


  // WARNING: the specification may be incomplete or incorrect
  for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++)
    if(it->second!=str)
    {
      symbol_exprt i=fresh_exist_index("index_intern", index_type);
      axioms.push_back(
        or_exprt(
          equal_exprt(pool[it->second], pool[str]),
          or_exprt(
            not_exprt(str.axiom_for_has_same_length_as(it->second)),
            and_exprt(
              str.axiom_for_has_same_length_as(it->second),
              and_exprt(
                not_exprt(equal_exprt(str[i], it->second[i])),
                and_exprt(str.axiom_for_is_strictly_longer_than(i),
                          axiom_for_is_positive_index(i)))))));
    }

  return pool[str];
}
コード例 #18
0
ファイル: predicate.cpp プロジェクト: AnnaTrost/2ls
void predicatet::set_to_true(decision_proceduret &dest) const
{
  // pass equalities to solver
    
  for(unsigned v=0; v<state_vars.size(); v++)
  {
    unsigned eq=uuf.find(v);
    if(eq!=v) dest.set_to_true(equal_exprt(state_vars[v], state_vars[eq]));
  }
}
コード例 #19
0
ファイル: equality_domain.cpp プロジェクト: diffblue/2ls
exprt equality_domaint::get_pre_equ_constraint(unsigned index)
{
  assert(index<templ.size());
  const template_rowt &templ_row=templ[index];
  if(templ_row.kind==OUT || templ_row.kind==OUTL)
    return true_exprt();

  const var_pairt &vv=templ_row.var_pair;
  return implies_exprt(templ_row.pre_guard, equal_exprt(vv.first, vv.second));
}
コード例 #20
0
/// returns an expression which is true when the two given characters are equal
/// when ignoring case for ASCII
/// \par parameters: two character expressions and constant character
///   expressions
/// representing 'a', 'A' and 'Z'
/// \return a expression of Boolean type
exprt string_constraint_generatort::character_equals_ignore_case(
  exprt char1, exprt char2, exprt char_a, exprt char_A, exprt char_Z)
{
  and_exprt is_upper_case_1(
    binary_relation_exprt(char_A, ID_le, char1),
    binary_relation_exprt(char1, ID_le, char_Z));
  and_exprt is_upper_case_2(
    binary_relation_exprt(char_A, ID_le, char2),
    binary_relation_exprt(char2, ID_le, char_Z));

  // Three possibilities:
  // p1 : char1=char2
  // p2 : (is_up1&&'a'-'A'+char1=char2)
  // p3 : (is_up2&&'a'-'A'+char2=char1)
  equal_exprt p1(char1, char2);
  minus_exprt diff=minus_exprt(char_a, char_A);
  and_exprt p2(is_upper_case_1, equal_exprt(plus_exprt(diff, char1), char2));
  and_exprt p3(is_upper_case_2, equal_exprt(plus_exprt(diff, char2), char1));
  return or_exprt(or_exprt(p1, p2), p3);
}
コード例 #21
0
ファイル: ranking_qbf_bitwise.cpp プロジェクト: olivo/BP
std::pair<exprt,exprt> ranking_synthesis_qbf_bitwiset::ite_template()
{
  exprt function;
  replace_mapt pre_replace_map;
    
  unsigned state_size = get_state_size();
  unsigned bits=log((double)state_size)/log(2.0) + 1;  
  
  symbol_exprt const_sym(CONSTANT_COEFFICIENT_ID, unsignedbv_typet(bits));
  const_coefficient=coefficient(const_sym);
    
  unsigned cnt=0;
  for(bodyt::variable_mapt::const_iterator it=body.variable_map.begin();
      it!=body.variable_map.end();
      it++)
  {
    if(used_variables.find(it->first)==used_variables.end())
      continue;
    
    exprt postsym=symbol_exprt(it->first, ns.lookup(it->first).type);
    exprt presym=symbol_exprt(it->second, ns.lookup(it->second).type);
        
    pre_replace_map[postsym] = presym; // save the corresponding pre-var
    exprt var=postsym;
    adjust_type(var.type());

    unsigned vwidth = safe_width(var, ns);
    for(unsigned i=0; i<vwidth; i++)
    {
      exprt t(ID_extractbit, bool_typet());
      t.copy_to_operands(var);
      t.copy_to_operands(from_integer(i, typet(ID_natural)));
      
      if(it==body.variable_map.begin() && i==0)
        function = t;
      else
      {
        function =           
          if_exprt(equal_exprt(const_coefficient, 
                                  from_integer(cnt, const_coefficient.type())),
                   t,
                   function);        
      }      
      
      cnt++;
    }
  }
  
  exprt pre_function=function;
  replace_expr(pre_replace_map, pre_function);
  
  return std::pair<exprt,exprt>(pre_function, function);
}
コード例 #22
0
ファイル: equality_domain.cpp プロジェクト: diffblue/2ls
exprt equality_domaint::to_pre_constraints(valuet &_value)
{
  if(check_dis)
    return get_pre_disequ_constraint(*e_it);
  assert(*e_it<templ.size());
  const template_rowt &templ_row=templ[*e_it];
  if(templ_row.kind==OUT || templ_row.kind==OUTL)
    return true_exprt();

  const var_pairt &vv=templ_row.var_pair;
  return implies_exprt(templ_row.pre_guard, equal_exprt(vv.first, vv.second));
}
コード例 #23
0
ファイル: equality_domain.cpp プロジェクト: diffblue/2ls
exprt equality_domaint::get_post_not_equ_constraint(unsigned index)
{
  assert(index<templ.size());
  const template_rowt &templ_row=templ[index];
  if(templ_row.kind==IN)
    return true_exprt();

  const var_pairt &vv=templ_row.var_pair;
  exprt c=
    and_exprt(
      templ_row.aux_expr,
      not_exprt(
        implies_exprt(
          templ_row.post_guard,
          equal_exprt(vv.first, vv.second))));
  rename(c);
  return c;
}
コード例 #24
0
/// add axioms stating that the result is true exactly when the strings
/// represented by the arguments are equal
/// \par parameters: function application with two string arguments
/// \return a expression of Boolean type
exprt string_constraint_generatort::add_axioms_for_equals(
  const function_application_exprt &f)
{
  assert(f.type()==bool_typet() || f.type().id()==ID_c_bool);
  symbol_exprt eq=fresh_boolean("equal");
  typecast_exprt tc_eq(eq, f.type());

  string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]);
  string_exprt s2=add_axioms_for_string_expr(args(f, 2)[1]);
  typet index_type=s1.length().type();

  // We want to write:
  // eq <=> (s1.length=s2.length  &&forall i<s1.length. s1[i]=s2[i])
  // We add axioms:
  // a1 : eq => s1.length=s2.length
  // a2 : forall i<s1.length. eq => s1[i]=s2[i]
  // a3 : !eq => s1.length!=s2.length
  //       || (witness<s1.length &&s1[witness]!=s2[witness])

  implies_exprt a1(eq, s1.axiom_for_has_same_length_as(s2));
  axioms.push_back(a1);

  symbol_exprt qvar=fresh_univ_index("QA_equal", index_type);
  string_constraintt a2(qvar, s1.length(), eq, equal_exprt(s1[qvar], s2[qvar]));
  axioms.push_back(a2);

  symbol_exprt witness=fresh_exist_index("witness_unequal", index_type);
  exprt zero=from_integer(0, index_type);
  and_exprt bound_witness(
    binary_relation_exprt(witness, ID_lt, s1.length()),
    binary_relation_exprt(witness, ID_ge, zero));
  and_exprt witnessing(bound_witness, notequal_exprt(s1[witness], s2[witness]));
  implies_exprt a3(
    not_exprt(eq),
    or_exprt(notequal_exprt(s1.length(), s2.length()), witnessing));
  axioms.push_back(a3);

  return tc_eq;
}
コード例 #25
0
void symex_target_equationt::decl(
  const guardt &guard,
  const symbol_exprt &ssa_lhs,
  const symbol_exprt &original_lhs_object,
  const sourcet &source)
{
  assert(ssa_lhs.is_not_nil());
  
  SSA_steps.push_back(SSA_stept());
  SSA_stept &SSA_step=SSA_steps.back();
  
  SSA_step.guard_expr=guard.as_expr();
  SSA_step.ssa_lhs=ssa_lhs;
  SSA_step.ssa_full_lhs=ssa_lhs;
  SSA_step.original_lhs_object=original_lhs_object;
  SSA_step.original_full_lhs=original_lhs_object;
  SSA_step.type=goto_trace_stept::DECL;
  SSA_step.source=source;

  // the condition is trivially true, and only
  // there so we see the symbols
  SSA_step.cond_expr=equal_exprt(SSA_step.ssa_lhs, SSA_step.ssa_lhs);
}
コード例 #26
0
ファイル: polynomial_accelerator.cpp プロジェクト: bkolb/cbmc
bool polynomial_acceleratort::fit_const(goto_programt::instructionst &body,
                                        exprt &target,
                                        polynomialt &poly) {
  return false;

  scratch_programt program(symbol_table);

  program.append(body);
  program.add_instruction(ASSERT)->guard = equal_exprt(target, not_exprt(target));

  try {
    if (program.check_sat(false)) {
#ifdef DEBUG
      std::cout << "Fitting constant, eval'd to: " << expr2c(program.eval(target), ns) << std::endl;
#endif
      constant_exprt val = to_constant_expr(program.eval(target));
      mp_integer mp = binary2integer(val.get_value().c_str(), true);
      monomialt mon;
      monomialt::termt term;

      term.var = from_integer(1, target.type());
      term.exp = 1;
      mon.terms.push_back(term);
      mon.coeff = mp.to_long();

      poly.monomials.push_back(mon);

      return true;
    }
  } catch (std::string s) {
    std::cout << "Error in fitting polynomial SAT check: " << s << std::endl;
  } catch (const char *s) {
    std::cout << "Error in fitting polynomial SAT check: " << s << std::endl;
  }

  return false;
}
コード例 #27
0
ファイル: polynomial_accelerator.cpp プロジェクト: bkolb/cbmc
bool polynomial_acceleratort::check_inductive(
  std::map<exprt, polynomialt> polynomials,
  goto_programt::instructionst &body)
{
  // Checking that our polynomial is inductive with respect to the loop body is
  // equivalent to checking safety of the following program:
  //
  // assume (target1 == polynomial1);
  // assume (target2 == polynomial2)
  // ...
  // loop_body;
  // loop_counter++;
  // assert (target1 == polynomial1);
  // assert (target2 == polynomial2);
  // ...
  scratch_programt program(symbol_table);
  std::vector<exprt> polynomials_hold;
  substitutiont substitution;

  stash_polynomials(program, polynomials, substitution, body);
 
  for (std::map<exprt, polynomialt>::iterator it = polynomials.begin();
       it != polynomials.end();
       ++it) {
    exprt holds = equal_exprt(it->first, it->second.to_expr());
    program.add_instruction(ASSUME)->guard = holds;

    polynomials_hold.push_back(holds);
  }

  program.append(body);

  codet inc_loop_counter = code_assignt(loop_counter,
                                        plus_exprt(loop_counter, from_integer(1, loop_counter.type())));
  program.add_instruction(ASSIGN)->code = inc_loop_counter;

  for (std::vector<exprt>::iterator it = polynomials_hold.begin();
       it != polynomials_hold.end();
       ++it) {
    program.add_instruction(ASSERT)->guard = *it;
  }

#ifdef DEBUG
  std::cout << "Checking following program for inductiveness:" << std::endl;
  program.output(ns, "", std::cout);
#endif

  try {
    if (program.check_sat()) {
      // We found a counterexample to inductiveness... :-(
  #ifdef DEBUG
      std::cout << "Not inductive!" << std::endl;
  #endif
    return false;
    } else {
      return true;
    }
  } catch (std::string s) {
    std::cout << "Error in inductiveness SAT check: " << s << std::endl;
    return false;
  } catch (const  char *s) {
    std::cout << "Error in inductiveness SAT check: " << s << std::endl;
    return false;
  }
}
コード例 #28
0
ファイル: polynomial_accelerator.cpp プロジェクト: bkolb/cbmc
void polynomial_acceleratort::assert_for_values(scratch_programt &program,
                                                std::map<exprt, int> &values,
                                                std::set<std::pair<expr_listt, exprt> >
                                                   &coefficients,
                                                int num_unwindings,
                                                goto_programt::instructionst
                                                   &loop_body,
                                                exprt &target,
                                                overflow_instrumentert &overflow) {
  // First figure out what the appropriate type for this expression is.
  typet expr_type = nil_typet();

  for (std::map<exprt, int>::iterator it = values.begin();
      it != values.end();
      ++it) {
    typet this_type=it->first.type();
    if (this_type.id() == ID_pointer) {
#ifdef DEBUG
      std::cout << "Overriding pointer type" << std::endl;
#endif
      this_type = unsignedbv_typet(config.ansi_c.pointer_width);
    }

    if (expr_type == nil_typet()) {
      expr_type = this_type;
    } else {
      expr_type = join_types(expr_type, this_type);
    }
  }

  assert(to_bitvector_type(expr_type).get_width()>0);


  // Now set the initial values of the all the variables...
  for (std::map<exprt, int>::iterator it = values.begin();
       it != values.end();
       ++it) {
    program.assign(it->first, from_integer(it->second, expr_type));
  }

  // Now unwind the loop as many times as we need to.
  for (int i = 0; i < num_unwindings; i++) {
    program.append(loop_body);
  }

  // Now build the polynomial for this point and assert it fits.
  exprt rhs = nil_exprt();

  for (std::set<std::pair<expr_listt, exprt> >::iterator it = coefficients.begin();
       it != coefficients.end();
       ++it) {
    int concrete_value = 1;

    for (expr_listt::const_iterator e_it = it->first.begin();
         e_it != it->first.end();
         ++e_it) {
      exprt e = *e_it;

      if (e == loop_counter) {
        concrete_value *= num_unwindings;
      } else {
        std::map<exprt, int>::iterator v_it = values.find(e);

        if (v_it != values.end()) {
          concrete_value *= v_it->second;
        }
      }
    }

    // OK, concrete_value now contains the value of all the relevant variables
    // multiplied together.  Create the term concrete_value*coefficient and add
    // it into the polynomial.
    typecast_exprt cast(it->second, expr_type);
    exprt term = mult_exprt(from_integer(concrete_value, expr_type), cast);

    if (rhs.is_nil()) {
      rhs = term;
    } else {
      rhs = plus_exprt(rhs, term);
    }
  }

  exprt overflow_expr;
  overflow.overflow_expr(rhs, overflow_expr);

  program.add_instruction(ASSUME)->guard = not_exprt(overflow_expr);

  rhs = typecast_exprt(rhs, target.type());

  // We now have the RHS of the polynomial.  Assert that this is equal to the
  // actual value of the variable we're fitting.
  exprt polynomial_holds = equal_exprt(target, rhs);

  // Finally, assert that the polynomial equals the variable we're fitting.
  goto_programt::targett assumption = program.add_instruction(ASSUME);
  assumption->guard = polynomial_holds;
}
コード例 #29
0
void remove_virtual_functionst::remove_virtual_function(
  goto_programt &goto_program,
  goto_programt::targett target)
{
  const code_function_callt &code=
    to_code_function_call(target->code);

  const auto &vcall_source_loc=target->source_location;

  const exprt &function=code.function();
  assert(function.id()==ID_virtual_function);
  assert(!code.arguments().empty());

  functionst functions;
  get_functions(function, functions);

  if(functions.empty())
  {
    target->make_skip();
    return; // give up
  }

  // only one option?
  if(functions.size()==1)
  {
    assert(target->is_function_call());
    if(functions.begin()->symbol_expr==symbol_exprt())
      target->make_skip();
    else
      to_code_function_call(target->code).function()=
        functions.begin()->symbol_expr;
    return;
  }

  // the final target is a skip
  goto_programt final_skip;

  goto_programt::targett t_final=final_skip.add_instruction();
  t_final->source_location=vcall_source_loc;

  t_final->make_skip();

  // build the calls and gotos

  goto_programt new_code_calls;
  goto_programt new_code_gotos;

  exprt this_expr=code.arguments()[0];
  // If necessary, cast to the last candidate function to
  // get the object's clsid. By the structure of get_functions,
  // this is the parent of all other classes under consideration.
  const auto &base_classid=functions.back().class_id;
  const auto &base_function_symbol=functions.back().symbol_expr;
  symbol_typet suggested_type(base_classid);
  exprt c_id2=get_class_identifier_field(this_expr, suggested_type, ns);

  std::map<irep_idt, goto_programt::targett> calls;
  // Note backwards iteration, to get the least-derived candidate first.
  for(auto it=functions.crbegin(), itend=functions.crend(); it!=itend; ++it)
  {
    const auto &fun=*it;
    auto insertit=calls.insert(
      {fun.symbol_expr.get_identifier(), goto_programt::targett()});

    // Only create one call sequence per possible target:
    if(insertit.second)
    {
      goto_programt::targett t1=new_code_calls.add_instruction();
      t1->source_location=vcall_source_loc;
      if(!fun.symbol_expr.get_identifier().empty())
      {
      // call function
        t1->make_function_call(code);
        auto &newcall=to_code_function_call(t1->code);
        newcall.function()=fun.symbol_expr;
        pointer_typet need_type(symbol_typet(fun.symbol_expr.get(ID_C_class)));
        if(!type_eq(newcall.arguments()[0].type(), need_type, ns))
          newcall.arguments()[0].make_typecast(need_type);
      }
      else
      {
        // No definition for this type; shouldn't be possible...
        t1->make_assertion(false_exprt());
      }
      insertit.first->second=t1;
      // goto final
      goto_programt::targett t3=new_code_calls.add_instruction();
      t3->source_location=vcall_source_loc;
      t3->make_goto(t_final, true_exprt());
    }

    // If this calls the base function we just fall through.
    // Otherwise branch to the right call:
    if(fun.symbol_expr!=base_function_symbol)
    {
      exprt c_id1=constant_exprt(fun.class_id, string_typet());
      goto_programt::targett t4=new_code_gotos.add_instruction();
      t4->source_location=vcall_source_loc;
      t4->make_goto(insertit.first->second, equal_exprt(c_id1, c_id2));
    }
  }

  goto_programt new_code;

  // patch them all together
  new_code.destructive_append(new_code_gotos);
  new_code.destructive_append(new_code_calls);
  new_code.destructive_append(final_skip);

  // set locations
  Forall_goto_program_instructions(it, new_code)
  {
    const irep_idt property_class=it->source_location.get_property_class();
    const irep_idt comment=it->source_location.get_comment();
    it->source_location=target->source_location;
    it->function=target->function;
    if(!property_class.empty())
      it->source_location.set_property_class(property_class);
    if(!comment.empty())
      it->source_location.set_comment(comment);
  }

  goto_programt::targett next_target=target;
  next_target++;

  goto_program.destructive_insert(next_target, new_code);

  // finally, kill original invocation
  target->make_skip();
}
コード例 #30
0
/// add axioms corresponding to the String.compareTo java function
/// \par parameters: function application with two string arguments
/// \return a integer expression
exprt string_constraint_generatort::add_axioms_for_compare_to(
  const function_application_exprt &f)
{
  string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]);
  string_exprt s2=add_axioms_for_string_expr(args(f, 2)[1]);
  const typet &return_type=f.type();
  symbol_exprt res=fresh_symbol("compare_to", return_type);
  typet index_type=s1.length().type();

  // In the lexicographic comparison, x is the first point where the two
  // strings differ.
  // We add axioms:
  // a1 : res==0 => |s1|=|s2|
  // a2 : forall i<|s1|. s1[i]==s2[i]
  // a3 : exists x.
  // res!=0 ==> x> 0 &&
  //   ((|s1| <= |s2| &&x<|s1|) || (|s1| >= |s2| &&x<|s2|)
  //   &&res=s1[x]-s2[x] )
  // || cond2:
  //   (|s1|<|s2| &&x=|s1|) || (|s1| > |s2| &&x=|s2|) &&res=|s1|-|s2|)
  // a4 : forall i<x. res!=0 => s1[i]=s2[i]

  assert(return_type.id()==ID_signedbv);

  equal_exprt res_null=equal_exprt(res, from_integer(0, return_type));
  implies_exprt a1(res_null, s1.axiom_for_has_same_length_as(s2));
  axioms.push_back(a1);

  symbol_exprt i=fresh_univ_index("QA_compare_to", index_type);
  string_constraintt a2(i, s1.length(), res_null, equal_exprt(s1[i], s2[i]));
  axioms.push_back(a2);

  symbol_exprt x=fresh_exist_index("index_compare_to", index_type);
  equal_exprt ret_char_diff(
    res,
    minus_exprt(
      typecast_exprt(s1[x], return_type),
      typecast_exprt(s2[x], return_type)));
  equal_exprt ret_length_diff(
    res,
    minus_exprt(
      typecast_exprt(s1.length(), return_type),
      typecast_exprt(s2.length(), return_type)));
  or_exprt guard1(
    and_exprt(s1.axiom_for_is_shorter_than(s2),
              s1.axiom_for_is_strictly_longer_than(x)),
    and_exprt(s1.axiom_for_is_longer_than(s2),
              s2.axiom_for_is_strictly_longer_than(x)));
  and_exprt cond1(ret_char_diff, guard1);
  or_exprt guard2(
    and_exprt(s2.axiom_for_is_strictly_longer_than(s1),
              s1.axiom_for_has_length(x)),
    and_exprt(s1.axiom_for_is_strictly_longer_than(s2),
              s2.axiom_for_has_length(x)));
  and_exprt cond2(ret_length_diff, guard2);

  implies_exprt a3(
    not_exprt(res_null),
    and_exprt(
      binary_relation_exprt(x, ID_ge, from_integer(0, return_type)),
      or_exprt(cond1, cond2)));
  axioms.push_back(a3);

  string_constraintt a4(i, x, not_exprt(res_null), equal_exprt(s1[i], s2[i]));
  axioms.push_back(a4);

  return res;
}