Skip to content

Improvements to code contracts [depends-on: #2646, #2676, blocks: #2712] #2677

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 13 commits into from

Conversation

qaphla
Copy link

@qaphla qaphla commented Aug 3, 2018

This provides a few changes which together serve to improve the havocking of variables when dealing with function calls (as well as a patch [02eb459] which doesn't really seem to fit anywhere else).

63b2af3 fixes a soundness issue with contract application by havocking the variables which could be touched by the function call being abstracted out.
2ec8f88 resolves an issue wherein function contracts were checked before initializing the dead and deallocated objects, and so any check that a pointer was not dead or deallocated would fail.
c3fcb36 switches contracts from using the local_may_alias analysis to the goto_rw analysis for finding the write sets of functions or loops.
a9354ac improves the documentation of the contracts feature.

This builds on #2646 because the changes in c3fcb36 benefit greatly from a less conservative approximation in goto_rw.

Only the commits mentioned by name in this are new. The others either come from #2646 or #2676.

klaas and others added 11 commits August 3, 2018 10:00
The previous implementation of code-contracts has a single flag
--apply-code-contracts, which created checks to verify that the
contracts are satisfied and also used the contracts to abstract
out the portions of code which had contracts provided.

This commit splits that process into two parts, one of which
only uses the contracts, without checking that they hold
(--apply-code-contracts) and the other of which (incomplete as of
this commit) both checks and applies, in a similar manner to the
existing method.

While it is clear that applying contracts without checking them
is unsound, it is nevertheless useful in verifying large pieces
of software in a modular fashion. If we verify a function to
satisfy its specification from an arbitrary environment, then
we can avoid needing to check that function again by using
--apply-code-contracts.
This commit completes the work started in the previous commit
by revising the existing contract-handling code into the new pass
--check-code-contracts, which first applies all contracts and then
checks them. By applying the contracts before checking begins, this
checks the relative correctness of each function/loop with respect
to the functions called by/loops contained in it. Since there can
be no infinite sequence of nested functions/loops, these relative
correctness results together imply the correctness of the overall
program. We take this approach rather than checking entirely
without using contracts because it allows significant reuse of
results --- a function that is called many times only needs to be
checked once, and all of its invocations will be abstracted out
by the contract application.
Several functions from the old implementation of code-contracts that
were made dead by the previous commits are removed by this commit.

Additionally, some variables which were formerly in use are no longer
needed, and so are removed.
This commit resolves an issue where ID_dynamic_object was used to
label two semantically distinct exprts.

One, with a single operand, was a boolean expression meaning that
the operand is a pointer to a dynamic object. This has been renamed
to ID_is_dynamic_object.

The second, with two operands, is an exprt representing a dynamic
object itself. This has stayed ID_dynamic_object.

Disambiguating which meaning was intended in each case was relatively
easy, as uses of these exprts frequently come with assertions
about the number of operands, and so this was used to inform which
instances of ID_dynamic_object should be changed and which should
be left the same.
When handling the case of pointers, goto_rw would mark both the object pointed
to and the pointer itself as written. For example, if x = &i, the line `*x = 1'
would yield a write set containing both x and i, instead of just i.

This resolves that issue by ensuring that value_set_dereference always
gives at least one object that the dereference can refer to.

This also resolves a bug wherein &a is marked as reading from a by
removing the ID_symbol special case from get_objects_address_of.A
…ions

Code contracts that introduce local declarations result in nested
typecheck_declaration calls. The artificial __CPROVER_return_value symbol must
then be added/removed by a single call only.
This commit changes the behaviour of --apply-code-contracts on
function calls. Previously, when applying contracts, a function
call would be replaced by an assertion that the precondition
holds, followed by an assumption that the postcondition holds.
This change inserts between that assert/assume pair code that
sets all variables that could be modified by the function being
called to be nondeterministic.
Because code contracts should be checked in an environment
constrained only by the preconditions, we want to check contracts
before initializing the dead and deallocated objects --- otherwise,
we fail to check the cases where a pointer argument to a function
points to a dead or deallocated object but is not NULL.

This commit resolves these issues by temporarily initializing dead
and deallocated objects to be the same fixed object before checking
contracts, and then performing the standard initialization to NULL.
klaas added 2 commits August 3, 2018 13:41
This change replaces the use of local_may_alias analysis in code
contracts with the more accurate goto_rw analysis. These analyses
are used to find the set of variables written to by a loop or
function so that we know which variables to make nondeterministic
when abstracting out those pieces of code.
This commit adds some documentation to code-contracts, as well as
fixing up small errors or confusing wording in existing comments.
Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR failed Diffblue compatibility checks (cbmc commit: 522c765).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/80904637
Status will be re-evaluated on next push.
Please contact @peterschrammel, @thk123, or @allredj for support.

Common spurious failures:

  • the cbmc commit has disappeared in the mean time (e.g. in a force-push)
  • the author is not in the list of contributors (e.g. first-time contributors).

@@ -65,6 +67,8 @@ jbmc/regression/**/tests-symex-driven-loading.log

# files stored by editors
*~
.*.swp
.*.swo

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this not redundant with the above?

@@ -184,6 +186,8 @@ void dep_graph_domaint::data_dependencies(
data_deps.insert(w_range.first);
found=true;
}
}
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change to this file appears unrelated.

@@ -414,16 +412,19 @@ void rw_range_sett::get_objects_typecast(

void rw_range_sett::get_objects_address_of(const exprt &object)
{
if(object.id() == ID_string_constant ||
if(object.id() == ID_symbol ||
object.id() == ID_string_constant ||
object.id() == ID_label ||
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ID_symbol case overrides the case below.

@@ -2141,7 +2141,7 @@ exprt c_typecheck_baset::do_special_functions(
throw 0;
}

exprt dynamic_object_expr=exprt(ID_dynamic_object, expr.type());
exprt dynamic_object_expr=exprt(ID_is_dynamic_object, expr.type());
dynamic_object_expr.operands()=expr.arguments();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use is_dynamic_object_exprt, which you are adding.

@kroening
Copy link
Member

kroening commented Aug 4, 2018

Given that new syntax is proposed here, did you consider ACSL?
https://github.com/acsl-language/acsl

Copy link
Collaborator

@martin-cs martin-cs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although I appreciate it is a pain, could we get the supporting PRs merged first and then look at this? I'm also very much with @kroening on the idea of annotation languages : the world may need another annotation language for C but it won't be one that is a partial subset of the features of an existing one. Interoperability is good and being able to compare wih / share benchmarks with tools like Frama-C would be great.

@tautschnig tautschnig changed the title Improvements to code contracts Improvements to code contracts [blocks: #2712] Nov 10, 2018
@tautschnig tautschnig removed their assignment Jan 4, 2019
@karkhaz karkhaz mentioned this pull request Jan 11, 2019
@tautschnig tautschnig changed the title Improvements to code contracts [blocks: #2712] Improvements to code contracts [depends-on: #2646, blocks: #2712] Feb 25, 2019
@tautschnig tautschnig changed the title Improvements to code contracts [depends-on: #2646, blocks: #2712] Improvements to code contracts [depends-on: #2646, #2676, blocks: #2712] Feb 25, 2019
@tautschnig tautschnig self-assigned this Feb 26, 2019
@TGWDB
Copy link
Contributor

TGWDB commented May 3, 2023

Closing due to age (no further comment on PR content), please reopen with rebase on develop if you intent to continue this work.

@TGWDB TGWDB closed this May 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants