Skip to content

Commit

Permalink
Add AligneType and redo secp256k1_context_create with alloc
Browse files Browse the repository at this point in the history
  • Loading branch information
elichai committed Aug 28, 2020
1 parent b2e315f commit a00cb2a
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 21 deletions.
3 changes: 3 additions & 0 deletions secp256k1-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ features = [ "recovery", "endomorphism", "lowmemory" ]
[build-dependencies]
cc = "1.0.28"

[dev-dependencies]
libc = "0.2"

[lib]
name = "secp256k1_sys"
path = "src/lib.rs"
Expand Down
39 changes: 20 additions & 19 deletions secp256k1-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,19 +324,21 @@ extern "C" {
#[no_mangle]
#[cfg(all(feature = "std", not(feature = "external-symbols")))]
pub unsafe extern "C" fn rustsecp256k1_v0_2_0_context_create(flags: c_uint) -> *mut Context {
use std::mem;
assert!(mem::align_of::<usize>() >= mem::align_of::<u8>());
assert_eq!(mem::size_of::<usize>(), mem::size_of::<&usize>());

let word_size = mem::size_of::<usize>();
let n_words = (secp256k1_context_preallocated_size(flags) + word_size - 1) / word_size;

let buf = vec![0usize; n_words + 1].into_boxed_slice();
let ptr = Box::into_raw(buf) as *mut usize;
::core::ptr::write(ptr, n_words);
let ptr: *mut usize = ptr.offset(1);

secp256k1_context_preallocated_create(ptr as *mut c_void, flags)
use core::mem;
use std::alloc;
assert!(ALIGN_TO >= mem::align_of::<usize>());
assert!(ALIGN_TO >= mem::align_of::<&usize>());
assert!(ALIGN_TO >= mem::size_of::<usize>());

// We need to allocate `ALIGN_TO` more bytes in order to write the amount of bytes back.
let bytes = secp256k1_context_preallocated_size(flags) + ALIGN_TO;
let layout = alloc::Layout::from_size_align(bytes, ALIGN_TO).unwrap();
let ptr = alloc::alloc(layout);
(ptr as *mut usize).write(bytes);
// We must offset a whole ALIGN_TO in order to preserve the same alignment
// this means we "lose" ALIGN_TO-size_of(usize) for padding.
let ptr = ptr.add(ALIGN_TO) as *mut c_void;
secp256k1_context_preallocated_create(ptr, flags)
}

#[cfg(all(feature = "std", not(feature = "external-symbols")))]
Expand All @@ -353,13 +355,12 @@ pub unsafe fn secp256k1_context_create(flags: c_uint) -> *mut Context {
#[no_mangle]
#[cfg(all(feature = "std", not(feature = "external-symbols")))]
pub unsafe extern "C" fn rustsecp256k1_v0_2_0_context_destroy(ctx: *mut Context) {
use std::alloc;
secp256k1_context_preallocated_destroy(ctx);
let ctx: *mut usize = ctx as *mut usize;

let n_words_ptr: *mut usize = ctx.offset(-1);
let n_words: usize = ::core::ptr::read(n_words_ptr);
let slice: &mut [usize] = slice::from_raw_parts_mut(n_words_ptr , n_words+1);
let _ = Box::from_raw(slice as *mut [usize]);
let ptr = (ctx as *mut u8).sub(ALIGN_TO);
let bytes = (ptr as *mut usize).read();
let layout = alloc::Layout::from_size_align(bytes, ALIGN_TO).unwrap();
alloc::dealloc(ptr, layout);
}

#[cfg(all(feature = "std", not(feature = "external-symbols")))]
Expand Down
25 changes: 23 additions & 2 deletions secp256k1-sys/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![allow(non_camel_case_types)]
use core::fmt;
use core::{fmt, mem};

pub type c_int = i32;
pub type c_uchar = u8;
Expand All @@ -26,18 +26,39 @@ impl fmt::Debug for c_void {
}
}

/// A type that is as aligned as the biggest alignment for fundamental types in C
/// since C11 that means as aligned as `max_align_t` is.
/// the exact size/alignment is unspecified.
// 16 matches is as big as the biggest alignment in any arch that rust supports https://github.com/rust-lang/rust/blob/2c31b45ae878b821975c4ebd94cc1e49f6073fd0/library/std/src/sys_common/alloc.rs
#[repr(align(16))]
#[derive(Default, Copy, Clone)]
pub struct AlignedType([u8; 16]);

impl AlignedType {
pub fn zeroed() -> Self {
Self([0u8; 16])
}
}

pub(crate) const ALIGN_TO: usize = mem::align_of::<AlignedType>();


#[cfg(test)]
mod tests {
extern crate libc;
use std::os::raw;
use std::mem;
use std::any::TypeId;
use types;
use {types, AlignedType};

#[test]
fn verify_types() {
assert_eq!(TypeId::of::<types::c_int>(), TypeId::of::<raw::c_int>());
assert_eq!(TypeId::of::<types::c_uchar>(), TypeId::of::<raw::c_uchar>());
assert_eq!(TypeId::of::<types::c_uint>(), TypeId::of::<raw::c_uint>());
assert_eq!(TypeId::of::<types::c_char>(), TypeId::of::<raw::c_char>());

assert!(mem::align_of::<AlignedType>() >= mem::align_of::<self::libc::max_align_t>());
}
}

Expand Down

0 comments on commit a00cb2a

Please sign in to comment.