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

Fix ClosureMutN soundness #40

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions libffi-rs/src/high/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ pub use middle::CodePtr;

/// Encapsulates an argument with its type information.
///
/// In order to set up calls using [`call`](index.html#method.call), we
/// In order to set up calls using [`fn@call`], we
/// need to wrap (a reference to) each argument in an `Arg`. The usual
/// way to do this is with function [`arg`](fn.arg.html).
/// way to do this is with function [`arg`].
#[derive(Clone, Debug)]
pub struct Arg<'a> {
// There should be some type T such that type_ is the middle-layer
Expand All @@ -37,10 +37,9 @@ pub struct Arg<'a> {
}

impl<'a> Arg<'a> {
/// Wraps an argument reference for passing to `high::call::call`.
/// Wraps an argument reference for passing to [`fn@call`].
///
/// For a shorter alias of the same, see
/// [`high::call::arg`](fn.arg.html).
/// For a shorter alias of the same, see [`fn@arg`].
pub fn new<T: super::CType>(arg: &'a T) -> Self {
Arg {
type_: T::reify().into_middle(),
Expand All @@ -50,15 +49,14 @@ impl<'a> Arg<'a> {
}
}

/// Constructs an [`Arg`](struct.Arg.html) for passing to
/// [`call`](fn.call.html).
/// Constructs an [`Arg`] for passing to [`fn@call`].
pub fn arg<T: super::CType>(arg: &T) -> Arg {
Arg::new(arg)
}

/// Performs a dynamic call to a C function.
///
/// To reduce boilerplate, see [`ffi_call!`](../../macro.ffi_call!.html).
/// To reduce boilerplate, see [`ffi_call!`].
///
/// # Examples
///
Expand All @@ -85,8 +83,9 @@ pub unsafe fn call<R: super::CType>(fun: CodePtr, args: &[Arg]) -> R {

/// Performs a dynamic call to a C function.
///
/// This macro provides sugar for `call::arg` and `call::call`. For more
/// control, see [`high::call::call`](high/call/fn.call.html).
/// This macro provides sugar for [`high::arg`](crate::high::arg) and
/// [`high::call`](fn@crate::high::call). For more control, see
/// [`high::call`](fn@crate::high::call).
///
/// # Examples
///
Expand Down
22 changes: 11 additions & 11 deletions libffi-rs/src/high/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,24 @@
//! used to turn Rust lambdas (or in generally, anything that implements
//! `Fn` or `FnMut`) into ordinary C function pointers. For example, a
//! Rust value of type `Fn(u32, u32) -> u64` can be turned into a
//! closure of type `Closure2<u32, u32, u64>` using
//! [`Closure2::new`](struct.Closure2.html#method.new). Then a C
//! closure of type [`Closure2<u32, u32, u64>`] using
//! [`Closure2::new`]. Then a C
//! function pointer of type `extern "C" fn(u32, u32) -> u64` can be
//! borrowed from the closure and passed to C.
//!
//! The above usage case eliminates much of the boilerplate involved in
//! creating a closure as compared to the `middle` and `low` layers, but
//! at the price of flexibility. Some flexibility can be recovered by
//! manually constructing and configuring a CIF (*e.g.,* a
//! [`Cif2`](struct.Cif2.html)) and then creating the closure with
//! [`Closure2::new_with_cif`](struct.Closure2.html#method.new_with_cif).
//! [`Cif2`]) and then creating the closure with
//! [`Closure2::new_with_cif`].
//!
//! See the [`call`](call/index.html) submodule for a simple interface
//! See the [`mod@call`] submodule for a simple interface
//! to dynamic calls to C functions.
//!
//! # Examples
//!
//! Here we use [`ClosureMut1`](struct.ClosureMut1.html), which is the type
//! Here we use [`ClosureMut1`], which is the type
//! for creating mutable closures of one argument. We use it to turn a
//! Rust lambda into a C function pointer.
//!
Expand All @@ -38,8 +38,8 @@
//! let mut x = 0u64;
//! let mut f = |y: u32| { x += y as u64; x };
//!
//! let closure = ClosureMut1::new(&mut f);
//! let counter = closure.code_ptr();
//! let mut closure = ClosureMut1::new(&mut f);
//! let counter = closure.code_ptr();
//!
//! assert_eq!(5, counter.call(5));
//! assert_eq!(6, counter.call(1));
Expand Down Expand Up @@ -279,7 +279,7 @@ macro_rules! define_closure_mod {
impl<'a, $( $T, )* R> $closure_mut<'a, $( $T, )* R> {
/// Gets the C code pointer that is used to invoke the
/// closure.
pub fn code_ptr(&self) -> & $fnptr <'a, $( $T, )* R> {
pub fn code_ptr(&mut self) -> & $fnptr <'a, $( $T, )* R> {
unsafe {
self.untyped.instantiate_code_ptr()
}
Expand Down Expand Up @@ -511,7 +511,7 @@ mod test {

let type_ = u64::reify();
let cif = Cif1::new(type_.clone(), type_.clone());
let closure = ClosureMut1::new_with_cif(cif, &mut f);
let mut closure = ClosureMut1::new_with_cif(cif, &mut f);

let counter = closure.code_ptr();

Expand All @@ -538,7 +538,7 @@ mod test {
x
};

let closure = ClosureMut1::new(&mut f);
let mut closure = ClosureMut1::new(&mut f);
let counter = closure.code_ptr();

assert_eq!(5, counter.call(5));
Expand Down
5 changes: 2 additions & 3 deletions libffi-rs/src/high/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ use super::super::middle;
///
/// In particular, the run-time value describes a particular C type,
/// while the type parameter `T` is the equivalent Rust type.
/// Instances of this type are created via the
/// [`CType`](trait.CType.html) trait.
/// Instances of this type are created via the [`CType`] trait.
#[derive(Clone, Debug)]
pub struct Type<T> {
untyped: middle::Type,
Expand All @@ -25,7 +24,7 @@ impl<T> Type<T> {
}

/// Gets the underlying representation as used by the
/// [`middle`](../../middle/index.html) layer.
/// [`mod@middle`] layer.
pub fn into_middle(self) -> middle::Type {
self.untyped
}
Expand Down
16 changes: 8 additions & 8 deletions libffi-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
//! The C libffi library provides two main facilities: assembling calls
//! to functions dynamically, and creating closures that can be called
//! as ordinary C functions. In Rust, the latter means that we can turn
//! a Rust lambda (or any object implementing `Fn`/`FnMut`) into an
//! a Rust lambda (or any object implementing [`Fn`]/[`FnMut`]) into an
//! ordinary C function pointer that we can pass as a callback to C.
//!
//! The easiest way to use this library is via the
//! [`high`](high/index.html) layer module, but more flexibility (and
//! less checking) is provided by the [`middle`](middle/index.html) and
//! [`low`](low/index.html) layers.
//! [`mod@high`] layer module, but more flexibility (and
//! less checking) is provided by the [`mod@middle`] and
//! [`mod@low`] layers.
//!
//! # Usage
//!
Expand Down Expand Up @@ -46,15 +46,15 @@
//! provide more safety and a simpler interface than the next layer
//! down. From top to bottom:
//!
//! - The [`high`](high/index.html) layer provides safe(?) and
//! - The [`mod@high`] layer provides safe(?) and
//! automatic marshalling of Rust closures into C function pointers.
//! - The [`middle`](middle/index.html) layer provides memory-managed
//! - The [`mod@middle`] layer provides memory-managed
//! abstractions for assembling calls and closures, but is unsafe
//! because it doesn’t check argument types.
//! - The [`low`](low/index.html) layer makes no attempts at safety,
//! - The [`mod@low`] layer makes no attempts at safety,
//! but provides a more idiomatically “Rusty” API than the underlying
//! C library.
//! - The [`raw`](raw/index.html) layer is a re-export of the
//! - The [`mod@raw`] layer is a re-export of the
//! [`libffi-sys`](https://crates.io/crates/libffi-sys) crate,
//! a direct mapping of the C libffi library into Rust, generated by
//! [bindgen](https://crates.io/crates/bindgen).
Expand Down
65 changes: 32 additions & 33 deletions libffi-rs/src/low.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
//!
//! This module also re-exports types and constants necessary for using the
//! library, so it should not be generally necessary to use the `raw` module.
//! While this is a bit “Rustier” than [`raw`](../raw/index.html), I’ve
//! While this is a bit “Rustier” than [`raw`](crate::raw), I’ve
//! avoided drastic renaming in favor of hewing close to the libffi API.
//! See [`middle`](../middle/index.html) for an easier-to-use approach.
//! See [`middle`](crate::middle) for an easier-to-use approach.

use std::mem;
use std::os::raw::{c_uint, c_void};
Expand All @@ -21,7 +21,7 @@ pub enum Error {
Abi,
}

/// The `Result` type specialized for libffi `Error`s.
/// The [`std::result::Result`] type specialized for libffi [`Error`]s.
pub type Result<T> = ::std::result::Result<T, Error>;

// Converts the raw status type to a `Result`.
Expand Down Expand Up @@ -122,12 +122,12 @@ impl CodePtr {

pub use raw::{ffi_abi, ffi_abi_FFI_DEFAULT_ABI, ffi_cif, ffi_closure, ffi_status, ffi_type};

/// Re-exports the `ffi_type` objects used to describe the types of
/// Re-exports the [`ffi_type`] objects used to describe the types of
/// arguments and results.
///
/// These are from [`raw`](../../raw/index.html), but are renamed by
/// removing the `ffi_type_` prefix. For example, `raw::ffi_type_void`
/// becomes `low::types::void`.
/// These are from [the raw layer](crate::raw), but are renamed by
/// removing the `ffi_type_` prefix. For example, [`raw::ffi_type_void`]
/// becomes [`types::void`].
pub mod types {
pub use crate::raw::{
ffi_type_double as double, ffi_type_float as float, ffi_type_pointer as pointer,
Expand All @@ -149,12 +149,12 @@ pub mod types {
pub use crate::raw::ffi_type_complex_longdouble as complex_longdouble;
}

/// Type tags used in constructing and inspecting `ffi_type`s.
/// Type tags used in constructing and inspecting [`ffi_type`]s.
///
/// For atomic types this tag doesn’t matter because libffi predeclares
/// [an instance of each one](types/index.html). However, for composite
/// [an instance of each one](mod@types). However, for composite
/// types (structs and complex numbers), we need to create a new
/// instance of the `ffi_type` struct. In particular, the `type_` field
/// instance of the [`ffi_type`] struct. In particular, the `type_` field
/// contains a value that indicates what kind of type is represented,
/// and we use these values to indicate that that we are describing a
/// struct or complex type.
Expand Down Expand Up @@ -207,7 +207,7 @@ pub mod type_tag {
/// We need to initialize a CIF before we can use it to call a function
/// or create a closure. This function lets us specify the calling
/// convention to use and the argument and result types. For varargs
/// CIF initialization, see [`prep_cif_var`](fn.prep_cif_var.html).
/// CIF initialization, see [`prep_cif_var`].
///
///
/// # Safety
Expand Down Expand Up @@ -260,7 +260,7 @@ pub unsafe fn prep_cif(
/// We need to initialize a CIF before we can use it to call a function
/// or create a closure. This function lets us specify the calling
/// convention to use and the argument and result types. For non-varargs
/// CIF initialization, see [`prep_cif`](fn.prep_cif.html).
/// CIF initialization, see [`prep_cif`].
///
/// # Safety
///
Expand Down Expand Up @@ -354,10 +354,9 @@ pub unsafe fn call<R>(cif: *mut ffi_cif, fun: CodePtr, args: *mut *mut c_void) -
/// pointer for calling it. The former acts as a handle to the closure,
/// and is used to configure and free it. The latter is the code pointer
/// used to invoke the closure. Before it can be invoked, it must be
/// initialized with [`prep_closure`](fn.prep_closure.html) and
/// [`prep_closure_mut`](fn.prep_closure_mut.html). The closure must be
/// deallocated using [`closure_free`](fn.closure_free.html), after
/// which point the code pointer should not be used.
/// initialized with [`prep_closure`] and [`prep_closure_mut`]. The
/// closure must be deallocated using [`closure_free`], after which
/// point the code pointer should not be used.
///
/// # Examples
///
Expand All @@ -380,8 +379,8 @@ pub fn closure_alloc() -> (*mut ffi_closure, CodePtr) {

/// Frees a closure.
///
/// Closures allocated with [`closure_alloc`](fn.closure_alloc.html)
/// must be deallocated with `closure_free`.
/// Closures allocated with [`closure_alloc`] must be deallocated with
/// [`closure_free`].
///
/// # Examples
///
Expand Down Expand Up @@ -420,7 +419,7 @@ pub type CallbackMut<U, R> = unsafe extern "C" fn(
userdata: &mut U,
);

/// The callback type expected by `raw::ffi_prep_closure_loc`.
/// The callback type expected by [`raw::ffi_prep_closure_loc`].
pub type RawCallback = unsafe extern "C" fn(
cif: *mut ffi_cif,
result: *mut c_void,
Expand All @@ -430,13 +429,13 @@ pub type RawCallback = unsafe extern "C" fn(

/// Initializes a closure with a callback function and userdata.
///
/// After allocating a closure with
/// [`closure_alloc`](fn.closure_alloc.html), it needs to be initialized
/// with a function `callback` to call and a pointer `userdata` to pass
/// to it. Invoking the closure’s code pointer will then pass the provided
/// arguments and the user data pointer to the callback.
/// After allocating a closure with [`closure_alloc`], it needs to be
/// initialized with a function `callback` to call and a pointer
/// `userdata` to pass to it. Invoking the closure’s code pointer will
/// then pass the provided arguments and the user data pointer to the
/// callback.
///
/// For mutable userdata use [`prep_closure_mut`](fn.prep_closure_mut.html).
/// For mutable userdata use [`prep_closure_mut`].
///
/// # Safety
///
Expand All @@ -452,7 +451,7 @@ pub type RawCallback = unsafe extern "C" fn(
/// - `userdata` — the closed-over value, stored in the closure and
/// passed to the callback upon invocation
/// - `code` — the closure’s code pointer, *i.e.*, the second component
/// returned by [`closure_alloc`](fn.closure_alloc.html).
/// returned by [`closure_alloc`].
///
/// # Result
///
Expand Down Expand Up @@ -522,13 +521,13 @@ pub unsafe fn prep_closure<U, R>(
/// Initializes a mutable closure with a callback function and (mutable)
/// userdata.
///
/// After allocating a closure with
/// [`closure_alloc`](fn.closure_alloc.html), it needs to be initialized
/// with a function `callback` to call and a pointer `userdata` to pass
/// to it. Invoking the closure’s code pointer will then pass the provided
/// arguments and the user data pointer to the callback.
/// After allocating a closure with [`closure_alloc`], it needs to be
/// initialized with a function `callback` to call and a pointer
/// `userdata` to pass to it. Invoking the closure’s code pointer will
/// then pass the provided arguments and the user data pointer to the
/// callback.
///
/// For immutable userdata use [`prep_closure`](fn.prep_closure.html).
/// For immutable userdata use [`prep_closure`].
///
/// # Safety
///
Expand All @@ -544,7 +543,7 @@ pub unsafe fn prep_closure<U, R>(
/// - `userdata` — the closed-over value, stored in the closure and
/// passed to the callback upon invocation
/// - `code` — the closure’s code pointer, *i.e.*, the second component
/// returned by [`closure_alloc`](fn.closure_alloc.html).
/// returned by [`closure_alloc`].
///
/// # Result
///
Expand Down
22 changes: 11 additions & 11 deletions libffi-rs/src/middle/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ use super::types::Type;

/// Provides a builder-style API for constructing CIFs and closures.
///
/// To use a builder, first construct it using [`Builder::new`](#method.new).
/// The default calling convention is `ffi_abi_FFI_DEFAULT_ABI`, and the default
/// function type is `extern "C" fn()` (or in C, `void(*)()`). Add
/// argument types to the function type with the [`arg`](#method.arg)
/// and [`args`](#method.args) methods. Set the result type with
/// [`res`](#method.res). Change the calling convention, if necessary,
/// with [`abi`](#method.abi).
/// To use a builder, first construct it using [`Builder::new`]. The
/// default calling convention is
/// [`ffi_abi_FFI_DEFAULT_ABI`](crate::low::ffi_abi_FFI_DEFAULT_ABI),
/// and the default function type is `extern "C" fn()` (or in C,
/// `void(*)()`). Add argument types to the function type with the
/// [`Builder::arg`] and [`args`](Builder::args) methods. Set the result type
/// with [`Builder::res`]. Change the calling convention, if necessary,
/// with [`Builder::abi`].
///
/// Once the builder is configured, construct a `Cif` with
/// [`into_cif`](#method.into_cif) or a closure with
/// [`into_closure`](#method.into_closure),
/// [`into_closure_mut`](#method.into_closure_mut), or
/// [`into_closure_once`](#method.into_closure_once).
/// [`Builder::into_cif`] or a closure with [`Builder::into_closure`],
/// [`into_closure_mut`](Builder::into_closure_mut), or
/// [`into_closure_once`](Builder::into_closure_once).
///
/// # Examples
///
Expand Down
Loading