Skip to content

Enforce __CPROVER_loop_invariant contracts in goto-instrument #5884

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

Merged

Conversation

SaswatPadhi
Copy link
Contributor

This PR resolves #5882.

It enforces __CPROVER_loop_invariant contract (in addition to function contracts) when --enforce-all-contracts or --enforce-contract <fun> flag is used with goto-instrument.

NOTE: The code_contracts.h and code_contracts.cpp files need a thorough clean up -- the return types seem inconsistent (void vs bool) for many functions that have similar behavior, and several functions don't use the C++11 range-based for loops etc. I would make a separate PR later for refactoring and cleanup. This PR only adds the invariant checking back into the contracts flags and enables related regression tests.

  • Each commit message has a non-empty body, explaining why the change was made.
  • Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • The feature or user visible behaviour. I have added or modified has been documented in the User Guide in doc/cprover-manual/
  • Regression or unit tests are included, or existing tests cover the modified code (in this case I have detailed which ones those are in the commit message).
  • My commit message includes data points confirming performance improvements (if claimed).
  • My PR is restricted to a single feature or bugfix.
  • White-space or formatting changes outside the feature-related changed lines are in commits of their own.

@codecov
Copy link

codecov bot commented Mar 4, 2021

Codecov Report

Merging #5884 (45b6d72) into develop (6779f39) will increase coverage by 0.04%.
The diff coverage is 82.60%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #5884      +/-   ##
===========================================
+ Coverage    72.90%   72.95%   +0.04%     
===========================================
  Files         1425     1425              
  Lines       154282   154281       -1     
===========================================
+ Hits        112485   112561      +76     
+ Misses       41797    41720      -77     
Impacted Files Coverage Δ
src/goto-instrument/code_contracts.h 100.00% <ø> (ø)
src/goto-instrument/code_contracts.cpp 91.01% <82.60%> (+10.12%) ⬆️
src/ansi-c/parser.y 78.10% <0.00%> (+0.20%) ⬆️
src/goto-programs/goto_convert.cpp 90.86% <0.00%> (+0.59%) ⬆️
src/analyses/cfg_dominators.h 100.00% <0.00%> (+1.44%) ⬆️
src/analyses/local_may_alias.cpp 60.27% <0.00%> (+2.73%) ⬆️
src/analyses/natural_loops.h 100.00% <0.00%> (+5.40%) ⬆️
src/goto-instrument/loop_utils.cpp 63.63% <0.00%> (+38.63%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7f998c4...45b6d72. Read the comment docs.

@tautschnig
Copy link
Collaborator

[...]

I would make a separate PR later for refactoring and cleanup. This PR only adds the invariant checking back into the contracts flags and enables related regression tests.

@SaswatPadhi Please make sure you sync with @feliperodri on this to avoid duplicate work.

Copy link
Collaborator

@feliperodri feliperodri left a comment

Choose a reason for hiding this comment

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

I'd aslo recommend you to break down the PR into at least two commits: one for the changes in code_contracts.* files and another for the updates in the regression tests.

@SaswatPadhi SaswatPadhi force-pushed the loop_invariant_contract_fix branch from a0a7304 to eae9473 Compare March 4, 2021 23:06
@SaswatPadhi SaswatPadhi requested a review from feliperodri March 4, 2021 23:10
@SaswatPadhi SaswatPadhi force-pushed the loop_invariant_contract_fix branch 2 times, most recently from 4c4c2cd to 5564547 Compare March 5, 2021 00:28
@feliperodri feliperodri added aws Bugs or features of importance to AWS CBMC users Code Contracts Function and loop contracts labels Mar 5, 2021
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.

Seems good. Comments are only minor improvements. Thanks for the contribution.

// look at all function calls
Forall_goto_program_instructions(ins, goto_function.body)
if(ins->is_function_call())
apply_contract(goto_function.body, ins);

Choose a reason for hiding this comment

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

Still d20bbe1

Case in point: In this case it's a bit hard for me to see why this loop was removed. It's combined with a fairly straightforward refactoring of the preceding loop so it's difficult for me see if this was an intentional change or a mistake that snuck in during refactoring.

Copy link
Contributor Author

@SaswatPadhi SaswatPadhi Mar 5, 2021

Choose a reason for hiding this comment

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

This particular function was perhaps the old entry point for the old contracts flag. It was used to replace loops with invariant contracts and function calls with function contracts. I removed this loop intentionally because the replacement of calls with contracts now happens in replace_calls. You can see a very similar loop in replace_calls:

for(auto &goto_function : goto_functions.function_map)
{
Forall_goto_program_instructions(ins, goto_function.second.body)
{
if(ins->is_function_call())
{
const code_function_callt &call = ins->get_function_call();
// TODO we don't handle function pointers
if(call.function().id() != ID_symbol)
continue;
const irep_idt &fun_name =
to_symbol_expr(call.function()).get_identifier();
auto found = std::find(
funs_to_replace.begin(), funs_to_replace.end(), id2string(fun_name));
if(found == funs_to_replace.end())
continue;
fail |= apply_contract(goto_function.second.body, ins);
}
}
}

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm ok with the actual changes, clang-format weirdness can be resolved (see my reply to your slack message), would prefer if the first commit was split up further before merging but not a blocker.

The `code_contracts` function was unused and the function contract
application part of it was improved in `replace_calls`.
This commit:
- removes this old unused functionality,
- renames `code_contracts` to `apply_loop_contract`, and
- renames `apply_contract` to `apply_function_contract`.
Loop invariant annotations were being silently ignored when goto-instrument was
invoked with `--enforce-contracts` or `--enforce-contract`.
These flags now enforce both function and loop invariant contracts.
@SaswatPadhi SaswatPadhi force-pushed the loop_invariant_contract_fix branch from 5564547 to 142ff6a Compare March 5, 2021 18:15
- Moved comments from .c files to descriptions in .desc files
- Added new tests to check multiple loops, nested loops, loop-local variables
- Enabled and clarified a regression test that was flagged as a buggy one
@SaswatPadhi SaswatPadhi force-pushed the loop_invariant_contract_fix branch from 142ff6a to 45b6d72 Compare March 5, 2021 18:17
@SaswatPadhi
Copy link
Contributor Author

Thanks for the review, @martin-cs and @hannes-steffenhagen-diffblue. I think I have addressed all your comments now. Please take another look and let me know if I should make any more changes.

@SaswatPadhi SaswatPadhi changed the title Loop invariant contracts are now enforced Enforce __CPROVER_loop_invariant contracts in goto-instrument Mar 5, 2021
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.

Yep; looks good.

@martin-cs
Copy link
Collaborator

I realise this isn't really the right place to ask this but... if you are considering a reworking / rewrite of the code contracts stuff:

  1. Is there any chance you could look at / incorporate / test / obsolete the k-induction code in goto-instrument? There were tests for this somewhere but I don't know if these are enabled.
  2. Could it get added to the manual? I think we are close to having one of the best deductive verification tools for C ( and with @danielsn and @tautschnig 's work on s2n, one of the best used ) but no-one outside would know (I am aware that goto-analyze also needs documentation).

@feliperodri feliperodri merged commit 6ad479d into diffblue:develop Mar 5, 2021
@SaswatPadhi SaswatPadhi deleted the loop_invariant_contract_fix branch March 5, 2021 20:42
@SaswatPadhi
Copy link
Contributor Author

Hi @martin-cs,

  1. Yes sure, that sounds very related to what I am working on, so I should look at the k-induction code as well. I will take a look at the code and tests next week.

  2. Good idea! @feliperodri is maintaining an internal Wiki page documenting the contracts stuff, but we should add these to the public manuals too. Could you please point us to where we should be adding them?

@martin-cs
Copy link
Collaborator

@SaswatPadhi

  1. src/goto-instrument/k-induction.{h,cpp} and regression/k-induction but it is not routinely run so who knows if it still works!
  2. doc/cprover-manual would be good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
aws Bugs or features of importance to AWS CBMC users bugfix Code Contracts Function and loop contracts
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Loop invariant contracts are ignored
5 participants