Ejemplo n.º 1
0
void goto_symext::symex_free(const expr2tc &expr)
{
  const code_free2t &code = to_code_free2t(expr);

  // Trigger 'free'-mode dereference of this pointer. Should generate various
  // dereference failure callbacks.
  expr2tc tmp = code.operand;
  dereference(tmp, false, true);

  address_of2tc addrof(code.operand->type, tmp);
  pointer_offset2tc ptr_offs(pointer_type2(), addrof);
  equality2tc eq(ptr_offs, zero_ulong);
  claim(eq, "Operand of free must have zero pointer offset");

  // Clear the alloc bit, and set the deallocated bit.
  guardt guard;
  type2tc sym_type = type2tc(new array_type2t(get_bool_type(),
                                              expr2tc(), true));
  pointer_object2tc ptr_obj(pointer_type2(), code.operand);

  symbol2tc dealloc_sym(sym_type, deallocd_arr_name);
  index2tc dealloc_index_expr(get_bool_type(), dealloc_sym, ptr_obj);
  expr2tc truth = true_expr;
  symex_assign_rec(dealloc_index_expr, truth, guard);

  symbol2tc valid_sym(sym_type, valid_ptr_arr_name);
  index2tc valid_index_expr(get_bool_type(), valid_sym, ptr_obj);
  expr2tc falsity = false_expr;
  symex_assign_rec(valid_index_expr, falsity, guard);
}
Ejemplo n.º 2
0
void goto_symext::symex_free(const expr2tc &expr)
{
  const code_free2t &code = to_code_free2t(expr);

  // Trigger 'free'-mode dereference of this pointer. Should generate various
  // dereference failure callbacks.
  expr2tc tmp = code.operand;
  dereference(tmp, false, true);

  // Don't rely on the output of dereference in free mode; instead fetch all
  // the internal dereference state for pointed at objects, and creates claims
  // that if pointed at, their offset is zero.
  internal_deref_items.clear();
  tmp = code.operand;
  // Create temporary, dummy, dereference
  tmp = dereference2tc(get_uint8_type(), tmp);
  dereference(tmp, false, false, true); // 'internal' dereference
  for (const auto &item : internal_deref_items) {
    guardt g = cur_state->guard;
    g.add(item.guard);
    expr2tc offset = item.offset;
    expr2tc eq = equality2tc(offset, zero_ulong);
    g.guard_expr(eq);
    claim(eq, "Operand of free must have zero pointer offset");
  }

  // Clear the alloc bit, and set the deallocated bit.
  guardt guard;
  type2tc sym_type = type2tc(new array_type2t(get_bool_type(),
                                              expr2tc(), true));
  pointer_object2tc ptr_obj(pointer_type2(), code.operand);

  symbol2tc dealloc_sym(sym_type, deallocd_arr_name);
  index2tc dealloc_index_expr(get_bool_type(), dealloc_sym, ptr_obj);
  expr2tc truth = true_expr;
  symex_assign_rec(dealloc_index_expr, truth, guard);

  symbol2tc valid_sym(sym_type, valid_ptr_arr_name);
  index2tc valid_index_expr(get_bool_type(), valid_sym, ptr_obj);
  expr2tc falsity = false_expr;
  symex_assign_rec(valid_index_expr, falsity, guard);
}
Ejemplo n.º 3
0
expr2tc
goto_symext::symex_mem(
  const bool is_malloc,
  const expr2tc &lhs,
  const sideeffect2t &code)
{
  if (is_nil_expr(lhs))
    return expr2tc(); // ignore

  // size
  type2tc type = code.alloctype;
  expr2tc size = code.size;
  bool size_is_one = false;

  if (is_nil_expr(size))
    size_is_one=true;
  else
  {
    cur_state->rename(size);
    mp_integer i;
    if (is_constant_int2t(size) && to_constant_int2t(size).as_ulong() == 1)
      size_is_one = true;
  }

  if (is_nil_type(type))
    type = char_type2();
  else if (is_union_type(type)) {
    // Filter out creation of instantiated unions. They're now all byte arrays.
    size_is_one = false;
    type = char_type2();
  }


  unsigned int &dynamic_counter = get_dynamic_counter();
  dynamic_counter++;

  // value
  symbolt symbol;

  symbol.base_name = "dynamic_" + i2string(dynamic_counter) +
                     (size_is_one ? "_value" : "_array");

  symbol.name = "symex_dynamic::" + id2string(symbol.base_name);
  symbol.lvalue = true;

  typet renamedtype = ns.follow(migrate_type_back(type));
  if(size_is_one)
    symbol.type=renamedtype;
  else
  {
    symbol.type=typet(typet::t_array);
    symbol.type.subtype()=renamedtype;
    symbol.type.size(migrate_expr_back(size));
  }

  symbol.type.dynamic(true);

  symbol.mode="C";

  new_context.add(symbol);

  type2tc new_type;
  migrate_type(symbol.type, new_type);

  address_of2tc rhs_addrof(get_empty_type(), expr2tc());

  if(size_is_one)
  {
    rhs_addrof.get()->type = get_pointer_type(pointer_typet(symbol.type));
    rhs_addrof.get()->ptr_obj = symbol2tc(new_type, symbol.name);
  }
  else
  {
    type2tc subtype;
    migrate_type(symbol.type.subtype(), subtype);
    expr2tc sym = symbol2tc(new_type, symbol.name);
    expr2tc idx_val = zero_ulong;
    expr2tc idx = index2tc(subtype, sym, idx_val);
    rhs_addrof.get()->type =
      get_pointer_type(pointer_typet(symbol.type.subtype()));
    rhs_addrof.get()->ptr_obj = idx;
  }

  expr2tc rhs = rhs_addrof;

  expr2tc ptr_rhs = rhs;

  if (!options.get_bool_option("force-malloc-success")) {
    symbol2tc null_sym(rhs->type, "NULL");
    sideeffect2tc choice(get_bool_type(), expr2tc(), expr2tc(), std::vector<expr2tc>(), type2tc(), sideeffect2t::nondet);

    rhs = if2tc(rhs->type, choice, rhs, null_sym);
    replace_nondet(rhs);

    ptr_rhs = rhs;
  }

  if (rhs->type != lhs->type)
    rhs = typecast2tc(lhs->type, rhs);

  cur_state->rename(rhs);
  expr2tc rhs_copy(rhs);

  guardt guard;
  symex_assign_rec(lhs, rhs, guard);

  pointer_object2tc ptr_obj(pointer_type2(), ptr_rhs);
  track_new_pointer(ptr_obj, new_type);

  dynamic_memory.push_back(allocated_obj(rhs_copy, cur_state->guard, !is_malloc));

  return rhs_addrof->ptr_obj;
}
Ejemplo n.º 4
0
void goto_symext::symex_realloc(const expr2tc &lhs, const sideeffect2t &code)
{
  expr2tc src_ptr = code.operand;
  expr2tc realloc_size = code.size;

  internal_deref_items.clear();
  dereference2tc deref(get_empty_type(), src_ptr);
  dereference(deref, dereferencet::INTERNAL);
  // src_ptr is now invalidated.

  // Free the given pointer. This just uses the pointer object from the pointer
  // variable that's the argument to realloc. It also leads to pointer validity
  // checking, and checks that the offset is zero.
  code_free2tc fr(code.operand);
  symex_free(fr);

  // We now have a list of things to work on. Recurse into them, build a result,
  // and then switch between those results afterwards.
  // Result list is the address of the reallocated piece of data, and the guard.
  std::list<std::pair<expr2tc, expr2tc>> result_list;
  for(auto &item : internal_deref_items)
  {
    expr2tc guard = item.guard;
    cur_state->rename_address(item.object);
    cur_state->guard.guard_expr(guard);
    target->renumber(guard, item.object, realloc_size, cur_state->source);
    type2tc new_ptr = type2tc(new pointer_type2t(item.object->type));
    address_of2tc addrof(new_ptr, item.object);
    result_list.emplace_back(addrof, item.guard);

    // Bump the realloc-numbering of the object. This ensures that, after
    // renaming, the address_of we just generated compares differently to
    // previous address_of's before the realloc.
    unsigned int cur_num = 0;
    if(cur_state->realloc_map.find(item.object) != cur_state->realloc_map.end())
    {
      cur_num = cur_state->realloc_map[item.object];
    }

    cur_num++;
    std::map<expr2tc, unsigned>::value_type v(item.object, cur_num);
    cur_state->realloc_map.insert(v);
  }

  // Rebuild a gigantic if-then-else chain from the result list.
  expr2tc result;
  if(result_list.size() == 0)
  {
    // Nothing happened; there was nothing, or only null, to point at.
    // In this case, just return right now and leave the pointer free. The
    // symex_free that occurred above should trigger a dereference failure.
    return;
  }

  result = expr2tc();
  for(auto const &it : result_list)
  {
    if(is_nil_expr(result))
      result = it.first;
    else
      result = if2tc(result->type, it.second, it.first, result);
  }

  // Install pointer modelling data into the relevant arrays.
  pointer_object2tc ptr_obj(pointer_type2(), result);
  track_new_pointer(ptr_obj, type2tc(), realloc_size);

  symex_assign(code_assign2tc(lhs, result), true);
}
Ejemplo n.º 5
0
bool
SuifPrinterModule::parse_and_print(ostream& output, const ObjectWrapper &obj,
				   const LString &name, const String &str, 
				   int _indent, int deref = 0)
{
  const Address what = obj.get_address();
  const MetaClass *type = obj.get_meta_class();
  //  ObjectWrapper obj(what, type);
  //output << "str:deref = " << deref << endl;
  int l_sep = list_separator;
  if (str.length() == 0) {
    return false;
  }
  if (deref)
    _indent -= istep;
  int str_length = str.length();
  bool need_indent = false;
  bool first_field = true;
  for (int i = 0; i < str_length; ++i) {
    if (str[i] != '%') {
      // If there are less than 2 extra stars don't print anything but the
      // fields.
      if (deref < 2) {
	// Need to check for \n and take care of indentation here
	switch(str[i]) {
	case '\n':
	  output << str[i];
	  if (str[i+1]) {
	    need_indent = true;
	    indent(output, _indent);
	  }
	  break;
	case '\t': indent(output, istep); break;
	case '\b': _indent -= istep; break;
	default: output << str[i];
	}
      }
    }
    else {
      ++i;
      if (str[i] == '%') {
	// Double % means print out a '%'
	output << '%';
      }
      else {
	// This has to be cleaned up a bit ...
	//int field_deref = deref?deref-1:0;
	int field_deref = 0;
	char buff[256];
	int j = 0;
	char c = str[i++];
	if (c == '*') {
	  ++field_deref;
	  while ((c = str[i++]) == '*')
	    ++ field_deref;
	}
	while (isalnum(c) || c == '_') {
	  buff[j++] = c;
	  c = str[i++];
	}
	i -= 2;
	buff[j] = 0;
	// Now retrieve the particular field and print it.
	if (!strcmp(buff, "Cl")) {
	  output << type->get_instance_name() << '('
		 << type->get_meta_class_id() << ") ";
	}
	else if (!strcmp(buff, "ii")) { // Deal with printing IInteger
	  IInteger *ii = (IInteger *)what;
	  output << ii->to_String().c_str();
	}
	else if (!strcmp(buff, "i")) { // Deal with printing int
	  output << *(int*)what;
	}
	else if (!strcmp(buff, "f")) { // float
	  output << *(float*)what;
	}
	else if (!strcmp(buff, "d")) { // double
	  output << *(double*)what;
	}
	else if (!strcmp(buff, "c")) { // char
	  output << *(char*)what;
	}
	else if (!strcmp(buff, "b")) { // byte
	  output << (int)*(char*)what;
	}
	else if (!strcmp(buff, "B")) { // bool
	  output << *(bool*)what;
	}
	else if (!strcmp(buff, "ls")) { // Deal with printing LStrings
	  LString str = *(LString*) what;
	  output << str;
	}
	else if (!strcmp(buff, "s")) { // Deal with printing Strings
	  String str = *(String*) what;
	  output << str;
	}
	else if (!strcmp(buff, "n")) { // Deal with name of field
	  if (!deref)
	    output << name;
	}
	else if (!strcmp(buff, "P")) {
	  if (obj.is_null())
	    output << "NULL";
	  else {
	    PointerWrapper ptr_obj(obj);
	    ObjectWrapper base_obj = ptr_obj.dereference();
	    if (ptr_obj.get_meta_class()->is_owning_pointer()) {
	      size_t ref = retrieve_tag(obj.get_object());
	      output << "t" << ref<< ": ";
	      print2(output, base_obj, emptyLString, 
		     _indent+istep, field_deref);
	    }
	    else {
	      print_pointer(output, ptr_obj, emptyLString, _indent, deref);
	    }
	  }
	}
	else if (!strcmp(buff, "R")) { // print the ref #
	  if (!what)
	    output << "NULL";
	  else {
	    //  PointerMetaClass *p = (PointerMetaClass*) type;
	    //  const Address baseAddr = *(Address*) type;
	    //ObjectWrapper obj(what, type);
	    size_t ref = retrieve_tag(obj);
	    output << "t" << ref<< ": ";
	  }
	}
	else if (!strcmp(buff, "LS")) {
	  list_separator = ' ';
	}
	else if (!strcmp(buff, "LN")) {
	  list_separator = '\n';
	}
	else if (!strcmp(buff, "LC")) {
	  list_separator = ',';
	}
	else if (!strcmp(buff, "ANNOTES")) {
	  // Special CASE for handling ANNOTATIONS
	  AggregateWrapper agg(obj);
	  LString field_name("_annotes");
	  FieldDescription *f = agg.get_field_description(field_name);
	  if (!f)
	    cerr << type->get_meta_class(what)->get_class_name()
		 << ":No field '" << field_name << "' found to print!!!\n";
	  else {
	    // Now we need to get the field offset and increment 'what'
	    if (field_deref != 0)
	      cerr << "Extra '*' for %ANNOTES\n";
	    FieldWrapper field = agg.get_field(field_name);
	    if (need_indent) {
	      indent(output, istep);
	      need_indent = false;
	    }
	    char old_sep = list_separator;
	    list_separator = '\n';
	    print2(output, 
		   field.get_object(),
		   field_name, _indent+istep,
		   1);
	    list_separator = old_sep;
	  }
	}
	else if (j) {
	  // Retrieve the field mentioned
	  // The following cast works as we should reach here only if it
	  // is not an elementary or pointer type.
	  AggregateWrapper agg(obj);
	  char *bf = buff;
	  LString field_name(bf);
	  FieldDescription *f = agg.get_field_description(field_name);
	  if (!f)
	    cerr << type->get_meta_class(what)->get_class_name()
		 << ":No field '" << field_name << "' found to print!!!\n";
	  else {
	    // Now we need to get the field offset and increment 'what'
	    if (deref)
	      if (!first_field) output << ' ';
	      else first_field = false;
	    FieldWrapper field = agg.get_field(field_name);
	    //char *f_add = (char*)what + f->get_offset();
	    //indent(output, _indent+istep);
	    if (need_indent) {
	      indent(output, istep);
	      need_indent = false;
	    }
	    if (deref && !field_deref)
	      field_deref = deref - 1;
	    //output << "\tstr:field_deref = " << field_deref << endl;
	    print2(output, 
		   field.get_object(),
		   field_name, _indent+istep,
		   field_deref);
	  }
	}
      }
    }
  }
  list_separator = l_sep;
  return true;
}