Example #1
0
void goto_convertt::convert_CPROVER_throw(
  const codet &code,
  goto_programt &dest)
{
  // set the 'exception' flag
  {
    goto_programt::targett t_set_exception=
      dest.add_instruction(ASSIGN);

    t_set_exception->source_location=code.source_location();
    t_set_exception->code=code_assignt(exception_flag(), true_exprt());
  }

  // do we catch locally?
  if(targets.throw_set)
  {
    // need to process destructor stack
    unwind_destructor_stack(code.source_location(), targets.throw_stack_size, dest);

    // add goto
    goto_programt::targett t=dest.add_instruction();
    t->make_goto(targets.throw_target);
    t->source_location=code.source_location();
  }
  else // otherwise, we do a return
  {
    // need to process destructor stack
    unwind_destructor_stack(code.source_location(), 0, dest);

    // add goto
    goto_programt::targett t=dest.add_instruction();
    t->make_goto(targets.return_target);
    t->source_location=code.source_location();
  }
}
Example #2
0
void goto_convertt::convert_try_catch(
  const codet &code,
  goto_programt &dest)
{
  assert(code.operands().size()>=2);
  
  // add the CATCH-push instruction to 'dest'
  goto_programt::targett catch_push_instruction=dest.add_instruction();
  catch_push_instruction->make_catch();
  catch_push_instruction->code.set_statement(ID_catch);
  catch_push_instruction->source_location=code.source_location();
  
  // the CATCH-push instruction is annotated with a list of IDs,
  // one per target
  irept::subt &exception_list=
    catch_push_instruction->code.add(ID_exception_list).get_sub();

  // add a SKIP target for the end of everything
  goto_programt end;
  goto_programt::targett end_target=end.add_instruction();
  end_target->make_skip();
  
  // the first operand is the 'try' block
  convert(to_code(code.op0()), dest);
  
  // add the CATCH-pop to the end of the 'try' block
  goto_programt::targett catch_pop_instruction=dest.add_instruction();
  catch_pop_instruction->make_catch();
  catch_pop_instruction->code.set_statement(ID_catch);
  
  // add a goto to the end of the 'try' block
  dest.add_instruction()->make_goto(end_target);

  for(unsigned i=1; i<code.operands().size(); i++)
  {
    const codet &block=to_code(code.operands()[i]);
  
    // grab the ID and add to CATCH instruction
    exception_list.push_back(irept(block.get(ID_exception_id)));
    
    goto_programt tmp;
    convert(block, tmp);
    catch_push_instruction->targets.push_back(tmp.instructions.begin());
    dest.destructive_append(tmp);

    // add a goto to the end of the 'catch' block
    dest.add_instruction()->make_goto(end_target);
  }

  // add the end-target  
  dest.destructive_append(end);
}
Example #3
0
void remove_function_pointerst::fix_return_type(
  code_function_callt &function_call,
  goto_programt &dest)
{  
  // are we returning anything at all?
  if(function_call.lhs().is_nil()) return;
  
  const code_typet &code_type=
    to_code_type(ns.follow(function_call.function().type()));
  
  // type already ok?
  if(type_eq(
       function_call.lhs().type(),
       code_type.return_type(), ns))
    return;

  symbolt &tmp_symbol=new_tmp_symbol();
  tmp_symbol.type=code_type.return_type();
  tmp_symbol.location=function_call.location();

  symbol_exprt tmp_symbol_expr;
  tmp_symbol_expr.type()=tmp_symbol.type;
  tmp_symbol_expr.set_identifier(tmp_symbol.name);
  
  exprt old_lhs=function_call.lhs();
  function_call.lhs()=tmp_symbol_expr;

  goto_programt::targett t_assign=dest.add_instruction();
  t_assign->make_assignment();
  t_assign->code=code_assignt(
    old_lhs, typecast_exprt(tmp_symbol_expr, old_lhs.type()));
}  
Example #4
0
void goto_convertt::convert_msc_leave(
  const codet &code,
  goto_programt &dest)
{
  if(!targets.leave_set)
  {
    error().source_location=code.find_source_location();
    error() << "leave without target" << eom;
    throw 0;
  }
  
  // need to process destructor stack
  for(unsigned d=targets.destructor_stack.size();
      d!=targets.leave_stack_size;
      d--)
  {
    codet d_code=targets.destructor_stack[d-1];
    d_code.add_source_location()=code.source_location();
    convert(d_code, dest);
  }

  goto_programt::targett t=dest.add_instruction();
  t->make_goto(targets.leave_target);
  t->source_location=code.source_location();
}
void goto_convertt::convert_java_try_catch(
  const codet &code,
  goto_programt &dest)
{
  assert(!code.operands().empty());

  // add the CATCH instruction to 'dest'
  goto_programt::targett catch_instruction=dest.add_instruction();
  catch_instruction->make_catch();
  catch_instruction->code.set_statement(ID_catch);
  catch_instruction->source_location=code.source_location();
  catch_instruction->function=code.source_location().get_function();

  // the CATCH instruction is annotated with a list of exception IDs
  const irept exceptions=code.op0().find(ID_exception_list);
  if(exceptions.is_not_nil())
  {
    irept::subt exceptions_sub=exceptions.get_sub();
    irept::subt &exception_list=
      catch_instruction->code.add(ID_exception_list).get_sub();
    exception_list.resize(exceptions_sub.size());
    for(size_t i=0; i<exceptions_sub.size(); ++i)
      exception_list[i].id(exceptions_sub[i].id());
  }

  // the CATCH instruction is also annotated with a list of handle labels
  const irept handlers=code.op0().find(ID_label);
  if(handlers.is_not_nil())
  {
    irept::subt handlers_sub=handlers.get_sub();
    irept::subt &handlers_list=
      catch_instruction->code.add(ID_label).get_sub();
    handlers_list.resize(handlers_sub.size());
    for(size_t i=0; i<handlers_sub.size(); ++i)
      handlers_list[i].id(handlers_sub[i].id());
  }

  // the CATCH instruction may also signal a handler
  if(code.op0().has_operands())
  {
    catch_instruction->code.get_sub().resize(1);
    catch_instruction->code.get_sub()[0]=code.op0().op0();
  }

  // add a SKIP target for the end of everything
  goto_programt end;
  goto_programt::targett end_target=end.add_instruction();
  end_target->make_skip();
  end_target->source_location=code.source_location();
  end_target->function=code.source_location().get_function();

  // add the end-target
  dest.destructive_append(end);
}
void goto_convertt::do_java_new(
  const exprt &lhs,
  const side_effect_exprt &rhs,
  goto_programt &dest)
{
  if(lhs.is_nil())
    throw "do_java_new without lhs is yet to be implemented";
    
  source_locationt location=rhs.source_location();

  assert(rhs.operands().empty());

  if(rhs.type().id()!=ID_pointer)
    throw "do_java_new returns pointer";

  typet object_type=rhs.type().subtype();
  
  // build size expression
  exprt object_size=size_of_expr(object_type, ns);
  
  if(object_size.is_nil())
    throw "do_java_new got nil object_size";

  // we produce a malloc side-effect, which stays
  side_effect_exprt malloc_expr(ID_malloc);
  malloc_expr.copy_to_operands(object_size);
  malloc_expr.type()=pointer_typet(object_type);

  goto_programt::targett t_n=dest.add_instruction(ASSIGN);
  t_n->code=code_assignt(lhs, malloc_expr);
  t_n->source_location=location;
  
  // zero-initialize the object
  dereference_exprt deref(lhs, object_type);
  exprt zero_object=zero_initializer(object_type, location, ns, get_message_handler());
  set_class_identifier(to_struct_expr(zero_object), ns, to_symbol_type(object_type));
  goto_programt::targett t_i=dest.add_instruction(ASSIGN);
  t_i->code=code_assignt(deref, zero_object);
  t_i->source_location=location;
}
Example #7
0
void goto_checkt::add_guarded_claim(
  const exprt &_expr,
  const std::string &comment,
  const std::string &property_class,
  const source_locationt &source_location,
  const exprt &src_expr,
  const guardt &guard)
{
  exprt expr(_expr);

  // first try simplifier on it
  if(enable_simplify)
    simplify(expr, ns);

  // throw away trivial properties?
  if(!retain_trivial && expr.is_true())
    return;

  // add the guard
  exprt guard_expr=guard.as_expr();

  exprt new_expr;

  if(guard_expr.is_true())
    new_expr.swap(expr);
  else
  {
    new_expr=exprt(ID_implies, bool_typet());
    new_expr.move_to_operands(guard_expr, expr);
  }

  if(assertions.insert(new_expr).second)
  {
    goto_program_instruction_typet type=
      enable_assert_to_assume?ASSUME:ASSERT;

    goto_programt::targett t=new_code.add_instruction(type);

    std::string source_expr_string=from_expr(ns, "", src_expr);

    t->guard.swap(new_expr);
    t->source_location=source_location;
    t->source_location.set_comment(comment+" in "+source_expr_string);
    t->source_location.set_property_class(property_class);
  }
}
void goto_convertt::do_function_call_other(
  const exprt &lhs,
  const exprt &function,
  const exprt::operandst &arguments,
  goto_programt &dest)
{
  // don't know what to do with it
  goto_programt::targett t=dest.add_instruction(FUNCTION_CALL);

  code_function_callt function_call;
  function_call.add_source_location()=function.source_location();
  function_call.lhs()=lhs;
  function_call.function()=function;
  function_call.arguments()=arguments;

  t->source_location=function.source_location();
  t->code.swap(function_call);
}
Example #9
0
void goto_checkt::add_guarded_claim(const exprt &_expr,
    const std::string &comment, const std::string &property,
    const locationt &location, const guardt &guard)
{
  bool all_claims = options.get_bool_option("all-claims");
  exprt expr(_expr);

  // first try simplifier on it
  if (!options.get_bool_option("no-simplify"))
  {
    expr2tc tmpexpr;
    migrate_expr(expr, tmpexpr);
    base_type(tmpexpr, ns);
    expr = migrate_expr_back(tmpexpr);
    simplify(expr);
  }

  if (!all_claims && expr.is_true())
    return;

  // add the guard
  exprt guard_expr = migrate_expr_back(guard.as_expr());

  exprt new_expr;

  if (guard_expr.is_true())
    new_expr.swap(expr);
  else
  {
    new_expr = exprt("=>", bool_typet());
    new_expr.move_to_operands(guard_expr, expr);
  }

  if (assertions.insert(new_expr).second)
  {
    goto_programt::targett t = new_code.add_instruction(ASSERT);
    migrate_expr(new_expr, t->guard);

    t->location = location;
    t->location.comment(comment);
    t->location.property(property);
  }
}
Example #10
0
void havoc_loopst::build_havoc_code(
  const goto_programt::targett loop_head,
  const modifiest &modifies,
  goto_programt &dest)
{
  for(modifiest::const_iterator
      m_it=modifies.begin();
      m_it!=modifies.end();
      m_it++)
  {
    exprt lhs=*m_it;
    exprt rhs=side_effect_expr_nondett(lhs.type());

    goto_programt::targett t=dest.add_instruction(ASSIGN);
    t->function=loop_head->function;
    t->source_location=loop_head->source_location;
    t->code=code_assignt(lhs, rhs);
    t->code.add_source_location()=loop_head->source_location;
  }
}
void goto_convertt::do_atomic_end(
  const exprt &lhs,
  const exprt &function,
  const exprt::operandst &arguments,
  goto_programt &dest)
{
  if(lhs.is_not_nil())
  {
    err_location(lhs);
    throw "atomic_end does not expect an LHS";
  }

  if(!arguments.empty())
  {
    err_location(function);
    throw "atomic_end takes no arguments";
  }

  goto_programt::targett t=dest.add_instruction(ATOMIC_END);
  t->source_location=function.source_location();
}
Example #12
0
void goto_inlinet::parameter_destruction(
  const source_locationt &source_location,
  const irep_idt &function_name,
  const code_typet &code_type,
  goto_programt &dest)
{
  const code_typet::parameterst &parameter_types=
    code_type.parameters();
  
  // iterates over the types of the parameters
  for(code_typet::parameterst::const_iterator
      it=parameter_types.begin();
      it!=parameter_types.end();
      it++)
  {
    const code_typet::parametert &parameter=*it;

    const irep_idt &identifier=parameter.get_identifier();

    if(identifier==irep_idt())
    {
      error().source_location=source_location;
      error() << "no identifier for function parameter" << eom;
      throw 0;
    }

    {
      const symbolt &symbol=ns.lookup(identifier);

      goto_programt::targett dead=dest.add_instruction();
      dead->make_dead();
      dead->code=code_deadt(symbol.symbol_expr());
      dead->code.add_source_location()=source_location;
      dead->source_location=source_location;
      dead->function=function_name; 
    }
  }
}
Example #13
0
void string_instrumentationt::invalidate_buffer(
  goto_programt &dest,
  goto_programt::const_targett target,
  const exprt &buffer,
  const typet &buf_type,
  const mp_integer &limit)
{
  irep_idt cntr_id="string_instrumentation::$counter";
  
  if(context.symbols.find(cntr_id)==context.symbols.end())
  {
    symbolt new_symbol;
    new_symbol.base_name="$counter";
    new_symbol.pretty_name=new_symbol.base_name;
    new_symbol.name=cntr_id;
    new_symbol.mode="C";
    new_symbol.type=uint_type();
    new_symbol.is_statevar=true;
    new_symbol.lvalue=true;
    new_symbol.static_lifetime=true;
    
    context.move(new_symbol);
  }
  
  const symbolt &cntr_sym=ns.lookup(cntr_id);
  
  // create a loop that runs over the buffer
  // and invalidates every element
  
  goto_programt::targett init=dest.add_instruction(ASSIGN);
  init->location=target->location;  
  init->code=code_assignt(symbol_expr(cntr_sym), gen_zero(cntr_sym.type));
  
  goto_programt::targett check=dest.add_instruction();
  check->location=target->location;  
  
  goto_programt::targett invalidate=dest.add_instruction(ASSIGN);
  invalidate->location=target->location;  
  
  goto_programt::targett increment=dest.add_instruction(ASSIGN);
  increment->location=target->location;  
  
  exprt plus("+", uint_type());
  plus.copy_to_operands(symbol_expr(cntr_sym));
  plus.copy_to_operands(gen_one(uint_type()));
  
  increment->code=code_assignt(symbol_expr(cntr_sym), plus);
  
  goto_programt::targett back=dest.add_instruction();
  back->location=target->location;  
  back->make_goto(check);
  back->guard=true_exprt();
  
  goto_programt::targett exit=dest.add_instruction();
  exit->location=target->location;  
  exit->make_skip();  
  
  exprt cnt_bs, bufp;
  
  if(buf_type.id()=="pointer")
    bufp = buffer;
  else
  {
    index_exprt index;
    index.array()=buffer;
    index.index()=gen_zero(uint_type());
    index.type()=buf_type.subtype();
    bufp = address_of_exprt(index);
  }
  
  exprt deref("dereference", buf_type.subtype());
  exprt b_plus_i("+", bufp.type());
  b_plus_i.copy_to_operands(bufp);
  b_plus_i.copy_to_operands(symbol_expr(cntr_sym));
  deref.copy_to_operands(b_plus_i);
  
  check->make_goto(exit);
  
  if(limit==0)
    check->guard=
          binary_relation_exprt(symbol_expr(cntr_sym), ">=", 
                                buffer_size(bufp));
  else
    check->guard=
          binary_relation_exprt(symbol_expr(cntr_sym), ">", 
                                from_integer(limit, uint_type()));
  
  exprt nondet=side_effect_expr_nondett(buf_type.subtype());
  invalidate->code=code_assignt(deref, nondet);
}
Example #14
0
void goto_inlinet::parameter_assignments(
  const source_locationt &source_location,
  const irep_idt &function_name,
  const code_typet &code_type,
  const exprt::operandst &arguments,
  goto_programt &dest)
{
  // iterates over the operands
  exprt::operandst::const_iterator it1=arguments.begin();

  const code_typet::parameterst &parameter_types=
    code_type.parameters();
  
  // iterates over the types of the parameters
  for(code_typet::parameterst::const_iterator
      it2=parameter_types.begin();
      it2!=parameter_types.end();
      it2++)
  {
    const code_typet::parametert &parameter=*it2;

    // this is the type the n-th argument should be
    const typet &par_type=ns.follow(parameter.type());

    const irep_idt &identifier=parameter.get_identifier();

    if(identifier==irep_idt())
    {
      error().source_location=source_location;
      error() << "no identifier for function parameter" << eom;
      throw 0;
    }

    {
      const symbolt &symbol=ns.lookup(identifier);

      goto_programt::targett decl=dest.add_instruction();
      decl->make_decl();
      decl->code=code_declt(symbol.symbol_expr());
      decl->code.add_source_location()=source_location;
      decl->source_location=source_location;
      decl->function=function_name; 
    }

    // this is the actual parameter
    exprt actual;

    // if you run out of actual arguments there was a mismatch
    if(it1==arguments.end())
    {
      warning().source_location=source_location;
      warning() << "call to `" << function_name << "': "
                << "not enough arguments, "
                << "inserting non-deterministic value" << eom;

      actual=side_effect_expr_nondett(par_type);
    }
    else
      actual=*it1;

    // nil means "don't assign"
    if(actual.is_nil())
    {    
    }
    else
    {
      // it should be the same exact type as the parameter,
      // subject to some exceptions
      if(!base_type_eq(par_type, actual.type(), ns))
      {
        const typet &f_partype = ns.follow(par_type);
        const typet &f_acttype = ns.follow(actual.type());
        
        // we are willing to do some conversion
        if((f_partype.id()==ID_pointer &&
            f_acttype.id()==ID_pointer) ||
           (f_partype.id()==ID_pointer &&
            f_acttype.id()==ID_array &&
            f_partype.subtype()==f_acttype.subtype()))
        {
          actual.make_typecast(par_type);
        }
        else if((f_partype.id()==ID_signedbv ||
                 f_partype.id()==ID_unsignedbv ||
                 f_partype.id()==ID_bool) &&
                (f_acttype.id()==ID_signedbv ||
                 f_acttype.id()==ID_unsignedbv ||
                 f_acttype.id()==ID_bool))  
        {
          actual.make_typecast(par_type);
        }
        else
        {
          error().source_location=actual.find_source_location();

          error() << "function call: argument `" << identifier
                  << "' type mismatch: argument is `"
                  // << from_type(ns, identifier, actual.type())
                  << actual.type().pretty()
                  << "', parameter is `"
                  << from_type(ns, identifier, par_type)
                  << "'" << eom;
          throw 0;
        }
      }

      // adds an assignment of the actual parameter to the formal parameter
      code_assignt assignment(symbol_exprt(identifier, par_type), actual);
      assignment.add_source_location()=source_location;

      dest.add_instruction(ASSIGN);
      dest.instructions.back().source_location=source_location;
      dest.instructions.back().code.swap(assignment);
      dest.instructions.back().function=function_name;      
    }

    if(it1!=arguments.end())
      ++it1;
  }

  if(it1!=arguments.end())
  {
    // too many arguments -- we just ignore that, no harm done
  }
}
void goto_convertt::do_function_call_symbol(
  const exprt &lhs,
  const symbol_exprt &function,
  const exprt::operandst &arguments,
  goto_programt &dest)
{
  if(function.get_bool("#invalid_object"))
    return; // ignore

  // lookup symbol
  const irep_idt &identifier=function.get_identifier();

  const symbolt *symbol;
  if(ns.lookup(identifier, symbol))
  {
    err_location(function);
    throw "error: function `"+id2string(identifier)+"' not found";
  }

  if(symbol->type.id()!=ID_code)
  {
    err_location(function);
    throw "error: function `"+id2string(identifier)+"' type mismatch: expected code";
  }
  
  if(identifier==CPROVER_PREFIX "assume" ||
     identifier=="__VERIFIER_assume")
  {
    if(arguments.size()!=1)
    {
      err_location(function);
      throw "`"+id2string(identifier)+"' expected to have one argument";
    }

    goto_programt::targett t=dest.add_instruction(ASSUME);
    t->guard=arguments.front();
    t->source_location=function.source_location();
    t->source_location.set("user-provided", true);
    
    // let's double-check the type of the argument
    if(t->guard.type().id()!=ID_bool)
      t->guard.make_typecast(bool_typet());

    if(lhs.is_not_nil())
    {
      err_location(function);
      throw id2string(identifier)+" expected not to have LHS";
    }
  }
  else if(identifier=="__VERIFIER_error")
  {
    if(!arguments.empty())
    {
      err_location(function);
      throw "`"+id2string(identifier)+"' expected to have no arguments";
    }

    goto_programt::targett t=dest.add_instruction(ASSERT);
    t->guard=false_exprt();
    t->source_location=function.source_location();
    t->source_location.set("user-provided", true);
    t->source_location.set_property_class(ID_assertion);

    if(lhs.is_not_nil())
    {
      err_location(function);
      throw id2string(identifier)+" expected not to have LHS";
    }
  }
  else if(has_prefix(id2string(identifier), "java::java.lang.AssertionError.<init>:"))
  {
    // insert function call anyway
    code_function_callt function_call;
    function_call.lhs()=lhs;
    function_call.function()=function;
    function_call.arguments()=arguments;
    function_call.add_source_location()=function.source_location();

    copy(function_call, FUNCTION_CALL, dest);

    if(arguments.size()!=1 && arguments.size()!=2)
    {
      err_location(function);
      throw "`"+id2string(identifier)+"' expected to have one or two arguments";
    }

    goto_programt::targett t=dest.add_instruction(ASSERT);
    t->guard=false_exprt();
    t->source_location=function.source_location();
    t->source_location.set("user-provided", true);
    t->source_location.set_property_class(ID_assertion);    
    t->source_location.set_comment("assertion at "+function.source_location().as_string());
  }
  else if(identifier=="assert" &&
          !ns.lookup(identifier).location.get_function().empty())
  {
    if(arguments.size()!=1)
    {
      err_location(function);
      throw "`"+id2string(identifier)+"' expected to have one argument";
    }

    goto_programt::targett t=dest.add_instruction(ASSERT);
    t->guard=arguments.front();
    t->source_location=function.source_location();
    t->source_location.set("user-provided", true);
    t->source_location.set_property_class(ID_assertion);
    t->source_location.set_comment("assertion "+id2string(from_expr(ns, "", t->guard)));
    
    // let's double-check the type of the argument
    if(t->guard.type().id()!=ID_bool)
      t->guard.make_typecast(bool_typet());

    if(lhs.is_not_nil())
    {
      err_location(function);
      throw id2string(identifier)+" expected not to have LHS";
    }
  }
  else if(identifier==CPROVER_PREFIX "assert")
  {
    if(arguments.size()!=2)
    {
      err_location(function);
      throw "`"+id2string(identifier)+"' expected to have two arguments";
    }
    
    const irep_idt description=
      get_string_constant(arguments[1]);

    goto_programt::targett t=dest.add_instruction(ASSERT);
    t->guard=arguments[0];
    t->source_location=function.source_location();
    t->source_location.set("user-provided", true);
    t->source_location.set_property_class(ID_assertion);
    t->source_location.set_comment(description);
    
    // let's double-check the type of the argument
    if(t->guard.type().id()!=ID_bool)
      t->guard.make_typecast(bool_typet());

    if(lhs.is_not_nil())
    {
      err_location(function);
      throw id2string(identifier)+" expected not to have LHS";
    }
  }
  else if(identifier==CPROVER_PREFIX "printf")
  {
    do_printf(lhs, function, arguments, dest);
  }
  else if(identifier==CPROVER_PREFIX "scanf")
  {
    do_scanf(lhs, function, arguments, dest);
  }
  else if(identifier==CPROVER_PREFIX "input" ||
          identifier=="__CPROVER::input")
  {
    do_input(lhs, function, arguments, dest);
  }
  else if(identifier==CPROVER_PREFIX "output" ||
          identifier=="__CPROVER::output")
  {
    do_output(lhs, function, arguments, dest);
  }
  else if(identifier==CPROVER_PREFIX "atomic_begin" ||
          identifier=="__CPROVER::atomic_begin" ||
          identifier=="__VERIFIER_atomic_begin")
  {
    do_atomic_begin(lhs, function, arguments, dest);
  }
  else if(identifier==CPROVER_PREFIX "atomic_end" ||
          identifier=="__CPROVER::atomic_end" ||
          identifier=="__VERIFIER_atomic_end")
  {
    do_atomic_end(lhs, function, arguments, dest);
  }
  else if(identifier==CPROVER_PREFIX "prob_biased_coin")
  {
    do_prob_coin(lhs, function, arguments, dest);
  }
  else if(has_prefix(id2string(identifier), CPROVER_PREFIX "prob_uniform_"))
  {
    do_prob_uniform(lhs, function, arguments, dest);
  }
  else if(has_prefix(id2string(identifier), "nondet_") ||
          has_prefix(id2string(identifier), "__VERIFIER_nondet_"))
  {
    // make it a side effect if there is an LHS
    if(lhs.is_nil()) return;
    
    exprt rhs;
    
    // We need to special-case for _Bool, which
    // can only be 0 or 1.
    if(lhs.type().id()==ID_c_bool)
    {
      rhs=side_effect_expr_nondett(bool_typet());
      rhs.add_source_location()=function.source_location();
      rhs.set(ID_C_identifier, identifier);
      rhs=typecast_exprt(rhs, lhs.type());
    } 
    else
    {
      rhs=side_effect_expr_nondett(lhs.type());
      rhs.add_source_location()=function.source_location();
      rhs.set(ID_C_identifier, identifier);
    }

    code_assignt assignment(lhs, rhs);
    assignment.add_source_location()=function.source_location();
    copy(assignment, ASSIGN, dest);
  }
  else if(has_prefix(id2string(identifier), CPROVER_PREFIX "uninterpreted_"))
  {
    // make it a side effect if there is an LHS
    if(lhs.is_nil()) return;

    function_application_exprt rhs;
    rhs.type()=lhs.type();
    rhs.add_source_location()=function.source_location();
    rhs.function()=function;
    rhs.arguments()=arguments;

    code_assignt assignment(lhs, rhs);
    assignment.add_source_location()=function.source_location();
    copy(assignment, ASSIGN, dest);
  }
  else if(has_prefix(id2string(identifier), CPROVER_PREFIX "array_set"))
  {
    do_array_set(lhs, function, arguments, dest);
  }
  else if(identifier==CPROVER_PREFIX "array_equal" ||
          identifier=="__CPROVER::array_equal")
  {
    do_array_equal(lhs, function, arguments, dest);
  }
  else if(identifier==CPROVER_PREFIX "array_copy" ||
          identifier=="__CPROVER::array_equal")
  {
    do_array_copy(lhs, function, arguments, dest);
  }
  else if(identifier=="printf")
  /*
          identifier=="fprintf" ||
          identifier=="sprintf" ||
          identifier=="snprintf")
  */
  {
    do_printf(lhs, function, arguments, dest);
  }
  else if(identifier=="__assert_fail" ||
          identifier=="_assert" ||
          identifier=="__assert_c99" ||
          identifier=="_wassert")
  {
    // __assert_fail is Linux
    // These take four arguments:
    // "expression", "file.c", line, __func__
    // klibc has __assert_fail with 3 arguments
    // "expression", "file.c", line

    // MingW has
    // void _assert (const char*, const char*, int);
    // with three arguments:
    // "expression", "file.c", line

    // This has been seen in Solaris 11.
    // Signature:
    // void __assert_c99(const char *desc, const char *file, int line, const char *func);

    // _wassert is Windows. The arguments are
    // L"expression", L"file.c", line

    if(arguments.size()!=4 &&
       arguments.size()!=3)
    {
      err_location(function);
      throw "`"+id2string(identifier)+"' expected to have four arguments";
    }
    
    const irep_idt description=
      "assertion "+id2string(get_string_constant(arguments[0]));

    goto_programt::targett t=dest.add_instruction(ASSERT);
    t->guard=false_exprt();
    t->source_location=function.source_location();
    t->source_location.set("user-provided", true);
    t->source_location.set_property_class(ID_assertion);
    t->source_location.set_comment(description);
    // we ignore any LHS
  }
  else if(identifier=="__assert_rtn" ||
          identifier=="__assert")
  {
    // __assert_rtn has been seen on MacOS;
    // __assert is FreeBSD and Solaris 11.
    // These take four arguments:
    // __func__, "file.c", line, "expression"
    // On Solaris 11, it's three arguments:
    // "expression", "file", line
    
    irep_idt description;
    
    if(arguments.size()==4)
    {
      description=
        "assertion "+id2string(get_string_constant(arguments[3]));
    }
    else if(arguments.size()==3)
    {
      description=
        "assertion "+id2string(get_string_constant(arguments[1]));
    }
    else
    {
      err_location(function);
      throw "`"+id2string(identifier)+"' expected to have four arguments";
    }

    goto_programt::targett t=dest.add_instruction(ASSERT);
    t->guard=false_exprt();
    t->source_location=function.source_location();
    t->source_location.set("user-provided", true);
    t->source_location.set_property_class(ID_assertion);
    t->source_location.set_comment(description);
    // we ignore any LHS
  }
  else if(identifier=="__assert_func")
  {
    // __assert_func is newlib (used by, e.g., cygwin)
    // These take four arguments:
    // "file.c", line, __func__, "expression"
    if(arguments.size()!=4)
    {
      err_location(function);
      throw "`"+id2string(identifier)+"' expected to have four arguments";
    }

    const irep_idt description=
      "assertion "+id2string(get_string_constant(arguments[3]));

    goto_programt::targett t=dest.add_instruction(ASSERT);
    t->guard=false_exprt();
    t->source_location=function.source_location();
    t->source_location.set("user-provided", true);
    t->source_location.set_property_class(ID_assertion);
    t->source_location.set_comment(description);
    // we ignore any LHS
  }
  else if(identifier==CPROVER_PREFIX "fence")
  {
    if(arguments.size()<1)
    {
      err_location(function);
      throw "`"+id2string(identifier)+"' expected to have at least one argument";
    }

    goto_programt::targett t=dest.add_instruction(OTHER);
    t->source_location=function.source_location();
    t->code.set(ID_statement, ID_fence);

    forall_expr(it, arguments)
    {
      const irep_idt kind=get_string_constant(*it);
      t->code.set(kind, true);
    }
  }
  else if(identifier=="__builtin_prefetch")
Example #16
0
void goto_inlinet::parameter_assignments(
  const locationt &location,
  const code_typet &code_type,
  const exprt::operandst &arguments,
  goto_programt &dest)
{
  // iterates over the operands
  exprt::operandst::const_iterator it1=arguments.begin();

  goto_programt::local_variablest local_variables;
  
  const code_typet::argumentst &argument_types=
    code_type.arguments();
  
  // iterates over the types of the arguments
  for(code_typet::argumentst::const_iterator
      it2=argument_types.begin();
      it2!=argument_types.end();
      it2++)
  {
    // if you run out of actual arguments there was a mismatch
    if(it1==arguments.end())
    {
      err_location(location);
      throw "function call: not enough arguments";
    }

    const exprt &argument=static_cast<const exprt &>(*it2);

    // this is the type the n-th argument should be
    const typet &arg_type=ns.follow(argument.type());

    const irep_idt &identifier=argument.cmt_identifier();

    if(identifier=="")
    {
      err_location(location);
      throw "no identifier for function argument";
    }

    {
      const symbolt &symbol=ns.lookup(identifier);

      goto_programt::targett decl=dest.add_instruction();
      decl->make_other();
      exprt tmp = code_declt(symbol_expr(symbol));
      migrate_expr(tmp, decl->code);
      decl->location=location;
      decl->function=location.get_function(); 
      decl->local_variables=local_variables;
    }

    local_variables.insert(identifier);
    
    // nil means "don't assign"
    if(it1->is_nil())
    {    
    }
    else
    {
      // this is the actual parameter
      exprt actual(*it1);

      // it should be the same exact type
      type2tc arg_type_2, actual_type_2;
      migrate_type(arg_type, arg_type_2);
      migrate_type(actual.type(), actual_type_2);
      if (!base_type_eq(arg_type_2, actual_type_2, ns))
      {
        const typet &f_argtype = ns.follow(arg_type);
        const typet &f_acttype = ns.follow(actual.type());
        
        // we are willing to do some conversion
        if((f_argtype.id()=="pointer" &&
            f_acttype.id()=="pointer") ||
           (f_argtype.is_array() &&
            f_acttype.id()=="pointer" &&
            f_argtype.subtype()==f_acttype.subtype()))
        {
          actual.make_typecast(arg_type);
        }
        else if((f_argtype.id()=="signedbv" ||
            f_argtype.id()=="unsignedbv" ||
            f_argtype.is_bool()) &&
           (f_acttype.id()=="signedbv" ||
            f_acttype.id()=="unsignedbv" ||
            f_acttype.is_bool()))  
        {
          actual.make_typecast(arg_type);
        }
        else
        {
          err_location(location);

          str << "function call: argument `" << identifier
              << "' type mismatch: got "
              << from_type(ns, identifier, it1->type())
              << ", expected "
              << from_type(ns, identifier, arg_type);
          throw 0;
        }
      }

      // adds an assignment of the actual parameter to the formal parameter
      code_assignt assignment(symbol_exprt(identifier, arg_type), actual);
      assignment.location()=location;

      dest.add_instruction(ASSIGN);
      dest.instructions.back().location=location;
      migrate_expr(assignment, dest.instructions.back().code);
      dest.instructions.back().local_variables=local_variables;
      dest.instructions.back().function=location.get_function();      
    }

    it1++;
  }

  if(it1!=arguments.end())
  {
    // too many arguments -- we just ignore that, no harm done
  }
}
Example #17
0
void goto_checkt::goto_check(goto_functiont &goto_function)
{
  {
    const symbolt *init_symbol;
    if(!ns.lookup(CPROVER_PREFIX "initialize", init_symbol))
      mode=init_symbol->mode;
  }

  assertions.clear();

  local_bitvector_analysist local_bitvector_analysis_obj(goto_function);
  local_bitvector_analysis=&local_bitvector_analysis_obj;

  goto_programt &goto_program=goto_function.body;

  Forall_goto_program_instructions(it, goto_program)
  {
    t=it;
    goto_programt::instructiont &i=*it;

    new_code.clear();

    // we clear all recorded assertions if
    // 1) we want to generate all assertions or
    // 2) the instruction is a branch target
    if(retain_trivial ||
       i.is_target())
      assertions.clear();

    check(i.guard);

    // magic ERROR label?
    for(optionst::value_listt::const_iterator
        l_it=error_labels.begin();
        l_it!=error_labels.end();
        l_it++)
    {
      if(std::find(i.labels.begin(), i.labels.end(), *l_it)!=i.labels.end())
      {
        goto_program_instruction_typet type=
          enable_assert_to_assume?ASSUME:ASSERT;

        goto_programt::targett t=new_code.add_instruction(type);

        t->guard=false_exprt();
        t->source_location=i.source_location;
        t->source_location.set_property_class("error label");
        t->source_location.set_comment("error label "+*l_it);
        t->source_location.set("user-provided", true);
      }
    }

    if(i.is_other())
    {
      const irep_idt &statement=i.code.get(ID_statement);

      if(statement==ID_expression)
      {
        check(i.code);
      }
      else if(statement==ID_printf)
      {
        forall_operands(it, i.code)
          check(*it);
      }
    }
    else if(i.is_assign())
    {
      const code_assignt &code_assign=to_code_assign(i.code);

      check(code_assign.lhs());
      check(code_assign.rhs());

      // the LHS might invalidate any assertion
      invalidate(code_assign.lhs());
    }
    else if(i.is_function_call())
    {
      const code_function_callt &code_function_call=
        to_code_function_call(i.code);

      // for Java, need to check whether 'this' is null
      // on non-static method invocations
      if(mode==ID_java &&
         enable_pointer_check &&
         !code_function_call.arguments().empty() &&
         code_function_call.function().type().id()==ID_code &&
         to_code_type(code_function_call.function().type()).has_this())
      {
        exprt pointer=code_function_call.arguments()[0];

        local_bitvector_analysist::flagst flags=
          local_bitvector_analysis->get(t, pointer);

        if(flags.is_unknown() || flags.is_null())
        {
          notequal_exprt not_eq_null(pointer, gen_zero(pointer.type()));

          add_guarded_claim(
            not_eq_null,
            "this is null on method invokation",
            "pointer dereference",
            i.source_location,
            pointer,
            guardt());
        }
      }

      forall_operands(it, code_function_call)
        check(*it);

      // the call might invalidate any assertion
      assertions.clear();
    }
    else if(i.is_return())
    {
      if(i.code.operands().size()==1)
      {
        check(i.code.op0());
        // the return value invalidate any assertion
        invalidate(i.code.op0());
      }
    }
    else if(i.is_throw())
    {
      if(i.code.get_statement()==ID_expression &&
         i.code.operands().size()==1 &&
         i.code.op0().operands().size()==1)
      {
        // must not throw NULL

        exprt pointer=i.code.op0().op0();

        if(pointer.type().subtype().get(ID_identifier)!="java::java.lang.AssertionError")
        {
          notequal_exprt not_eq_null(pointer, gen_zero(pointer.type()));

          add_guarded_claim(
            not_eq_null,
            "throwing null",
            "pointer dereference",
            i.source_location,
            pointer,
            guardt());
        }
      }

      // this has no successor
      assertions.clear();
    }
    else if(i.is_assert())
    {
      if(i.source_location.get_bool("user-provided") &&
         i.source_location.get_property_class()!="error label" &&
         !enable_assertions)
        i.type=SKIP;
    }
    else if(i.is_assume())
    {
      if(!enable_assumptions)
        i.type=SKIP;
    }
    else if(i.is_dead())
    {
      if(enable_pointer_check)
      {
        assert(i.code.operands().size()==1);
        const symbol_exprt &variable=to_symbol_expr(i.code.op0());

        // is it dirty?
        if(local_bitvector_analysis->dirty(variable))
        {
          // need to mark the dead variable as dead
          goto_programt::targett t=new_code.add_instruction(ASSIGN);
          exprt address_of_expr=address_of_exprt(variable);
          exprt lhs=ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr();
          if(!base_type_eq(lhs.type(), address_of_expr.type(), ns))
            address_of_expr.make_typecast(lhs.type());
          exprt rhs=if_exprt(
            side_effect_expr_nondett(bool_typet()), address_of_expr, lhs, lhs.type());
          t->source_location=i.source_location;
          t->code=code_assignt(lhs, rhs);
          t->code.add_source_location()=i.source_location;
        }
      }
    }
    else if(i.is_end_function())
    {
      if(i.function==goto_functionst::entry_point() &&
         enable_memory_leak_check)
      {
        const symbolt &leak=ns.lookup(CPROVER_PREFIX "memory_leak");
        const symbol_exprt leak_expr=leak.symbol_expr();

        // add self-assignment to get helpful counterexample output
        goto_programt::targett t=new_code.add_instruction();
        t->make_assignment();
        t->code=code_assignt(leak_expr, leak_expr);

        source_locationt source_location;
        source_location.set_function(i.function);

        equal_exprt eq(leak_expr, gen_zero(ns.follow(leak.type)));
        add_guarded_claim(
          eq,
          "dynamically allocated memory never freed",
          "memory-leak",
          source_location,
          eq,
          guardt());
      }
    }

    for(goto_programt::instructionst::iterator
        i_it=new_code.instructions.begin();
        i_it!=new_code.instructions.end();
        i_it++)
    {
      if(i_it->source_location.is_nil())
      {
        i_it->source_location.id(irep_idt());

        if(it->source_location.get_file()!=irep_idt())
          i_it->source_location.set_file(it->source_location.get_file());

        if(it->source_location.get_line()!=irep_idt())
          i_it->source_location.set_line(it->source_location.get_line());

        if(it->source_location.get_function()!=irep_idt())
          i_it->source_location.set_function(it->source_location.get_function());

        if(it->source_location.get_column()!=irep_idt())
          i_it->source_location.set_column(it->source_location.get_column());
      }

      if(i_it->function==irep_idt()) i_it->function=it->function;
    }

    // insert new instructions -- make sure targets are not moved

    while(!new_code.instructions.empty())
    {
      goto_program.insert_before_swap(it, new_code.instructions.front());
      new_code.instructions.pop_front();
      it++;
    }
  }
Example #18
0
void goto_inlinet::replace_return(
  goto_programt &dest,
  const exprt &lhs,
  const exprt &constrain __attribute__((unused)) /* ndebug */)
{
  for(goto_programt::instructionst::iterator
      it=dest.instructions.begin();
      it!=dest.instructions.end();
      it++)
  {
    if(it->is_return())
    {
      if(lhs.is_not_nil())
      {
        goto_programt tmp;
        goto_programt::targett assignment=tmp.add_instruction(ASSIGN);
        
        const code_return2t &ret = to_code_return2t(it->code);
        code_assignt code_assign(lhs, migrate_expr_back(ret.operand));

        // this may happen if the declared return type at the call site
        // differs from the defined return type
        if(code_assign.lhs().type()!=
           code_assign.rhs().type())
          code_assign.rhs().make_typecast(code_assign.lhs().type());

        migrate_expr(code_assign, assignment->code);
        assignment->location=it->location;
        assignment->local_variables=it->local_variables;
        assignment->function=it->location.get_function();
void goto_convertt::do_cpp_new(
  const exprt &lhs,
  const side_effect_exprt &rhs,
  goto_programt &dest)
{
  if(lhs.is_nil())
    throw "do_cpp_new without lhs is yet to be implemented";
  
  // build size expression
  exprt object_size=
    static_cast<const exprt &>(rhs.find(ID_sizeof));

  bool new_array=rhs.get(ID_statement)==ID_cpp_new_array;
  
  exprt count;

  if(new_array)
  {
    count=static_cast<const exprt &>(rhs.find(ID_size));

    if(count.type()!=object_size.type())
      count.make_typecast(object_size.type());

    // might have side-effect
    clean_expr(count, dest);
  }

  exprt tmp_symbol_expr;

  // is this a placement new?
  if(rhs.operands().empty()) // no, "regular" one
  {
    // call __new or __new_array
    exprt new_symbol=
      ns.lookup(new_array?"__new_array":"__new").symbol_expr();
    
    const code_typet &code_type=
      to_code_type(new_symbol.type());

    const typet &return_type=
      code_type.return_type();

    assert(code_type.parameters().size()==1 ||
           code_type.parameters().size()==2);

    const symbolt &tmp_symbol=
      new_tmp_symbol(return_type, "new", dest, rhs.source_location());
    
    tmp_symbol_expr=tmp_symbol.symbol_expr();
    
    code_function_callt new_call;
    new_call.function()=new_symbol;
    if(new_array) new_call.arguments().push_back(count);
    new_call.arguments().push_back(object_size);
    new_call.set("#type", lhs.type().subtype());
    new_call.lhs()=tmp_symbol_expr;
    new_call.add_source_location()=rhs.source_location();
    
    convert(new_call, dest);
  }
  else if(rhs.operands().size()==1)
  {
    // call __placement_new
    exprt new_symbol=
      ns.lookup(new_array?"__placement_new_array":"__placement_new").symbol_expr();
    
    const code_typet &code_type=
      to_code_type(new_symbol.type());

    const typet &return_type=code_type.return_type();
    
    assert(code_type.parameters().size()==2 ||
           code_type.parameters().size()==3);

    const symbolt &tmp_symbol=
      new_tmp_symbol(return_type, "new", dest, rhs.source_location());

    tmp_symbol_expr=tmp_symbol.symbol_expr();

    code_function_callt new_call;
    new_call.function()=new_symbol;
    if(new_array) new_call.arguments().push_back(count);
    new_call.arguments().push_back(object_size);
    new_call.arguments().push_back(rhs.op0()); // memory location
    new_call.set("#type", lhs.type().subtype());
    new_call.lhs()=tmp_symbol_expr;
    new_call.add_source_location()=rhs.source_location();

    for(unsigned i=0; i<code_type.parameters().size(); i++)
      if(new_call.arguments()[i].type()!=code_type.parameters()[i].type())
        new_call.arguments()[i].make_typecast(code_type.parameters()[i].type());
    
    convert(new_call, dest);
  }
  else
    throw "cpp_new expected to have 0 or 1 operands";

  goto_programt::targett t_n=dest.add_instruction(ASSIGN);
  t_n->code=code_assignt(
    lhs, typecast_exprt(tmp_symbol_expr, lhs.type()));
  t_n->source_location=rhs.find_source_location();
    
  // grab initializer
  goto_programt tmp_initializer;
  cpp_new_initializer(lhs, rhs, tmp_initializer);

  dest.destructive_append(tmp_initializer);
}
Example #20
0
void string_instrumentationt::do_format_string_write(
  goto_programt &dest,
  goto_programt::const_targett target,
  const code_function_callt::argumentst &arguments,
  unsigned format_string_inx,
  unsigned argument_start_inx,
  const std::string &function_name)
{
  const exprt &format_arg = arguments[format_string_inx];
    
  if(format_arg.id()=="address_of" &&
     format_arg.op0().id()=="index" &&
     format_arg.op0().op0().id()==ID_string_constant) // constant format
  {
    format_token_listt token_list;
    parse_format_string(format_arg.op0().op0(), token_list);
    
    unsigned args=0;
    
    for(format_token_listt::const_iterator it=token_list.begin();
        it!=token_list.end();
        it++)
    {
      if(find(it->flags.begin(), it->flags.end(), format_tokent::ASTERISK)!=
         it->flags.end()) 
        continue; // asterisk means `ignore this'
      
      switch(it->type)
      {
        case format_tokent::STRING:
        {
            
          const exprt &argument=arguments[argument_start_inx+args];
          const typet &arg_type=ns.follow(argument.type());
          
          goto_programt::targett assertion=dest.add_instruction();
          assertion->location=target->location;
          assertion->location.set("property", "string");
          std::string comment("format string buffer overflow in ");
          comment += function_name;
          assertion->location.set("comment", comment);
          
          if(it->field_width!=0)
          {
            exprt fwidth = from_integer(it->field_width, uint_type());
            exprt fw_1("+", uint_type());
            exprt one = gen_one(uint_type());
            fw_1.move_to_operands(fwidth);
            fw_1.move_to_operands(one); // +1 for 0-char
            
            exprt fw_lt_bs;
            
            if(arg_type.id()=="pointer")
              fw_lt_bs=binary_relation_exprt(fw_1, "<=", buffer_size(argument));
            else
            {
              index_exprt index;
              index.array()=argument;
              index.index()=gen_zero(uint_type());
              address_of_exprt aof(index);
              fw_lt_bs=binary_relation_exprt(fw_1, "<=", buffer_size(aof));
            }
            
            assertion->make_assertion(fw_lt_bs);
          }
          else
          {
            // this is a possible overflow.
            assertion->make_assertion(false_exprt());
          }
          
          // now kill the contents
          invalidate_buffer(dest, target, argument, arg_type, it->field_width);
          
          args++;
          break;
        }
        case format_tokent::TEXT:
        case format_tokent::UNKNOWN:
        {          
          // nothing
          break;
        }
        default: // everything else
        {
          const exprt &argument=arguments[argument_start_inx+args];
          const typet &arg_type=ns.follow(argument.type());
          
          goto_programt::targett assignment=dest.add_instruction(ASSIGN);
          assignment->location=target->location;
          
          exprt lhs("dereference", arg_type.subtype());
          lhs.copy_to_operands(argument);
          
          exprt rhs=side_effect_expr_nondett(lhs.type());
          rhs.location()=target->location;
           
          assignment->code=code_assignt(lhs, rhs);
          
          args++;
          break;
        }
      }
    }
  }
  else // non-const format string
  {    
    for(unsigned i=argument_start_inx; i<arguments.size(); i++)
    {    
      const typet &arg_type=ns.follow(arguments[i].type());
      
      // Note: is_string_type() is a `good guess' here. Actually
      // any of the pointers could point into an array. But it
      // would suck if we had to invalidate all variables.
      // Luckily this case isn't needed too often.
      if(is_string_type(arg_type))
      {
        goto_programt::targett assertion=dest.add_instruction();
        assertion->location=target->location;
        assertion->location.set("property", "string");
        std::string comment("format string buffer overflow in ");
        comment += function_name;
        assertion->location.set("comment", comment);

        // as we don't know any field width for the %s that 
        // should be here during runtime, we just report a 
        // possibly false positive
        assertion->make_assertion(false_exprt());
        
        invalidate_buffer(dest, target, arguments[i], arg_type, 0);
      }
      else
      {
        goto_programt::targett assignment = dest.add_instruction(ASSIGN);
        assignment->location=target->location;
        
        exprt lhs("dereference", arg_type.subtype());
        lhs.copy_to_operands(arguments[i]);
        
        exprt rhs=side_effect_expr_nondett(lhs.type());
        rhs.location()=target->location;
         
        assignment->code=code_assignt(lhs, rhs);
      }
    }
  }
}
Example #21
0
void string_instrumentationt::do_format_string_read(
  goto_programt &dest,
  goto_programt::const_targett target,
  const code_function_callt::argumentst &arguments,
  unsigned format_string_inx,
  unsigned argument_start_inx,
  const std::string &function_name)
{
  const exprt &format_arg = arguments[format_string_inx];
  
  if(format_arg.id()=="address_of" &&
     format_arg.op0().id()=="index" &&
     format_arg.op0().op0().id()==ID_string_constant)
  {
    format_token_listt token_list;
    parse_format_string(format_arg.op0().op0(), token_list);
    
    unsigned args=0;
    
    for(format_token_listt::const_iterator it=token_list.begin();
        it!=token_list.end();
        it++)
    {
      if(it->type==format_tokent::STRING)
      {
        const exprt &arg = arguments[argument_start_inx+args];
        const typet &arg_type = ns.follow(arg.type());
        
        if(arg.id()!=ID_string_constant) // we don't need to check constants
        {
          goto_programt::targett assertion=dest.add_instruction();
          assertion->location=target->location;
          assertion->location.set("property", "string");
          std::string comment("zero-termination of string argument of ");
          comment += function_name;
          assertion->location.set("comment", comment);
          
          exprt temp(arg);
          
          if(arg_type.id()!="pointer")
          {
            index_exprt index;
            index.array()=temp;
            index.index()=gen_zero(uint_type());
            index.type()=arg_type.subtype();            
            temp=address_of_exprt(index);            
          }
          
          assertion->make_assertion(is_zero_string(temp));
        }
      }
      
      if(it->type!=format_tokent::TEXT && 
         it->type!=format_tokent::UNKNOWN) args++;
      
      if(find(it->flags.begin(), it->flags.end(), format_tokent::ASTERISK)!=
         it->flags.end())
        args++; // just eat the additional argument          
    }
  }
  else // non-const format string
  {
    goto_programt::targett format_ass=dest.add_instruction();
    format_ass->make_assertion(is_zero_string(arguments[1]));
    format_ass->location=target->location;
    format_ass->location.set("property", "string");
    std::string comment("zero-termination of format string of ");
    comment += function_name;
    format_ass->location.set("comment", comment);
    
    for(unsigned i=2; i<arguments.size(); i++)
    {
      const exprt &arg = arguments[i];
      const typet &arg_type=ns.follow(arguments[i].type());
      
      if(arguments[i].id()!=ID_string_constant &&
         is_string_type(arg_type))
      {
        goto_programt::targett assertion=dest.add_instruction();        
        assertion->location=target->location;
        assertion->location.set("property", "string");
        std::string comment("zero-termination of string argument of ");
        comment += function_name;
        assertion->location.set("comment", comment);
        
        exprt temp(arg);
                  
        if(arg_type.id()!="pointer")
        {
          index_exprt index;
          index.array()=temp;
          index.index()=gen_zero(uint_type());
          index.type()=arg_type.subtype();            
          temp=address_of_exprt(index);            
        }
        
        assertion->make_assertion(is_zero_string(temp));
      }
    }
  }
}
Example #22
0
void convert(const xmlt &xml, goto_programt &goto_program)
{
  goto_program.clear();
  goto_programt::instructionst &instructions = goto_program.instructions;

  xmlt::elementst::const_iterator it = xml.elements.begin();
  for(; it != xml.elements.end(); it++)
  {
    goto_programt::targett inst = goto_program.add_instruction();
    inst->targets.clear();

    if(it->name=="goto")
    {
      inst->type = GOTO;
    }
    else if(it->name=="assume")
    {
      inst->type = ASSUME;
    }
    else if(it->name=="assert")
    {
      inst->type = ASSERT;
    }
    else if(it->name=="skip")
    {
      inst->type = SKIP;
    }
    else if(it->name=="end_function")
    {
      inst->type = END_FUNCTION;
    }
    else if(it->name=="location")
    {
      inst->type = LOCATION;
    }
    else if(it->name=="dead")
    {
      inst->type = DEAD;
    }
    else if(it->name=="atomic_begin")
    {
      inst->type = ATOMIC_BEGIN;
    }
    else if(it->name=="atomic_end")
    {
      inst->type = ATOMIC_END;
    }
    else if(it->name=="return")
    {
      inst->make_return();
    }
    else if(it->name=="instruction") // OTHER
    {
      inst->make_other();
    }
    else if(it->name=="assign")
    {
      inst->make_other();
      inst->type=ASSIGN;
    }
    else if(it->name=="functioncall")
    {
      inst->make_other();
      inst->type=FUNCTION_CALL;
    }
    else if(it->name=="thread_start")
    {
      inst->type = START_THREAD;
    }
    else if(it->name=="thread_end")
    {
      inst->type = END_THREAD;
    }
    else
    {
      std::cout << "Unknown instruction type encountered (" << it->name << ")";
      std::cout << std::endl;
      return;
    }

    xmlt::elementst::const_iterator eit = it->elements.begin();
    for(; eit != it->elements.end(); eit++)
    {
      if(eit->name=="location")
      {
        convert(*eit, inst->location);
      }
      else if(eit->name=="variables")
      {
      }
      else if(eit->name=="labels")
      {
        xmlt::elementst::const_iterator lit = eit->elements.begin();
        for(; lit != eit->elements.end(); lit++)
        {
          if(lit->name=="label")
          {
            std::string ls = lit->get_attribute("name");
            inst->labels.push_back(ls);
          }
          else
          {
            std::cout << "Unknown node in labels section." << std::endl;
            return;
          }
        }
      }
      else if(eit->name=="guard")
      {
        inst->guard.remove("value");
        convert(*eit, inst->guard);
      }
      else if(eit->name=="code")
      {
        convert(*eit, inst->code);
      }
      else if(eit->name=="targets")
      {
        // Don't do anything here, we'll need a second run for that
      }
      else if(eit->name=="comment")
      {
        inst->location.set("comment", eit->data);
      }
      else if(eit->name=="function")
      {
        inst->function = eit->data;
      }
    }
  }

  // assign line numbers
  goto_program.compute_location_numbers();

  // second run, for targets
  goto_programt::targett ins_it = instructions.begin();
  it = xml.elements.begin();
  for(; it != xml.elements.end() && ins_it!=instructions.end(); it++)
  {
    xmlt::elementst::const_iterator eit = it->elements.begin();
    for(; eit != it->elements.end(); eit++)
    {
      if(eit->name=="targets")
      {
        xmlt::elementst::const_iterator tit = eit->elements.begin();
        for(; tit != eit->elements.end(); tit++)
        {
          if(tit->name=="target")
          {
            goto_programt::targett tins =
              find_instruction(xml, instructions, tit->data);
            if(tins != instructions.end())
            {
              // Here we insert the iterators that somehow seem
              // to be strange afterwards (see line 87)
              ins_it->targets.push_back(tins);
            }
            else
            {
              std::cout << "Warning: instruction not found when "
              "resolving target links." << std::endl;
            }
          }
          else
          {
            std::cout << "Unknown node in targets section." << std::endl;
            return;
          }
        }
      }
    }
    ins_it++;
  }

  // resolve links
  goto_program.update();

  // std::cout << "TNI: " << goto_program.target_numbers.size() << std::endl;
}
void goto_convertt::do_java_new_array(
  const exprt &lhs,
  const side_effect_exprt &rhs,
  goto_programt &dest)
{
  if(lhs.is_nil())
    throw "do_java_new_array without lhs is yet to be implemented";
    
  source_locationt location=rhs.source_location();

  assert(rhs.operands().size()>=1); // one per dimension
  
  if(rhs.type().id()!=ID_pointer)
    throw "do_java_new_array returns pointer";

  typet object_type=rhs.type().subtype();
  
  // build size expression
  exprt object_size=size_of_expr(object_type, ns);
  
  if(object_size.is_nil())
    throw "do_java_new_array got nil object_size";

  // we produce a malloc side-effect, which stays
  side_effect_exprt malloc_expr(ID_malloc);
  malloc_expr.copy_to_operands(object_size);
  malloc_expr.type()=pointer_typet(object_type);

  goto_programt::targett t_n=dest.add_instruction(ASSIGN);
  t_n->code=code_assignt(lhs, malloc_expr);
  t_n->source_location=location;
  
  // multi-dimensional?
  
  assert(ns.follow(object_type).id()==ID_struct);
  const struct_typet &struct_type=to_struct_type(ns.follow(object_type));
  assert(struct_type.components().size()==3);

  // if it's an array, we need to set the length field
  dereference_exprt deref(lhs, object_type);
  member_exprt length(deref, struct_type.components()[1].get_name(), struct_type.components()[1].type());
  goto_programt::targett t_s=dest.add_instruction(ASSIGN);
  t_s->code=code_assignt(length, rhs.op0());
  t_s->source_location=location;
  
  // we also need to allocate space for the data
  member_exprt data(deref, struct_type.components()[2].get_name(), struct_type.components()[2].type());
  side_effect_exprt data_cpp_new_expr(ID_cpp_new_array, data.type());
  data_cpp_new_expr.set(ID_size, rhs.op0());
  goto_programt::targett t_p=dest.add_instruction(ASSIGN);
  t_p->code=code_assignt(data, data_cpp_new_expr);
  t_p->source_location=location;
  
  // zero-initialize the data
  exprt zero_element=gen_zero(data.type().subtype());
  codet array_set(ID_array_set);
  array_set.copy_to_operands(data, zero_element);
  goto_programt::targett t_d=dest.add_instruction(OTHER);
  t_d->code=array_set;
  t_d->source_location=location;

  if(rhs.operands().size()>=2)
  {
    // produce
    // for(int i=0; i<size; i++) tmp[i]=java_new(dim-1);
    // This will be converted recursively.
    
    goto_programt tmp;

    symbol_exprt tmp_i=
      new_tmp_symbol(index_type(), "index", tmp, location).symbol_expr();

    code_fort for_loop;
    
    side_effect_exprt sub_java_new=rhs;
    sub_java_new.operands().erase(sub_java_new.operands().begin());
    
    side_effect_exprt inc(ID_assign);
    inc.operands().resize(2);
    inc.op0()=tmp_i;
    inc.op1()=plus_exprt(tmp_i, gen_one(tmp_i.type()));
    
    dereference_exprt deref_expr(plus_exprt(data, tmp_i), data.type().subtype());
    
    for_loop.init()=code_assignt(tmp_i, gen_zero(tmp_i.type()));
    for_loop.cond()=binary_relation_exprt(tmp_i, ID_lt, rhs.op0());
    for_loop.iter()=inc;
    for_loop.body()=code_skipt();
    for_loop.body()=code_assignt(deref_expr, sub_java_new);

    convert(for_loop, tmp);
    dest.destructive_append(tmp);
  }
}