Fix ssl-vendor (OpenSSL) (#7985)

Closes: #7893

Fix 1:
`foreign-types-shared` needs to match `openssl`'s version. Bumping it is
a SemVer violation because the latest versions of the crate aren't
backwards compatible with older versions.
See: rust-openssl/rust-openssl#2461

Fix 2:
The second fix is to align the `openssl` module with the latest
`host_env` and `ssl` changes.
This commit is contained in:
Joshua Megnauth authored and GitHub committed 2026-05-28 12:16:08 +09:00
1 parent e80a14ba12
commit 7d54ba502e
4 files changed
+44 -33

No files matched your search

+4
View File
@@ -140,6 +140,10 @@ jobs:
run: cargo build --no-default-features --features ssl-openssl
if: runner.os == 'Linux'
- name: Test vendored OpenSSL build
run: cargo build --no-default-features --features ssl-vendor
if: runner.os == 'Linux'
# - name: Install tk-dev for tkinter build
# run: sudo apt-get update && sudo apt-get install -y tk-dev
# if: runner.os == 'Linux'
+1
View File
@@ -217,6 +217,7 @@ exitcode = "1.1.2"
flame = "0.2.2"
flamer = "0.5"
flate2 = { version = "1.1.9", default-features = false }
# Bump only when the openssl crate bumps it
foreign-types-shared = "0.1"
gethostname = "1.0.2"
getrandom = { version = "0.3", features = ["std"] }
+31 -33
View File
@@ -65,7 +65,7 @@ mod _ssl {
LazyLock, PyMappedRwLockReadGuard, PyMutex, PyRwLock, PyRwLockReadGuard,
PyRwLockWriteGuard,
},
socket::{self, PySocket},
socket::{self, PySocket, SockWaitKind, sock_wait},
vm::{
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
builtins::{
@@ -2297,34 +2297,31 @@ mod _ssl {
needs: SslNeeds,
deadline: &SocketDeadline,
vm: &VirtualMachine,
) -> SelectRet {
let sock = match self.0.sock_opt() {
Some(s) => s,
None => return SelectRet::Closed,
) -> PyResult<SelectRet> {
let Some(sock) = self.0.sock_opt() else {
return Ok(SelectRet::Closed);
};
// For blocking sockets without timeout, call sock_wait with None timeout
// For blocking sockets without timeout, call sock_select with None timeout
// to actually block waiting for data instead of busy-looping
let timeout = match &deadline {
Ok(deadline) => match deadline.checked_duration_since(Instant::now()) {
Some(d) => Some(d),
None => return SelectRet::TimedOut,
None => return Ok(SelectRet::TimedOut),
},
Err(true) => None, // Blocking: no timeout, wait indefinitely
Err(false) => return SelectRet::Nonblocking,
Err(false) => return Ok(SelectRet::Nonblocking),
};
let res = socket::sock_wait(
&sock,
match needs {
SslNeeds::Read => socket::SockWaitKind::Read,
SslNeeds::Write => socket::SockWaitKind::Write,
},
timeout,
vm,
);
match res {
Ok(true) => SelectRet::TimedOut,
_ => SelectRet::Ok,
}
let wait_kind = match needs {
SslNeeds::Read => SockWaitKind::Read,
SslNeeds::Write => SockWaitKind::Write,
};
sock_wait(&*sock, wait_kind, timeout, vm).map(|timed_out| {
if timed_out {
SelectRet::TimedOut
} else {
SelectRet::Ok
}
})
}
fn socket_needs(
@@ -2332,14 +2329,15 @@ mod _ssl {
err: &ssl::Error,
deadline: &SocketDeadline,
vm: &VirtualMachine,
) -> (Option<SslNeeds>, SelectRet) {
) -> PyResult<(Option<SslNeeds>, SelectRet)> {
let needs = match err.code() {
ssl::ErrorCode::WANT_READ => Some(SslNeeds::Read),
ssl::ErrorCode::WANT_WRITE => Some(SslNeeds::Write),
_ => None,
};
let state = needs.map_or(SelectRet::Ok, |needs| self.select(needs, deadline, vm));
(needs, state)
let state =
needs.map_or(Ok(SelectRet::Ok), |needs| self.select(needs, deadline, vm))?;
Ok((needs, state))
}
}
@@ -2857,7 +2855,7 @@ mod _ssl {
break;
}
// Wait briefly for peer's close_notify before retrying
match socket_stream.select(SslNeeds::Read, &deadline, vm) {
match socket_stream.select(SslNeeds::Read, &deadline, vm)? {
SelectRet::TimedOut => {
return Err(socket::timeout_error_msg(
vm,
@@ -2895,7 +2893,7 @@ mod _ssl {
};
// Wait on the socket
match socket_stream.select(needs, &deadline, vm) {
match socket_stream.select(needs, &deadline, vm)? {
SelectRet::TimedOut => {
let msg = if err == sys::SSL_ERROR_WANT_READ {
"The read operation timed out"
@@ -2991,7 +2989,7 @@ mod _ssl {
let (needs, state) = stream
.get_ref()
.expect("handshake called in bio mode; should only be called in socket mode")
.socket_needs(&err, &timeout, vm);
.socket_needs(&err, &timeout, vm)?;
match state {
SelectRet::TimedOut => {
// Clean up SNI ex_data before returning error
@@ -3045,7 +3043,7 @@ mod _ssl {
.get_ref()
.expect("write called in bio mode; should only be called in socket mode");
let timeout = socket_ref.timeout_deadline();
let state = socket_ref.select(SslNeeds::Write, &timeout, vm);
let state = socket_ref.select(SslNeeds::Write, &timeout, vm)?;
match state {
SelectRet::TimedOut => {
return Err(socket::timeout_error_msg(
@@ -3065,7 +3063,7 @@ mod _ssl {
let (needs, state) = stream
.get_ref()
.expect("write called in bio mode; should only be called in socket mode")
.socket_needs(&err, &timeout, vm);
.socket_needs(&err, &timeout, vm)?;
match state {
SelectRet::TimedOut => {
return Err(socket::timeout_error_msg(
@@ -3236,7 +3234,7 @@ mod _ssl {
let (needs, state) = stream
.get_ref()
.expect("read called in bio mode; should only be called in socket mode")
.socket_needs(&err, &timeout, vm);
.socket_needs(&err, &timeout, vm)?;
match state {
SelectRet::TimedOut => {
return Err(socket::timeout_error_msg(
@@ -4149,7 +4147,7 @@ mod bio {
use openssl_sys as sys;
use std::marker::PhantomData;
pub struct MemBioSlice<'a>(*mut sys::BIO, PhantomData<&'a [u8]>);
pub(super) struct MemBioSlice<'a>(*mut sys::BIO, PhantomData<&'a [u8]>);
impl Drop for MemBioSlice<'_> {
fn drop(&mut self) {
@@ -4160,7 +4158,7 @@ mod bio {
}
impl<'a> MemBioSlice<'a> {
pub fn new(buf: &'a [u8]) -> Result<MemBioSlice<'a>, ErrorStack> {
pub(super) fn new(buf: &'a [u8]) -> Result<MemBioSlice<'a>, ErrorStack> {
openssl::init();
assert!(buf.len() <= c_int::MAX as usize);
@@ -4172,7 +4170,7 @@ mod bio {
Ok(MemBioSlice(bio, PhantomData))
}
pub fn as_ptr(&self) -> *mut sys::BIO {
pub(super) fn as_ptr(&self) -> *mut sys::BIO {
self.0
}
}
+8
View File
@@ -125,6 +125,10 @@ pub(crate) mod ssl_error {
)
}
#[cfg_attr(
all(feature = "ssl-openssl", not(feature = "ssl-rustls")),
expect(dead_code)
)]
pub(crate) fn create_ssl_zero_return_error(vm: &VirtualMachine) -> PyRef<PyOSError> {
vm.new_os_subtype_error(
PySSLZeroReturnError::class(&vm.ctx).to_owned(),
@@ -133,6 +137,10 @@ pub(crate) mod ssl_error {
)
}
#[cfg_attr(
all(feature = "ssl-openssl", not(feature = "ssl-rustls")),
expect(dead_code)
)]
pub(crate) fn create_ssl_syscall_error(
vm: &VirtualMachine,
msg: impl Into<String>,