Add AligneType and redo secp256k1_context_create with alloc

This commit is contained in:
Elichai Turkel 2020-08-28 13:58:07 +03:00
parent 11e9641d21
commit 7b99784837
No known key found for this signature in database
GPG Key ID: 9383CDE9E8E66A7F
3 changed files with 45 additions and 20 deletions

View File

@ -21,6 +21,9 @@ features = [ "recovery", "endomorphism", "lowmemory" ]
[build-dependencies]
cc = "1.0.28"
[dev-dependencies]
libc = "0.2"
[features]
default = ["std"]
recovery = []

View File

@ -534,19 +534,21 @@ extern "C" {
#[no_mangle]
#[cfg(all(feature = "std", not(feature = "external-symbols")))]
pub unsafe extern "C" fn rustsecp256k1_v0_3_1_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>());
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>());
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)
// 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")))]
@ -563,13 +565,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_3_1_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")))]

View File

@ -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;
@ -26,11 +26,30 @@ 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 currently 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 {
AlignedType([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() {
@ -38,6 +57,8 @@ mod tests {
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>());
}
}