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

Incorrect verification results for function/closure dyn traits #240

Closed
avanhatt opened this issue Jun 21, 2021 · 4 comments · Fixed by #373
Closed

Incorrect verification results for function/closure dyn traits #240

avanhatt opened this issue Jun 21, 2021 · 4 comments · Fixed by #373
Assignees
Labels
[C] Bug This is a bug. Something isn't working. [F] Soundness Kani failed to detect an issue

Comments

@avanhatt
Copy link
Contributor

The following fails to verify:

fn foo(fun: &mut dyn FnMut(i32) -> i32) -> i32 {
    fun(1)
}

fn main() {
    let r = foo(&mut move |z : i32| { z } );
    assert!(r == 1); // should succeed
}

In the generated CBMC-C code, in some places we pass the closure argument as a tuple, but in others we expect the flattened int.

@avanhatt avanhatt added [C] Bug This is a bug. Something isn't working. Area: compilation labels Jun 21, 2021
@avanhatt
Copy link
Contributor Author

This is blocking #220

@avanhatt
Copy link
Contributor Author

A similar example (without an explicit FnOnce) that demonstrates that this is a soundness issue:

fn takes_dyn_fun(fun: &dyn Fn() -> u32) {
    let x = fun();
}

pub fn unit_to_u32() -> u32 {
    assert!(false); 
    0
}

fn main() {
    takes_dyn_fun(&unit_to_u32)
}

Should fail from this explicit assert false, but:

VERIFICATION SUCCESSFUL

@avanhatt avanhatt changed the title Can't verify FnOnce dyn trait closure Incorrect verification results for function/closure dyn traits Jun 24, 2021
@avanhatt avanhatt added the [F] Soundness Kani failed to detect an issue label Jun 24, 2021
@avanhatt avanhatt self-assigned this Jun 25, 2021
@avanhatt
Copy link
Contributor Author

avanhatt commented Jun 25, 2021

This does fail as expected with --pointer-check:

$ rmc --gen-c src/test/cbmc/DynTrait/dyn_fn_minimal.rs --pointer-check | grep FAIL
[pointer_dereference.7] invalid function pointer: FAILURE
VERIFICATION FAILED

But, this means we are generating some bad function dereference, so still a bug.

@avanhatt
Copy link
Contributor Author

avanhatt commented Jul 28, 2021

Weird thing to maybe investigate separately:

The following hangs RMC at the gotoc-cc call (?!?)

    // Create a nested boxed once-callable closure
    let f: Box<Box<dyn FnOnce(i32)>> = Box::new(Box::new(|x| assert!(x == 1)));
    f(1);

    // Create a pointer to a closure
    let g = |y| assert!(y == 2);
    let p: &dyn Fn(i32) = &g;
    p(2);

    // Additional level of pointer nesting
    let q: &dyn Fn(i32) = &p;
    q(2);

Even though the first chunk of code should be independent from the 2nd, commenting it out gets rid of the hang.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[C] Bug This is a bug. Something isn't working. [F] Soundness Kani failed to detect an issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant