diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 000000000..ead90b492 --- /dev/null +++ b/clippy.toml @@ -0,0 +1,4 @@ +disallowed-methods = [ + { path = "std::slice::from_raw_parts", reason = "use util::from_raw_parts instead" }, + { path = "std::slice::from_raw_parts_mut", reason = "use util::from_raw_parts_mut instead" }, +] diff --git a/openssl/src/asn1.rs b/openssl/src/asn1.rs index 8618be0e9..03340820d 100644 --- a/openssl/src/asn1.rs +++ b/openssl/src/asn1.rs @@ -32,7 +32,6 @@ use std::convert::TryInto; use std::ffi::CString; use std::fmt; use std::ptr; -use std::slice; use std::str; use crate::bio::MemBio; @@ -41,7 +40,7 @@ use crate::error::ErrorStack; use crate::nid::Nid; use crate::stack::Stackable; use crate::string::OpensslString; -use crate::{cvt, cvt_p}; +use crate::{cvt, cvt_p, util}; use openssl_macros::corresponds; foreign_type_and_impl_send_sync! { @@ -457,7 +456,7 @@ impl Asn1StringRef { /// [`as_utf8`]: struct.Asn1String.html#method.as_utf8 #[corresponds(ASN1_STRING_get0_data)] pub fn as_slice(&self) -> &[u8] { - unsafe { slice::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr()), self.len()) } + unsafe { util::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr()), self.len()) } } /// Returns the number of bytes in the string. @@ -597,7 +596,7 @@ impl Asn1BitStringRef { /// Returns the Asn1BitString as a slice. #[corresponds(ASN1_STRING_get0_data)] pub fn as_slice(&self) -> &[u8] { - unsafe { slice::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr() as *mut _), self.len()) } + unsafe { util::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr() as *mut _), self.len()) } } /// Returns the number of bytes in the string. @@ -637,7 +636,7 @@ impl Asn1OctetStringRef { /// Returns the octet string as an array of bytes. #[corresponds(ASN1_STRING_get0_data)] pub fn as_slice(&self) -> &[u8] { - unsafe { slice::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr().cast()), self.len()) } + unsafe { util::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr().cast()), self.len()) } } /// Returns the number of bytes in the octet string. @@ -701,7 +700,7 @@ impl Asn1Object { pub fn as_slice(&self) -> &[u8] { unsafe { let len = ffi::OBJ_length(self.as_ptr()); - slice::from_raw_parts(ffi::OBJ_get0_data(self.as_ptr()), len) + util::from_raw_parts(ffi::OBJ_get0_data(self.as_ptr()), len) } } } diff --git a/openssl/src/bio.rs b/openssl/src/bio.rs index 1595f89f1..d5232d2ee 100644 --- a/openssl/src/bio.rs +++ b/openssl/src/bio.rs @@ -2,10 +2,10 @@ use cfg_if::cfg_if; use libc::c_int; use std::marker::PhantomData; use std::ptr; -use std::slice; use crate::cvt_p; use crate::error::ErrorStack; +use crate::util; pub struct MemBioSlice<'a>(*mut ffi::BIO, PhantomData<&'a [u8]>); @@ -63,11 +63,7 @@ impl MemBio { unsafe { let mut ptr = ptr::null_mut(); let len = ffi::BIO_get_mem_data(self.0, &mut ptr); - if len == 0 { - &[] - } else { - slice::from_raw_parts(ptr as *const _ as *const _, len as usize) - } + util::from_raw_parts(ptr as *const _ as *const _, len as usize) } } diff --git a/openssl/src/ssl/bio.rs b/openssl/src/ssl/bio.rs index a5561dc72..16485624f 100644 --- a/openssl/src/ssl/bio.rs +++ b/openssl/src/ssl/bio.rs @@ -9,10 +9,9 @@ use std::io; use std::io::prelude::*; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::ptr; -use std::slice; -use crate::cvt_p; use crate::error::ErrorStack; +use crate::{cvt_p, util}; pub struct StreamState { pub stream: S, @@ -89,7 +88,7 @@ unsafe extern "C" fn bwrite(bio: *mut BIO, buf: *const c_char, len: c_ BIO_clear_retry_flags(bio); let state = state::(bio); - let buf = slice::from_raw_parts(buf as *const _, len as usize); + let buf = util::from_raw_parts(buf as *const _, len as usize); match catch_unwind(AssertUnwindSafe(|| state.stream.write(buf))) { Ok(Ok(len)) => len as c_int, @@ -111,7 +110,7 @@ unsafe extern "C" fn bread(bio: *mut BIO, buf: *mut c_char, len: c_int) BIO_clear_retry_flags(bio); let state = state::(bio); - let buf = slice::from_raw_parts_mut(buf as *mut _, len as usize); + let buf = util::from_raw_parts_mut(buf as *mut _, len as usize); match catch_unwind(AssertUnwindSafe(|| state.stream.read(buf))) { Ok(Ok(len)) => len as c_int, diff --git a/openssl/src/ssl/callbacks.rs b/openssl/src/ssl/callbacks.rs index be8909ee4..ccf530850 100644 --- a/openssl/src/ssl/callbacks.rs +++ b/openssl/src/ssl/callbacks.rs @@ -10,7 +10,6 @@ use libc::{c_int, c_uchar, c_uint, c_void}; use std::ffi::CStr; use std::mem; use std::ptr; -use std::slice; #[cfg(any(ossl111, boringssl))] use std::str; use std::sync::Arc; @@ -28,6 +27,7 @@ use crate::ssl::{ }; #[cfg(ossl111)] use crate::ssl::{ClientHelloResponse, ExtensionContext}; +use crate::util; #[cfg(any(ossl111, boringssl))] use crate::util::ForeignTypeRefExt; #[cfg(ossl111)] @@ -85,9 +85,9 @@ where None }; // Give the callback mutable slices into which it can write the identity and psk. - let identity_sl = slice::from_raw_parts_mut(identity as *mut u8, max_identity_len as usize); + let identity_sl = util::from_raw_parts_mut(identity as *mut u8, max_identity_len as usize); #[allow(clippy::unnecessary_cast)] - let psk_sl = slice::from_raw_parts_mut(psk as *mut u8, max_psk_len as usize); + let psk_sl = util::from_raw_parts_mut(psk as *mut u8, max_psk_len as usize); match (*callback)(ssl, hint, identity_sl, psk_sl) { Ok(psk_len) => psk_len as u32, Err(e) => { @@ -126,7 +126,7 @@ where }; // Give the callback mutable slices into which it can write the psk. #[allow(clippy::unnecessary_cast)] - let psk_sl = slice::from_raw_parts_mut(psk as *mut u8, max_psk_len as usize); + let psk_sl = util::from_raw_parts_mut(psk as *mut u8, max_psk_len as usize); match (*callback)(ssl, identity, psk_sl) { Ok(psk_len) => psk_len as u32, Err(e) => { @@ -197,7 +197,7 @@ where .ex_data(SslContext::cached_ex_index::()) .expect("BUG: alpn callback missing") as *const F; #[allow(clippy::unnecessary_cast)] - let protos = slice::from_raw_parts(inbuf as *const u8, inlen as usize); + let protos = util::from_raw_parts(inbuf as *const u8, inlen as usize); match (*callback)(ssl, protos) { Ok(proto) => { @@ -416,7 +416,7 @@ where .ex_data(SslContext::cached_ex_index::()) .expect("BUG: get session callback missing") as *const F; #[allow(clippy::unnecessary_cast)] - let data = slice::from_raw_parts(data as *const u8, len as usize); + let data = util::from_raw_parts(data as *const u8, len as usize); match (*callback)(ssl, data) { Some(session) => { @@ -460,7 +460,7 @@ where .ex_data(SslContext::cached_ex_index::()) .expect("BUG: stateless cookie generate callback missing") as *const F; #[allow(clippy::unnecessary_cast)] - let slice = slice::from_raw_parts_mut(cookie as *mut u8, ffi::SSL_COOKIE_LENGTH as usize); + let slice = util::from_raw_parts_mut(cookie as *mut u8, ffi::SSL_COOKIE_LENGTH as usize); match (*callback)(ssl, slice) { Ok(len) => { *cookie_len = len as size_t; @@ -488,7 +488,7 @@ where .ex_data(SslContext::cached_ex_index::()) .expect("BUG: stateless cookie verify callback missing") as *const F; #[allow(clippy::unnecessary_cast)] - let slice = slice::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len); + let slice = util::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len); (*callback)(ssl, slice) as c_int } @@ -511,7 +511,7 @@ where // compatibility. See comments in dtls1.h. #[allow(clippy::unnecessary_cast)] let slice = - slice::from_raw_parts_mut(cookie as *mut u8, ffi::DTLS1_COOKIE_LENGTH as usize - 1); + util::from_raw_parts_mut(cookie as *mut u8, ffi::DTLS1_COOKIE_LENGTH as usize - 1); match (*callback)(ssl, slice) { Ok(len) => { *cookie_len = len as c_uint; @@ -551,7 +551,7 @@ where .expect("BUG: cookie verify callback missing") as *const F; #[allow(clippy::unnecessary_cast)] let slice = - slice::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len as usize); + util::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len as usize); (*callback)(ssl, slice) as c_int } } @@ -663,7 +663,7 @@ where .expect("BUG: custom ext parse callback missing") as *const F; let ectx = ExtensionContext::from_bits_truncate(context); #[allow(clippy::unnecessary_cast)] - let slice = slice::from_raw_parts(input as *const u8, inlen); + let slice = util::from_raw_parts(input as *const u8, inlen); let cert = if ectx.contains(ExtensionContext::TLS1_3_CERTIFICATE) { Some((chainidx, X509Ref::from_ptr(x))) } else { diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index a540d4146..322ca9541 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -77,6 +77,7 @@ use crate::ssl::bio::BioMethod; use crate::ssl::callbacks::*; use crate::ssl::error::InnerError; use crate::stack::{Stack, StackRef, Stackable}; +use crate::util; use crate::util::{ForeignTypeExt, ForeignTypeRefExt}; use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef}; #[cfg(any(ossl102, boringssl, libressl261))] @@ -101,7 +102,6 @@ use std::ops::{Deref, DerefMut}; use std::panic::resume_unwind; use std::path::Path; use std::ptr; -use std::slice; use std::str; use std::sync::{Arc, Mutex}; @@ -708,7 +708,7 @@ pub fn select_next_proto<'a>(server: &[u8], client: &'a [u8]) -> Option<&'a [u8] client.len() as c_uint, ); if r == ffi::OPENSSL_NPN_NEGOTIATED { - Some(slice::from_raw_parts(out as *const u8, outlen as usize)) + Some(util::from_raw_parts(out as *const u8, outlen as usize)) } else { None } @@ -2174,7 +2174,7 @@ impl SslSessionRef { let mut len = 0; let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len); #[allow(clippy::unnecessary_cast)] - slice::from_raw_parts(p as *const u8, len as usize) + util::from_raw_parts(p as *const u8, len as usize) } } @@ -2650,7 +2650,7 @@ impl SslRef { if data.is_null() { None } else { - Some(slice::from_raw_parts(data, len as usize)) + Some(util::from_raw_parts(data, len as usize)) } } } @@ -2928,7 +2928,7 @@ impl SslRef { if len < 0 { None } else { - Some(slice::from_raw_parts(p as *const u8, len as usize)) + Some(util::from_raw_parts(p as *const u8, len as usize)) } } } @@ -3099,7 +3099,7 @@ impl SslRef { if len == 0 { None } else { - Some(slice::from_raw_parts(ptr, len)) + Some(util::from_raw_parts(ptr, len)) } } } @@ -3118,7 +3118,7 @@ impl SslRef { if len == 0 { None } else { - Some(slice::from_raw_parts(ptr, len)) + Some(util::from_raw_parts(ptr, len)) } } } @@ -3137,7 +3137,7 @@ impl SslRef { if len == 0 { None } else { - Some(slice::from_raw_parts(ptr, len)) + Some(util::from_raw_parts(ptr, len)) } } } @@ -3191,7 +3191,7 @@ impl SslRef { if len == 0 { None } else { - Some(slice::from_raw_parts(ptr, len)) + Some(util::from_raw_parts(ptr, len)) } } } @@ -3764,7 +3764,7 @@ impl SslStream { pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result { // SAFETY: `ssl_read_uninit` does not de-initialize the buffer. unsafe { - self.ssl_read_uninit(slice::from_raw_parts_mut( + self.ssl_read_uninit(util::from_raw_parts_mut( buf.as_mut_ptr().cast::>(), buf.len(), )) @@ -3997,7 +3997,7 @@ impl Read for SslStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { // SAFETY: `read_uninit` does not de-initialize the buffer unsafe { - self.read_uninit(slice::from_raw_parts_mut( + self.read_uninit(util::from_raw_parts_mut( buf.as_mut_ptr().cast::>(), buf.len(), )) diff --git a/openssl/src/util.rs b/openssl/src/util.rs index d852a4b9d..c903a3209 100644 --- a/openssl/src/util.rs +++ b/openssl/src/util.rs @@ -1,4 +1,5 @@ use crate::error::ErrorStack; +use crate::util; use foreign_types::{ForeignType, ForeignTypeRef}; use libc::{c_char, c_int, c_void}; use std::any::Any; @@ -49,7 +50,7 @@ where let callback = &mut *(cb_state as *mut CallbackState); let result = panic::catch_unwind(AssertUnwindSafe(|| { - let pass_slice = slice::from_raw_parts_mut(buf as *mut u8, size as usize); + let pass_slice = util::from_raw_parts_mut(buf as *mut u8, size as usize); callback.cb.take().unwrap()(pass_slice) })); @@ -91,3 +92,27 @@ pub trait ForeignTypeRefExt: ForeignTypeRef { } } impl ForeignTypeRefExt for FT {} + +/// The same as `slice::from_raw_parts`, except that `data` may be `NULL` if +/// `len` is 0. +pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { + if len == 0 { + &[] + } else { + // Using this to implement the preferred API + #[allow(clippy::disallowed_methods)] + slice::from_raw_parts(data, len) + } +} + +/// The same as `slice::from_raw_parts_mut`, except that `data` may be `NULL` +/// if `len` is 0. +pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { + if len == 0 { + &mut [] + } else { + // Using this to implement the preferred API + #[allow(clippy::disallowed_methods)] + slice::from_raw_parts_mut(data, len) + } +} diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 05aec9a9c..df0991a4d 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -20,7 +20,6 @@ use std::mem; use std::net::IpAddr; use std::path::Path; use std::ptr; -use std::slice; use std::str; use crate::asn1::{ @@ -37,7 +36,7 @@ use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef, Public}; use crate::ssl::SslRef; use crate::stack::{Stack, StackRef, Stackable}; use crate::string::OpensslString; -use crate::util::{ForeignTypeExt, ForeignTypeRefExt}; +use crate::util::{self, ForeignTypeExt, ForeignTypeRefExt}; use crate::{cvt, cvt_n, cvt_p, cvt_p_const}; use openssl_macros::corresponds; @@ -662,7 +661,7 @@ impl X509Ref { if ptr.is_null() { None } else { - Some(slice::from_raw_parts(ptr, len as usize)) + Some(util::from_raw_parts(ptr, len as usize)) } } } @@ -2157,7 +2156,7 @@ impl GeneralNameRef { let len = ffi::ASN1_STRING_length(d as *mut _); #[allow(clippy::unnecessary_cast)] - let slice = slice::from_raw_parts(ptr as *const u8, len as usize); + let slice = util::from_raw_parts(ptr as *const u8, len as usize); // IA5Strings are stated to be ASCII (specifically IA5). Hopefully // OpenSSL checks that when loading a certificate but if not we'll // use this instead of from_utf8_unchecked just in case. @@ -2211,7 +2210,7 @@ impl GeneralNameRef { let len = ffi::ASN1_STRING_length(d as *mut _); #[allow(clippy::unnecessary_cast)] - Some(slice::from_raw_parts(ptr as *const u8, len as usize)) + Some(util::from_raw_parts(ptr as *const u8, len as usize)) } } }