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 offset intrinsic #1094

Merged
merged 13 commits into from
Apr 26, 2022
Merged

Conversation

adpaco-aws
Copy link
Contributor

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

Description of changes:

Changes the offset intrinsic to use addition with overflow to detect overflow, but computes the actual destination pointer with regular addition. This fixes spurious failures that appeared when offsets were negative or being substracted.

In addition, standard pointer checks cover the case where the pointer is dereferenced outside the object bounds. I've observed that this works as expected: One byte past the object is fine, more than that is not. 5 test cases included.

Resolved issues:

Resolves #1082
Part of #727

Call-outs:

Testing:

  • How is this change tested? Adds 5 test cases.

  • 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 22, 2022 20:08
Copy link
Contributor

@celinval celinval left a comment

Choose a reason for hiding this comment

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

Just small comments. Don't worry about moving the tests to expected, but it is something I recommend for the future.

let ptr: *const u8 = s.as_ptr();

unsafe {
let x = *offset(ptr, 4) as char;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: For cases like this, I recommend using the expected test suite. kani-verify-fail is very fragile.

Not a blocker though.

@@ -1,12 +0,0 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR MIT
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 prefer if we don't delete this one in favor of things that call the intrinsic directly. This is actually closer to what the user code would look like. Can you please just rename it?

@adpaco-aws
Copy link
Contributor Author

Thanks, I moved the negative tests to expected and restored the "fixme" test (sorry about that).

1 similar comment
@adpaco-aws
Copy link
Contributor Author

Thanks, I moved the negative tests to expected and restored the "fixme" test (sorry about that).

let src_ptr = fargs.remove(0);
let offset = fargs.remove(0);
// Check that the computation would not overflow an `isize`
let dst_ptr_of = src_ptr.clone().cast_to(Type::ssize_t()).add_overflow(offset.clone());
Copy link
Contributor

Choose a reason for hiding this comment

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

This does integer arithmatic, not pointer arithmatic, and I think will give the wrong results

Copy link
Contributor

Choose a reason for hiding this comment

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

I.e.: You should account for the pointee size.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right, should be getting the right results now.

@adpaco-aws adpaco-aws requested review from danielsn and celinval April 26, 2022 20:24
Copy link
Contributor

@celinval celinval left a comment

Choose a reason for hiding this comment

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

Can you add a test that exercise the new check? Something like:

/// Check that an offset that overflow an isize::MAX triggers a verification failure.
#[kani::proof]
unsafe fn check_wrap_offset() {
        let v : &[u128] = &[0; 200];
        let v_100 : *const u128 = &v[100];
        let max_offset = usize::MAX / std::mem::size_of::<u128>();
        let v_wrap : *const u128 = v_100.offset((max_offset + 1).try_into().unwrap());
        assert_eq!(v_100, v_wrap);
        assert_eq!(*v_100, *v_wrap);
}

Copy link
Contributor

@danielsn danielsn left a comment

Choose a reason for hiding this comment

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

Approved modulo @celinval comments

@adpaco-aws
Copy link
Contributor Author

Addressed all @celinval's comments, including the proposed test case.

@danielsn danielsn merged commit efe7acb into model-checking:main Apr 26, 2022
@adpaco-aws adpaco-aws mentioned this pull request Apr 27, 2022
tedinski pushed a commit that referenced this pull request Apr 27, 2022
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.

Pointer sub() operation is giving spurious overflow check error
3 participants