Skip to content

Commit

Permalink
Merge pull request sfackler#1359 from stbuehler/const-ptr-api-macro
Browse files Browse the repository at this point in the history
Add and use const_ptr_api macro in openssl-sys
  • Loading branch information
sfackler committed Oct 25, 2020
2 parents e796b76 + 1dbeb8c commit f958176
Show file tree
Hide file tree
Showing 10 changed files with 395 additions and 441 deletions.
12 changes: 3 additions & 9 deletions openssl-sys/src/asn1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,8 @@ extern "C" {
pub fn ASN1_TIME_set_string_X509(s: *mut ASN1_TIME, str: *const c_char) -> c_int;
}

cfg_if! {
if #[cfg(any(ossl110, libressl280))] {
extern "C" {
pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_uchar, s: *const ASN1_STRING) -> c_int;
}
} else {
extern "C" {
pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_uchar, s: *mut ASN1_STRING) -> c_int;
}
const_ptr_api! {
extern "C" {
pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_uchar, s: #[const_ptr_if(any(ossl110, libressl280))] ASN1_STRING) -> c_int;
}
}
39 changes: 8 additions & 31 deletions openssl-sys/src/bio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,10 @@ pub unsafe fn BIO_get_mem_data(b: *mut BIO, pp: *mut *mut c_char) -> c_long {
BIO_ctrl(b, BIO_CTRL_INFO, 0, pp as *mut c_void)
}

cfg_if! {
if #[cfg(any(ossl110, libressl280))] {
extern "C" {
pub fn BIO_s_file() -> *const BIO_METHOD;
pub fn BIO_new(type_: *const BIO_METHOD) -> *mut BIO;
}
} else {
extern "C" {
pub fn BIO_s_file() -> *mut BIO_METHOD;
pub fn BIO_new(type_: *mut BIO_METHOD) -> *mut BIO;
}
const_ptr_api! {
extern "C" {
pub fn BIO_s_file() -> #[const_ptr_if(any(ossl110, libressl280))] BIO_METHOD;
pub fn BIO_new(type_: #[const_ptr_if(any(ossl110, libressl280))] BIO_METHOD) -> *mut BIO;
}
}
extern "C" {
Expand All @@ -88,26 +81,10 @@ extern "C" {
pub fn BIO_free_all(b: *mut BIO);
}

cfg_if! {
if #[cfg(any(ossl110, libressl280))] {
extern "C" {
pub fn BIO_s_mem() -> *const BIO_METHOD;
}
} else {
extern "C" {
pub fn BIO_s_mem() -> *mut BIO_METHOD;
}
}
}
cfg_if! {
if #[cfg(any(ossl102, libressl280))] {
extern "C" {
pub fn BIO_new_mem_buf(buf: *const c_void, len: c_int) -> *mut BIO;
}
} else {
extern "C" {
pub fn BIO_new_mem_buf(buf: *mut c_void, len: c_int) -> *mut BIO;
}
const_ptr_api! {
extern "C" {
pub fn BIO_s_mem() -> #[const_ptr_if(any(ossl110, libressl280))] BIO_METHOD;
pub fn BIO_new_mem_buf(buf: #[const_ptr_if(any(ossl102, libressl280))] c_void, len: c_int) -> *mut BIO;
}
}

Expand Down
60 changes: 16 additions & 44 deletions openssl-sys/src/evp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,9 @@ extern "C" {
outl: *mut c_int,
) -> c_int;
}
cfg_if! {
if #[cfg(any(ossl111b, libressl280))] {
extern "C" {
pub fn EVP_PKEY_size(pkey: *const EVP_PKEY) -> c_int;
}
} else {
extern "C" {
pub fn EVP_PKEY_size(pkey: *mut EVP_PKEY) -> c_int;
}
const_ptr_api! {
extern "C" {
pub fn EVP_PKEY_size(pkey: #[const_ptr_if(any(ossl111b, libressl280))] EVP_PKEY) -> c_int;
}
}
cfg_if! {
Expand All @@ -206,23 +200,13 @@ cfg_if! {
}
}
}
cfg_if! {
if #[cfg(any(ossl102, libressl280))] {
extern "C" {
pub fn EVP_DigestVerifyFinal(
ctx: *mut EVP_MD_CTX,
sigret: *const c_uchar,
siglen: size_t,
) -> c_int;
}
} else {
extern "C" {
pub fn EVP_DigestVerifyFinal(
ctx: *mut EVP_MD_CTX,
sigret: *mut c_uchar,
siglen: size_t,
) -> c_int;
}
const_ptr_api! {
extern "C" {
pub fn EVP_DigestVerifyFinal(
ctx: *mut EVP_MD_CTX,
sigret: #[const_ptr_if(any(ossl102, libressl280))] c_uchar,
siglen: size_t,
) -> c_int;
}
}

Expand Down Expand Up @@ -317,15 +301,9 @@ extern "C" {

pub fn EVP_PKEY_id(pkey: *const EVP_PKEY) -> c_int;
}
cfg_if! {
if #[cfg(any(ossl110, libressl280))] {
extern "C" {
pub fn EVP_PKEY_bits(key: *const EVP_PKEY) -> c_int;
}
} else {
extern "C" {
pub fn EVP_PKEY_bits(key: *mut EVP_PKEY) -> c_int;
}
const_ptr_api! {
extern "C" {
pub fn EVP_PKEY_bits(key: #[const_ptr_if(any(ossl110, libressl280))] EVP_PKEY) -> c_int;
}
}
extern "C" {
Expand Down Expand Up @@ -456,15 +434,9 @@ extern "C" {
) -> c_int;
}

cfg_if! {
if #[cfg(any(ossl110, libressl280))] {
extern "C" {
pub fn EVP_PKCS82PKEY(p8: *const PKCS8_PRIV_KEY_INFO) -> *mut EVP_PKEY;
}
} else {
extern "C" {
pub fn EVP_PKCS82PKEY(p8: *mut PKCS8_PRIV_KEY_INFO) -> *mut EVP_PKEY;
}
const_ptr_api! {
extern "C" {
pub fn EVP_PKCS82PKEY(p8: #[const_ptr_if(any(ossl110, libressl280))] PKCS8_PRIV_KEY_INFO) -> *mut EVP_PKEY;
}
}

Expand Down
1 change: 1 addition & 0 deletions openssl-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
unused_imports
)]
#![doc(html_root_url = "https://docs.rs/openssl-sys/0.9")]
#![recursion_limit = "128"] // configure fixed limit across all rust versions

extern crate libc;

Expand Down
209 changes: 209 additions & 0 deletions openssl-sys/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,212 @@ macro_rules! const_fn {
)*
}
}

// openssl changes `*mut` to `*const` in certain parameters in certain versions;
// in C this is ABI and (mostly) API compatible.
//
// We need to handle this explicitly, and this macro helps annotate which
// parameter got converted in which version.
//
// Input is:
// extern "C" {
// #[attributes...]
// pub fn name(args) -> rettype; // `-> rettype` optional
// // more functions...
// }
//
// This macro replaces `#[const_ptr_if(...)]` in types with `*const` or `*mut`
// (depending on the inner cfg flags)
//
// Walks through all argument and return types, but only finds inner types of
// `*const` and `*mut`; doesn't walk arrays or generics.
//
// NOTE: can't abstract `pub` as `$fn_vis:vis`, as ctest macro handling doesn't
// support it (old syntax crate). But we really only need `pub` anyway.
//
// NOTE: ctest seams to simply ignore macros it can't expand (whatever the
// reason)
macro_rules! const_ptr_api {
// ----------------------------------------------------------------
// (partialarg): partial argument, waiting for "final" argument type
// MAGIC PART 1: hande conditional const ptr in argument type
( (partialarg)
{ $(#[$fn_attr:meta])* pub fn $fn_name:ident }
$args_packed:tt
[ $($part_arg:tt)* ]
[ #[const_ptr_if( $($cfg:tt)* )] $($arg_rem:tt)* ]
$ret_packed:tt
) => {
const_ptr_api!( (partialarg) { #[cfg($($cfg)*)] $(#[$fn_attr])* pub fn $fn_name } $args_packed [ $($part_arg)* *const ] [ $($arg_rem)* ] $ret_packed );
const_ptr_api!( (partialarg) { #[cfg(not($($cfg)*))] $(#[$fn_attr])* pub fn $fn_name } $args_packed [ $($part_arg)* *mut ] [ $($arg_rem)* ] $ret_packed );
};
// continue partial argument with `*mut` pointer (might need special const handling in inner type)
( (partialarg)
$def_packed:tt
$args_packed:tt
[ $($part_arg:tt)* ]
[ *mut $($arg_rem:tt)* ]
$ret_packed:tt
) => {
const_ptr_api!( (partialarg) $def_packed $args_packed [ $($part_arg)* *mut ] [ $($arg_rem)* ] $ret_packed );
};
// continue partial argument with `*const` pointer (might need special const handling in inner type)
( (partialarg)
$def_packed:tt
$args_packed:tt
[ $($part_arg:tt)* ]
[ *const $($arg_rem:tt)* ]
$ret_packed:tt
) => {
const_ptr_api!( (partialarg) $def_packed $args_packed [ $($part_arg)* *const ] [ $($arg_rem)* ] $ret_packed );
};
// finish partial argument with trailing comma
( (partialarg)
$def_packed:tt
{ $($args_tt:tt)* }
[ $($part_arg:tt)* ]
[ $arg_ty:ty, $($arg_rem:tt)* ]
$ret_packed:tt
) => {
const_ptr_api!( (parseargs) $def_packed { $($args_tt)* { $($part_arg)* $arg_ty } } [ $($arg_rem)* ] $ret_packed );
};
// finish final partial argument (no trailing comma)
( (partialarg)
$def_packed:tt
{ $($args_tt:tt)* }
[ $($part_arg:tt)* ]
[ $arg_ty:ty ]
$ret_packed:tt
) => {
const_ptr_api!( (parseargs) $def_packed { $($args_tt)* { $($part_arg)* $arg_ty } } [ ] $ret_packed );
};

// ----------------------------------------------------------------
// (parseargs): parsing arguments
// start next argument
( (parseargs)
$def_packed:tt
$args_packed:tt
[ $arg_name:ident : $($arg_rem:tt)* ]
$ret_packed:tt
) => {
const_ptr_api!( (partialarg) $def_packed $args_packed [ $arg_name: ] [ $($arg_rem)* ] $ret_packed );
};
// end of arguments, there is a return type; start parsing it
( (parseargs)
$def_packed:tt
$args_packed:tt
[ ]
[ -> $($rem:tt)* ]
) => {
const_ptr_api!( (partialret) $def_packed $args_packed [] [ $($rem)* ] );
};
// end of arguments, no return type
( (parseargs)
$def_packed:tt
$args_packed:tt
[ ]
[ ]
) => {
const_ptr_api!( (generate) $def_packed $args_packed { () } );
};

// ----------------------------------------------------------------
// (partialret): have partial return type, waiting for final return type
// MAGIC PART 2: hande conditional const ptr in return type
( (partialret)
{ $(#[$fn_attr:meta])* pub fn $fn_name:ident }
$args_packed:tt
[ $($part_ret:tt)* ]
[ #[const_ptr_if( $($cfg:tt)* )] $($rem:tt)* ]
) => {
const_ptr_api!( (partialret) { #[cfg($($cfg)*)] $(#[$fn_attr])* pub fn $fn_name } $args_packed [ $($part_ret)* *const ] [ $($rem)* ] );
const_ptr_api!( (partialret) { #[cfg(not($($cfg)*))] $(#[$fn_attr])* pub fn $fn_name } $args_packed [ $($part_ret)* *mut ] [ $($rem)* ] );
};
// `* mut` part in return type; continue parsing to find inner conditional const ptr
( (partialret)
$def_packed:tt
$args_packed:tt
[ $($part_ret:tt)* ]
[ *mut $($rem:tt)* ]
) => {
const_ptr_api!( (partialret) $def_packed $args_packed [ $($part_ret)* *mut ] [ $($rem)* ] );
};
// `* const` part in return type; continue parsing to find inner conditional const ptr
( (partialret)
$def_packed:tt
$args_packed:tt
[ $($part_ret:tt)* ]
[ *const $($rem:tt)* ]
) => {
const_ptr_api!( (partialret) $def_packed $args_packed [ $($part_ret)* *const ] [ $($rem)* ] );
};
// final part of return type
( (partialret)
$def_packed:tt
$args_packed:tt
[ $($part_ret:tt)* ]
[ $ret_ty:ty ]
) => {
const_ptr_api!( (generate) $def_packed $args_packed { $($part_ret)* $ret_ty } );
};

// ----------------------------------------------------------------
// generate
( (generate)
{ $(#[$fn_attr:meta])* pub fn $fn_name:ident }
{ $({ $arg_name:ident: $($arg_ty:tt)* })* }
{ $ret_ty:ty }
) => {
extern "C" {
$(#[$fn_attr])*
pub fn $fn_name( $(
$arg_name: $($arg_ty)*
),* ) -> $ret_ty;
}
};

// ----------------------------------------------------------------
// (fn): gather tokens for return type until ";"
// found end; start parsing current function, and parse remaining functions
( (fn)
$def_packed:tt
$arg_tts_packed:tt
$ret_packed:tt
[ ; $($rem:tt)* ]
) => {
const_ptr_api!( (parseargs) $def_packed {} $arg_tts_packed $ret_packed );
const_ptr_api!( (extern) [ $($rem)* ] );
};
// not ";" - all other tokens are part of the return type.
// don't expand return type yet; otherwise we'd have to remember in which branch `rem` needs
// to be used to parse further functions.
( (fn)
$def_packed:tt
$arg_tts_packed:tt
[ $($ret_tt:tt)* ]
[ $tt:tt $($rem:tt)* ]
) => {
const_ptr_api!( (fn) $def_packed $arg_tts_packed [ $($ret_tt)* $tt ] [ $($rem)* ] );
};

// ----------------------------------------------------------------
// (extern): in extern block, find next function
// try to split into functions as fast as possible to reduce recursion depth
( (extern) [
$(#[$fn_attr:meta])*
pub fn $fn_name:ident( $($arg_rem:tt)* ) $($rem:tt)*
] ) => {
const_ptr_api!( (fn)
{ $(#[$fn_attr])* pub fn $fn_name } [ $($arg_rem)* ] [] [ $($rem)* ]
);
};
// end of extern block
( (extern) [] ) => {};

// ----------------------------------------------------------------
// macro start; find extern block
( extern "C" { $($rem:tt)* } ) => {
const_ptr_api!( (extern) [ $($rem)* ] );
};
}

0 comments on commit f958176

Please sign in to comment.