suzusuzu / virtualization-rs

virtualization-rs provides the API of the Apple Virtualization.framework in Rust language.
MIT License
63 stars 14 forks source link

NSArray and VZMACAddress causes segmentation fault after dropped #4

Open siketyan opened 1 year ago

siketyan commented 1 year ago

Some ref-counted pointer defined in this crate causes segmentation fault on leaved from the scope and dropped. While dropping, runtime::objc_release is called by Drop trait tweak and the NSArray get dropped, but autorelease is also active and Foundation framework tries to release the array. In this time the NSArray is already released, so segmentation fault will be occurred.

Also I confirmed this occurs on VZMACAddress, but does not occur on other ones e.g. VZVirtioEntropyDeviceConfiguration.

I think these objects are autoreleased because they are not init ed or alloc ed in this crate; [NSArray arrayWithObjects:] or [VZMACAddress randomLocallyAdministeredAddress:] do enable autorelease on the objects initiated. These are also class methods (+).

How to reproduce

Cargo.toml

[package]
name = "virtualization-rs-segfault"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cacao = { version = "0.3.2", features = ["appkit"] }
virtualization-rs = { git = "https://github.com/suzusuzu/virtualization-rs.git", rev = "56daf26" }

main.rs

use cacao::appkit::{App, AppDelegate};
use virtualization_rs::base::NSArray;
use virtualization_rs::virtualization::entropy_device::{VZEntropyDeviceConfiguration, VZVirtioEntropyDeviceConfiguration};

#[derive(Default)]
struct MyApp {}

impl AppDelegate for MyApp {
    fn did_finish_launching(&self) {
        let entropy = VZVirtioEntropyDeviceConfiguration::new();
        let arr: NSArray<VZVirtioEntropyDeviceConfiguration> = NSArray::array_with_objects(vec![entropy.id()]);
    }
}

fn main() {
    App::new("jp.s6n.virtualization-rs-segfault", MyApp::default()).run();
}

Log

    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/virtualization-rs-segfault`

Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

LLDB

(lldb) target create "./target/debug/virtualization-rs-segfault"
Current executable set to '/Users/siketyan/.local/src/github.com/siketyan/virtualization-rs-segfault/target/debug/virtualization-rs-segfault' (arm64).
(lldb) r
Process 11308 launched: '/Users/siketyan/.local/src/github.com/siketyan/virtualization-rs-segfault/target/debug/virtualization-rs-segfault' (arm64)
Process 11308 stopped
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x3eaddead4e50)
    frame #0: 0x00000001aaab05f8 libobjc.A.dylib`objc_release + 16
libobjc.A.dylib`objc_release:
->  0x1aaab05f8 <+16>: ldr    x17, [x2, #0x20]
    0x1aaab05fc <+20>: tbz    w17, #0x2, 0x1aaab065c    ; <+116>
    0x1aaab0600 <+24>: tbz    w16, #0x0, 0x1aaab0678    ; <+144>
    0x1aaab0604 <+28>: lsr    x17, x16, #55
Target 0: (virtualization-rs-segfault) stopped.
(lldb) bt
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x3eaddead4e50)
  * frame #0: 0x00000001aaab05f8 libobjc.A.dylib`objc_release + 16
    frame #1: 0x00000001aaab80b4 libobjc.A.dylib`AutoreleasePoolPage::releaseUntil(objc_object**) + 196
    frame #2: 0x00000001aaab4b7c libobjc.A.dylib`objc_autoreleasePoolPop + 256
    frame #3: 0x00000001aaeea620 CoreFoundation`_CFAutoreleasePoolPop + 32
    frame #4: 0x00000001abe769c0 Foundation`-[NSAutoreleasePool drain] + 140
    frame #5: 0x00000001abe77ac0 Foundation`_NSAppleEventManagerGenericHandler + 92
    frame #6: 0x00000001b1248518 AE`___lldb_unnamed_symbol827 + 1620
    frame #7: 0x00000001b1247e44 AE`___lldb_unnamed_symbol826 + 44
    frame #8: 0x00000001b1240f18 AE`aeProcessAppleEvent + 488
    frame #9: 0x00000001b486ecf8 HIToolbox`AEProcessAppleEvent + 68
    frame #10: 0x00000001ae14825c AppKit`_DPSNextEvent + 1408
    frame #11: 0x00000001ae1470f4 AppKit`-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 716
    frame #12: 0x00000001ae13b558 AppKit`-[NSApplication run] + 464
    frame #13: 0x0000000100014408 virtualization-rs-segfault`_$LT$$LP$$RP$$u20$as$u20$objc..message..MessageArguments$GT$::invoke::hd842232bc33a96dd(imp=(libobjc.A.dylib`objc_msgSend), obj=0x0000000100305c00, sel=Sel @ 0x000000016fdfebc0, (null)=<unavailable>) at mod.rs:128:17
    frame #14: 0x0000000100012f18 virtualization-rs-segfault`objc::message::platform::send_unverified::hda504436024afc22(obj=0x0000000100305c00, sel=Sel @ 0x000000016fdfec30, args=<unavailable>) at mod.rs:27:9
    frame #15: 0x00000001000074d8 virtualization-rs-segfault`cacao::appkit::app::App$LT$T$GT$::run::hff63b404d89f6cc2 [inlined] objc::message::send_message::h0800889f39975f07(obj=0x0000000100305c00, sel=Sel @ 0x000000016fdfedf0, args=<unavailable>) at mod.rs:178:5
    frame #16: 0x00000001000074c4 virtualization-rs-segfault`cacao::appkit::app::App$LT$T$GT$::run::hff63b404d89f6cc2(self=0x000000016fdfef50) at mod.rs:125:25
    frame #17: 0x0000000100001f38 virtualization-rs-segfault`virtualization_rs_segfault::main::h3218fa48aa72b0a4 at main.rs:18:5
    frame #18: 0x00000001000084ac virtualization-rs-segfault`core::ops::function::FnOnce::call_once::h566d1fa376ccdf0e((null)=(virtualization-rs-segfault`virtualization_rs_segfault::main::h3218fa48aa72b0a4 at main.rs:17), (null)=<unavailable>) at function.rs:250:5
    frame #19: 0x000000010000c2c0 virtualization-rs-segfault`std::sys_common::backtrace::__rust_begin_short_backtrace::ha3859fbbe81c04ca(f=(virtualization-rs-segfault`virtualization_rs_segfault::main::h3218fa48aa72b0a4 at main.rs:17)) at backtrace.rs:121:18
    frame #20: 0x00000001000023fc virtualization-rs-segfault`std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::h57ac2a828d1e64a9 at rt.rs:166:18
    frame #21: 0x0000000100072dd8 virtualization-rs-segfault`std::rt::lang_start_internal::h443d2b6847a9fc56 [inlined] core::ops::function::impls::_$LT$impl$u20$core..ops..function..FnOnce$LT$A$GT$$u20$for$u20$$RF$F$GT$::call_once::hcceb02c1aa23714f at function.rs:287:13 [opt]
    frame #22: 0x0000000100072dd0 virtualization-rs-segfault`std::rt::lang_start_internal::h443d2b6847a9fc56 [inlined] std::panicking::try::do_call::hf102f78665387b93 at panicking.rs:483:40 [opt]
    frame #23: 0x0000000100072dd0 virtualization-rs-segfault`std::rt::lang_start_internal::h443d2b6847a9fc56 [inlined] std::panicking::try::h2dc1b2bbf9c9f30c at panicking.rs:447:19 [opt]
    frame #24: 0x0000000100072dd0 virtualization-rs-segfault`std::rt::lang_start_internal::h443d2b6847a9fc56 [inlined] std::panic::catch_unwind::hdfa9ffe95c9af17a at panic.rs:140:14 [opt]
    frame #25: 0x0000000100072dd0 virtualization-rs-segfault`std::rt::lang_start_internal::h443d2b6847a9fc56 [inlined] std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::h616e22053180e8b1 at rt.rs:148:48 [opt]
    frame #26: 0x0000000100072dd0 virtualization-rs-segfault`std::rt::lang_start_internal::h443d2b6847a9fc56 [inlined] std::panicking::try::do_call::hfc6e78544ea0445b at panicking.rs:483:40 [opt]
    frame #27: 0x0000000100072dd0 virtualization-rs-segfault`std::rt::lang_start_internal::h443d2b6847a9fc56 [inlined] std::panicking::try::h3dddbf8d06905891 at panicking.rs:447:19 [opt]
    frame #28: 0x0000000100072dd0 virtualization-rs-segfault`std::rt::lang_start_internal::h443d2b6847a9fc56 [inlined] std::panic::catch_unwind::h39d4e51c24609954 at panic.rs:140:14 [opt]
    frame #29: 0x0000000100072dd0 virtualization-rs-segfault`std::rt::lang_start_internal::h443d2b6847a9fc56 at rt.rs:148:20 [opt]
    frame #30: 0x00000001000023c8 virtualization-rs-segfault`std::rt::lang_start::hd3d4337c3203e391(main=(virtualization-rs-segfault`virtualization_rs_segfault::main::h3218fa48aa72b0a4 at main.rs:17), argc=1, argv=0x000000016fdff420, sigpipe='\0') at rt.rs:165:17
    frame #31: 0x0000000100001fa0 virtualization-rs-segfault`main + 36
    frame #32: 0x00000001aaaf3f28 dyld`start + 2236

System

macOS 13.4, MacBook Air (M2), Arm64

suzusuzu commented 1 year ago

Thanks for the bug report. I am aware that the problem is caused by the confusion between autorelase objectt and non-autorelase object.