Exemple #1
0
void goto_checkt::invalidate(const exprt &lhs)
{
  if(lhs.id()==ID_index)
    invalidate(to_index_expr(lhs).array());
  else if(lhs.id()==ID_member)
    invalidate(to_member_expr(lhs).struct_op());
  else if(lhs.id()==ID_symbol)
  {
    // clear all assertions about 'symbol'
    find_symbols_sett find_symbols_set;
    find_symbols_set.insert(to_symbol_expr(lhs).get_identifier());

    for(assertionst::iterator
        it=assertions.begin();
        it!=assertions.end();
        ) // no it++
    {
      assertionst::iterator next=it;
      next++;

      if(has_symbol(*it, find_symbols_set) ||
         has_dereference(*it))
        assertions.erase(it);

      it=next;
    }
  }
  else
  {
    // give up, clear all
    assertions.clear();
  }
}
Exemple #2
0
static bool has_dereference(const exprt &expr)
{
  if (expr.id() == "dereference")
    return true;
  else if (expr.id() == "index" && expr.op0().type().id() == "pointer")
    // This is an index of a pointer, which is a dereference
    return true;
  else if (expr.operands().size() > 0 && expr.op0().is_not_nil())
    // Recurse through all subsequent source objects, which are always operand
    // zero.
    return has_dereference(expr.op0());
  else
    return false;
}
Exemple #3
0
void goto_checkt::bounds_check(const exprt &expr, const guardt &guard)
{
  if (options.get_bool_option("no-bounds-check"))
    return;

  if (expr.id() != "index")
    return;

  if (expr.operands().size() != 2)
    throw "index takes two operands";

  // Don't bounds check the initial index of argv in the "main" function; it's
  // always correct, and just adds needless claims. In the past a "no bounds
  // check" attribute in old irep handled this.
  if (expr.op0().id_string() == "symbol"
      && expr.op0().identifier() == "c::argv'"
      && expr.op1().id_string() == "symbol"
      && expr.op1().identifier() == "c::argc'")
    return;

  if (expr.op0().id_string() == "symbol"
      && expr.op0().identifier() == "c::envp'"
      && expr.op1().id_string() == "symbol"
      && expr.op1().identifier() == "c::envp_size'")
    return;

  typet array_type = ns.follow(expr.op0().type());

  if (array_type.id() == "pointer")
    return;  // done by the pointer code
  else if (array_type.id() == "incomplete_array")
  {
    std::cerr << expr.pretty() << std::endl;
    throw "index got incomplete array";
  }
  else if (!array_type.is_array())
    throw "bounds check expected array type, got " + array_type.id_string();

  // Otherwise, if there's a dereference in the array source, this bounds check
  // should be performed by the symex-time dereferencing code, as the base thing
  // being accessed may be anything.
  if (has_dereference(expr.op0()))
    return;

  std::string name = "array bounds violated: " + array_name(expr.op0());
  const exprt &index = expr.op1();

  if (index.type().id() != "unsignedbv")
  {
    // we undo typecasts to signedbv
    if (index.id() == "typecast" && index.operands().size() == 1
        && index.op0().type().id() == "unsignedbv")
    {
      // ok
    }
    else
    {
      mp_integer i;

      if (!to_integer(index, i) && i >= 0)
      {
        // ok
      }
      else
      {
        exprt zero = gen_zero(index.type());

        if (zero.is_nil())
          throw "no zero constant of index type " + index.type().to_string();

        exprt inequality(">=", bool_typet());
        inequality.copy_to_operands(index, zero);

        add_guarded_claim(inequality, name + " lower bound", "array bounds",
            expr.find_location(), guard);
      }
    }
  }

  {
    if (array_type.size_irep().is_nil())
      throw "index array operand of wrong type";

    const exprt &size = (const exprt &) array_type.size_irep();

    if (size.id() != "infinity")
    {
      exprt inequality("<", bool_typet());
      inequality.copy_to_operands(index, size);

      // typecast size
      if (inequality.op1().type() != inequality.op0().type())
        inequality.op1().make_typecast(inequality.op0().type());

      add_guarded_claim(inequality, name + " upper bound", "array bounds",
          expr.find_location(), guard);
    }
  }
}