Skip to content

Soundess issues #3

@madsmtm

Description

@madsmtm

From a quick skim, I found the following important safety mistakes, that leads to unsound code (unsoundness = a safe abstract which a downstream user can use to violate memory safety without writing unsafe themselves).

Note that I completely understand the reasoning behind these mistakes, most have only been fixed in objc2 very recently!

  • arc::Retain<T> allows access to &mut T (through DerefMut), which is not safe for almost all classes.

    use cidre::ns;
    
    let mut s1 = ns::String::with_str("already lowercase");
    let mut s2 = s1.retained();
    let s1: &mut ns::String = &mut *s1;
    let s2: &mut ns::String = &mut *s2;
    // The mutable references s1 and s2 now alias
  • Autoreleased references are not bound to a pool, meaning that they can be accessed after they've been reclaimed by the pool.

    use cidre::{ns, objc};
    
    let s = ns::String::with_str("My String");
    let lowercased = objc::autoreleasepool(|| {
        s.lowercased_ar()
        // The newly created string is released and deallocated here
    });
    // But we can still use it here
    println!("{lowercased}");
  • Message sending to methods in the new family leaks, since new returns an object with +1 retain count.

    use cidre::mtl;
    let device = mtl::Device::default().unwrap();
    
    // Created with +1 retain count, and retained, so it ends up at +2
    let cmd_queue = device.new_cmd_queue();
    // Retain count decremented only once
    drop(cmd_queue);
    // The CmdQueue is leaked

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions