Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unwind safety issues for FFI functions #98

Open
VaynNecol opened this issue May 2, 2022 · 2 comments
Open

Unwind safety issues for FFI functions #98

VaynNecol opened this issue May 2, 2022 · 2 comments

Comments

@VaynNecol
Copy link

#[no_mangle]
pub unsafe extern "C" fn stretch_node_compute_layout(
    stretch: *mut c_void,
    node: *mut c_void,
    width: f32,
    height: f32,
    create_layout: fn(*const f32) -> *mut c_void,
) -> *mut c_void {
    let mut stretch = Box::from_raw(stretch as *mut Stretch);
    let node = Box::from_raw(node as *mut Node);

    stretch
        .compute_layout(
            *node,
            Size {
                width: if f32::is_nan(width) { Number::Undefined } else { Number::Defined(width) },
                height: if f32::is_nan(height) { Number::Undefined } else { Number::Defined(height) },
            },
        )
        .unwrap();

    let mut output = vec![];
    copy_output(&stretch, *node, &mut output);

    Box::leak(stretch);
    Box::leak(node);

    create_layout(output.as_ptr())
}

The unwinding of stretch.compute_layout will introduce double free due to the deallocation of stretch and node.

#[no_mangle]
pub unsafe extern "C" fn stretch_node_compute_layout(
    stretch: *mut c_void,
    node: *mut c_void,
    width: f32,
    height: f32,
    create_layout: fn(*const f32) -> *mut c_void,
) -> *mut c_void {
    let mut stretch = mem::ManuallyDrop::new(Box::from_raw(stretch as *mut Stretch));
    let node = mem::ManuallyDrop::new(Box::from_raw(node as *mut Node));

    stretch
        .compute_layout(
            *node,
            Size {
                width: if f32::is_nan(width) { Number::Undefined } else { Number::Defined(width) },
                height: if f32::is_nan(height) { Number::Undefined } else { Number::Defined(height) },
            },
        )
        .unwrap();

    let mut output = vec![];
    copy_output(&stretch, *node, &mut output);
    create_layout(output.as_ptr())
}

The modification is zero-cost.

@jkelleyrtp
Copy link

Can you make this issue/PR against http://github.com/dioxusLabs/stretch/ ? We're maintaining an active fork with fixes and improvements.

@VaynNecol
Copy link
Author

Can you make this issue/PR against http://github.com/dioxusLabs/stretch/ ? We're maintaining an active fork with fixes and improvements.

sure,please check on the issue in your fork, and we give a more detailed description

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants