Skip to content

Handle::from_raw can't pass miri tests with strict provenance due to integer to pointer cast #996

@06393993

Description

@06393993

With the following test:

    #[test]
    fn test_from_raw() {
        let _ = <vk::Instance as vk::Handle>::from_raw(20);
    }

and the command to run miri test: MIRIFLAGS="-Zmiri-tree-borrows -Zmiri-backtrace=full" cargo +nightly miri nextest run --all-targets --all-features -j20 --no-fail-fast -E'test(test_from_raw)' (with miri and cargo-nextest set up), I end up with the following error:

    test vk::tests::test_from_raw ... 
  stderr ───
    error: unsupported operation: integer-to-pointer casts and `ptr::with_exposed_provenance` are not supported with `-Zmiri-strict-provenance`
       --> ash/src/vk/macros.rs:142:22
        |
    142 |                   Self(x as _)
        |                        ^^^^^^ integer-to-pointer casts and `ptr::with_exposed_provenance` are not supported with `-Zmiri-strict-provenance`


I am writing Vulkan layers in Rust, use vk::Handle::from_raw extensively, and use miri with tree borrows to catch UB for my unsafe code. Therefore, I am wondering if the upstream is willing to accept a PR that removes the integer to pointer casting in vk::Handle::from_raw.

I have 2 different proposals with different drawbacks:

  • Change the definition of a handle type, e.g. vk::Instance to struct Instance(usize). The disadvantage is that:

    • The implementation of null(e.g. ash::vk::Instance::null) has to change. We either change the method from a const fn to a non const fn with Self(::core::ptr::null_mut::<u8>() as usize), or we use Self(0). Dropping const will break the API slightly, while using 0 is not great because it is not guaranteed that C++'s nullptr or C's NULL is 0.
    • While usize should be the same size as *mut u8 on platforms supported by Vulkan, so that ABI should be kept. However, I am not sure if this is strongly guaranteed by Rust.
  • Use ::core::ptr::with_addr to implement Handle::from_raw, i.e., ::core::ptr::dangling_mut::<u8>().with_addr(x). However, with_addr is not introduced until Rust 1.84.0, so we either need to change MSRV or use crates like rustversion for conditional compilation based on the Rust version which adds new dependencies and complicates code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions