diff --git a/src/context.rs b/src/context.rs index 460ac52a2..ef7b1d6ed 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,8 +1,7 @@ use core::marker::PhantomData; use core::mem::{self, ManuallyDrop}; -use ffi::{self, CPtr, types::AlignedType}; +use ffi::{self, types::AlignedType}; use ffi::types::{c_uint, c_void}; -use Error; use Secp256k1; #[cfg(feature = "std")] @@ -232,28 +231,31 @@ unsafe impl<'buf> Context for AllPreallocated<'buf> { impl<'buf, C: Context + 'buf> Secp256k1 { /// Lets you create a context with preallocated buffer in a generic manner(sign/verify/all) - pub fn preallocated_gen_new(buf: &'buf mut [u8]) -> Result, Error> { + /// + /// # Safety + /// * The pointer must be valid for [`preallocate_size_gen()`](#method.preallocated_gen_new) bytes + /// * The pointer must be as aligned as [`ffi::types::AlignedType`](../secp256k1-sys/src/types.html#AlignedType) + /// * The pointer must be writeable. + pub unsafe fn preallocated_gen_new(buf: *mut c_void) -> Secp256k1 { #[cfg(target_arch = "wasm32")] ffi::types::sanity_checks_for_wasm(); - if buf.len() < Self::preallocate_size_gen() { - return Err(Error::NotEnoughMemory); - } - Ok(Secp256k1 { - ctx: unsafe { - ffi::secp256k1_context_preallocated_create( - buf.as_mut_c_ptr() as *mut c_void, - C::FLAGS) - }, + Secp256k1 { + ctx: ffi::secp256k1_context_preallocated_create(buf, C::FLAGS), phantom: PhantomData, size: 0, // We don't care about the size because it's the caller responsibility to deallocate. - }) + } } } impl<'buf> Secp256k1> { /// Creates a new Secp256k1 context with all capabilities - pub fn preallocated_new(buf: &'buf mut [u8]) -> Result>, Error> { + /// + /// # Safety + /// * The pointer must be valid for [`preallocate_size()`](#method.preallocate_size) bytes + /// * The pointer must be as aligned as [`ffi::types::AlignedType`](../secp256k1-sys/src/types.html#AlignedType) + /// * The pointer must be writeable. + pub unsafe fn preallocated_new(buf: *mut c_void) -> Secp256k1> { Secp256k1::preallocated_gen_new(buf) } /// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for a context @@ -283,7 +285,12 @@ impl<'buf> Secp256k1> { impl<'buf> Secp256k1> { /// Creates a new Secp256k1 context that can only be used for signing - pub fn preallocated_signing_only(buf: &'buf mut [u8]) -> Result>, Error> { + /// + /// # Safety + /// * The pointer must be valid for [`preallocate_size_gen()`](#method.preallocate_size_gen) bytes + /// * The pointer must be as aligned as [`ffi::types::AlignedType`](../secp256k1-sys/src/types.html#AlignedType) + /// * The pointer must be writeable. + pub unsafe fn preallocated_signing_only(buf: *mut c_void) -> Secp256k1> { Secp256k1::preallocated_gen_new(buf) } @@ -315,7 +322,12 @@ impl<'buf> Secp256k1> { impl<'buf> Secp256k1> { /// Creates a new Secp256k1 context that can only be used for verification - pub fn preallocated_verification_only(buf: &'buf mut [u8]) -> Result>, Error> { + /// + /// # Safety + /// * The pointer must be valid for [`preallocate_verification_size()`](#method.preallocate_verification_size) bytes + /// * The pointer must be as aligned as [`ffi::types::AlignedType`](../secp256k1-sys/src/types.html#AlignedType) + /// * The pointer must be writeable. + pub unsafe fn preallocated_verification_only(buf: *mut c_void) -> Secp256k1> { Secp256k1::preallocated_gen_new(buf) } diff --git a/src/lib.rs b/src/lib.rs index dcbd1af35..5fa66d645 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -548,8 +548,6 @@ pub enum Error { InvalidRecoveryId, /// Invalid tweak for add_*_assign or mul_*_assign InvalidTweak, - /// Didn't pass enough memory to context creation with preallocated memory - NotEnoughMemory, } impl Error { @@ -562,7 +560,6 @@ impl Error { Error::InvalidSecretKey => "secp: malformed or out-of-range secret key", Error::InvalidRecoveryId => "secp: bad recovery id", Error::InvalidTweak => "secp: bad tweak", - Error::NotEnoughMemory => "secp: not enough memory allocated", } } } @@ -788,6 +785,7 @@ fn from_hex(hex: &str, target: &mut [u8]) -> Result { mod tests { use rand::{RngCore, thread_rng}; use std::str::FromStr; + use std::alloc::{alloc, dealloc, Layout}; use std::marker::PhantomData; use key::{SecretKey, PublicKey}; @@ -795,7 +793,7 @@ mod tests { use super::constants; use super::{Secp256k1, Signature, Message}; use super::Error::{InvalidMessage, IncorrectSignature, InvalidSignature}; - use ffi; + use ffi::{self, types::AlignedType}; use context::*; macro_rules! hex { @@ -872,13 +870,17 @@ mod tests { #[test] fn test_preallocation() { - let mut buf_ful = vec![0u8; Secp256k1::preallocate_size()]; - let mut buf_sign = vec![0u8; Secp256k1::preallocate_signing_size()]; - let mut buf_vfy = vec![0u8; Secp256k1::preallocate_verification_size()]; -// - let full = Secp256k1::preallocated_new(&mut buf_ful).unwrap(); - let sign = Secp256k1::preallocated_signing_only(&mut buf_sign).unwrap(); - let vrfy = Secp256k1::preallocated_verification_only(&mut buf_vfy).unwrap(); + const ALIGN_TO: usize = std::mem::align_of::(); + let ful_layout = Layout::from_size_align(Secp256k1::preallocate_size(), ALIGN_TO).unwrap(); + let sign_layout = Layout::from_size_align(Secp256k1::preallocate_signing_size(), ALIGN_TO).unwrap(); + let vrf_layout = Layout::from_size_align(Secp256k1::preallocate_verification_size(), ALIGN_TO).unwrap(); + let buf_ful = unsafe { alloc(ful_layout) }; + let buf_sign = unsafe { alloc(sign_layout) }; + let buf_vfy = unsafe { alloc(vrf_layout)} ; + + let full = unsafe { Secp256k1::preallocated_new(buf_ful as _) }; + let sign = unsafe { Secp256k1::preallocated_signing_only(buf_sign as _) }; + let vrfy = unsafe { Secp256k1::preallocated_verification_only(buf_vfy as _) }; // drop(buf_vfy); // The buffer can't get dropped before the context. // println!("{:?}", buf_ful[5]); // Can't even read the data thanks to the borrow checker. @@ -892,6 +894,11 @@ mod tests { // Try verifying assert!(vrfy.verify(&msg, &sig, &pk).is_ok()); assert!(full.verify(&msg, &sig, &pk).is_ok()); + unsafe { + dealloc(buf_ful, ful_layout); + dealloc(buf_sign, sign_layout); + dealloc(buf_vfy, vrf_layout); + } } #[test]