CBMC
Loading...
Searching...
No Matches
memory_predicates.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Predicates to specify memory footprint in function contracts.
4
5Author: Felipe R. Monteiro
6
7Date: July 2021
8
9\*******************************************************************/
10
13
14#include "memory_predicates.h"
15
16#include <util/arith_tools.h>
17#include <util/c_types.h>
18#include <util/config.h>
19#include <util/fresh_symbol.h>
20#include <util/prefix.h>
21
25
27#include "utils.h"
28
30{
31 return function_set;
32}
33
35{
37
39 {
40 if(ins->is_function_call())
41 {
42 const auto &function = ins->call_function();
43
44 if(function.id() != ID_symbol)
45 {
46 log.error().source_location = ins->source_location();
47 log.error() << "Function pointer used in function invoked by "
48 "function contract: "
50 throw 0;
51 }
52 else
53 {
54 const irep_idt &fun_name = to_symbol_expr(function).get_identifier();
55 if(function_set.find(fun_name) == function_set.end())
56 {
57 function_set.insert(fun_name);
58 auto called_fun = goto_functions.function_map.find(fun_name);
59 if(called_fun == goto_functions.function_map.end())
60 {
61 log.warning() << "Could not find function '" << fun_name
62 << "' in goto-program." << messaget::eom;
63 throw 0;
64 }
65 if(called_fun->second.body_available())
66 {
67 const goto_programt &program = called_fun->second.body;
68 (*this)(program);
69 }
70 else
71 {
72 log.warning() << "No body for function: " << fun_name
73 << "invoked from function contract." << messaget::eom;
74 }
75 }
76 }
77 }
78 }
79}
80
81std::set<goto_programt::targett, goto_programt::target_less_than> &
86
91
93{
95 {
96 if(ins->is_function_call())
97 {
98 const auto &function = ins->call_function();
99
100 if(function.id() == ID_symbol)
101 {
102 const irep_idt &fun_name = to_symbol_expr(function).get_identifier();
103
104 if(fun_name == (CPROVER_PREFIX + std::string("is_fresh")))
105 {
106 function_set.insert(ins);
107 }
108 }
109 }
110 }
111}
112
122
132
133//
134//
135// Code largely copied from model_argc_argv.cpp
136//
137//
138
143
145{
146 source_locationt source_location;
147 add_pragma_disable_assigns_check(source_location);
149 program.add(
154 from_integer(0, get_memmap_type().element_type()), get_memmap_type()),
155 source_location));
156}
157
159{
160 source_locationt source_location;
161 add_pragma_disable_assigns_check(source_location);
162 program.add(
164}
165
167{
169 log.debug() << "Creating declarations: \n" << decl_string << "\n";
170
171 std::istringstream iss(decl_string);
172
176 ansi_c_language.parse(iss, "", log.get_message_handler());
177 config.ansi_c.preprocessor = pp;
178
180 ansi_c_language.typecheck(
181 tmp_symbol_table, "<built-in-library>", log.get_message_handler());
182 exprt value = nil_exprt();
183
185
186 // Add the new functions into the goto functions table.
188 tmp_functions.function_map[ensures_fn_name]);
189
191 tmp_functions.function_map[requires_fn_name]);
192
193 for(const auto &symbol_pair : tmp_symbol_table.symbols)
194 {
195 if(
196 symbol_pair.first == memmap_name ||
197 symbol_pair.first == ensures_fn_name ||
198 symbol_pair.first == requires_fn_name || symbol_pair.first == "malloc")
199 {
201 }
202 // Parameters are stored as scoped names in the symbol table.
203 else if(
204 (has_prefix(
209 {
211 }
212 }
213
216}
217
220 const std::string &fn_name,
221 bool add_address_of)
222{
223 // adjusting the expression for the first argument, if required
225 {
226 INVARIANT(
227 as_const(*ins).call_arguments().size() > 0,
228 "Function must have arguments");
229 ins->call_arguments()[0] = address_of_exprt(ins->call_arguments()[0]);
230 }
231
232 // fixing the function name.
233 to_symbol_expr(ins->call_function()).set_identifier(fn_name);
234
235 // pass the memory mmap
236 ins->call_arguments().push_back(address_of_exprt(
238}
239
240/* Declarations for contract enforcement */
241
243 goto_modelt &goto_model,
244 message_handlert &message_handler,
245 const irep_idt &_fun_id)
246 : is_fresh_baset(goto_model, message_handler, _fun_id)
247{
248 std::stringstream ssreq, ssensure, ssmemmap;
249 ssreq << CPROVER_PREFIX "enforce_requires_is_fresh";
250 this->requires_fn_name = ssreq.str();
251
252 ssensure << CPROVER_PREFIX "enforce_ensures_is_fresh";
253 this->ensures_fn_name = ssensure.str();
254
255 ssmemmap << CPROVER_PREFIX "is_fresh_memory_map_" << fun_id;
256 this->memmap_name = ssmemmap.str();
257
258 const auto &mode = goto_model.symbol_table.lookup_ref(_fun_id).mode;
261 "",
262 this->memmap_name,
264 mode,
266}
267
269{
270 // Check if symbols are already declared
272 return;
273
274 std::ostringstream oss;
275 std::string cprover_prefix(CPROVER_PREFIX);
276 oss << "_Bool " << requires_fn_name
277 << "(void **elem, " + cprover_prefix + "size_t size, _Bool *mmap) { \n"
278 << "#pragma CPROVER check push\n"
279 << "#pragma CPROVER check disable \"pointer\"\n"
280 << "#pragma CPROVER check disable \"pointer-primitive\"\n"
281 << "#pragma CPROVER check disable \"pointer-overflow\"\n"
282 << "#pragma CPROVER check disable \"signed-overflow\"\n"
283 << "#pragma CPROVER check disable \"unsigned-overflow\"\n"
284 << "#pragma CPROVER check disable \"conversion\"\n"
285 << " *elem = malloc(size); \n"
286 << " if (!*elem) return 0; \n"
287 << " mmap[" + cprover_prefix + "POINTER_OBJECT(*elem)] = 1; \n"
288 << " return 1; \n"
289 << "#pragma CPROVER check pop\n"
290 << "} \n"
291 << "\n"
292 << "_Bool " << ensures_fn_name
293 << "(void *elem, " + cprover_prefix + "size_t size, _Bool *mmap) { \n"
294 << "#pragma CPROVER check push\n"
295 << "#pragma CPROVER check disable \"pointer\"\n"
296 << "#pragma CPROVER check disable \"pointer-primitive\"\n"
297 << "#pragma CPROVER check disable \"pointer-overflow\"\n"
298 << "#pragma CPROVER check disable \"signed-overflow\"\n"
299 << "#pragma CPROVER check disable \"unsigned-overflow\"\n"
300 << "#pragma CPROVER check disable \"conversion\"\n"
301 << " _Bool ok = (!mmap[" + cprover_prefix + "POINTER_OBJECT(elem)] && "
302 << cprover_prefix + "r_ok(elem, size)); \n"
303 << " mmap[" + cprover_prefix << "POINTER_OBJECT(elem)] = 1; \n"
304 << " return ok; \n"
305 << "#pragma CPROVER check pop\n"
306 << "}";
307
308 add_declarations(oss.str());
309}
310
315
320
322 goto_modelt &goto_model,
323 message_handlert &message_handler,
324 const irep_idt &_fun_id)
325 : is_fresh_baset(goto_model, message_handler, _fun_id)
326{
327 std::stringstream ssreq, ssensure, ssmemmap;
328 ssreq << CPROVER_PREFIX "replace_requires_is_fresh";
329 this->requires_fn_name = ssreq.str();
330
331 ssensure << CPROVER_PREFIX "replace_ensures_is_fresh";
332 this->ensures_fn_name = ssensure.str();
333
334 ssmemmap << CPROVER_PREFIX "is_fresh_memory_map_" << fun_id;
335 this->memmap_name = ssmemmap.str();
336
337 const auto &mode = goto_model.symbol_table.lookup_ref(_fun_id).mode;
340 "",
341 this->memmap_name,
343 mode,
345}
346
348{
349 // Check if symbols are already declared
351 return;
352
353 std::ostringstream oss;
354 std::string cprover_prefix(CPROVER_PREFIX);
355 oss << "static _Bool " << requires_fn_name
356 << "(void *elem, " + cprover_prefix + "size_t size, _Bool *mmap) { \n"
357 << "#pragma CPROVER check push\n"
358 << "#pragma CPROVER check disable \"pointer\"\n"
359 << "#pragma CPROVER check disable \"pointer-primitive\"\n"
360 << "#pragma CPROVER check disable \"pointer-overflow\"\n"
361 << "#pragma CPROVER check disable \"signed-overflow\"\n"
362 << "#pragma CPROVER check disable \"unsigned-overflow\"\n"
363 << "#pragma CPROVER check disable \"conversion\"\n"
364 << " _Bool r_ok = " + cprover_prefix + "r_ok(elem, size); \n"
365 << " if (mmap[" + cprover_prefix + "POINTER_OBJECT(elem)]"
366 << " != 0 || !r_ok) return 0; \n"
367 << " mmap[" << cprover_prefix + "POINTER_OBJECT(elem)] = 1; \n"
368 << " return 1; \n"
369 << "#pragma CPROVER check pop\n"
370 << "} \n"
371 << " \n"
372 << "_Bool " << ensures_fn_name
373 << "(void **elem, " + cprover_prefix + "size_t size, _Bool *mmap) { \n"
374 << "#pragma CPROVER check push\n"
375 << "#pragma CPROVER check disable \"pointer\"\n"
376 << "#pragma CPROVER check disable \"pointer-primitive\"\n"
377 << "#pragma CPROVER check disable \"pointer-overflow\"\n"
378 << "#pragma CPROVER check disable \"signed-overflow\"\n"
379 << "#pragma CPROVER check disable \"unsigned-overflow\"\n"
380 << "#pragma CPROVER check disable \"conversion\"\n"
381 << " *elem = malloc(size); \n"
382 << " return (*elem != 0); \n"
383 << "#pragma CPROVER check pop\n"
384 << "} \n";
385
386 add_declarations(oss.str());
387}
388
393
configt config
Definition config.cpp:25
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
const T & as_const(T &value)
Return a reference to the same object but ensures the type is const.
Definition as_const.h:14
unsignedbv_typet unsigned_char_type()
Definition c_types.cpp:127
bitvector_typet c_index_type()
Definition c_types.cpp:16
Operator to return the address of an object.
virtual void clear()
Reset the abstract state.
Definition ai.h:265
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Array constructor from single element.
Definition std_expr.h:1558
Arrays with given size.
Definition std_types.h:807
struct configt::ansi_ct ansi_c
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Base class for all expressions.
Definition expr.h:56
Predicate to be used with the exprt::visit() function.
void operator()(goto_programt &prog)
std::set< goto_programt::targett, goto_programt::target_less_than > & is_fresh_calls()
std::set< goto_programt::targett, goto_programt::target_less_than > function_set
void operator()(const goto_programt &prog)
const goto_functionst & goto_functions
std::set< irep_idt > & function_calls()
std::set< irep_idt > function_set
message_handlert & message_handler
A collection of goto functions.
function_mapt function_map
bool can_produce_function(const irep_idt &id) const override
Determines if this model can produce a body for the given function.
Definition goto_model.h:95
symbol_tablet symbol_table
Symbol table.
Definition goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition goto_model.h:34
A generic container class for the GOTO intermediate representation of one function.
static instructiont make_dead(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
instructionst::iterator targett
static instructiont make_assignment(const code_assignt &_code, const source_locationt &l=source_locationt::nil())
Create an assignment instruction.
targett add(instructiont &&instruction)
Adds a given instruction at the end.
static instructiont make_decl(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
Array index operator.
Definition std_expr.h:1470
An expression denoting infinity.
Definition std_expr.h:3224
virtual void create_ensures_fn_call(goto_programt::targett &target)=0
const irep_idt & fun_id
void update_fn_call(goto_programt::targett &target, const std::string &name, bool add_address_of)
std::string ensures_fn_name
message_handlert & message_handler
std::string requires_fn_name
void add_memory_map_decl(goto_programt &program)
void update_requires(goto_programt &requires_)
void add_memory_map_dead(goto_programt &program)
array_typet get_memmap_type()
goto_modelt & goto_model
void add_declarations(const std::string &decl_string)
std::string memmap_name
void update_ensures(goto_programt &ensures)
virtual void create_requires_fn_call(goto_programt::targett &target)=0
is_fresh_enforcet(goto_modelt &goto_model, message_handlert &message_handler, const irep_idt &_fun_id)
virtual void create_ensures_fn_call(goto_programt::targett &target)
virtual void create_requires_fn_call(goto_programt::targett &target)
virtual void create_declarations()
is_fresh_replacet(goto_modelt &goto_model, message_handlert &message_handler, const irep_idt &_fun_id)
virtual void create_ensures_fn_call(goto_programt::targett &target)
virtual void create_declarations()
virtual void create_requires_fn_call(goto_programt::targett &target)
Class that provides messages with a built-in verbosity 'level'.
Definition message.h:154
static eomt eom
Definition message.h:289
The NIL expression.
Definition std_expr.h:3208
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
const symbolt & lookup_ref(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
The symbol table.
virtual std::pair< symbolt &, bool > insert(symbolt symbol) override
Author: Diffblue Ltd.
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition symbol.cpp:121
bool has_prefix(const std::string &s, const std::string &prefix)
Definition converter.cpp:13
#define CPROVER_PREFIX
symbolt & get_fresh_aux_symbol(const typet &type, const std::string &name_prefix, const std::string &basename_prefix, const source_locationt &source_location, const irep_idt &symbol_mode, const namespacet &ns, symbol_table_baset &symbol_table)
Installs a fresh-named symbol with respect to the given namespace ns with the requested name pattern ...
Fresh auxiliary symbol creation.
Goto Programs with Functions.
#define forall_goto_program_instructions(it, program)
#define Forall_goto_program_instructions(it, program)
void add_pragma_disable_assigns_check(source_locationt &location)
Adds a pragma on a source_locationt to disable inclusion checking.
Specify write set in function contracts.
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
double log(double x)
Definition math.c:2449
Predicates to specify memory footprint in function contracts.
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
void recreate_initialize_function(goto_modelt &goto_model, message_handlert &message_handler)
Regenerates the CPROVER_INITIALIZE function, which initializes all non-function symbols of the goto m...
#define INITIALIZE_FUNCTION
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:272
#define size_type
Definition unistd.c:186