-
Notifications
You must be signed in to change notification settings - Fork 238
Description
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.