Skip to content

Commit a369db2

Browse files
committed
Add in requested checking / setting of private data to null to avoid double free
1 parent 039a1b4 commit a369db2

1 file changed

Lines changed: 16 additions & 14 deletions

File tree

datafusion/ffi/src/physical_optimizer.rs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,17 @@ pub struct FFI_PhysicalOptimizerRule {
4646

4747
pub schema_check: unsafe extern "C" fn(&Self) -> bool,
4848

49-
/// Used to create a clone on the provider of the execution plan. This should
49+
/// Used to create a clone on the rule. This should
5050
/// only need to be called by the receiver of the plan.
5151
pub clone: unsafe extern "C" fn(plan: &Self) -> Self,
5252

5353
/// Release the memory of the private data when it is no longer being used.
5454
pub release: unsafe extern "C" fn(arg: &mut Self),
5555

56-
/// Return the major DataFusion version number of this provider.
56+
/// Return the major DataFusion version number of this rule.
5757
pub version: unsafe extern "C" fn() -> u64,
5858

59-
/// Internal data. This is only to be accessed by the provider of the plan.
59+
/// Internal data. This is only to be accessed by the provider of the rule.
6060
/// A [`ForeignPhysicalOptimizerRule`] should never attempt to access this data.
6161
pub private_data: *mut c_void,
6262

@@ -108,10 +108,13 @@ unsafe extern "C" fn schema_check_fn_wrapper(rule: &FFI_PhysicalOptimizerRule) -
108108
rule.inner().schema_check()
109109
}
110110

111-
unsafe extern "C" fn release_fn_wrapper(provider: &mut FFI_PhysicalOptimizerRule) {
112-
let private_data =
113-
unsafe { Box::from_raw(provider.private_data as *mut RulePrivateData) };
114-
drop(private_data);
111+
unsafe extern "C" fn release_fn_wrapper(rule: &mut FFI_PhysicalOptimizerRule) {
112+
unsafe {
113+
debug_assert!(!rule.private_data.is_null());
114+
let private_data = Box::from_raw(rule.private_data as *mut RulePrivateData);
115+
drop(private_data);
116+
rule.private_data = std::ptr::null_mut();
117+
}
115118
}
116119

117120
unsafe extern "C" fn clone_fn_wrapper(
@@ -172,20 +175,20 @@ impl FFI_PhysicalOptimizerRule {
172175
/// This wrapper struct exists on the receiver side of the FFI interface, so it has
173176
/// no guarantees about being able to access the data in `private_data`. Any functions
174177
/// defined on this struct must only use the stable functions provided in
175-
/// FFI_PhysicalOptimizerRule to interact with the foreign table provider.
178+
/// FFI_PhysicalOptimizerRule to interact with the foreign rule.
176179
#[derive(Debug)]
177180
pub struct ForeignPhysicalOptimizerRule(pub FFI_PhysicalOptimizerRule);
178181

179182
unsafe impl Send for ForeignPhysicalOptimizerRule {}
180183
unsafe impl Sync for ForeignPhysicalOptimizerRule {}
181184

182185
impl From<&FFI_PhysicalOptimizerRule> for Arc<dyn PhysicalOptimizerRule + Send + Sync> {
183-
fn from(provider: &FFI_PhysicalOptimizerRule) -> Self {
184-
if (provider.library_marker_id)() == crate::get_library_marker_id() {
185-
return Arc::clone(provider.inner());
186+
fn from(rule: &FFI_PhysicalOptimizerRule) -> Self {
187+
if (rule.library_marker_id)() == crate::get_library_marker_id() {
188+
return Arc::clone(rule.inner());
186189
}
187190

188-
Arc::new(ForeignPhysicalOptimizerRule(provider.clone()))
191+
Arc::new(ForeignPhysicalOptimizerRule(rule.clone()))
189192
as Arc<dyn PhysicalOptimizerRule + Send + Sync>
190193
}
191194
}
@@ -230,9 +233,8 @@ mod tests {
230233
use datafusion_physical_optimizer::PhysicalOptimizerRule;
231234
use datafusion_physical_plan::ExecutionPlan;
232235

233-
use crate::execution_plan::tests::EmptyExec;
234-
235236
use super::*;
237+
use crate::execution_plan::tests::EmptyExec;
236238

237239
#[derive(Debug)]
238240
struct NoOpRule {

0 commit comments

Comments
 (0)