Skip to content

Commit 66ab70f

Browse files
committed
Added a C Ptr trait that returns a null pointer for ZSTs
1 parent a055c3f commit 66ab70f

File tree

5 files changed

+95
-2
lines changed

5 files changed

+95
-2
lines changed

src/ffi.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
//! # FFI bindings
1717
//! Direct bindings to the underlying C library functions. These should
1818
//! not be needed for most users.
19-
use core::{mem, hash, slice};
19+
use core::{mem, hash, slice, ptr};
2020
use types::*;
2121

2222
/// Flag for context to enable no precomputation
@@ -366,6 +366,38 @@ unsafe fn strlen(mut str_ptr: *const c_char) -> usize {
366366
}
367367

368368

369+
/// A trait for producing pointers that will always be valid in C. (assuming NULL pointer is a valid no-op)
370+
/// Rust doesn't promise what pointers does it give to ZST (https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts)
371+
/// In case the type is empty this trait will give a NULL pointer, which should be handled in C.
372+
///
373+
pub(crate) trait CPtr {
374+
type Target;
375+
fn as_c_ptr(&self) -> *const Self::Target;
376+
fn as_mut_c_ptr(&mut self) -> *mut Self::Target;
377+
}
378+
379+
impl<T> CPtr for [T] {
380+
type Target = T;
381+
fn as_c_ptr(&self) -> *const Self::Target {
382+
if self.is_empty() {
383+
ptr::null()
384+
} else {
385+
self.as_ptr()
386+
}
387+
}
388+
389+
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
390+
if self.is_empty() {
391+
ptr::null::<Self::Target>() as *mut _
392+
} else {
393+
self.as_mut_ptr()
394+
}
395+
}
396+
}
397+
398+
399+
400+
369401
#[cfg(feature = "fuzztarget")]
370402
mod fuzz_dummy {
371403
extern crate std;

src/key.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use super::Error::{self, InvalidPublicKey, InvalidSecretKey};
2424
use Signing;
2525
use Verification;
2626
use constants;
27-
use ffi;
27+
use ffi::{self, CPtr};
2828

2929
/// Secret 256-bit key used as `x` in an ECDSA signature
3030
pub struct SecretKey([u8; constants::SECRET_KEY_SIZE]);
@@ -355,6 +355,18 @@ impl PublicKey {
355355
}
356356
}
357357

358+
impl CPtr for PublicKey {
359+
type Target = ffi::PublicKey;
360+
fn as_c_ptr(&self) -> *const Self::Target {
361+
self.as_ptr()
362+
}
363+
364+
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
365+
self.as_mut_ptr()
366+
}
367+
}
368+
369+
358370
/// Creates a new public key from a FFI public key
359371
impl From<ffi::PublicKey> for PublicKey {
360372
#[inline]

src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ pub use key::PublicKey;
161161
pub use context::*;
162162
use core::marker::PhantomData;
163163
use core::ops::Deref;
164+
use ffi::CPtr;
164165

165166
/// An ECDSA signature
166167
#[derive(Copy, Clone, PartialEq, Eq)]
@@ -380,6 +381,17 @@ impl Signature {
380381
}
381382
}
382383

384+
impl CPtr for Signature {
385+
type Target = ffi::Signature;
386+
fn as_c_ptr(&self) -> *const Self::Target {
387+
self.as_ptr()
388+
}
389+
390+
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
391+
self.as_mut_ptr()
392+
}
393+
}
394+
383395
/// Creates a new signature from a FFI signature
384396
impl From<ffi::Signature> for Signature {
385397
#[inline]

src/macros.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,24 @@ macro_rules! impl_array_newtype {
122122
&dat[..]
123123
}
124124
}
125+
impl ::ffi::CPtr for $thing {
126+
type Target = $ty;
127+
fn as_c_ptr(&self) -> *const Self::Target {
128+
if self.is_empty() {
129+
::core::ptr::null()
130+
} else {
131+
self.as_ptr()
132+
}
133+
}
134+
135+
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
136+
if self.is_empty() {
137+
::core::ptr::null::<Self::Target>() as *mut _
138+
} else {
139+
self.as_mut_ptr()
140+
}
141+
}
142+
}
125143
}
126144
}
127145

src/recovery/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use super::{Secp256k1, Message, Error, Signature, Verification, Signing};
2323
use super::ffi as super_ffi;
2424
pub use key::SecretKey;
2525
pub use key::PublicKey;
26+
use self::super_ffi::CPtr;
2627

2728
mod ffi;
2829

@@ -82,6 +83,12 @@ impl RecoverableSignature {
8283
&self.0 as *const _
8384
}
8485

86+
/// Obtains a raw mutable pointer suitable for use with FFI functions
87+
#[inline]
88+
pub fn as_mut_ptr(&mut self) -> *mut ffi::RecoverableSignature {
89+
&mut self.0 as *mut _
90+
}
91+
8592
#[inline]
8693
/// Serializes the recoverable signature in compact format
8794
pub fn serialize_compact(&self) -> (RecoveryId, [u8; 64]) {
@@ -116,6 +123,18 @@ impl RecoverableSignature {
116123
}
117124
}
118125

126+
127+
impl CPtr for RecoverableSignature {
128+
type Target = ffi::RecoverableSignature;
129+
fn as_c_ptr(&self) -> *const Self::Target {
130+
self.as_ptr()
131+
}
132+
133+
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
134+
self.as_mut_ptr()
135+
}
136+
}
137+
119138
/// Creates a new recoverable signature from a FFI one
120139
impl From<ffi::RecoverableSignature> for RecoverableSignature {
121140
#[inline]

0 commit comments

Comments
 (0)