예제 #1
0
path_symex_statet initial_state(
  var_mapt &var_map,
  const locst &locs,
  path_symex_historyt &path_symex_history)
{
  return path_symex_statet(
    var_map,
    locs,
    path_symex_step_reft(path_symex_history),
    path_symex_statet::branchest());
}
예제 #2
0
파일: path_search.cpp 프로젝트: Dthird/CBMC
path_searcht::resultt path_searcht::operator()(
  const goto_functionst &goto_functions)
{
#ifdef PATH_SYMEX_FORK
  // Disable output because there is no meaningful way
  // to write text when multiple path_search processes
  // run concurrently. This could be remedied by piping
  // to individual files or inter-process communication,
  // a performance bottleneck, however.
  *messaget::mstream.message_handler=NULL;
#endif

  locst locs(ns);
  var_mapt var_map(ns);
  
  locs.build(goto_functions);

  // this is the container for the history-forest  
  path_symex_historyt history;
  
  queue.push_back(initial_state(var_map, locs, history));
  
  // set up the statistics
  number_of_paths=0;
  number_of_instructions=0;
  number_of_dropped_states=0;
  number_of_VCCs=0;
  number_of_VCCs_after_simplification=0;
  number_of_failed_properties=0;
  number_of_fast_forward_steps=0;

  // stop the time
  start_time=current_time();
  
  initialize_property_map(goto_functions);
  
  while(!queue.empty())
  {
    // Pick a state from the queue,
    // according to some heuristic.
    queuet::iterator state=pick_state();

    // fast forwarding required?
    if(state->is_lazy())
    {
      assert(state->is_executable());
      assert(state->history.is_nil());

      // keep allocated memory, this is faster than
      // instantiating a new empty vector and map
      history.clear();
      var_map.clear();
      state->history=path_symex_step_reft(history);

      // restore all fields of a lazy state by symbolic
      // execution along previously recorded branches
      const queuet::size_type queue_size=queue.size();
      do
      {
        number_of_fast_forward_steps++;

        path_symex(*state, queue);
#ifdef PATH_SYMEX_OUTPUT
        status() << "Fast forward thread " << state->get_current_thread()
                 << "/" << state->threads.size()
                 << " PC " << state->pc() << messaget::eom;
#endif
      }
      while(state->is_lazy() && state->is_executable());
      assert(queue.size() == queue_size);
    }
    
    // TODO: check lazy states before fast forwarding, or perhaps it
    // is better to even check before inserting into queue
    if(drop_state(*state))
    {
      number_of_dropped_states++;
      queue.erase(state);
      continue;
    }
    
    if(!state->is_executable())
    {
      queue.erase(state);
      continue;
    }
    
    // count only executable instructions
    number_of_instructions++;

#ifdef PATH_SYMEX_OUTPUT
    status() << "Queue " << queue.size()
             << " thread " << state->get_current_thread()
             << "/" << state->threads.size()
             << " PC " << state->pc() << messaget::eom;
#endif

    // an error, possibly?
    if(state->get_instruction()->is_assert())
    {
      if(show_vcc)
        do_show_vcc(*state, ns);
      else
      {
        check_assertion(*state, ns);
        
        // all assertions failed?
        if(number_of_failed_properties==property_map.size())
          break;
      }
    }

#ifdef PATH_SYMEX_FORK
    if(try_await())
    {
      debug() << "Child process has terminated "
                 "so exit parent" << messaget::eom;
      break;
    }
#endif

    // execute and record whether a "branch" occurred
    const queuet::size_type queue_size = queue.size();
    path_symex(*state, queue);

    assert(queue_size <= queue.size());
    number_of_paths += (queue.size() - queue_size);
  }

#ifdef PATH_SYMEX_FORK
  int exit_status=await();
  if(exit_status==0 && number_of_failed_properties!=0)
  {
    // the eldest child process (if any) reports found bugs
    report_statistics();
    return UNSAFE;
  }
  else
  {
    // either a child found and reported a bug or
    // the parent's search partition is safe
    switch (exit_status)
    {
    case 0: return SAFE;
    case 10: return UNSAFE;
    default: return ERROR;
    }
  }
#else
  report_statistics();

  return number_of_failed_properties==0?SAFE:UNSAFE;
#endif
}