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

Bug: AsImpl::as_impl should be unsafe #2498

Closed
kaivol opened this issue May 10, 2023 · 1 comment · Fixed by #2565
Closed

Bug: AsImpl::as_impl should be unsafe #2498

kaivol opened this issue May 10, 2023 · 1 comment · Fixed by #2565
Labels
enhancement New feature or request

Comments

@kaivol
Copy link
Contributor

kaivol commented May 10, 2023

Which crate is this about?

windows

Crate version

0.48.0

Summary

When using the #[implement(IInterface)] macro, e.g. like this

#[implement(IStringable)]
struct Object1(u32);

impl IStringable_Impl for Object1 {
    fn ToString(&self) -> Result<HSTRING> {
        Ok("Object1".into())
    }
}

the generated AsImpl::as_impl looks like this

impl ::windows::core::AsImpl<Object1> for IStringable {
    fn as_impl(&self) -> &Object1 {
        let this = ::windows::core::Interface::as_raw(self);
        unsafe {
            let this = (this as *mut *mut ::core::ffi::c_void).sub(1 + 0) as *mut Object1_Impl;
            &(*this).this
        }
    }
}

and allows getting a &Object1 from any &IStringable, regardless of whether the IStringable has actually been created from an Object1 or by the #[implement] macro at all. This is of course unsound.

Toolchain version/configuration

No response

Reproducible example

use windows::core::*;
use windows::Foundation::*;

#[implement(IStringable)]
struct Object1(u32);

impl IStringable_Impl for Object1 {
    fn ToString(&self) -> Result<HSTRING> {
        Ok("Object1".into())
    }
}

#[implement(IStringable)]
struct Object2(f32);

impl IStringable_Impl for Object2 {
    fn ToString(&self) -> Result<HSTRING> {
        Ok("Object2".into())
    }
}

#[test]
fn test() {
    let obj1: IStringable = Object1(1337).into();
    let obj2 = AsImpl::<Object2>::as_impl(&obj1);
    assert_eq!(obj2.0, f32::from_bits(1337));
}

Crate manifest

[package]
name = "test"
version = "0.0.0"
edition = "2018"

[dependencies.windows]
version = "0.48.0"
features = [
    "implement",
    "Win32_Foundation",
]

Expected behavior

The example should not compile.

Actual behavior

The example does compile.

@kaivol kaivol added the bug Something isn't working label May 10, 2023
@kennykerr
Copy link
Collaborator

Agreed, that should probably be unsafe.

@kennykerr kennykerr added enhancement New feature or request and removed bug Something isn't working labels May 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants