Added a C Ptr trait that returns a null pointer for ZSTs

This commit is contained in:
Elichai Turkel 2019-08-16 14:48:03 -04:00
parent a055c3fdc0
commit 66ab70f991
No known key found for this signature in database
GPG Key ID: 9383CDE9E8E66A7F
5 changed files with 95 additions and 2 deletions

View File

@ -16,7 +16,7 @@
//! # FFI bindings
//! Direct bindings to the underlying C library functions. These should
//! not be needed for most users.
use core::{mem, hash, slice};
use core::{mem, hash, slice, ptr};
use types::*;
/// Flag for context to enable no precomputation
@ -366,6 +366,38 @@ unsafe fn strlen(mut str_ptr: *const c_char) -> usize {
}
/// A trait for producing pointers that will always be valid in C. (assuming NULL pointer is a valid no-op)
/// Rust doesn't promise what pointers does it give to ZST (https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts)
/// In case the type is empty this trait will give a NULL pointer, which should be handled in C.
///
pub(crate) trait CPtr {
type Target;
fn as_c_ptr(&self) -> *const Self::Target;
fn as_mut_c_ptr(&mut self) -> *mut Self::Target;
}
impl<T> CPtr for [T] {
type Target = T;
fn as_c_ptr(&self) -> *const Self::Target {
if self.is_empty() {
ptr::null()
} else {
self.as_ptr()
}
}
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
if self.is_empty() {
ptr::null::<Self::Target>() as *mut _
} else {
self.as_mut_ptr()
}
}
}
#[cfg(feature = "fuzztarget")]
mod fuzz_dummy {
extern crate std;

View File

@ -24,7 +24,7 @@ use super::Error::{self, InvalidPublicKey, InvalidSecretKey};
use Signing;
use Verification;
use constants;
use ffi;
use ffi::{self, CPtr};
/// Secret 256-bit key used as `x` in an ECDSA signature
pub struct SecretKey([u8; constants::SECRET_KEY_SIZE]);
@ -355,6 +355,18 @@ impl PublicKey {
}
}
impl CPtr for PublicKey {
type Target = ffi::PublicKey;
fn as_c_ptr(&self) -> *const Self::Target {
self.as_ptr()
}
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
self.as_mut_ptr()
}
}
/// Creates a new public key from a FFI public key
impl From<ffi::PublicKey> for PublicKey {
#[inline]

View File

@ -161,6 +161,7 @@ pub use key::PublicKey;
pub use context::*;
use core::marker::PhantomData;
use core::ops::Deref;
use ffi::CPtr;
/// An ECDSA signature
#[derive(Copy, Clone, PartialEq, Eq)]
@ -380,6 +381,17 @@ impl Signature {
}
}
impl CPtr for Signature {
type Target = ffi::Signature;
fn as_c_ptr(&self) -> *const Self::Target {
self.as_ptr()
}
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
self.as_mut_ptr()
}
}
/// Creates a new signature from a FFI signature
impl From<ffi::Signature> for Signature {
#[inline]

View File

@ -122,6 +122,24 @@ macro_rules! impl_array_newtype {
&dat[..]
}
}
impl ::ffi::CPtr for $thing {
type Target = $ty;
fn as_c_ptr(&self) -> *const Self::Target {
if self.is_empty() {
::core::ptr::null()
} else {
self.as_ptr()
}
}
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
if self.is_empty() {
::core::ptr::null::<Self::Target>() as *mut _
} else {
self.as_mut_ptr()
}
}
}
}
}

View File

@ -23,6 +23,7 @@ use super::{Secp256k1, Message, Error, Signature, Verification, Signing};
use super::ffi as super_ffi;
pub use key::SecretKey;
pub use key::PublicKey;
use self::super_ffi::CPtr;
mod ffi;
@ -82,6 +83,12 @@ impl RecoverableSignature {
&self.0 as *const _
}
/// Obtains a raw mutable pointer suitable for use with FFI functions
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut ffi::RecoverableSignature {
&mut self.0 as *mut _
}
#[inline]
/// Serializes the recoverable signature in compact format
pub fn serialize_compact(&self) -> (RecoveryId, [u8; 64]) {
@ -116,6 +123,18 @@ impl RecoverableSignature {
}
}
impl CPtr for RecoverableSignature {
type Target = ffi::RecoverableSignature;
fn as_c_ptr(&self) -> *const Self::Target {
self.as_ptr()
}
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
self.as_mut_ptr()
}
}
/// Creates a new recoverable signature from a FFI one
impl From<ffi::RecoverableSignature> for RecoverableSignature {
#[inline]