Go to the documentation of this file.
30 static const char LOG_HEADER[] =
"assigns clause checking: ";
34 "contracts:propagate-static-local";
38 const auto &pragmas = source_location.
get_pragmas();
49 "contracts:disable:assigns-check";
54 location.
add_pragma(
"disable:pointer-primitive-check");
55 location.
add_pragma(
"disable:pointer-overflow-check");
56 location.
add_pragma(
"disable:signed-overflow-check");
57 location.
add_pragma(
"disable:unsigned-overflow-check");
58 location.
add_pragma(
"disable:conversion-check");
66 const auto &pragmas = target->source_location().get_pragmas();
93 if(
auto target = expr_try_dynamic_cast<conditional_target_group_exprt>(expr))
119 "symbol is not tracked :" +
from_expr(
ns,
"", symbol_expr));
160 "the instrumented function must exist in the model");
173 std::unordered_set<symbol_exprt, irep_hash> symbols;
176 for(
const auto &expr : propagated)
179 for(
const auto &sym : symbols)
192 std::unordered_set<symbol_exprt, irep_hash> symbols;
195 for(
const auto &sym : symbols)
198 for(
const auto &expr : propagated)
209 for(; it != end; it++)
211 const auto &loc = it->source_location();
212 const auto &loc_fun = loc.get_function();
215 auto &itv = covered_locations[loc_fun];
216 if(loc_fun == ambient_function_id)
229 log.
debug() <<
"Ignoring instruction without function attribute"
242 "Expected an assignment of the form `symbol_exprt := "
243 "side_effect_expr_nondett`");
249 if(it->is_function_call())
251 const auto &fun_expr = it->call_function();
254 fun_expr.id() == ID_symbol,
255 "Local static search requires function pointer removal");
261 "Function " +
id2string(fun_id) +
"not in function map");
264 if(covered_locations.find(fun_id) == covered_locations.end())
267 covered_locations[fun_id].anywhere();
285 std::unordered_set<symbol_exprt, irep_hash> &dest)
287 for(
const auto &sym_pair :
st)
289 const auto &sym = sym_pair.second;
290 if(sym.is_static_lifetime)
292 const auto &loc = sym.location;
293 if(!loc.get_function().empty())
295 const auto &itv = covered_locations.find(loc.get_function());
296 if(itv != covered_locations.end() && itv->second.contains(sym.location))
297 dest.insert(sym.symbol_expr());
328 while(instruction_it != instruction_end)
333 (pred && !pred(instruction_it)))
346 const auto &decl_symbol = instruction_it->decl_symbol();
362 else if(instruction_it->is_function_call())
368 const auto &symbol = instruction_it->dead_symbol();
384 log.
warning() <<
"Found a `DEAD` variable " << symbol.get_identifier()
385 <<
" without corresponding `DECL`, at: "
390 instruction_it->is_other() &&
391 instruction_it->get_other().get_statement() == ID_havoc_object)
393 auto havoc_argument = instruction_it->get_other().operands().front();
395 havoc_object.add_source_location() = instruction_it->source_location();
417 for(
const auto &target : group.
targets())
445 const std::string &suffix,
453 const exprt &condition,
454 const exprt &target)
const
457 const auto &valid_var =
461 const auto &lower_bound_var =
465 const auto &upper_bound_var =
469 if(target.
id() == ID_pointer_object)
492 const auto &ptr = funcall.arguments().at(0);
512 const auto &ptr = funcall.arguments().at(0);
513 const auto &size = funcall.arguments().at(1);
528 const auto &ptr = funcall.arguments().at(0);
545 const auto &ptr = funcall.arguments().at(0);
546 const auto &size = funcall.arguments().at(1);
547 const auto &is_ptr_to_ptr = funcall.arguments().at(2);
565 <<
" in assigns clauses not supported in this version";
575 "no definite size for lvalue target:\n" + target.
pretty());
628 bool allow_null_target)
const
639 if(allow_null_target)
647 bool allow_null_target,
661 std::string
comment =
"Check that ";
679 bool include_stack_allocated,
694 const auto &orig_comment = source_location.
get_comment();
695 std::string
comment =
"Check that ";
725 pointer_offset(car.lower_bound_var())},
727 pointer_offset(car.upper_bound_var()),
728 pointer_offset(candidate_car.upper_bound_var())}}},
735 bool include_stack_allocated)
const
738 (!include_stack_allocated ||
775 if(include_stack_allocated)
805 const exprt &condition,
812 log.
warning() <<
"Ignored duplicate expression '"
814 <<
"' in assigns clause spec at "
816 return found->second;
833 log.
warning() <<
"Ignored duplicate stack-allocated target '"
836 return found->second;
862 log.
warning() <<
"Ignored duplicate static local var target '"
865 return found->second;
888 not_exprt{same_object(
889 tracked_car.lower_bound_var(), freed_car.lower_bound_var())}},
917 <<
"skipping checking on assignment to local symbol "
955 <<
"skipping check on assignment to local composite member expression "
980 <<
format(target->decl_symbol()) <<
" as assignable"
987 <<
format(target->decl_symbol())
1005 auto lhs = instruction_it->assign_lhs();
1006 lhs.add_source_location() = instruction_it->source_location();
1017 instruction_it->is_function_call(),
1018 "The first argument of instrument_call_statement should always be "
1021 const auto &callee_name =
1024 if(callee_name ==
"malloc")
1027 if(function_call.lhs().is_not_nil())
1031 object.add_source_location() = function_call.source_location();
1043 else if(callee_name ==
"free")
1045 const auto &ptr = instruction_it->call_arguments().front();
1047 object.add_source_location() = instruction_it->source_location();
#define Forall_goto_program_instructions(it, program)
#define UNREACHABLE
This should be used to mark dead code.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
bool can_cast_expr< symbol_exprt >(const exprt &base)
const irep_idt & get_function() const
const irep_idt & get_comment() const
static exprt conditional_cast(const exprt &expr, const typet &type)
bool is_assignable(const exprt &expr)
Returns true iff the argument is one of the following:
cond_target_exprt_to_car_mapt from_spec_assigns
Map from conditional target expressions of assigns clauses to corresponding conditional address range...
const code_function_callt & to_code_function_call(const goto_instruction_codet &code)
void insert_before_swap_and_advance(goto_programt &destination, goto_programt::targett &target, goto_programt &payload)
Insert a goto program before a target instruction iterator and advance the iterator.
side_effect_expr_function_callt & to_side_effect_expr_function_call(exprt &expr)
bool has_subexpr(const exprt &expr, const std::function< bool(const exprt &)> &pred)
returns true if the expression has a subexpression that satisfies pred
exprt pointer_object(const exprt &p)
std::string as_string() const
bool can_cast_expr< side_effect_expr_function_callt >(const exprt &base)
void set_comment(const irep_idt &comment)
const car_exprt & create_car_from_spec_assigns(const exprt &condition, const exprt &target)
Class that represents a single conditional target.
void set_function(const irep_idt &function)
void traverse_instructions(const irep_idt ambient_function_id, goto_programt::const_targett it, const goto_programt::const_targett end, covered_locationst &covered_locations, propagated_static_localst &propagated) const
Traverses the given list of instructions, updating the given coverage map, recursing into function ca...
exprt null_pointer(const exprt &pointer)
source_locationt & source_location_nonconst()
The type of an expression, extends irept.
const irept::named_subt & get_pragmas() const
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
void check_inclusion_heap_allocated_and_invalidate_aliases(const exprt &expr, goto_programt &dest)
Generates inclusion check instructions for an argument passed to free.
void create_snapshot(const car_exprt &car, goto_programt &dest) const
Returns snapshot instructions for a car_exprt.
const exprt & condition() const
Condition expression. When this condition holds the target is allowed.
const char CONTRACT_PRAGMA_DISABLE_ASSIGNS_CHECK[]
A local pragma used to keep track and skip already instrumented instructions.
symbol_exprt_to_car_mapt from_stack_alloc
Map from DECL symbols to corresponding conditional address ranges.
void check_inclusion_assignment(const exprt &lhs, goto_programt &dest) const
Generates inclusion check instructions for an assignment, havoc or havoc_object instruction.
bool has_disable_assigns_check_pragma(const goto_programt::const_targett &target)
Returns true iff the target instruction is tagged with a 'CONTRACT_PRAGMA_DISABLE_ASSIGNS_CHECK' prag...
void invalidate_car(const car_exprt &tracked_car, const car_exprt &freed_car, goto_programt &result) const
Adds an assignment in dest to invalidate the tracked car if was valid before and was pointing to the ...
void add_pragma(const irep_idt &pragma)
targett add(instructiont &&instruction)
Adds a given instruction at the end.
void invalidate_heap_and_spec_aliases(const car_exprt &freed_car, goto_programt &dest) const
Generates instructions to invalidate all targets aliased with a car that was passed to free,...
The plus expression Associativity is not specified.
bool empty() const
Is the program empty?
Base class for all expressions.
symbol_exprt_to_car_mapt from_static_local
Map to from detected or propagated static local symbols to corresponding conditional address ranges.
void inclusion_check_assertion(const car_exprt &lhs, bool allow_null_lhs, bool include_stack_allocated, goto_programt &dest) const
Returns an inclusion check assertion of lhs over all tracked cars.
exprt target_validity_expr(const car_exprt &car, bool allow_null_target) const
Returns the target validity expression for a car_exprt.
bool is_true() const
Return whether the expression is a constant representing true.
static const char PROPAGATE_STATIC_LOCAL_PRAGMA[]
Pragma used to mark assignments to static locals that need to be propagated.
const exprt & target_size() const
Size of the target in bytes.
function_mapt function_map
const symbol_exprt & lower_bound_var() const
Identifier of the lower address bound snapshot variable.
Expression to hold a symbol (variable)
static instructiont make_decl(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
bool is_assigns_clause_replacement_tracking_comment(const irep_idt &comment)
Returns true if the given comment matches the type of comments created by make_assigns_clause_replace...
static instructiont make_assignment(const code_assignt &_code, const source_locationt &l=source_locationt::nil())
Create an assignment instruction.
void target_validity_assertion(const car_exprt &car, bool allow_null_target, goto_programt &dest) const
Generates the target validity assertion for the given car and adds it to dest.
void clean(exprt &guard, goto_programt &dest, const irep_idt &mode)
Allows to clean expressions of side effects.
void add_pragma_disable_pointer_checks(source_locationt &location)
Adds a pragma on a source location disable all pointer checks.
const irep_idt & function_id
Name of the instrumented function.
const symbol_exprt & upper_bound_var() const
Identifier of the upper address bound snapshot variable.
const symbol_exprt & valid_var() const
Identifier of the validity snapshot variable.
typet & type()
Return the type of the expression.
const pointer_object_exprt & to_pointer_object_expr(const exprt &expr)
Cast an exprt to a pointer_object_exprt.
exprt disjunction(const exprt::operandst &op)
1) generates a disjunction for two or more operands 2) for one operand, returns the operand 3) return...
const namespacet ns
Program namespace.
static instructiont make_assertion(const exprt &g, const source_locationt &l=source_locationt::nil())
bool can_cast_expr< side_effect_expr_nondett >(const exprt &base)
car_exprt create_car_expr(const exprt &condition, const exprt &target) const
Creates a conditional address range expression from a cleaned-up condition and target expression.
const std::string & id2string(const irep_idt &d)
bool must_track_dead(const goto_programt::const_targett &target) const
Returns true iff a DEAD x must be processed to update the write set.
source_locationt source_location
exprt inclusion_check_single(const car_exprt &lhs, const car_exprt &candidate_car) const
Returns inclusion check expression for a single candidate location.
symbol_tablet & st
Program symbol table.
const car_exprt & create_car_from_static_local(const symbol_exprt &target)
bool has_propagate_static_local_pragma(const source_locationt &source_location)
const irep_idt & get_identifier() const
void add_pragma_disable_assigns_check(source_locationt &location)
Adds a pragma on a source_locationt to disable inclusion checking.
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
signedbv_typet signed_size_type()
exprt simplify_expr(exprt src, const namespacet &ns)
bool is_local_composite_access(const exprt &expr) const
Returns true iff expr is an access to a locally declared symbol and does not contain dereference or a...
exprt inclusion_check_full(const car_exprt &lhs, bool allow_null_lhs, bool include_stack_allocated) const
Returns an inclusion check expression of lhs over all tracked cars.
void add_propagate_static_local_pragma(source_locationt &source_location)
Sets a pragma to mark assignments to static local variables that need to be propagated upwards in the...
pointer_typet pointer_type(const typet &subtype)
const irep_idt & mode
Language mode.
car_expr_listt from_heap_alloc
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
exprt object_size(const exprt &pointer)
bool must_track_decl(const goto_programt::const_targett &target) const
Returns true iff a DECL x must be explicitly added to the write set.
const irep_idt & id() const
static const char LOG_HEADER[]
header for log messages
std::vector< exprt > operandst
The Boolean constant false.
const goto_functionst & functions
Other functions of the model.
bool must_check_assign(const goto_programt::const_targett &target)
Returns true iff an ASSIGN lhs := rhs instruction must be instrumented.
void instrument_assign_statement(goto_programt::targett &instruction_it, goto_programt &body) const
Inserts an assertion in body immediately before the assignment at instruction_it, to ensure that the ...
A class for an expression that represents a conditional target or a list of targets sharing a common ...
exprt pointer_offset(const exprt &pointer)
const exprt & condition() const
const exprt::operandst & targets() const
bitvector_typet char_type()
instructionst instructions
The list of instructions in the goto program.
void track_static_locals_between(goto_programt::const_targett it, const goto_programt::const_targett end, goto_programt &dest)
Searches the goto instructions reachable between the given it and end target instructions to identify...
Deprecated expression utility functions.
virtual bool is_not_local_or_dirty_local(const irep_idt &ident) const =0
Returns true iff the given ident is either non-locally declared or is locally-declared but dirty.
message_handlert & get_message_handler()
void track_static_locals(goto_programt &dest)
Searches the goto instructions reachable from the start to the end of the instrumented function's ins...
void invalidate_stack_allocated(const symbol_exprt &symbol_expr, goto_programt &dest)
Generate instructions to invalidate a stack-allocated object that goes DEAD in dest.
void track_plain_spec_target(const exprt &expr, goto_programt &dest)
Track and generate snaphsot instructions and target validity checking assertions for a conditional ta...
void instrument_call_statement(goto_programt::targett &instruction_it, goto_programt &body)
Inserts an assertion in body immediately before the function call at instruction_it,...
const exprt & target() const
The target expression.
const symbolt create_fresh_symbol(const std::string &suffix, const typet &type, const source_locationt &location) const
Creates a fresh symbolt with given suffix, scoped to function_id.
bool must_track_decl_or_dead(const irep_idt &ident) const
Returns true iff a function-local symbol must be tracked.
A predicate that indicates that an address range is ok to write.
#define PRECONDITION_WITH_DIAGNOSTICS(CONDITION,...)
std::unordered_map< irep_idt, location_intervalt > covered_locationst
Map type from function identifiers to covered locations.
void instrument_instructions(goto_programt &body, goto_programt::targett instruction_it, const goto_programt::targett &instruction_end, const std::function< bool(const goto_programt::targett &)> &pred={})
Instruments a sequence of instructions with inclusion checks.
void collect_static_symbols(covered_locationst &covered_locations, std::unordered_set< symbol_exprt, irep_hash > &dest)
Collects static symbols from the symbol table that have a source location included in one of the cove...
exprt same_object(const exprt &p1, const exprt &p2)
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
const car_exprt & create_car_from_heap_alloc(const exprt &target)
const exprt & target_start_address() const
Start address of the target.
A generic container class for the GOTO intermediate representation of one function.
void track_heap_allocated(const exprt &expr, goto_programt &dest)
Track a whole heap-alloc object and generate snaphsot instructions in dest.
optionalt< exprt > size_of_expr(const typet &type, const namespacet &ns)
instructionst::const_iterator const_targett
void track_spec_target(const exprt &expr, goto_programt &dest)
Track an assigns clause target and generate snaphsot instructions and well-definedness assertions in ...
const symbolt & new_tmp_symbol(const typet &type, const source_locationt &location, const irep_idt &mode, symbol_table_baset &symtab, std::string suffix, bool is_auxiliary)
Adds a fresh and uniquely named symbol to the symbol table.
cfg_infot & cfg_info
CFG information for simplification.
Class that represents a normalized conditional address range, with:
Binary less than or equal operator expression.
Operator to return the address of an object.
unsignedbv_typet size_type()
void track_spec_target_group(const conditional_target_group_exprt &group, goto_programt &dest)
Track and generate snaphsot instructions and target validity checking assertions for a conditional ta...
The Boolean constant true.
std::unordered_set< symbol_exprt, irep_hash > propagated_static_localst
mstreamt & warning() const
static std::string comment(const rw_set_baset::entryt &entry, bool write)
This class represents an instruction in the GOTO intermediate representation.
const source_locationt & source_location() const
bool stack_allocated_is_tracked(const symbol_exprt &symbol_expr) const
Returns true if the expression is tracked.
std::string from_expr(const namespacet &ns, const irep_idt &identifier, const exprt &expr)
void track_stack_allocated(const symbol_exprt &symbol_expr, goto_programt &dest)
Track a stack-allocated object and generate snaphsot instructions in dest.
instructionst::iterator targett
std::string from_expr_using_mode(const namespacet &ns, const irep_idt &mode, const exprt &expr)
Formats an expression using the given namespace, using the given mode to retrieve the language printe...
virtual bool is_local(const irep_idt &ident) const =0
Returns true iff ident is locally declared.
const car_exprt & create_car_from_stack_alloc(const symbol_exprt &target)
void set_property_class(const irep_idt &property_class)