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

transmute_unchecked contracts and harnesses #185

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

AlexLB99
Copy link

This is a draft pull request towards solving #19.

Changes

  • Added wrappers for transmute_unchecked()
  • Annotated these wrappers with contracts
  • Wrote harnesses that verify these wrappers

Note: the reason we write wrappers for transmute_unchecked() and we annotate those wrappers is that function contracts do not appear to be currently supported for compiler intrinsics (as discussed in #3345). Also, rather than using a single wrapper for transmute_unchecked(), we write several with different constraints on the input (since leaving the function parameters completely generic severely restricts what we can do in the contracts, e.g., testing for equality).

This is not intended to be a complete solution for verifying transmute_unchecked(), but instead a proof of concept to see how aligned this is with the expected solution. Any feedback would be greatly appreciated -- thank you!

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

@patricklam
Copy link

hi @celinval and @feliperodri! Thoughts most welcome.

@AlexLB99 AlexLB99 changed the title Transmute unchecked transmute_unchecked contracts and harnesses Nov 27, 2024
@tautschnig
Copy link
Member

Can the CI failures please be addressed?

@patricklam
Copy link

I guess that we can't trigger the workflow @tautschnig

@tautschnig
Copy link
Member

You might unintentionally have reverted submodule changes?

@AlexLB99 AlexLB99 closed this Dec 2, 2024
@AlexLB99 AlexLB99 force-pushed the transmute_unchecked branch from b163ae0 to 7e8a03d Compare December 2, 2024 19:56
@AlexLB99 AlexLB99 reopened this Dec 2, 2024
@patricklam
Copy link

Is it supposed to say "this workflow requires approval from a maintainer"?

@AlexLB99
Copy link
Author

AlexLB99 commented Dec 2, 2024

You might unintentionally have reverted submodule changes?

I believe the issue may have been a merge conflict caused by a recent upstream commit that moved intrinsic.rs (which is the file being modified here) to another location. I think in theory the problem should be fixed now @tautschnig

@tautschnig
Copy link
Member

Is it supposed to say "this workflow requires approval from a maintainer"?

Yes, we have opted for those rules out of caution.

@tautschnig
Copy link
Member

You might unintentionally have reverted submodule changes?

It looks like those are still present.

@AlexLB99
Copy link
Author

AlexLB99 commented Dec 3, 2024

You might unintentionally have reverted submodule changes?

It looks like those are still present.

Ah yes I see what you meant, it looks like there were some changes to library/stdarch. I've reverted those changes, so I think everything should be good to go now 👍

@patricklam
Copy link

@tautschnig can we get the ci to run?

@tautschnig
Copy link
Member

@tautschnig can we get the ci to run?

CI run has been approved and is in progress.

@patricklam
Copy link

Requesting a review again...

@@ -4537,6 +4537,32 @@ pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize
)
}

#[requires(crate::mem::size_of::<T>() >= crate::mem::size_of::<U>())] //U cannot be larger than T
#[ensures(|ret: &U| (ret as *const U as usize) % crate::mem::align_of::<U>() == 0)] //check that the output has expected alignment
pub unsafe fn transmute_unchecked_wrapper<T,U>(input: T) -> U {
Copy link

Choose a reason for hiding this comment

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

Can you please add a comment on why we need this and make this function private?

//This requires means [output is char implies input is valid unicode value]
#[requires(type_name::<U>() != type_name::<char>() || (input <= T::from(0xD7FF) || (input >= T::from(0xE000) && input <= T::from(0x10FFFF)) ))]
#[ensures(|ret: &U| (ret as *const U as usize) % crate::mem::align_of::<U>() == 0)]
pub unsafe fn transmute_unchecked_from_u32<T,U>(input: T) -> U
Copy link

Choose a reason for hiding this comment

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

I don't think we want to generate type specific wrappers.

Copy link
Author

Choose a reason for hiding this comment

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

Thank you for your comments!

One thing I was wondering, we couldn't find any ways to verify type-specific properties without putting constraints on the input/output types (hence the type-specific wrappers). In that case, would it be better to leave all type-specific validity checks to the "-Z valid-value-checks" logic, and to only verify generic properties in the generic wrapper (e.g., #[ensures(|ret: &U| (ub_checks::can_dereference(ret as *const U)))])?

@@ -4537,6 +4537,32 @@ pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize
)
}

#[requires(crate::mem::size_of::<T>() >= crate::mem::size_of::<U>())] //U cannot be larger than T
Copy link

Choose a reason for hiding this comment

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

We don't need to size requirement since this is a compilation error according to the transmute documentation. We do need to state that input T is a valid U value. One possibility would be to use the can_dereference method from ub_checks.

However, with Kani, the value validity checks are still incomplete (see model-checking/kani#3203) for current limitations.

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