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

Verus checking code in some external_body functions #1151

Open
hayley-leblanc opened this issue May 31, 2024 · 2 comments
Open

Verus checking code in some external_body functions #1151

hayley-leblanc opened this issue May 31, 2024 · 2 comments

Comments

@hayley-leblanc
Copy link
Collaborator

Hi folks, I'm writing some code involving MaybeUninit in external_body functions and have found that Verus is incorrectly checking the bodies of some of these functions. The specific case I encountered involves obtaining a mutable reference to a MaybeUninit object; attempting to verify an external_body function that does this results in a verification error about &mut not being supported.

An example of such a function that does not verify:

#[verifier::external_body]
fn test_maybe_uninit() {
    let mut maybe_uninit: MaybeUninit<u64> = MaybeUninit::uninit();
    let mut bytes: &mut [MaybeUninit<u8>] = maybe_uninit.as_bytes_mut();
    let new_bytes: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0];
    MaybeUninit::write_slice(bytes, &new_bytes);
}

Attempting to verify this function results in error: The verifier does not yet support the following Rust feature: &mut types, except in special cases.

This does not happen with all external_body functions involving mutable references; for example, this function verifies as expected:

#[verifier::external_body]
fn test_vec() {
    let mut vec = vec![1, 2, 3];
    let mut bytes: &mut [u8] = vec.as_mut_slice();
    let new_bytes: [u8; 3] = [0, 0, 0];
    bytes.copy_from_slice(&new_bytes);
}

Both functions are implemented at https://play.verus-lang.org/?version=stable&mode=basic&edition=2021&gist=a677a25cc24042da30e69c076811d4c1

I also noticed that removing #[verifier::external_body] from test_maybe_uninit() results in a different error: error: The verifier does not yet support the following Rust feature: &mut dereference in this position (note: &mut dereference is implicit here)

@Chris-Hawblitzel
Copy link
Collaborator

This may be related to #657 .

@Chris-Hawblitzel
Copy link
Collaborator

For anyone who encounters this, the current recommended workaround is to move the code into an external function, called by the external_body function:

#[verifier::external]
fn test_maybe_uninit_external() {
    let mut maybe_uninit: MaybeUninit<u64> = MaybeUninit::uninit();
    let mut bytes: &mut [MaybeUninit<u8>] = maybe_uninit.as_bytes_mut();
    let new_bytes: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0];
    MaybeUninit::write_slice(bytes, &new_bytes);
}
    
#[verifier::external_body]
#[inline(always)]
fn test_maybe_uninit() {
    test_maybe_uninit_external()
}

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

No branches or pull requests

2 participants