Skip to content

Global LOAD_POINTER in call_main will leak host for multiple assignments. #46

@labyrinth-ssr

Description

@labyrinth-ssr

rust-vst2/src/host.rs

Lines 340 to 344 in 244e14b

/// Call the VST entry point and retrieve a (possibly null) pointer.
unsafe fn call_main(&mut self) -> *mut AEffect {
LOAD_POINTER = Box::into_raw(Box::new(self.host.clone())) as *mut c_void;
(self.main)(callback_wrapper::<T>)
}

with Box::into_raw(Box::new(self.host.clone())), the pointee is on the heap. Multiple assignments will cause the old value to leak.

Probable fix is like:
If call_main should only be called once, adding an Atomic to guarantee assigning only once.

const UNINITIALIZED: usize = 0;
const INITIALIZING: usize = 1;
const INITIALIZED: usize = 2;
static GLOBAL_INIT: AtomicUsize = AtomicUsize::new(UNINITIALIZED);
pub struct SetGlobalDefaultError {
    _no_construct: (),
}

unsafe fn call_main(&mut self) -> Result<*mut AEffect, SetGlobalDefaultError>  {
        if GLOBAL_INIT
                .compare_exchange(
                    UNINITIALIZED,
                    INITIALIZING,
                    Ordering::SeqCst,
                    Ordering::SeqCst,
                )
                .is_ok()
            {
              LOAD_POINTER = Box::into_raw(Box::new(self.host.clone())) as *mut c_void;
              (self.main)(callback_wrapper::<T>)
            }  else {
              Err(SetGlobalDefaultError { _no_construct: () })
            }
} 

Otherwise change the else branch to:

           else {
              drop(Box::from_raw(LOAD_POINTER));
              LOAD_POINTER = Box::into_raw(Box::new(self.host.clone())) as *mut c_void;
              (self.main)(callback_wrapper::<T>)
          }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions