Skip to content
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

Audit for ptr_guaranteed_<cmp> #1090

Merged
merged 13 commits into from
Apr 27, 2022

Conversation

adpaco-aws
Copy link
Contributor

@adpaco-aws adpaco-aws commented Apr 21, 2022

Description of changes:

Completes the audit for ptr_guaranteed_<cmp>. These behave as regular pointer comparison at runtime.

Resolved issues:

Part of #727

Call-outs:

Testing:

  • How is this change tested? Adds 2 tests.

  • Is this a refactor change? No.

Checklist

  • Each commit message has a non-empty body, explaining why the change was made
  • Methods or procedures are documented
  • Regression or unit tests are included, or existing tests cover the modified code
  • My PR is restricted to a single feature or bugfix

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.

@adpaco-aws adpaco-aws requested a review from a team as a code owner April 21, 2022 21:45
@adpaco-aws adpaco-aws changed the title Ptr guaranteed audit Audit for ptr_guaranteed_<cmp> Apr 21, 2022
@adpaco-aws adpaco-aws force-pushed the ptr_guaranteed-audit branch from d036af4 to 17a9819 Compare April 21, 2022 21:56
ptr_guaranteed_eq | Partial | |
ptr_guaranteed_ne | Partial | |
ptr_guaranteed_eq | Yes | Over-approximation: Returns nondet. value even if comparison is true |
ptr_guaranteed_ne | Yes | Over-approximation: Returns nondet. value even if comparison is true |
Copy link
Contributor

Choose a reason for hiding this comment

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

Should one of these say "false"

Copy link
Contributor Author

@adpaco-aws adpaco-aws Apr 22, 2022

Choose a reason for hiding this comment

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

No, these are not symmetric in the sense that if one returns true, the other one returns false. Under some circumstances, both may return false even if one of them would return true using standard (in)equality, which is the desired behavior. See https://doc.rust-lang.org/std/primitive.pointer.html#method.guaranteed_eq for more details.

@@ -17,5 +17,8 @@ fn mmap() -> *mut MyCVoid {
fn main() {
let v = mmap();
assert!(v != MAP_FAILED);
// The assertion below fails because it must be using `ptr_guaranteed_eq` or
Copy link
Contributor

Choose a reason for hiding this comment

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

Why must 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.

The test broke because the intrinsics changed here are less precise now. This is just a hint I wanted to include for when we come back to fix the test.

Comment on lines 5 to 6
// equal, which causes the test to pass in the `else` branch. The `if`
// branch is unreachable.
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we test that this branch is unreachable, maybe with an assert false?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because we are assuming ptr1 == ptr2, the unreachable assertion is in practice assert!(false).

if ptr_guaranteed_eq(ptr1, ptr2) {
assert!(ptr1 == ptr2);
} else {
assert!(ptr1 != ptr2);
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you use expect_fail instead? Tests with kani-verify-fail would succeed even if CBMC crashes.


#[kani::proof]
fn test_ptr_eq(ptr1: *const u8, ptr2: *const u8) {
kani::assume(ptr1 == ptr2);
Copy link
Contributor

Choose a reason for hiding this comment

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

I would remove this assumption. The assertion on line 14 should still hold.


#[kani::proof]
fn test_ptr_eq(ptr1: *const u8, ptr2: *const u8) {
kani::assume(ptr1 != ptr2);
Copy link
Contributor

Choose a reason for hiding this comment

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

If you use expect_fail() this test can be merged with the one above.

@@ -17,5 +17,8 @@ fn mmap() -> *mut MyCVoid {
fn main() {
let v = mmap();
assert!(v != MAP_FAILED);
// The assertion below fails because it must be using `ptr_guaranteed_eq` or
// `ptr_guaranteed_eq`, which now returns a nondet. value if the result of
// the comparison is true
assert!(v.is_null());
Copy link
Contributor

Choose a reason for hiding this comment

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

Humm... let's sync offline. We might have to revert the behavior. We don't want ptr::is_null() to become nondet. :(

@adpaco-aws adpaco-aws force-pushed the ptr_guaranteed-audit branch from befd424 to 2760dc8 Compare April 26, 2022 20:17
@adpaco-aws
Copy link
Contributor Author

The PR is ready to review again.

We had a discussion where we agreed that these intrinsics should be implemented as regular comparison instead of being over-approximated, otherwise we get nondet. results for comparison like ptr::is_null. This has been noted in both the Kani documentation and code.

@adpaco-aws adpaco-aws requested review from danielsn and celinval April 26, 2022 20:24
@@ -0,0 +1,15 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// kani-verify-fail
Copy link
Contributor

Choose a reason for hiding this comment

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

Is kani-verify-fail required?

Copy link
Contributor Author

@adpaco-aws adpaco-aws Apr 27, 2022

Choose a reason for hiding this comment

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

It was not needed, but I changed the tests to have (each) two positive harnesses instead.

Comment on lines 252 to 253
// are used for regular comparison in `std` when they shouldn't. An earlier
// version that returned nondet. values when the result of the comparison
Copy link
Contributor

Choose a reason for hiding this comment

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

because they are used for regular comparison in std when they shouldn't

This sounds a bit too strong for me. The documentation (https://doc.rust-lang.org/beta/std/primitive.pointer.html#method.guaranteed_eq) says that this may spuriously return false in compile-time evaluation, which I understood to mean that it may block some optimizations, etc., but it can never impact correctness since it behaves like ==/!= at run-time (which is what we're modeling).

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 for making this clear! Removed the comments here and in Kani docs.

fn test_ptr_eq(ptr1: *const u8, ptr2: *const u8) {
kani::assume(ptr1 != ptr2);
assert!(ptr_guaranteed_ne(ptr1, ptr2));
kani::expect_fail(ptr1 == ptr2, "Pointers aren't equal");
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this use !ptr_guaranteed_ne? And will it even be reachable given how we turn assert into assert; assume

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 changed the tests to have (each) two positive harnesses instead, please check.

Copy link
Contributor

@zhassan-aws zhassan-aws left a comment

Choose a reason for hiding this comment

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

Thanks @adpaco-aws!

@adpaco-aws
Copy link
Contributor Author

Merging this PR now, but if you have any other concerns please let me know and I'll take care of them.

@adpaco-aws adpaco-aws merged commit 844a486 into model-checking:main Apr 27, 2022
@adpaco-aws adpaco-aws mentioned this pull request Apr 27, 2022
tedinski pushed a commit that referenced this pull request Apr 27, 2022
* Audit for `ptr_guaranteed_<cmp>`

* Update docs

* Add two tests
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.

4 participants