diff options
| author | Jonas Schievink <[email protected]> | 2016-06-13 21:47:02 +0200 |
|---|---|---|
| committer | Jonas Schievink <[email protected]> | 2016-06-26 18:25:54 +0200 |
| commit | f0b4a032d5a6cdf3928318e113dcfd7e0ecf03f9 (patch) | |
| tree | c72ab006de830f2cbcab2e479344bc928149268a /openssl/src | |
| parent | Add PKey::private_key_from_pem_cb (diff) | |
| download | rust-openssl-f0b4a032d5a6cdf3928318e113dcfd7e0ecf03f9.tar.xz rust-openssl-f0b4a032d5a6cdf3928318e113dcfd7e0ecf03f9.zip | |
Try to propagate callback panics
Diffstat (limited to 'openssl/src')
| -rw-r--r-- | openssl/src/crypto/pkey.rs | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index f59ee40a..8ae9aa20 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -1,9 +1,10 @@ use libc::{c_int, c_uint, c_ulong, c_char, c_void}; +use std::any::Any; use std::io; use std::io::prelude::*; use std::iter::repeat; use std::mem; -use std::panic::catch_unwind; +use std::panic; use std::ptr; use std::slice; use bio::MemBio; @@ -100,21 +101,26 @@ impl PKey { /// /// The callback will be passed the password buffer and should return the number of characters /// placed into the buffer. - pub fn private_key_from_pem_cb<R, F>(reader: &mut R, mut pass_cb: F) -> Result<PKey, SslError> + pub fn private_key_from_pem_cb<R, F>(reader: &mut R, pass_cb: F) -> Result<PKey, SslError> where R: Read, F: FnMut(&mut [i8]) -> usize { + struct CallbackState<F: FnMut(&mut [i8]) -> usize> { + cb: F, + panic: Option<Box<Any + Send + 'static>>, + } + extern "C" fn user_cb_wrapper<F>(buf: *mut c_char, size: c_int, _rwflag: c_int, user_cb: *mut c_void) -> c_int where F: FnMut(&mut [i8]) -> usize { - let result = catch_unwind(|| { + let result = panic::catch_unwind(|| { // build a `i8` slice to pass to the user callback let pass_slice = unsafe { slice::from_raw_parts_mut(buf, size as usize) }; - let callback = unsafe { &mut *(user_cb as *mut F) }; + let callback = unsafe { &mut *(user_cb as *mut CallbackState<F>) }; - callback(pass_slice) + (callback.cb)(pass_slice) }); if let Ok(len) = result { @@ -124,6 +130,11 @@ impl PKey { } } + let mut cb = CallbackState { + cb: pass_cb, + panic: None, + }; + let mut mem_bio = try!(MemBio::new()); try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); @@ -131,7 +142,11 @@ impl PKey { let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(), ptr::null_mut(), Some(user_cb_wrapper::<F>), - &mut pass_cb as *mut _ as *mut c_void)); + &mut cb as *mut _ as *mut c_void)); + + if let Some(panic) = cb.panic { + panic::resume_unwind(panic); + } Ok(PKey { evp: evp as *mut ffi::EVP_PKEY, |