Skip to content

Commit 082c3bd

Browse files
committed
Use NonNull for Secp256k1 inner context field
For raw pointers that can never be null Rust provides the `core::ptr::NonNull` type. Our `Secp256k1` type has an inner field that is a non-null pointer; use `NonNull` for it. Fix: #534
1 parent 3760ef6 commit 082c3bd

File tree

6 files changed

+69
-40
lines changed

6 files changed

+69
-40
lines changed

src/context.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use core::marker::PhantomData;
22
use core::mem::ManuallyDrop;
3+
use core::ptr::NonNull;
34

45
#[cfg(feature = "alloc")]
56
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
@@ -116,6 +117,7 @@ mod private {
116117
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
117118
mod alloc_only {
118119
use core::marker::PhantomData;
120+
use core::ptr::NonNull;
119121

120122
use super::private;
121123
use crate::alloc::alloc;
@@ -209,7 +211,10 @@ mod alloc_only {
209211
#[allow(unused_mut)] // ctx is not mutated under some feature combinations.
210212
let mut ctx = Secp256k1 {
211213
ctx: unsafe {
212-
ffi::secp256k1_context_preallocated_create(ptr as *mut c_void, C::FLAGS)
214+
NonNull::new_unchecked(ffi::secp256k1_context_preallocated_create(
215+
ptr as *mut c_void,
216+
C::FLAGS,
217+
))
213218
},
214219
phantom: PhantomData,
215220
};
@@ -261,15 +266,18 @@ mod alloc_only {
261266

262267
impl<C: Context> Clone for Secp256k1<C> {
263268
fn clone(&self) -> Secp256k1<C> {
264-
let size = unsafe { ffi::secp256k1_context_preallocated_clone_size(self.ctx as _) };
269+
let size = unsafe { ffi::secp256k1_context_preallocated_clone_size(self.ctx.as_ptr()) };
265270
let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
266271
let ptr = unsafe { alloc::alloc(layout) };
267272
if ptr.is_null() {
268273
alloc::handle_alloc_error(layout);
269274
}
270275
Secp256k1 {
271276
ctx: unsafe {
272-
ffi::secp256k1_context_preallocated_clone(self.ctx, ptr as *mut c_void)
277+
NonNull::new_unchecked(ffi::secp256k1_context_preallocated_clone(
278+
self.ctx.as_ptr(),
279+
ptr as *mut c_void,
280+
))
273281
},
274282
phantom: PhantomData,
275283
}
@@ -321,10 +329,10 @@ impl<'buf, C: Context + 'buf> Secp256k1<C> {
321329
}
322330
Ok(Secp256k1 {
323331
ctx: unsafe {
324-
ffi::secp256k1_context_preallocated_create(
332+
NonNull::new_unchecked(ffi::secp256k1_context_preallocated_create(
325333
buf.as_mut_c_ptr() as *mut c_void,
326334
C::FLAGS,
327-
)
335+
))
328336
},
329337
phantom: PhantomData,
330338
})
@@ -355,7 +363,7 @@ impl<'buf> Secp256k1<AllPreallocated<'buf>> {
355363
pub unsafe fn from_raw_all(
356364
raw_ctx: *mut ffi::Context,
357365
) -> ManuallyDrop<Secp256k1<AllPreallocated<'buf>>> {
358-
ManuallyDrop::new(Secp256k1 { ctx: raw_ctx, phantom: PhantomData })
366+
ManuallyDrop::new(Secp256k1 { ctx: NonNull::new_unchecked(raw_ctx), phantom: PhantomData })
359367
}
360368
}
361369

@@ -386,7 +394,7 @@ impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
386394
pub unsafe fn from_raw_signing_only(
387395
raw_ctx: *mut ffi::Context,
388396
) -> ManuallyDrop<Secp256k1<SignOnlyPreallocated<'buf>>> {
389-
ManuallyDrop::new(Secp256k1 { ctx: raw_ctx, phantom: PhantomData })
397+
ManuallyDrop::new(Secp256k1 { ctx: NonNull::new_unchecked(raw_ctx), phantom: PhantomData })
390398
}
391399
}
392400

@@ -417,6 +425,6 @@ impl<'buf> Secp256k1<VerifyOnlyPreallocated<'buf>> {
417425
pub unsafe fn from_raw_verification_only(
418426
raw_ctx: *mut ffi::Context,
419427
) -> ManuallyDrop<Secp256k1<VerifyOnlyPreallocated<'buf>>> {
420-
ManuallyDrop::new(Secp256k1 { ctx: raw_ctx, phantom: PhantomData })
428+
ManuallyDrop::new(Secp256k1 { ctx: NonNull::new_unchecked(raw_ctx), phantom: PhantomData })
421429
}
422430
}

src/ecdsa/mod.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ impl<C: Signing> Secp256k1<C> {
258258
// an invalid signature from a valid `Message` and `SecretKey`
259259
assert_eq!(
260260
ffi::secp256k1_ecdsa_sign(
261-
self.ctx,
261+
self.ctx.as_ptr(),
262262
&mut ret,
263263
msg.as_c_ptr(),
264264
sk.as_c_ptr(),
@@ -307,7 +307,7 @@ impl<C: Signing> Secp256k1<C> {
307307
// an invalid signature from a valid `Message` and `SecretKey`
308308
assert_eq!(
309309
ffi::secp256k1_ecdsa_sign(
310-
self.ctx,
310+
self.ctx.as_ptr(),
311311
&mut ret,
312312
msg.as_c_ptr(),
313313
sk.as_c_ptr(),
@@ -388,8 +388,12 @@ impl<C: Verification> Secp256k1<C> {
388388
pk: &PublicKey,
389389
) -> Result<(), Error> {
390390
unsafe {
391-
if ffi::secp256k1_ecdsa_verify(self.ctx, sig.as_c_ptr(), msg.as_c_ptr(), pk.as_c_ptr())
392-
== 0
391+
if ffi::secp256k1_ecdsa_verify(
392+
self.ctx.as_ptr(),
393+
sig.as_c_ptr(),
394+
msg.as_c_ptr(),
395+
pk.as_c_ptr(),
396+
) == 0
393397
{
394398
Err(Error::IncorrectSignature)
395399
} else {

src/ecdsa/recovery.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ impl<C: Signing> Secp256k1<C> {
158158
// an invalid signature from a valid `Message` and `SecretKey`
159159
assert_eq!(
160160
ffi::secp256k1_ecdsa_sign_recoverable(
161-
self.ctx,
161+
self.ctx.as_ptr(),
162162
&mut ret,
163163
msg.as_c_ptr(),
164164
sk.as_c_ptr(),
@@ -208,7 +208,12 @@ impl<C: Verification> Secp256k1<C> {
208208
) -> Result<key::PublicKey, Error> {
209209
unsafe {
210210
let mut pk = super_ffi::PublicKey::new();
211-
if ffi::secp256k1_ecdsa_recover(self.ctx, &mut pk, sig.as_c_ptr(), msg.as_c_ptr()) != 1
211+
if ffi::secp256k1_ecdsa_recover(
212+
self.ctx.as_ptr(),
213+
&mut pk,
214+
sig.as_c_ptr(),
215+
msg.as_c_ptr(),
216+
) != 1
212217
{
213218
return Err(Error::InvalidSignature);
214219
}

src/key.rs

+21-12
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ impl PublicKey {
459459
let mut pk = ffi::PublicKey::new();
460460
// We can assume the return value because it's not possible to construct
461461
// an invalid `SecretKey` without transmute trickery or something.
462-
let res = ffi::secp256k1_ec_pubkey_create(secp.ctx, &mut pk, sk.as_c_ptr());
462+
let res = ffi::secp256k1_ec_pubkey_create(secp.ctx.as_ptr(), &mut pk, sk.as_c_ptr());
463463
debug_assert_eq!(res, 1);
464464
PublicKey(pk)
465465
}
@@ -575,7 +575,7 @@ impl PublicKey {
575575
#[must_use = "you forgot to use the negated public key"]
576576
pub fn negate<C: Verification>(mut self, secp: &Secp256k1<C>) -> PublicKey {
577577
unsafe {
578-
let res = ffi::secp256k1_ec_pubkey_negate(secp.ctx, &mut self.0);
578+
let res = ffi::secp256k1_ec_pubkey_negate(secp.ctx.as_ptr(), &mut self.0);
579579
debug_assert_eq!(res, 1);
580580
}
581581
self
@@ -593,7 +593,9 @@ impl PublicKey {
593593
tweak: &Scalar,
594594
) -> Result<PublicKey, Error> {
595595
unsafe {
596-
if ffi::secp256k1_ec_pubkey_tweak_add(secp.ctx, &mut self.0, tweak.as_c_ptr()) == 1 {
596+
if ffi::secp256k1_ec_pubkey_tweak_add(secp.ctx.as_ptr(), &mut self.0, tweak.as_c_ptr())
597+
== 1
598+
{
597599
Ok(self)
598600
} else {
599601
Err(Error::InvalidTweak)
@@ -613,7 +615,9 @@ impl PublicKey {
613615
other: &Scalar,
614616
) -> Result<PublicKey, Error> {
615617
unsafe {
616-
if ffi::secp256k1_ec_pubkey_tweak_mul(secp.ctx, &mut self.0, other.as_c_ptr()) == 1 {
618+
if ffi::secp256k1_ec_pubkey_tweak_mul(secp.ctx.as_ptr(), &mut self.0, other.as_c_ptr())
619+
== 1
620+
{
617621
Ok(self)
618622
} else {
619623
Err(Error::InvalidTweak)
@@ -817,7 +821,7 @@ impl KeyPair {
817821
pub fn from_secret_key<C: Signing>(secp: &Secp256k1<C>, sk: &SecretKey) -> KeyPair {
818822
unsafe {
819823
let mut kp = ffi::KeyPair::new();
820-
if ffi::secp256k1_keypair_create(secp.ctx, &mut kp, sk.as_c_ptr()) == 1 {
824+
if ffi::secp256k1_keypair_create(secp.ctx.as_ptr(), &mut kp, sk.as_c_ptr()) == 1 {
821825
KeyPair(kp)
822826
} else {
823827
panic!("the provided secret key is invalid: it is corrupted or was not produced by Secp256k1 library")
@@ -842,7 +846,7 @@ impl KeyPair {
842846

843847
unsafe {
844848
let mut kp = ffi::KeyPair::new();
845-
if ffi::secp256k1_keypair_create(secp.ctx, &mut kp, data.as_c_ptr()) == 1 {
849+
if ffi::secp256k1_keypair_create(secp.ctx.as_ptr(), &mut kp, data.as_c_ptr()) == 1 {
846850
Ok(KeyPair(kp))
847851
} else {
848852
Err(Error::InvalidSecretKey)
@@ -895,7 +899,9 @@ impl KeyPair {
895899
let mut data = crate::random_32_bytes(rng);
896900
unsafe {
897901
let mut keypair = ffi::KeyPair::new();
898-
while ffi::secp256k1_keypair_create(secp.ctx, &mut keypair, data.as_c_ptr()) == 0 {
902+
while ffi::secp256k1_keypair_create(secp.ctx.as_ptr(), &mut keypair, data.as_c_ptr())
903+
== 0
904+
{
899905
data = crate::random_32_bytes(rng);
900906
}
901907
KeyPair(keypair)
@@ -946,8 +952,11 @@ impl KeyPair {
946952
tweak: &Scalar,
947953
) -> Result<KeyPair, Error> {
948954
unsafe {
949-
let err =
950-
ffi::secp256k1_keypair_xonly_tweak_add(secp.ctx, &mut self.0, tweak.as_c_ptr());
955+
let err = ffi::secp256k1_keypair_xonly_tweak_add(
956+
secp.ctx.as_ptr(),
957+
&mut self.0,
958+
tweak.as_c_ptr(),
959+
);
951960
if err != 1 {
952961
return Err(Error::InvalidTweak);
953962
}
@@ -1243,7 +1252,7 @@ impl XOnlyPublicKey {
12431252
unsafe {
12441253
let mut pubkey = ffi::PublicKey::new();
12451254
let mut err = ffi::secp256k1_xonly_pubkey_tweak_add(
1246-
secp.ctx,
1255+
secp.ctx.as_ptr(),
12471256
&mut pubkey,
12481257
self.as_c_ptr(),
12491258
tweak.as_c_ptr(),
@@ -1253,7 +1262,7 @@ impl XOnlyPublicKey {
12531262
}
12541263

12551264
err = ffi::secp256k1_xonly_pubkey_from_pubkey(
1256-
secp.ctx,
1265+
secp.ctx.as_ptr(),
12571266
&mut self.0,
12581267
&mut pk_parity,
12591268
&pubkey,
@@ -1306,7 +1315,7 @@ impl XOnlyPublicKey {
13061315
let tweaked_ser = tweaked_key.serialize();
13071316
unsafe {
13081317
let err = ffi::secp256k1_xonly_pubkey_tweak_add_check(
1309-
secp.ctx,
1318+
secp.ctx.as_ptr(),
13101319
tweaked_ser.as_c_ptr(),
13111320
tweaked_parity.to_i32(),
13121321
&self.0,

src/lib.rs

+15-12
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ pub mod schnorr;
180180
mod serde_util;
181181

182182
use core::marker::PhantomData;
183+
use core::ptr::NonNull;
183184
use core::{fmt, mem, str};
184185

185186
#[cfg(feature = "bitcoin-hashes")]
@@ -369,7 +370,7 @@ impl std::error::Error for Error {
369370

370371
/// The secp256k1 engine, used to execute all signature operations.
371372
pub struct Secp256k1<C: Context> {
372-
ctx: *mut ffi::Context,
373+
ctx: NonNull<ffi::Context>,
373374
phantom: PhantomData<C>,
374375
}
375376

@@ -387,9 +388,10 @@ impl<C: Context> Eq for Secp256k1<C> {}
387388
impl<C: Context> Drop for Secp256k1<C> {
388389
fn drop(&mut self) {
389390
unsafe {
390-
let size = ffi::secp256k1_context_preallocated_clone_size(self.ctx);
391-
ffi::secp256k1_context_preallocated_destroy(self.ctx);
392-
C::deallocate(self.ctx as _, size);
391+
let size = ffi::secp256k1_context_preallocated_clone_size(self.ctx.as_ptr());
392+
ffi::secp256k1_context_preallocated_destroy(self.ctx.as_ptr());
393+
394+
C::deallocate(self.ctx.as_ptr() as _, size);
393395
}
394396
}
395397
}
@@ -405,7 +407,7 @@ impl<C: Context> Secp256k1<C> {
405407
/// shouldn't be needed with normal usage of the library. It enables
406408
/// extending the Secp256k1 with more cryptographic algorithms outside of
407409
/// this crate.
408-
pub fn ctx(&self) -> &*mut ffi::Context { &self.ctx }
410+
pub fn ctx(&self) -> NonNull<ffi::Context> { self.ctx }
409411

410412
/// Returns the required memory for a preallocated context buffer in a generic manner(sign/verify/all).
411413
pub fn preallocate_size_gen() -> usize {
@@ -432,7 +434,7 @@ impl<C: Context> Secp256k1<C> {
432434
/// see comment in libsecp256k1 commit d2275795f by Gregory Maxwell.
433435
pub fn seeded_randomize(&mut self, seed: &[u8; 32]) {
434436
unsafe {
435-
let err = ffi::secp256k1_context_randomize(self.ctx, seed.as_c_ptr());
437+
let err = ffi::secp256k1_context_randomize(self.ctx.as_ptr(), seed.as_c_ptr());
436438
// This function cannot fail; it has an error return for future-proofing.
437439
// We do not expose this error since it is impossible to hit, and we have
438440
// precedent for not exposing impossible errors (for example in
@@ -556,11 +558,12 @@ mod tests {
556558
let ctx_sign = unsafe { ffi::secp256k1_context_create(SignOnlyPreallocated::FLAGS) };
557559
let ctx_vrfy = unsafe { ffi::secp256k1_context_create(VerifyOnlyPreallocated::FLAGS) };
558560

559-
let full: Secp256k1<AllPreallocated> = Secp256k1 { ctx: ctx_full, phantom: PhantomData };
561+
let full: Secp256k1<AllPreallocated> =
562+
Secp256k1 { ctx: unsafe { NonNull::new_unchecked(ctx_full) }, phantom: PhantomData };
560563
let sign: Secp256k1<SignOnlyPreallocated> =
561-
Secp256k1 { ctx: ctx_sign, phantom: PhantomData };
564+
Secp256k1 { ctx: unsafe { NonNull::new_unchecked(ctx_sign) }, phantom: PhantomData };
562565
let vrfy: Secp256k1<VerifyOnlyPreallocated> =
563-
Secp256k1 { ctx: ctx_vrfy, phantom: PhantomData };
566+
Secp256k1 { ctx: unsafe { NonNull::new_unchecked(ctx_vrfy) }, phantom: PhantomData };
564567

565568
let (sk, pk) = full.generate_keypair(&mut rand::thread_rng());
566569
let msg = Message::from_slice(&[2u8; 32]).unwrap();
@@ -590,9 +593,9 @@ mod tests {
590593
let ctx_sign = Secp256k1::signing_only();
591594
let ctx_vrfy = Secp256k1::verification_only();
592595

593-
let mut full = unsafe { Secp256k1::from_raw_all(ctx_full.ctx) };
594-
let mut sign = unsafe { Secp256k1::from_raw_signing_only(ctx_sign.ctx) };
595-
let mut vrfy = unsafe { Secp256k1::from_raw_verification_only(ctx_vrfy.ctx) };
596+
let mut full = unsafe { Secp256k1::from_raw_all(ctx_full.ctx.as_ptr()) };
597+
let mut sign = unsafe { Secp256k1::from_raw_signing_only(ctx_sign.ctx.as_ptr()) };
598+
let mut vrfy = unsafe { Secp256k1::from_raw_verification_only(ctx_vrfy.ctx.as_ptr()) };
596599

597600
let (sk, pk) = full.generate_keypair(&mut rand::thread_rng());
598601
let msg = Message::from_slice(&[2u8; 32]).unwrap();

src/schnorr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ impl<C: Signing> Secp256k1<C> {
107107
assert_eq!(
108108
1,
109109
ffi::secp256k1_schnorrsig_sign(
110-
self.ctx,
110+
self.ctx.as_ptr(),
111111
sig.as_mut_c_ptr(),
112112
msg.as_c_ptr(),
113113
keypair.as_c_ptr(),
@@ -168,7 +168,7 @@ impl<C: Verification> Secp256k1<C> {
168168
) -> Result<(), Error> {
169169
unsafe {
170170
let ret = ffi::secp256k1_schnorrsig_verify(
171-
self.ctx,
171+
self.ctx.as_ptr(),
172172
sig.as_c_ptr(),
173173
msg.as_c_ptr(),
174174
32,

0 commit comments

Comments
 (0)