Skip to content

Commit 0192dd0

Browse files
author
Remi Delmas
committed
Check inferred loop assigns clauses instead of blinding trusting them.
1 parent f046844 commit 0192dd0

File tree

1 file changed

+39
-17
lines changed

1 file changed

+39
-17
lines changed

src/goto-instrument/contracts/contracts.cpp

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -252,13 +252,30 @@ void code_contractst::check_apply_loop_contracts(
252252
loop_head,
253253
add_pragma_disable_assigns_check(generated_code));
254254

255-
// havoc the variables that may be modified
256-
assignst assigns;
255+
assignst to_havoc;
256+
257257
if(assigns_clause.is_nil())
258258
{
259+
// No assigns clause was specified for this loop.
260+
// Infer memory locations assigned by the loop from the loop instructions
261+
// and the inferred alisaing relation.
259262
try
260263
{
261-
get_assigns(local_may_alias, loop, assigns);
264+
get_assigns(local_may_alias, loop, to_havoc);
265+
log.warning() << "No loop assigns clause provided. Inferred targets {";
266+
// Add inferred targets to the loop assigns clause.
267+
bool ran_once = false;
268+
for(auto &target : to_havoc)
269+
{
270+
if(ran_once)
271+
log.warning() << ", ";
272+
ran_once = true;
273+
log.warning() << from_expr(ns, target.id(), target);
274+
loop_assigns.add_to_write_set(target);
275+
}
276+
log.warning()
277+
<< "}. Please specify an assigns clause if verification fails."
278+
<< messaget::eom;
262279
}
263280
catch(const analysis_exceptiont &exc)
264281
{
@@ -271,24 +288,29 @@ void code_contractst::check_apply_loop_contracts(
271288
}
272289
else
273290
{
274-
assigns.insert(
291+
// An assigns clause was specified for this loop.
292+
// Add the targets to the set of expressions to havoc.
293+
// TODO: Should we add the automatically detected local static variables
294+
// too ? (they are present in loop_assigns but not in assigns_clause, and
295+
// they are not necessarily touched by the loop).
296+
to_havoc.insert(
275297
assigns_clause.operands().cbegin(), assigns_clause.operands().cend());
298+
}
276299

277-
// Create snapshots of write set CARs.
278-
// This must be done before havocing the write set.
279-
for(const auto &car : loop_assigns.get_write_set())
280-
{
281-
auto snapshot_instructions = car.generate_snapshot_instructions();
282-
insert_before_swap_and_advance(
283-
goto_function.body, loop_head, snapshot_instructions);
284-
};
300+
// Create snapshots of write set CARs.
301+
// This must be done before havocing the write set.
302+
for(const auto &car : loop_assigns.get_write_set())
303+
{
304+
auto snapshot_instructions = car.generate_snapshot_instructions();
305+
insert_before_swap_and_advance(
306+
goto_function.body, loop_head, snapshot_instructions);
307+
};
285308

286-
// Perform write set instrumentation on the entire loop.
287-
check_frame_conditions(
288-
function_name, goto_function.body, loop_head, loop_end, loop_assigns);
289-
}
309+
// Perform write set instrumentation on the entire loop.
310+
check_frame_conditions(
311+
function_name, goto_function.body, loop_head, loop_end, loop_assigns);
290312

291-
havoc_assigns_targetst havoc_gen(assigns, ns);
313+
havoc_assigns_targetst havoc_gen(to_havoc, ns);
292314
havoc_gen.append_full_havoc_code(
293315
loop_head->source_location(), generated_code);
294316

0 commit comments

Comments
 (0)