Skip to content

TCFType should be an unsafe trait #364

@roblabla

Description

@roblabla

I believe implementing TCFType should require an unsafe impl, as implementing it on a non-Core Foundation type can easily lead to UB from the assumptions made in other types. For instance, the following code is almost certain to cause issue, despite not requiring any unsafe code:

extern crate core_foundation;

use core_foundation::base::{TCFType, TCFTypeRef, CFTypeID, CFTypeRef};
use core_foundation::array::CFArray;
use std::os::raw::c_void;

#[derive(Clone, Copy)]
struct MyFakeCFType;
impl TCFType for MyFakeCFType {
    type Ref = MyFakeCFType;
    fn as_concrete_TypeRef(&self) -> Self::Ref { MyFakeCFType }
    unsafe fn wrap_under_create_rule(r: Self::Ref) -> Self { r }
    fn type_id() -> CFTypeID { 0 }
    fn as_CFTypeRef(&self) -> CFTypeRef { std::ptr::null_mut() }
    unsafe fn wrap_under_get_rule(r: Self::Ref) -> Self { r }
}

impl TCFTypeRef for MyFakeCFType {
    fn as_void_ptr(&self) -> *const c_void { self as *const _ as _ }
    unsafe fn from_void_ptr(ptr: *const c_void) -> Self { MyFakeCFType }
}

#[test]
fn test1() {
    MyFakeCFType.retain_count();
}

#[test]
fn test2() {
    let arr = CFArray::from_CFTypes(&[MyFakeCFType; 32]);
    arr.show()
}

This code has no unsafe code (though it does have two unsafe functions, they aren't even what's causing the issue in our case! Besides, unsafe function signify a contract that the caller must uphold - the callee is free to do whatever it wants.)

The truth is, both TCFType's default functions and the various from_CFTypes* functions in other places of the library assume that a type implementing TCFType is, in fact, a Core Foundation type (which here means a wrapper around a pointer to an object allocated with a CFAllocator that starts with the CFRuntimeBase type, or something along those lines). It doesn't seem possible to make those functions safe without ensuring that the implementation of the TCFType is correct. As such, TCFType should, IMO, be marked as an unsafe trait.

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