Skip to content

CFMutableDictionary's API is unsound #362

Open
@roblabla

Description

@roblabla

Split from #361

CFMutableDictionary has multiple really problematic soundness issues:

  1. The CFDictionaryCreate callback is always kCFTypeDictionary*CallBacks, despite the default type arguments being *const c_void. This makes it really easy to cause UB with the CFMutableDictionary type, simply by calling CFMutableDictionary::add with an arbitrary pointer or null.
  2. Again with CFMutableDictionary, to_untyped trivially allows casting an arbitrary pointer to a concrete type.

Here's an example of both problems:

#[test]
fn this_is_very_ub() {
    let dict: CFMutableDictionary<CFString, CFString> = CFMutableDictionary::new();
    let mut dict_untyped = dict.to_untyped();
    let test = CFString::new("test");
    dict_untyped.add(&test.to_void(), &std::ptr::null());
    let val = dict.get(&test);
    println!("{}", val.char_len());
}

This will cause a crash in safe rust.

To fix this, I believe CFMutableDictionary::to_untyped should return an immutable CFDictionary, preventing the user from creating types from arbitrary pointers. If this is not desirable, then it should be made unsafe. into_untyped is similarly unsound when combined with clone (which simply increases the refcnt).

Additionally, with_capacity should either use NULL KeyCallBacks/ValueCallBacks (making CoreFoundation default to pointer equality and... unsure how hashing works?) or enforce that K/V be TCFType. Similarly, from_CFType_pairs should enforce K, V: TCFType.

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