Skip to content

Block function command line option #1566

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 2 commits into from

Conversation

polgreen
Copy link
Contributor

@polgreen polgreen commented Nov 7, 2017

Blocks a function by replacing the function body with assume_false.
This is similar to --undefined-function-is-assume-false, but gives the flexibility to havoc undefined functions and block specific functions in one go without needing multiple calls to goto-instrument.

I still need to create a unit test and add it to this pull request, but any early feedback welcome


if(entry->second.body_available())
{
message.status() << "Removing body of " << identifier
Copy link
Member

Choose a reason for hiding this comment

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

Should be "Blocking"

else if(entry->second.is_inlined())
{
message.warning() << "Function " << identifier << " is inlined, "
<< "instantiations will not be removed"
Copy link
Member

Choose a reason for hiding this comment

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

"removed" -> "blocked"

goto_model.goto_functions.function_map.find(identifier);

if(entry==goto_model.goto_functions.function_map.end())
{
Copy link
Member

Choose a reason for hiding this comment

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

run clang-format

entry->second.body.add_instruction()->make_assumption(false_exprt());
}

void block_functions(
Copy link
Member

Choose a reason for hiding this comment

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

doxygen here

Copy link
Contributor

@thk123 thk123 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 (pending the clang-format and doxygen changes).

@@ -1521,6 +1529,7 @@ void goto_instrument_parse_optionst::help()
" --model-argc-argv <n> model up to <n> command line arguments\n"
// NOLINTNEXTLINE(whitespace/line_length)
" --remove-function-body <f> remove the implementation of function <f> (may be repeated)\n"
" --block-function <f> replace body of function <f> with assume(false), effectively block all paths through function\n" // NOLINT(*)
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider adding (may be repeated) as above to indicate it can be used more than once.

@martin-cs
Copy link
Collaborator

Seems reasonable enough on first glance. Ping me when the other comments have been applied and the "do not merge" has been removed.

@@ -70,3 +70,48 @@ void remove_functions(
for(const auto &f : names)
remove_function(goto_model, f, message_handler);
}

void block_function(
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be nice to have some Doxygen comments for this function, as @peterschrammel mentioned.

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 now moved the doxygen from the .h file to the .cpp file now, although I understood that in general the rule was to put it in the header file?

Copy link
Contributor

@smowton smowton left a comment

Choose a reason for hiding this comment

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

Looks reasonable, some nitpicks on style. @peterschrammel @martin-cs do either of you know of standard terminology for this? "Block" made me think of "basic block" first and foremost. --mark-function-unreachable perhaps?

/// \brief Replace calls to the function with assume(false).
/// This effectively blocks any paths through the function
/// or depending on return values from the function.
/// \param goto_model input program to be modifier
Copy link
Contributor

Choose a reason for hiding this comment

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

typo modified


/// \brief Replace calls to the function with assume(false).
/// This effectively blocks any paths through the function
/// or depending on return values from the function.
Copy link
Contributor

Choose a reason for hiding this comment

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

return values or side-effects

/// \param identifier name of function to block
/// \param message_handler Error/status output
void block_function(
goto_modelt &goto_model,
Copy link
Contributor

Choose a reason for hiding this comment

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

indent 2 I think

{
message.status() << "Blocking all calls to " << identifier << messaget::eom;

Forall_goto_functions(it, goto_model.goto_functions)
Copy link
Contributor

Choose a reason for hiding this comment

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

Braces around multi-line forall

{
messaget message(message_handler);

goto_functionst::function_mapt::iterator entry=
Copy link
Contributor

Choose a reason for hiding this comment

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

Spaces around = / ==

{
ins.make_assumption(false_exprt());
ins.source_location.set_comment(
"`"+id2string(identifier)+"' is undefined");
Copy link
Contributor

Choose a reason for hiding this comment

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

That's an odd comment. How about "...was explicitly marked unusable by command-line option --block-function"?

ins.make_assumption(false_exprt());
ins.source_location.set_comment(
"`"+id2string(identifier)+"' is undefined");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

How about simply replacing the function body, rather than every callsite?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So, originally I did that (have a look at 8708282), but I got into difficulties when it started violating the asset at line 320 of local_bitvector_analysis.cpp:
assert(succ<loc_infos.size())

I attempted to find a solution to this, and ended up deciding to mirror the code in undefined_function_abort_path (which is, in principle, doing a very similar thing)

Do you know how to solve the assertion violation? I assume that loc_infos needs updating somehow, but I wasn't able to work out how

Copy link
Contributor

Choose a reason for hiding this comment

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

loc_infos is created when local-bitvector-analysis is run, after you've messed with the GOTO programs, so it won't need updating, but this does suggest the alteration somehow left the GOTO program in an inconsistent state. Couldn't say how without some deeper debugging though. I'd be happy to keep this as-is in the meantime, but it'd be a good cleanup to do if time permits.

@smowton
Copy link
Contributor

smowton commented Nov 22, 2017

Oh one more thing, should make the name of the cpp / h file consistent with the eventually chosen name for the pass

@polgreen
Copy link
Contributor Author

is "block-calls-to-function" more descriptive? I don't like "mark-function-unreachable" as to me that sounds too similar to "mark-unreachable-functions", I think "make-function-unreachable" might be better, but it's not clear how it is being made unreachable.

The equivalent command for doing this for an undefined function is just "undefined-function-is-assume-false", so we could make this "make-function-assume-false"

@smowton
Copy link
Contributor

smowton commented Nov 24, 2017

make-function-assume-false is fine with me

@smowton
Copy link
Contributor

smowton commented Nov 24, 2017

Rather than merge develop into this, please rebase this branch on current develop

@polgreen
Copy link
Contributor Author

Yeah, I'm on it. The last rebase was awful, some of the changes to the regression tests for java strings created conflicts in basically every single test.desc. In the end I gave up and checked out develop and cherry-picked my changes on it.

@polgreen
Copy link
Contributor Author

I rebased this on the current branch when I made the last comment, what else is left for me to do?

@tautschnig
Copy link
Collaborator

I was just confused by the "I'm on it" I guess. Re-assigning to @peterschrammel to evaluate the "Do not merge" and possibly actually approve and merge.

@polgreen
Copy link
Contributor Author

Sorry, I think I posted the comment slightly before I pushed the rebase and then just forgot to post an update

@@ -1521,6 +1530,9 @@ void goto_instrument_parse_optionst::help()
" --model-argc-argv <n> model up to <n> command line arguments\n"
// NOLINTNEXTLINE(whitespace/line_length)
" --remove-function-body <f> remove the implementation of function <f> (may be repeated)\n"
" --make-function-assume-false <f>\n"
" replace calls to function <f> with assume(false) (may be repeated)\n" // NOLINT(*)
" through function (may be repeated).\n"
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo?

Copy link
Contributor

@smowton smowton left a comment

Choose a reason for hiding this comment

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

Think the help text has got mangled, otherwise lgtm

polgreen and others added 2 commits December 3, 2017 12:37
Blocks all paths through a function by replacing the function calls with assume_false.
This is similar to --undefined-function-is-assume-false, but gives the flexibility to havoc undefined functions and block specific functions without needing multiple calls to goto-instrument.

Needed for aggressive slicer work
@polgreen
Copy link
Contributor Author

polgreen commented Dec 4, 2017

help text is fixed

@martin-cs
Copy link
Collaborator

I don't want to be That Guy but ... would this be best addressed as part of a comprehensive solution to : #1585 ?

@polgreen
Copy link
Contributor Author

I think the suggested solution to #1585 was to create stub bodies for the functions and insert the changes into the stub bodies.

Originally that is what I did for this PR and there is a discussion with @smowton about this in the comments above. I created stub bodies for the functions and inserted "assume(false)" into the stub bodies. This change was fine when I applied it to the version of CBMC I was using at the time. When I applied it to develop it caused violation of the assert at line 320 of local_bitvector_analysis.cpp:
assert(succ<loc_infos.size())

I couldn't fix this and decided it made sense to mirror the code in undefined_function_abort_path instead (which is doing a very similar thing).

So, the options are:

  • this pull request could be left consistent with undefined_function_abort_path
  • this pull request could be changed to create a stub body and add instructions to it, but I would need some help debugging the assertion violation described above. It will then be inconsistent with undefined_function_abort_path.
  • all the possible ways of handling undefined functions could be changed to be consistent. I don't have time to do this before the end of January, so if this is the solution it's best it is assigned to someone else

@martin-cs
Copy link
Collaborator

Assorted thoughts...

  1. The assertion failure looks like a corrupted goto-program. The most obvious source is not calling update() after modifying it. Without code it is harder to be clear.

  2. Consistency, especially between similar tasks, if good but shouldn't keep us going down the wrong road (if we are).

  3. Given the variety of behaviours that are potentially desirable for functions without bodies and the need for consistency between back-ends I think the "transform the program" approach is the right way forward.

I'm certainly happy to review, probably to help program even but it will have to be late January at the earliest.

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.

7 participants