Skip to content

Invariant cleanup goto programs sz #2968

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 1 commit into from
Oct 4, 2018
Merged

Conversation

xbauch
Copy link
Contributor

@xbauch xbauch commented Sep 17, 2018

No description provided.

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

throw "property "+id2string(*property_set.begin())+" not found";
INVARIANT_WITH_DIAGNOSTICS(
property_set.empty(),
"Property ",
Copy link
Member

Choose a reason for hiding this comment

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

start with lower case (several occurrences)

Copy link
Member

Choose a reason for hiding this comment

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

This one is a message that is aimed at the user; it is NOT checking an invariant!

@@ -281,7 +282,7 @@ void string_instrumentationt::do_sprintf(
{
error().source_location=target->source_location;
error() << "sprintf expected to have two or more arguments" << eom;
throw 0;
UNREACHABLE;
Copy link
Member

Choose a reason for hiding this comment

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

The check as a whole should be an invariant (several occurrences).

Copy link
Member

Choose a reason for hiding this comment

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

This is not an invariant either; it is an input condition check. An invariant is something that the program maintains internally, and not something it expects the environment to provide.

Copy link
Member

Choose a reason for hiding this comment

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

I would expect this to be ensured by the C frontend (which it actually does). After that we should be able to assume it invariant.

Copy link
Member

@kroening kroening left a comment

Choose a reason for hiding this comment

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

There is a fundamental confusion here between invariants and input checks.

@xbauch
Copy link
Contributor Author

xbauch commented Sep 18, 2018

I've tried distinguishing between user input error and invariants. Unknown user input is handled by a new exception class and invalid input by the invalid_user_input_exceptiont. The messages were unified to start lower case and end without full stop.

if(!goto_functions.function_map.count(entry_point))
throw "entry point not found";
INVARIANT(
goto_functions.function_map.count(entry_point), "entry point not found");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do all current invocations of this function make sure this invariant truly holds?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well it's not guaranteed by the invocation; I guess it's more like a property of a well-formed goto-program. Maybe a DATA_INVARIANT would be more appropriate.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd say the fix is to make sure it is guaranteed by all current invocations. The INVARIANT then makes this future-proof as additional invocation points added later on may fail to do the same check.

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 dag a bit deeper and the input goto_model is (so far always) a product of read_goto_binary. I've added a post-condition to the read_bin_goto_object_v4 function, so that only models with entry points are presently produced.

Copy link
Member

Choose a reason for hiding this comment

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

This is really not guaranteed, and it's not desired to be guaranteed.
This is really a 'user input error'.

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 think we use invalid_user_input exceptions for invalid command line options. On one hand the error originates from the source code but on the other hand the well-formedness of a goto-programs requires an entry point. For now the code throws incorrect_goto_program exception, but I can re-write it, if incorrect_source_program would be more accurate.


throw invalid_user_input_exceptiont(
"sprintf expected to have two or more arguments",
"sprintf(char *str, const char *format, ...);");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is the error() output above now redundant? It certainly seems to be a bad idea to duplicate text?

@@ -55,7 +55,7 @@ std::string as_vcd_binary(
}
else if(expr.id()==ID_union)
{
assert(expr.operands().size()==1);
INVARIANT(expr.operands().size() == 1, "union only takes 1 operand");
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd suggest to use union_exprt/to_union_expr. Let's not duplicate invariant checks.

@kroening
Copy link
Member

Another problem is that throwing an exception is very terminal -- we may wish to record the fact that there is an error, and continue processing, possibly to generate further error messages.

@tautschnig
Copy link
Collaborator

Another problem is that throwing an exception is very terminal -- we may wish to record the fact that there is an error, and continue processing, possibly to generate further error messages.

Yes, but whether this can or cannot be done is very context dependent, and I'm not sure this specifically applies to any of the changes in this PR?

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

@@ -158,6 +158,8 @@ static bool read_bin_goto_object_v4(

functions.compute_location_numbers();

POSTCONDITION(functions.function_map.count(goto_functionst::entry_point()));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit pick: Visual Studio warns about this conversion from an integer to a Boolean. So either add != 0 or use functions.function_map.find(...) != functions.function_map.end().

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 comparison with 0.

if(ptr==nullptr)
throw "symbol "+id2string(symbol.name)+" has unknown mode";
INVARIANT_WITH_DIAGNOSTICS(
ptr != nullptr, "symbol ", id2string(symbol.name), " has unknown mode");
Copy link
Collaborator

Choose a reason for hiding this comment

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

There is #2984, which will do away with all this code...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Rolled back all changes in this file, hopefully #2984 will clean it adequately.

#include <ctime>

#include <util/invariant.h>
Copy link
Collaborator

Choose a reason for hiding this comment

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

No invariant added?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed as now redundant, invariant check is inside to_union_expr.

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

@xbauch
Copy link
Contributor Author

xbauch commented Sep 20, 2018

Squashed the commits, rebased, re-worked to use the incorrect_goto_program_exceptiont from #2996.

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


POSTCONDITION(
goto_model.goto_functions.function_map.count(
goto_functionst::entry_point()) != 0);
}
Copy link
Member

Choose a reason for hiding this comment

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

This is certainly not guaranteed to hold -- we may wish to instrument goto binaries before linking is completed.

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, removed.

throw "property "+id2string(*property_set.begin())+" not found";
throw invalid_user_input_exceptiont(
"property " + id2string(*property_set.begin()) + " unknown",
"--property id");
}
Copy link
Member

Choose a reason for hiding this comment

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

That new exception isn't caught!

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 catch blocks to all call sites.

if(!goto_functions.function_map.count(entry_point))
throw "entry point not found";
INVARIANT(
goto_functions.function_map.count(entry_point), "entry point not found");
Copy link
Member

Choose a reason for hiding this comment

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

This is really not guaranteed, and it's not desired to be guaranteed.
This is really a 'user input error'.

@@ -73,7 +75,8 @@ void slice_global_inits(goto_modelt &goto_model)

goto_functionst::function_mapt::iterator f_it;
f_it=goto_functions.function_map.find(INITIALIZE_FUNCTION);
assert(f_it!=goto_functions.function_map.end());
INVARIANT(
f_it != goto_functions.function_map.end(), "initialize function not found");

Copy link
Member

Choose a reason for hiding this comment

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

This isn't an internal invariant, but a well-formed-ness condition on the goto binary.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to incorrect goto exception.

throw 0;
throw incorrect_goto_program_exceptiont(
"sprintf expected to have two or more arguments",
target->source_location);
}
Copy link
Member

Choose a reason for hiding this comment

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

This isn't really a property of the goto-program, but one of the original source code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Introduced new exception for source code errors (used a few times in this file).

throw 0;
throw incorrect_goto_program_exceptiont(
"snprintf expected to have three or more arguments",
target->source_location);
}
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.

@@ -55,8 +54,7 @@ std::string as_vcd_binary(
}
else if(expr.id()==ID_union)
{
assert(expr.operands().size()==1);
return as_vcd_binary(expr.op0(), ns);
return as_vcd_binary(to_union_expr(expr).op0(), ns);
}
Copy link
Member

Choose a reason for hiding this comment

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

I'd write .op() above.

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.

throw invalid_user_input_exceptiont(
"version no longer supported",
"supported version = " + std::to_string(current_goto_version));
else if(version > current_goto_version)
Copy link
Member

Choose a reason for hiding this comment

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

If you print the current version, also print the version of the goto binary.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

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

@@ -541,6 +542,12 @@ bool cbmc_parse_optionst::set_properties()
::set_properties(goto_model, cmdline.get_values("property"));
}

catch(const incorrect_goto_program_exceptiont &e)
Copy link
Member

Choose a reason for hiding this comment

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

I don't like these try-catch blocks that do not perform any recovery action. In my opinion, all the try-catch blocks in cbmc_parse_options can be removed because the only action that is taken is to exit. The same can be achieved in a much cleaner way by catching those exceptions at top-level (parse_optionst) only.

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, it's much neater catching them all in parse_option_baset.

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

@@ -76,6 +76,11 @@ int parse_options_baset::main()
std::cerr << e.what() << "\n";
return CPROVER_EXIT_USAGE_ERROR;
}
catch(const incorrect_goto_program_exceptiont &e)
Copy link
Member

Choose a reason for hiding this comment

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

Isn't that subsumed by the case below?

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 guess the intention is to distinguish individual exception classes, maybe different error message or return code. There is not dedicated error code for incorrect goto programs, only for PARSE_ERROR.

Copy link
Member

Choose a reason for hiding this comment

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

parse_options_baset is mean to be very broadly applicable -- including in programs that do not know anything about goto_programs. I would go for a broader superclass here.

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, catching incorrect_goto_program is omitted, and cprover_exception_baset is caught directly.

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

if(!goto_functions.function_map.count(entry_point))
throw "entry point not found";
if(goto_functions.function_map.count(entry_point) == 0)
throw incorrect_goto_program_exceptiont("entry point not found");

Copy link
Member

Choose a reason for hiding this comment

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

I'd say it's misleading to throw this exception. A goto program without entry point is in no way malformed or incorrect.

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 think that invalid_user_input would be misleading as well, so I've added user_input_error exception (locally in slice_global_inits until use elsewhere is required).

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

@chrisr-diffblue
Copy link
Contributor

@kroening - Could you re-review this PR when you have a moment or two? we think this is now just blocked on your input.

}

std::string what() const
{
Copy link
Member

Choose a reason for hiding this comment

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

Add 'override'

{
}
std::string what() const
{
Copy link
Member

Choose a reason for hiding this comment

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

override

@xbauch xbauch force-pushed the cleanup_goto-s-z branch 2 times, most recently from 059e0a1 to 3aee09c Compare October 4, 2018 11:57
@xbauch xbauch merged commit b9b40ed into diffblue:develop Oct 4, 2018
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: cb844be).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/86887302

@xbauch xbauch deleted the cleanup_goto-s-z branch December 4, 2018 08:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants