Add consistent null pointer checks to CLAP wrapper
Just like we do for the VST3 wrapper.
This commit is contained in:
parent
66012f9787
commit
78b815fede
|
@ -1,8 +1,10 @@
|
|||
#[macro_use]
|
||||
mod util;
|
||||
|
||||
mod context;
|
||||
mod descriptor;
|
||||
mod factory;
|
||||
mod plugin;
|
||||
mod util;
|
||||
|
||||
/// Re-export for the wrapper.
|
||||
pub use self::factory::Factory;
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
// Clippy doesn't understand it when we use a unit in our `check_null_ptr!()` maccro, even if we
|
||||
// explicitly pattern match on that unit
|
||||
#![allow(clippy::unused_unit)]
|
||||
|
||||
use clap_sys::events::{
|
||||
clap_event_header, clap_event_note, clap_event_param_mod, clap_event_param_value,
|
||||
clap_input_events, clap_output_events, CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_MIDI,
|
||||
|
@ -483,12 +487,9 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
plugin: *const clap_plugin,
|
||||
process: *const clap_process,
|
||||
) -> clap_process_status {
|
||||
check_null_ptr!(CLAP_PROCESS_ERROR, plugin, process);
|
||||
let wrapper = &*(plugin as *const Self);
|
||||
|
||||
if process.is_null() {
|
||||
return CLAP_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
// Panic on allocations if the `assert_process_allocs` feature has been enabled, and make
|
||||
// sure that FTZ is set up correctly
|
||||
process_wrapper(|| {
|
||||
|
@ -525,7 +526,12 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
);
|
||||
|
||||
// Right now we don't handle any auxiliary outputs
|
||||
nih_debug_assert!(!process.audio_outputs.is_null());
|
||||
check_null_ptr_msg!(
|
||||
"Null pointers passed for audio outputs in process function",
|
||||
CLAP_PROCESS_ERROR,
|
||||
process.audio_outputs,
|
||||
(*process.audio_outputs).data32
|
||||
);
|
||||
let audio_outputs = &*process.audio_outputs;
|
||||
let num_output_channels = audio_outputs.channel_count as usize;
|
||||
|
||||
|
@ -536,7 +542,6 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
// flags?
|
||||
let mut output_buffer = wrapper.output_buffer.write();
|
||||
output_buffer.with_raw_vec(|output_slices| {
|
||||
nih_debug_assert!(!audio_outputs.data32.is_null());
|
||||
nih_debug_assert_eq!(num_output_channels, output_slices.len());
|
||||
for (output_channel_idx, output_channel_slice) in
|
||||
output_slices.iter_mut().enumerate()
|
||||
|
@ -597,12 +602,9 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
plugin: *const clap_plugin,
|
||||
id: *const c_char,
|
||||
) -> *const c_void {
|
||||
check_null_ptr!(ptr::null(), plugin, id);
|
||||
let wrapper = &*(plugin as *const Self);
|
||||
|
||||
if id.is_null() {
|
||||
return ptr::null();
|
||||
}
|
||||
|
||||
// TODO: Implement the other useful extensions. Like uh audio inputs.
|
||||
let id = CStr::from_ptr(id);
|
||||
if id == CStr::from_ptr(CLAP_EXT_PARAMS) {
|
||||
|
@ -623,6 +625,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
}
|
||||
|
||||
unsafe extern "C" fn ext_params_count(plugin: *const clap_plugin) -> u32 {
|
||||
check_null_ptr!(0, plugin);
|
||||
let wrapper = &*(plugin as *const Self);
|
||||
|
||||
// NOTE: We add a bypass parameter ourselves on index `plugin.param_hashes.len()`, so
|
||||
|
@ -635,13 +638,11 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
param_index: i32,
|
||||
param_info: *mut clap_param_info,
|
||||
) -> bool {
|
||||
check_null_ptr!(false, plugin, param_info);
|
||||
let wrapper = &*(plugin as *const Self);
|
||||
|
||||
// Parameter index `self.param_ids.len()` is our own bypass parameter
|
||||
if param_info.is_null()
|
||||
|| param_index < 0
|
||||
|| param_index > wrapper.param_hashes.len() as i32
|
||||
{
|
||||
if param_index < 0 || param_index > wrapper.param_hashes.len() as i32 {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -694,12 +695,9 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
param_id: clap_id,
|
||||
value: *mut f64,
|
||||
) -> bool {
|
||||
check_null_ptr!(false, plugin, value);
|
||||
let wrapper = &*(plugin as *const Self);
|
||||
|
||||
if value.is_null() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if param_id == *BYPASS_PARAM_HASH {
|
||||
*value = if wrapper.bypass_state.load(Ordering::SeqCst) {
|
||||
1.0
|
||||
|
@ -724,12 +722,9 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
display: *mut c_char,
|
||||
size: u32,
|
||||
) -> bool {
|
||||
check_null_ptr!(false, plugin, display);
|
||||
let wrapper = &*(plugin as *const Self);
|
||||
|
||||
if display.is_null() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let dest = std::slice::from_raw_parts_mut(display, size as usize);
|
||||
|
||||
if param_id == *BYPASS_PARAM_HASH {
|
||||
|
@ -762,12 +757,9 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
display: *const c_char,
|
||||
value: *mut f64,
|
||||
) -> bool {
|
||||
check_null_ptr!(false, plugin, display, value);
|
||||
let wrapper = &*(plugin as *const Self);
|
||||
|
||||
if display.is_null() || value.is_null() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let display = match CStr::from_ptr(display).to_str() {
|
||||
Ok(s) => s,
|
||||
Err(_) => return false,
|
||||
|
@ -800,6 +792,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
in_: *const clap_input_events,
|
||||
out: *const clap_output_events,
|
||||
) {
|
||||
check_null_ptr!((), plugin);
|
||||
let wrapper = &*(plugin as *const Self);
|
||||
|
||||
if !in_.is_null() {
|
||||
|
|
|
@ -1,5 +1,23 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
/// Early exit out of a function with the specified return value when one of the passed pointers is
|
||||
/// null.
|
||||
macro_rules! check_null_ptr {
|
||||
($ret:expr, $ptr:expr $(, $ptrs:expr)* $(, )?) => {
|
||||
check_null_ptr_msg!("Null pointer passed to function", $ret, $ptr $(, $ptrs)*)
|
||||
};
|
||||
}
|
||||
|
||||
/// The same as [check_null_ptr!], but with a custom message.
|
||||
macro_rules! check_null_ptr_msg {
|
||||
($msg:expr, $ret:expr, $ptr:expr $(, $ptrs:expr)* $(, )?) => {
|
||||
if $ptr.is_null() $(|| $ptrs.is_null())* {
|
||||
nih_debug_assert_failure!($msg);
|
||||
return $ret;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Send+Sync wrapper around CLAP host extension pointers.
|
||||
pub struct ClapPtr<T> {
|
||||
inner: *const T,
|
||||
|
|
Loading…
Reference in a new issue