Skip to content

Add tests to check semantics of pointer primitives #5324

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 3 commits into from
May 14, 2020

Conversation

danpoe
Copy link
Contributor

@danpoe danpoe commented Apr 27, 2020

  • Each commit message has a non-empty body, explaining why the change was made.
  • n/a Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • n/a 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).
  • n/a My commit message includes data points confirming performance improvements (if claimed).
  • My PR is restricted to a single feature or bugfix.
  • n/a White-space or formatting changes outside the feature-related changed lines are in commits of their own.

@danpoe danpoe added the aws Bugs or features of importance to AWS CBMC users label Apr 27, 2020
@danpoe danpoe force-pushed the tests/cprover-memory-primitives branch 3 times, most recently from 828ace9 to 04a8998 Compare April 28, 2020 11:42
--
^warning: ignoring
--
Check that uninitialized pointers are not considered pointing to dynamic objects
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this what we want? Or should it be non-det whether this is true?

In particular, is there a doc where all these expectations are laid out?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think I agree with @danielsn, though I'm not clear what I as a user am trying to get out asserting on this property. But in general, seems safest for it to fail if you assert either way (in my mental model - you're asserting on UB, so whatever you assert, it should be false)

Copy link
Contributor Author

@danpoe danpoe May 11, 2020

Choose a reason for hiding this comment

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

@thk123 cbmc doesn't necessarily behave like that on UB. In general, one needs the appropriate check flags to be enabled to catch certain cases. For example, signed integer overflow is UB, though one needs to enable --signed-overflow-check to catch that case. Otherwise, the values will just wrap around.

In general though, I think it's a good idea for operations to be nondet in such cases as far as possible. So yes, I've changed the test to check for both the negated and the non-negated condition, and have specified that both should fail in the test.desc file.

--
^warning: ignoring
--
Check that __CPROVER_same_object() is true when given a pointer variable, and an
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be worth it check that an offset into the object also maintains the same object property?

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

--
^warning: ignoring
--
Check that __CPROVER_same_object() is false when given two pointers, with one
Copy link
Contributor

Choose a reason for hiding this comment

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

Is that expected? malloc is allowed to (and often does) reuse objects

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this depends on how you plan to use _same_object? assert(same_object(p1, p2) certainly must fail. I think since this is an internal, it should be more exact, in this case, we know they are not the same object, they are the result of two separate mallocs. However, I would expect assert(p1 != p2) to fail, since is possible they could have the same address since the memory has been freed.

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, assert(p1 != p2) should fail, though currently the way malloc is modelled in cbmc it doesn't reuse addresses.

@danielsn
Copy link
Contributor

My overall question: is there a doc explaining the expected semantics of each primitive? When given a reference to (list not necessarily complete)

  1. a global
  2. a stack variable
  3. a malloced variable
  4. an unconstrained variable
  5. a freed / out of scope variable
  6. an out of bounds access on a valid pointer

@danielsn
Copy link
Contributor

Also, what happens if we semi-constrain a variable? e.g.

int *x;
__CPROVER_assume(x != null); // or __CPROVER_assume(x == null)
assert(__CPROVER_dynamic_object(x));

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.

Looks good - I think we need to check some of them are actually havoicing by adding asserts for either direction

--
^warning: ignoring
--
Check that uninitialized pointers are not considered pointing to dynamic objects
Copy link
Contributor

Choose a reason for hiding this comment

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

I think I agree with @danielsn, though I'm not clear what I as a user am trying to get out asserting on this property. But in general, seems safest for it to fail if you assert either way (in my mental model - you're asserting on UB, so whatever you assert, it should be false)

--
^warning: ignoring
--
Check that __CPROVER_same_object() is false when given two pointers, with one
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this depends on how you plan to use _same_object? assert(same_object(p1, p2) certainly must fail. I think since this is an internal, it should be more exact, in this case, we know they are not the same object, they are the result of two separate mallocs. However, I would expect assert(p1 != p2) to fail, since is possible they could have the same address since the memory has been freed.

@danpoe danpoe force-pushed the tests/cprover-memory-primitives branch 4 times, most recently from 305ed1f to ac5c944 Compare May 11, 2020 14:31
@danpoe danpoe marked this pull request as ready for review May 13, 2020 11:53
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.

Thanks seems good (clang-format is complaining on travis)

@danpoe danpoe force-pushed the tests/cprover-memory-primitives branch from ac5c944 to 175d74f Compare May 14, 2020 17:25
@danpoe danpoe merged commit 004fd96 into diffblue:develop May 14, 2020
@danpoe danpoe deleted the tests/cprover-memory-primitives branch June 2, 2020 17:05
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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants