Skip to content

Skeleton for well-formedness checking of goto models [blocks: #3118, #3147, #3188, #3191, #3187, #3193] #3123

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
merged 17 commits into from
Nov 9, 2018

Conversation

danpoe
Copy link
Contributor

@danpoe danpoe commented Oct 8, 2018

This PR introduces a framework for well-formedness checking of goto models. It also introduces two new macros DATA_CHECK() and DATA_CHECK_WITH_DIAGNOSTICS() for use in the various validation methods (like validate(), validate_full() on expressions). Based on the value of a variable vm (the validation mode, which is an enum with values INVARIANT or EXCEPTION), when a well-formedness check fails either a DATA_INVARIANT() fails or an incorrect_goto_program_exceptiont is thrown.

  • Each commit message has a non-empty body, explaining why the change was made.
  • My contribution is formatted in line with CODING_STANDARD.md.
  • Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • 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).
  • n/a 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.

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: bcca1a6).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/87221686
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).

@danpoe danpoe force-pushed the feature/well-formedness-checking branch 2 times, most recently from a293f3e to 37a4de4 Compare October 8, 2018 16:18
C<expr_type>()(expr, std::forward<Args>(args)...)

template <template <typename> class C, typename... Args>
void call_on_expr(const exprt &expr, Args &&... args)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This function simulates virtual call resolution on exprt via a case distinction on id(). The structs call_checkt, call_validatet, and call_validate_fullt in validate.h specify the method to be called (check(), validate(), and validate_full() resp.) and take as a template parameter the expression type to cast to.

else
{
CALL_ON_EXPR(exprt);
}
Copy link
Contributor Author

@danpoe danpoe Oct 8, 2018

Choose a reason for hiding this comment

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

Cases for more expressions will be added here in the future.

Copy link
Member

Choose a reason for hiding this comment

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

In the end the last case should fail an invariant in order to actually detect when something is missing. For now it would be good if it could output a warning or so.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've added a macro REPORT_UNIMPLEMENTED_EXPRESSION_CHECKS that can be set when compiling. If enabled the ids for currently unimplemented expression checks are reported to stderr.

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: 37a4de4).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/87236032
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).

/// reported via DATA_INVARIANT violations or exceptions.
void validate(const namespacet &ns, const validation_modet vm) const
{
for(const auto &entry : function_map)
Copy link
Contributor

Choose a reason for hiding this comment

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

I have this loop on the goto_model level: one less file to modify. But this works just as good.

xbauch pushed a commit to xbauch/cbmc that referenced this pull request Oct 9, 2018
…e#3123

The condition to be checked is the same. Interface function name was changed to
follow the above PR. Also the check is now optional via command line.
@danpoe danpoe force-pushed the feature/well-formedness-checking branch 2 times, most recently from 42bf8fe to 41cb816 Compare October 10, 2018 11:09
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: 42bf8fe).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/87472451
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).

template <typename T>
struct call_checkt
{
static_assert(std::is_base_of<irept, T>::value, "");
Copy link
Member

Choose a reason for hiding this comment

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

missing message (several occurrences)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm, the message wouldn't really add anything here. With C++17 the message will become optional then we could remove it.

else
{
CALL_ON_EXPR(exprt);
}
Copy link
Member

Choose a reason for hiding this comment

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

In the end the last case should fail an invariant in order to actually detect when something is missing. For now it would be good if it could output a warning or so.

}
else
{
CALL_ON_TYPE(typet);
Copy link
Member

Choose a reason for hiding this comment

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

see comment for exprt

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a macro REPORT_UNIMPLEMENTED_TYPE_CHECKS

}
else
{
CALL_ON_CODE(codet);
Copy link
Member

Choose a reason for hiding this comment

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

see comment for exprt

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added a macro REPORT_UNIMPLEMENTED_CODE_CHECKS

}

/// Check that the given code statement is well-formed, assuming that all its
/// enclosed statements, subexpressions, etc. have all ready been checked for
Copy link
Member

Choose a reason for hiding this comment

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

already?

///
/// The validation mode indicates whether well-formedness check failures are
/// reported via DATA_INVARIANT violations or exceptions.
void check(const validation_modet vm = validation_modet::INVARIANT) const
Copy link
Member

Choose a reason for hiding this comment

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

see comment for exprt

Copy link
Contributor Author

Choose a reason for hiding this comment

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

see reply for exprt :)

@@ -972,6 +978,7 @@ void cbmc_parse_optionst::help()
" --xml-ui use XML-formatted output\n"
" --xml-interface bi-directional XML interface\n"
" --json-ui use JSON-formatted output\n"
" --validate-goto-model enables additional well-formedness checks on the goto program\n" // NOLINT(*)
Copy link
Member

Choose a reason for hiding this comment

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

break long help text and align below enables

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You mean so the output of --help will be at most 80 characters wide, or that the code should be at most 80 characters wide, or both?

Copy link
Contributor

Choose a reason for hiding this comment

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

" --fp-reachability-slice f remove instructions that cannot appear on a trace\n" \
" that visits all given functions. The list of\n" \
" functions has to be given as a comma separated\n" \
" list f.\n" \

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks @xbauch. So that seems to suggest 80 characters in the output but not necessarily in the code. I'm gonna change it to that.

@@ -526,6 +526,12 @@ int cbmc_parse_optionst::doit()
if(set_properties())
return CPROVER_EXIT_SET_PROPERTIES_FAILED;

if(cmdline.isset("validate-goto-model"))
Copy link
Member

Choose a reason for hiding this comment

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

Would we like to have this in the other driver programs too?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I would have thought goto-instrument was the place for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I think we should have the option in all of the tools to validate the goto model.

@martin-cs I think also in e.g. cbmc it would make sense to validate the goto program as a safety net sort of thing. Once right after goto_convert and perhaps once more before goto_symex to check that all the transformation passes like remove_function_pointers, etc. did not produce an ill-formed goto model.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@danpoe : I'm very much in favour of validating the program between all transformation passes; that sounds great. To the point I might suggest making that the last step of each transformation. I think this will need to be able to check for various "normal forms" as well, i.e. returns and function pointers removed, etc. ( @tautschnig may have opinions on this subject ). As I first envisaged this, that should be enough to prove that all of the DATA_INVARIANTs hold.

i also like the "with exceptions when we load it and with invariants after" approach. My only question is about the specific, user accessible command-line flag to just check the validity of the goto-program and nothing else. That seems like something we definitely want but that it should probably be in goto-instrument as a "checking and modifying the goto-program" bit of functionality, rather than in every tool.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yes, that makes sense. @sonodtt is currently working on some additional checks of the goto program that will allow to pass flags that indicate whether function pointers and returns are expected to have been removed.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Cool.

@sonodtt : having looked at this in the past ( #751 is the first bit I have written down ), may I suggest that you make the flags independent for each feature. For example, one of the last few differences between the static_analyst and ait frameworks is that the later requires the abscence of function pointers (naturally or removed) and return removal. function pointer removal is an (at the moment undocumented) precondition of return removal and so on. It would be amazing if we could actually map out and enforce these requirements on "normal forms".

@danpoe danpoe force-pushed the feature/well-formedness-checking branch from 41cb816 to 0316f5f Compare October 10, 2018 12:11
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.

This seems like a useful and a worthwhile thing to do. I'm not sure I quite 'get' the architecture of this but I think I could be persuaded. I slightly worry that this might lead to duplication of checks but that is better than not having any at all!

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: 41cb816).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/87476584
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).

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.

Passed Diffblue compatibility checks (cbmc commit: 0316f5f).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/87480682

xbauch pushed a commit to xbauch/cbmc that referenced this pull request Oct 10, 2018
Using DATA_CHECK instead of calling error handling directly.

/// This macro takes a condition which denotes a well-formedness criterion on
/// goto programs, expressions, instructions, etc. Based on the value of the
/// variable vm (the validation mode), it either uses DATA_INVARIANT() to check
Copy link
Contributor

Choose a reason for hiding this comment

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

I may have missed a global declaration of vm somewhere, but from what I've seen it looks like vm is just 'whatever variable of that name is in scope at the moment?` - Could you either make that explicit in the docs and/or actually add a global declaration for it somewhere? I'm otherwise wondering what the compile error messages might look like if someone tries to use these macros outside of a validate() function, or if the try to declare a variable of a different type but the same name... :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I've added some doc and added a static assertion to check that vm has the expected type.

@danpoe danpoe force-pushed the feature/well-formedness-checking branch from 0316f5f to 69c46d5 Compare October 10, 2018 16:04
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.

Passed Diffblue compatibility checks (cbmc commit: 69c46d5).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/87519725

@danpoe danpoe force-pushed the feature/well-formedness-checking branch from 69c46d5 to 5befa49 Compare October 10, 2018 18:05
@danpoe danpoe force-pushed the feature/well-formedness-checking branch from af3aa4f to d638ea7 Compare November 9, 2018 12:18
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.

✔️
Passed Diffblue compatibility checks (cbmc commit: d638ea7).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/90857933

DATA_CHECK(
base_type_eq(code.op0().type(), code.op1().type(), ns),
"lhs and rhs of assignment must have same type");
}
Copy link
Member

Choose a reason for hiding this comment

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

It is no longer necessary to use base_type_eq to compare types -- you can simply use == !

Copy link
Collaborator

Choose a reason for hiding this comment

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

That's not quite the case just yet, is it? Otherwise we should have a major campaign removing all cases of base_type_eq.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, we should have that campaign, together with getting rid of most instances of ns.follow().

DATA_CHECK(
base_type_eq(expr.op0().type(), expr.op1().type(), ns),
"lhs and rhs of binary relation expression should have same type");
}
Copy link
Member

Choose a reason for hiding this comment

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

Same here

@kroening
Copy link
Member

kroening commented Nov 9, 2018

If you use == instead of base_type_eq, then the namespace that gets passed around becomes unused. If that bugs you, you could use it to check whether the tag types are in the symbol table, and whether symbol_exprt identifiers are in the symbol table.

@kroening kroening assigned danpoe and unassigned kroening Nov 9, 2018
@danpoe
Copy link
Contributor Author

danpoe commented Nov 9, 2018

Checking that all symbols/tags in the goto program exist in the symbol table and are consistent with the corresponding entries is the topic of @xbauch's PR #3118.

@kroening
Copy link
Member

kroening commented Nov 9, 2018

Ok, if that is meant to remain separate, then you could get rid of the namespacet parameters.

@tautschnig tautschnig merged commit f08e23b into diffblue:develop Nov 9, 2018
xbauch pushed a commit to xbauch/cbmc that referenced this pull request Nov 14, 2018
Follows the diffblue#3123 skeleton with additional checks in SSA_stept.
xbauch pushed a commit to xbauch/cbmc that referenced this pull request Nov 16, 2018
Follows the diffblue#3123 skeleton with additional checks in SSA_stept. Adds a condition
such that renaming checks are only run with the validate option.
xbauch pushed a commit to xbauch/cbmc that referenced this pull request Nov 16, 2018
Follows the diffblue#3123 skeleton with additional checks in SSA_stept. Adds a condition
such that renaming checks are only run with the validate option.
xbauch pushed a commit to xbauch/cbmc that referenced this pull request Nov 30, 2018
Follows the diffblue#3123 skeleton with additional checks in SSA_stept. Adds a condition
such that renaming checks are only run with the validate option.
@danpoe danpoe deleted the feature/well-formedness-checking branch June 2, 2020 17:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants