Skip to content

Commit 128779a

Browse files
Fix ssl-vendor (OpenSSL)
Closes: RustPython#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.
1 parent 9701c46 commit 128779a

5 files changed

Lines changed: 52 additions & 40 deletions

File tree

‎.github/workflows/ci.yaml‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ jobs:
140140
run: cargo build --no-default-features --features ssl-openssl
141141
if: runner.os == 'Linux'
142142

143+
- name: Test vendored OpenSSL build
144+
run: cargo build --no-default-features --features ssl-vendor
145+
if: runner.os == 'Linux'
146+
143147
# - name: Install tk-dev for tkinter build
144148
# run: sudo apt-get update && sudo apt-get install -y tk-dev
145149
# if: runner.os == 'Linux'

‎Cargo.lock‎

Lines changed: 2 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@ exitcode = "1.1.2"
202202
flame = "0.2.2"
203203
flamer = "0.5"
204204
flate2 = { version = "1.1.9", default-features = false }
205-
foreign-types-shared = "0.3.1"
205+
# Bump only when the openssl crate bumps it
206+
foreign-types-shared = "0.1"
206207
gethostname = "1.0.2"
207208
getrandom = { version = "0.3", features = ["std"] }
208209
glob = "0.3"

‎crates/stdlib/src/openssl.rs‎

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ mod _ssl {
6565
LazyLock, PyMappedRwLockReadGuard, PyMutex, PyRwLock, PyRwLockReadGuard,
6666
PyRwLockWriteGuard,
6767
},
68-
socket::{self, PySocket},
68+
socket::{self, PySocket, SockWaitKind, sock_wait},
6969
vm::{
7070
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
7171
builtins::{
@@ -2292,47 +2292,52 @@ mod _ssl {
22922292
self.0.get_timeout().map(|d| Instant::now() + d)
22932293
}
22942294

2295-
fn select(&self, needs: SslNeeds, deadline: &SocketDeadline) -> SelectRet {
2296-
let sock = match self.0.sock_opt() {
2297-
Some(s) => s,
2298-
None => return SelectRet::Closed,
2295+
fn select(
2296+
&self,
2297+
needs: SslNeeds,
2298+
deadline: &SocketDeadline,
2299+
vm: &VirtualMachine,
2300+
) -> PyResult<SelectRet> {
2301+
let Some(sock) = self.0.sock_opt() else {
2302+
return Ok(SelectRet::Closed);
22992303
};
23002304
// For blocking sockets without timeout, call sock_select with None timeout
23012305
// to actually block waiting for data instead of busy-looping
23022306
let timeout = match &deadline {
23032307
Ok(deadline) => match deadline.checked_duration_since(Instant::now()) {
23042308
Some(d) => Some(d),
2305-
None => return SelectRet::TimedOut,
2309+
None => return Ok(SelectRet::TimedOut),
23062310
},
23072311
Err(true) => None, // Blocking: no timeout, wait indefinitely
2308-
Err(false) => return SelectRet::Nonblocking,
2312+
Err(false) => return Ok(SelectRet::Nonblocking),
23092313
};
2310-
let res = socket::sock_select(
2311-
&sock,
2312-
match needs {
2313-
SslNeeds::Read => socket::SelectKind::Read,
2314-
SslNeeds::Write => socket::SelectKind::Write,
2315-
},
2316-
timeout,
2317-
);
2318-
match res {
2319-
Ok(true) => SelectRet::TimedOut,
2320-
_ => SelectRet::Ok,
2321-
}
2314+
let wait_kind = match needs {
2315+
SslNeeds::Read => SockWaitKind::Read,
2316+
SslNeeds::Write => SockWaitKind::Write,
2317+
};
2318+
sock_wait(&*sock, wait_kind, timeout, vm).map(|timed_out| {
2319+
if timed_out {
2320+
SelectRet::TimedOut
2321+
} else {
2322+
SelectRet::Ok
2323+
}
2324+
})
23222325
}
23232326

23242327
fn socket_needs(
23252328
&self,
23262329
err: &ssl::Error,
23272330
deadline: &SocketDeadline,
2328-
) -> (Option<SslNeeds>, SelectRet) {
2331+
vm: &VirtualMachine,
2332+
) -> PyResult<(Option<SslNeeds>, SelectRet)> {
23292333
let needs = match err.code() {
23302334
ssl::ErrorCode::WANT_READ => Some(SslNeeds::Read),
23312335
ssl::ErrorCode::WANT_WRITE => Some(SslNeeds::Write),
23322336
_ => None,
23332337
};
2334-
let state = needs.map_or(SelectRet::Ok, |needs| self.select(needs, deadline));
2335-
(needs, state)
2338+
let state =
2339+
needs.map_or(Ok(SelectRet::Ok), |needs| self.select(needs, deadline, vm))?;
2340+
Ok((needs, state))
23362341
}
23372342
}
23382343

@@ -2850,7 +2855,7 @@ mod _ssl {
28502855
break;
28512856
}
28522857
// Wait briefly for peer's close_notify before retrying
2853-
match socket_stream.select(SslNeeds::Read, &deadline) {
2858+
match socket_stream.select(SslNeeds::Read, &deadline, vm)? {
28542859
SelectRet::TimedOut => {
28552860
return Err(socket::timeout_error_msg(
28562861
vm,
@@ -2888,7 +2893,7 @@ mod _ssl {
28882893
};
28892894

28902895
// Wait on the socket
2891-
match socket_stream.select(needs, &deadline) {
2896+
match socket_stream.select(needs, &deadline, vm)? {
28922897
SelectRet::TimedOut => {
28932898
let msg = if err == sys::SSL_ERROR_WANT_READ {
28942899
"The read operation timed out"
@@ -2984,7 +2989,7 @@ mod _ssl {
29842989
let (needs, state) = stream
29852990
.get_ref()
29862991
.expect("handshake called in bio mode; should only be called in socket mode")
2987-
.socket_needs(&err, &timeout);
2992+
.socket_needs(&err, &timeout, vm)?;
29882993
match state {
29892994
SelectRet::TimedOut => {
29902995
// Clean up SNI ex_data before returning error
@@ -3038,7 +3043,7 @@ mod _ssl {
30383043
.get_ref()
30393044
.expect("write called in bio mode; should only be called in socket mode");
30403045
let timeout = socket_ref.timeout_deadline();
3041-
let state = socket_ref.select(SslNeeds::Write, &timeout);
3046+
let state = socket_ref.select(SslNeeds::Write, &timeout, vm)?;
30423047
match state {
30433048
SelectRet::TimedOut => {
30443049
return Err(socket::timeout_error_msg(
@@ -3058,7 +3063,7 @@ mod _ssl {
30583063
let (needs, state) = stream
30593064
.get_ref()
30603065
.expect("write called in bio mode; should only be called in socket mode")
3061-
.socket_needs(&err, &timeout);
3066+
.socket_needs(&err, &timeout, vm)?;
30623067
match state {
30633068
SelectRet::TimedOut => {
30643069
return Err(socket::timeout_error_msg(
@@ -3229,7 +3234,7 @@ mod _ssl {
32293234
let (needs, state) = stream
32303235
.get_ref()
32313236
.expect("read called in bio mode; should only be called in socket mode")
3232-
.socket_needs(&err, &timeout);
3237+
.socket_needs(&err, &timeout, vm)?;
32333238
match state {
32343239
SelectRet::TimedOut => {
32353240
return Err(socket::timeout_error_msg(
@@ -4142,7 +4147,7 @@ mod bio {
41424147
use openssl_sys as sys;
41434148
use std::marker::PhantomData;
41444149

4145-
pub struct MemBioSlice<'a>(*mut sys::BIO, PhantomData<&'a [u8]>);
4150+
pub(super) struct MemBioSlice<'a>(*mut sys::BIO, PhantomData<&'a [u8]>);
41464151

41474152
impl Drop for MemBioSlice<'_> {
41484153
fn drop(&mut self) {
@@ -4153,7 +4158,7 @@ mod bio {
41534158
}
41544159

41554160
impl<'a> MemBioSlice<'a> {
4156-
pub fn new(buf: &'a [u8]) -> Result<MemBioSlice<'a>, ErrorStack> {
4161+
pub(super) fn new(buf: &'a [u8]) -> Result<MemBioSlice<'a>, ErrorStack> {
41574162
openssl::init();
41584163

41594164
assert!(buf.len() <= c_int::MAX as usize);
@@ -4165,7 +4170,7 @@ mod bio {
41654170
Ok(MemBioSlice(bio, PhantomData))
41664171
}
41674172

4168-
pub fn as_ptr(&self) -> *mut sys::BIO {
4173+
pub(super) fn as_ptr(&self) -> *mut sys::BIO {
41694174
self.0
41704175
}
41714176
}

‎crates/stdlib/src/ssl/error.rs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ pub(crate) mod ssl_error {
125125
)
126126
}
127127

128+
#[cfg_attr(
129+
all(feature = "ssl-openssl", not(feature = "ssl-rustls")),
130+
expect(dead_code)
131+
)]
128132
pub(crate) fn create_ssl_zero_return_error(vm: &VirtualMachine) -> PyRef<PyOSError> {
129133
vm.new_os_subtype_error(
130134
PySSLZeroReturnError::class(&vm.ctx).to_owned(),
@@ -133,6 +137,10 @@ pub(crate) mod ssl_error {
133137
)
134138
}
135139

140+
#[cfg_attr(
141+
all(feature = "ssl-openssl", not(feature = "ssl-rustls")),
142+
expect(dead_code)
143+
)]
136144
pub(crate) fn create_ssl_syscall_error(
137145
vm: &VirtualMachine,
138146
msg: impl Into<String>,

0 commit comments

Comments
 (0)