Fix verify data free function

Turns out this is called with a null pointer if you never set the data
which didn't end up doing anything until the recent zeroing drop
changes.

Also use a map of indexes since statics in generic functions don't
monomorphize
This commit is contained in:
Steven Fackler 2015-03-29 10:18:30 -07:00
parent c315e05368
commit 2b1a9a7814
3 changed files with 29 additions and 23 deletions

View File

@ -21,10 +21,9 @@ path = "../openssl-sys"
version = "0.5.2" version = "0.5.2"
[dependencies] [dependencies]
bitflags = "0.1.1"
lazy_static = "0.1"
libc = "0.1" libc = "0.1"
[dev-dependencies] [dev-dependencies]
rustc-serialize = "0.3" rustc-serialize = "0.3"
[dependencies]
bitflags = "0.1.1"

View File

@ -1,15 +1,16 @@
#![feature(unsafe_destructor, core, io, std_misc, unique)] #![feature(unsafe_destructor, core, io, std_misc, unique, collections)]
#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/openssl")] #![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/openssl")]
#[macro_use] #[macro_use]
extern crate bitflags; extern crate bitflags;
extern crate libc; extern crate libc;
#[macro_use]
extern crate lazy_static;
extern crate openssl_sys as ffi;
#[cfg(test)] #[cfg(test)]
extern crate rustc_serialize as serialize; extern crate rustc_serialize as serialize;
extern crate openssl_sys as ffi;
mod macros; mod macros;
pub mod asn1; pub mod asn1;

View File

@ -1,4 +1,6 @@
use libc::{c_int, c_void, c_long}; use libc::{c_int, c_void, c_long};
use std::any::TypeId;
use std::collections::HashMap;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::fmt; use std::fmt;
use std::io; use std::io;
@ -10,9 +12,10 @@ use std::num::FromPrimitive;
use std::num::Int; use std::num::Int;
use std::path::Path; use std::path::Path;
use std::ptr; use std::ptr;
use std::sync::{Once, ONCE_INIT, Arc}; use std::sync::{Once, ONCE_INIT, Arc, Mutex};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::cmp; use std::cmp;
use std::marker::Reflect;
#[cfg(feature = "npn")] #[cfg(feature = "npn")]
use libc::{c_uchar, c_uint}; use libc::{c_uchar, c_uint};
#[cfg(feature = "npn")] #[cfg(feature = "npn")]
@ -124,29 +127,30 @@ pub enum SslVerifyMode {
SslVerifyNone = ffi::SSL_VERIFY_NONE SslVerifyNone = ffi::SSL_VERIFY_NONE
} }
lazy_static! {
static ref INDEXES: Mutex<HashMap<TypeId, c_int>> = Mutex::new(HashMap::new());
}
// Creates a static index for user data of type T // Creates a static index for user data of type T
// Registers a destructor for the data which will be called // Registers a destructor for the data which will be called
// when context is freed // when context is freed
fn get_verify_data_idx<T>() -> c_int { fn get_verify_data_idx<T: Reflect + 'static>() -> c_int {
static mut VERIFY_DATA_IDX: c_int = -1;
static mut INIT: Once = ONCE_INIT;
extern fn free_data_box<T>(_parent: *mut c_void, ptr: *mut c_void, extern fn free_data_box<T>(_parent: *mut c_void, ptr: *mut c_void,
_ad: *mut ffi::CRYPTO_EX_DATA, _idx: c_int, _ad: *mut ffi::CRYPTO_EX_DATA, _idx: c_int,
_argl: c_long, _argp: *mut c_void) { _argl: c_long, _argp: *mut c_void) {
let _: Box<T> = unsafe { mem::transmute(ptr) }; if ptr != 0 as *mut _ {
let _: Box<T> = unsafe { mem::transmute(ptr) };
}
} }
unsafe { *INDEXES.lock().unwrap().entry(TypeId::of::<T>()).or_insert_with(|| {
INIT.call_once(|| { unsafe {
let f: ffi::CRYPTO_EX_free = free_data_box::<T>; let f: ffi::CRYPTO_EX_free = free_data_box::<T>;
let idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, let idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, Some(f));
None, Some(f));
assert!(idx >= 0); assert!(idx >= 0);
VERIFY_DATA_IDX = idx; idx
}); }
VERIFY_DATA_IDX })
}
} }
/// Creates a static index for the list of NPN protocols. /// Creates a static index for the list of NPN protocols.
@ -196,7 +200,8 @@ extern fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX)
} }
extern fn raw_verify_with_data<T>(preverify_ok: c_int, extern fn raw_verify_with_data<T>(preverify_ok: c_int,
x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int { x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int
where T: Reflect + 'static {
unsafe { unsafe {
let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx(); let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx();
let ssl = ffi::X509_STORE_CTX_get_ex_data(x509_ctx, idx); let ssl = ffi::X509_STORE_CTX_get_ex_data(x509_ctx, idx);
@ -352,7 +357,8 @@ impl SslContext {
// a function handling it // a function handling it
pub fn set_verify_with_data<T>(&mut self, mode: SslVerifyMode, pub fn set_verify_with_data<T>(&mut self, mode: SslVerifyMode,
verify: VerifyCallbackData<T>, verify: VerifyCallbackData<T>,
data: T) { data: T)
where T: Reflect + 'static {
let data = Box::new(data); let data = Box::new(data);
unsafe { unsafe {
ffi::SSL_CTX_set_ex_data(*self.ctx, VERIFY_IDX, ffi::SSL_CTX_set_ex_data(*self.ctx, VERIFY_IDX,