Example #1
0
void rw_sett::assign(const exprt &lhs, const exprt &rhs)
{
  read(rhs);
  read_write_rec(lhs, false, true, "", guardt());
}
Example #2
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 #3
0
void simulator_loop_detectiont::build_loop_recurrence(
    symex_target_equationt &equation,
    goto_symex_statet &end_state,
    loop_begint &loop_begin,
    const exprt &parameter_expr,
    std::list<exprt> &recurrences,
    std::map<goto_programt::const_targett,code_assignt> &instructions,
    std::map<goto_programt::const_targett,exprt> &closed_forms)
{
  // find start in equation

  symex_target_equationt::SSA_stepst::iterator
    start_it=equation.get_SSA_step(loop_begin.state_nr);

  // build the problem

  std::map<exprt, exprt> problem;
  std::set<exprt> start_values, end_values;

  for(symex_target_equationt::SSA_stepst::iterator
      e_it=start_it; e_it!=equation.SSA_steps.end(); e_it++)
  {
    symex_target_equationt::SSA_stept &s=*e_it;

    if(s.is_assignment())
    {
      const exprt &lhs=s.ssa_lhs;
      const exprt &rhs=s.ssa_rhs;

      // compute start/end values
      start_values.insert(rename(loop_begin.state, s.original_lhs_object));
      end_values.insert(rename(end_state, s.original_lhs_object));

      if (!s.original_lhs_object.get_bool("induction_symbol"))
      {
        problem[lhs]=rhs;      
#if 0
        std::cout << "Part of the problem: " << 
          from_expr (ns, "", lhs) << " := " << from_expr (ns, "", rhs)
          << std::endl;
#endif
      }
    }
  }

  // create a new parameter variable
  loop_infos.push_back(loop_infot());

  loop_infos.back().parameter=parameter_expr;

  // solve the problem

  replace_mapt solution;
  recurrence_solver::solve_recurrence(parameter_expr, 
      start_values, 
      end_values, 
      loop_begin.state,
      end_state,
      problem, 
      solution,
      concrete_model.ns);  

  // put in solution

  for(symex_target_equationt::SSA_stepst::iterator
      e_it=start_it; e_it!=equation.SSA_steps.end(); e_it++)
  {
    bool has_recurrence = false;
    symex_target_equationt::SSA_stept &s=*e_it;

#ifdef DEBUG
    std::cout << "*** " << s.pc->location << std::endl;
#endif

    if(s.is_assignment())
    {
      if (solution[s.ssa_lhs].id()!=ID_nondet_symbol && 
          solution[s.ssa_lhs] != s.ssa_rhs &&
          !s.ssa_lhs.get_bool("induction_symbol"))
        has_recurrence = true;

#ifdef DEBUG
      std::cout << "ASSIGNMENT BEFORE: " << from_expr(ns, "", s.ssa_lhs) << " := "
        << from_expr(ns, "", s.rhs) << std::endl;
#endif

      if(!s.original_lhs_object.get_bool("induction_symbol"))
        s.ssa_rhs=solution[s.ssa_lhs];

#ifdef DEBUG
      std::cout << "ASSIGNMENT AFTER: " << from_expr(ns, "", s.ssa_lhs) << " := "
        << from_expr(ns, "", s.rhs) << std::endl;
#endif

      // fix cond
      assert(s.cond_expr.id()==ID_equal && s.cond_expr.operands().size()==2);
      s.cond_expr.op1()=s.ssa_rhs;

      // remember the recurrence instruction and the
      // closed form for WP computation
      code_assignt instruction(s.ssa_lhs, solution[s.ssa_lhs]);
      end_state.get_original_name(instruction);
      instructions[s.source.pc] = instruction;
      if(has_recurrence)
      {
        exprt equality=equal_exprt(s.ssa_lhs, solution[s.ssa_lhs]);
        if(!s.ssa_lhs.get_bool("induction_symbol"))
        {
          closed_forms[s.source.pc]=equality;
        }
      }
    }
    else if(s.is_assert())
    {
#ifdef DEBUG
      std::cout << "ASSERT: " << from_expr(ns, "", s.cond) << std::endl;
#endif
    }
    else if(s.is_assume())
    {
#ifdef DEBUG
      std::cout << "ASSUME: " << from_expr(ns, "", s.cond) << std::endl;
#endif
    }
  }

  // assign parameter, so we can grab it from a counterexample
  exprt tmp(parameter_expr);

  equation.assignment(
      guardt(),
      to_symbol_expr(parameter_expr),
      to_symbol_expr(parameter_expr),
      to_symbol_expr(parameter_expr),
      to_symbol_expr(parameter_expr),
      tmp,
      loop_begin.state.source,
      symex_targett::STATE);

  // now clean up the recurrence predicates used for refinement
  recurrence_solver::cleanup_recurrence_predicates(equation,
      loop_begin.state_nr,
      end_state,
      problem, 
      closed_forms,
      recurrences,
      concrete_model.ns);
}