Skip to content

Make goto_rw slightly less conservative [depends-on: #3769, blocks: #2677, #2694] #2646

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

Conversation

qaphla
Copy link

@qaphla qaphla commented Jul 31, 2018

This addresses the issues mentioned in #748 using a slightly different approach.

The issue that arose previously was that value_set_dereference failed to translate dereferences of pointers to dynamic objects into accesses of objects, and so *x = 1 would write to x but not to *x. This change ensures that an object access is always generated, and so *x = 1 can be made to no longer write to x without influencing the correctness of analyses such as dependence_graph. This change is contained in f095e43.

In order to resolve this issue, we first had to disambiguate two different exprts which were using the same ID but were semantically distinct. This is done in 87e8ab1, and more description of how it was possible to determine which meaning was intended in each case is provided in the commit message.

The final commit (a6db625) includes a test case that was introduced by #748. This pull request does not make that test case work, but since it does resolve most of the other issues resolved by #748, it made sense to introduce the test here as well.

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.

is_dynamic_object seems like a good change to me -- though invalid_pointer_exprt for example should then also become is_invalid_pointer_exprt? Also suggest if you're introducing such an expression to give it an exprt-derived helper class (inheriting from unary_predicate_exprt I would imagine).

I don't know enough about goto_rw to comment whether the change will have unintended consequences unfortunately, so must practically defer to @tautschnig or @peterschrammel here.

@@ -175,7 +175,9 @@ void dep_graph_domaint::data_dependencies(
{
bool found=false;
for(const auto &wr : w_range.second)
{
Copy link
Contributor

Choose a reason for hiding this comment

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

Give simple re-styles like this their own commit

else if(expr.id()==ID_dynamic_object)
{
// Dynamic object expressions should always have two operands.
PRECONDITION(expr.operands().size() == 2);
Copy link
Contributor

Choose a reason for hiding this comment

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

Redundant with to_dynamic_object_expr

// Dynamic object expressions should always have two operands.
PRECONDITION(expr.operands().size() == 2);
const auto obj_instance = to_dynamic_object_expr(expr).get_instance();
add(mode, "dynamic_object-" + std::to_string(obj_instance), 0, -1);
Copy link
Contributor

Choose a reason for hiding this comment

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

Any risk of name clash? Most analyses seem to namespace dynamic objects to avoid this

const symbolt *symbol_ptr;
if(ns.lookup(identifier, symbol_ptr))
const symbolt *symbol_ptr = nullptr;
if(ns.lookup(identifier, symbol_ptr) &&
Copy link
Contributor

Choose a reason for hiding this comment

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

Move the ns.lookup() out of the test?

@@ -3574,7 +3574,7 @@ std::string expr2ct::convert_with_precedence(
else if(src.id()==ID_invalid_pointer)
return convert_function(src, "__CPROVER_invalid_pointer", precedence=16);

else if(src.id()==ID_dynamic_object)
else if(src.id()==ID_is_dynamic_object)
return convert_function(src, "DYNAMIC_OBJECT", precedence=16);
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider the same improvement to the pretty-printed code too? (i.e. "DYNAMIC_OBJECT" -> "IS_DYNAMIC_OBJECT")

@qaphla
Copy link
Author

qaphla commented Aug 1, 2018

I agree that, for example, invalid_pointer_exprt should become is_invalid_pointer_exprt, though this seems like it's not the right set of changes for that to go with.

I've addressed the other comments in the next version of this PR.

@@ -45,7 +45,7 @@ literalt bv_pointerst::convert_rest(const exprt &expr)
}
}
}
else if(expr.id()==ID_dynamic_object)
else if(expr.id()==ID_is_dynamic_object)
{
if(operands.size()==1 &&
Copy link
Collaborator

Choose a reason for hiding this comment

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

These should probably become DATA_INVARIANTS but this is a clean up and not vital for this PR.

Copy link
Author

Choose a reason for hiding this comment

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

These being the condition operands.size() == 1 && operands[0].type().id() == ID_pointer?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes. They should be enforced on exprt creation with PRECONDITION, on conversion with DATA_INVARIANT (as you have done in std_expr) and then referenced / checked with DATA_INVARIANT when they are relevant for the usage (for example here).

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.

I think so. Can people who care about the full slicer and have test suites for it ( @polgreen @tautschnig @danpoe @chrisr-diffblue ) have a quick run with this PR.

if(expr.operands().size()!=1)
return true;
// This should hold as a result of the expr ID being is_dynamic_object.
PRECONDITION(expr.operands().size() == 1);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Pedantry! DATA_INVARIANT because it is something that should always be true for think kind of exprt.

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

@polgreen
Copy link
Contributor

polgreen commented Aug 3, 2018

I did a quick run of this PR, rebased against develop, and with PR #2642 cherry-picked on top of it.

I don't think it's introduced any new bugs for me. The full slicer does terminate with "identifier not found", but develop does too.

klaas added 4 commits August 9, 2018 15:21
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
@tautschnig tautschnig self-assigned this Nov 10, 2018
@tautschnig tautschnig changed the title Make goto_rw slightly less conservative Make goto_rw slightly less conservative [blocks: #2677] Nov 10, 2018
@tautschnig tautschnig changed the title Make goto_rw slightly less conservative [blocks: #2677] Make goto_rw slightly less conservative [blocks: #2677, #2694] Nov 10, 2018
@tautschnig tautschnig changed the title Make goto_rw slightly less conservative [blocks: #2677, #2694] Make goto_rw slightly less conservative [depends-on: #3769, blocks: #2677, #2694] Feb 25, 2019
owen-mc-diffblue pushed a commit to owen-mc-diffblue/cbmc that referenced this pull request Feb 28, 2019
This branch is not taken by symex but it is taken by the slicer. The code
I've removed has no effect, as far as I can tell, and may have been left
over from an old implementation from before the beginning of the git
history.

Note, there is a commit that splits ID_dynamic_object into two different
ids. See diffblue#2646 and diffblue#3769 for more details.
@owen-mc-diffblue
Copy link
Contributor

I've pulled out the commit "Disambiguates two exprts with the same ID." as #4479, and added a related change.

@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.

8 participants