Skip to content

Warn about Box::from_raw::<c_void> #9679

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

Closed
andreubotella opened this issue Oct 18, 2022 · 1 comment
Closed

Warn about Box::from_raw::<c_void> #9679

andreubotella opened this issue Oct 18, 2022 · 1 comment
Assignees
Labels
A-lint Area: New lints

Comments

@andreubotella
Copy link
Contributor

andreubotella commented Oct 18, 2022

What it does

Often in FFI, some APIs will take *c_void or *mut c_void to indicate arbitrary objects from the caller side. When interacting with such APIs in Rust it is common to allocate something with {Box,Rc,Arc}::into_raw and then casting the raw pointer. For deallocating you often get the c_void pointer back from the FFI API and you would turn it into the corresponding owned/shared pointer with {Box,Rc,Arc}::from_raw, after which you can drop it.

However, it is easy to run into the pitfall of calling from_raw with the c_void pointer. Note that the definition of, say, Box::from_raw is:

pub unsafe fn from_raw(raw: *mut T) -> Box<T>

meaning that if you pass a *mut c_void you will get a Box<c_void>. Per the safety requirements in the documentation, for this to be safe, c_void would need to have the same memory layout as the original type, which is often not the case. And even if it was the case, if the original type or one of its fields (or one of its fields, recursively) had a Drop implementation, that implementation would not run when this newly recreated box is dropped. (And similarly for Rc and Arc.)

While it is possible to purposefully create a Box<c_void>, it's hard to see any case where it would be useful. Therefore, uses of Box::from_raw::<c_void> can be safely assumed to be a mistake, and clippy should have a lint for it.

Lint Name

from-raw-cvoid

Category

No response

Advantage

  • Remove an easy pitfall of FFI, particularly with some C or C++ APIs.

Drawbacks

  • Might conflict with genuine usages of Box<c_void>, but those are incredibly rare, and not good practice.

Example

use std::ffi::c_void;

let ptr = Box::into_raw(Box::new(42usize)) as *mut c_void;
// pass `ptr` through C FFI or something.
let _ = unsafe { Box::from_raw(ptr) };

Could be written as:

use std::ffi::c_void;

let ptr = Box::into_raw(Box::new(42usize)) as *mut c_void;
// pass `ptr` through C FFI or something.
let _ = unsafe { Box::from_raw(ptr as *mut usize) };
@andreubotella andreubotella added the A-lint Area: New lints label Oct 18, 2022
@roynrishingha
Copy link
Contributor

@rustbot claim

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints
Projects
None yet
Development

No branches or pull requests

2 participants