Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 4 additions & 9 deletions crates/common/src/rc.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
#[cfg(not(feature = "threading"))]
use alloc::rc::Rc;
#[cfg(feature = "threading")]
use alloc::sync::Arc;

// type aliases instead of new-types because you can't do `fn method(self: PyRc<Self>)` with a
// newtype; requires the arbitrary_self_types unstable feature

#[cfg(feature = "threading")]
pub type PyRc<T> = Arc<T>;
#[cfg(not(feature = "threading"))]
pub type PyRc<T> = Rc<T>;
pub type PyRc<T> = cfg_select! {
feature = "threading" => alloc::sync::Arc::<T>,
_ => alloc::rc::Rc::<T>,
};
8 changes: 4 additions & 4 deletions crates/common/src/refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ const WEAK_COUNT: usize = 1 << STRONG_WIDTH;
reason = "refcount overflow must preserve upstream abort semantics"
)]
fn refcount_overflow() -> ! {
#[cfg(feature = "std")]
std::process::abort();
#[cfg(not(feature = "std"))]
core::panic!("refcount overflow");
cfg_select! {
feature = "std" => std::process::abort(),
_ => core::panic!("refcount overflow"),
}
}

/// State wraps reference count + flags in a single word (platform usize)
Expand Down
9 changes: 4 additions & 5 deletions crates/common/src/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ use core::fmt;
use core::ops::{Bound, RangeBounds};
use core::sync::atomic::Ordering::Relaxed;

#[cfg(not(target_arch = "wasm32"))]
#[allow(non_camel_case_types)]
pub type wchar_t = libc::wchar_t;
#[cfg(target_arch = "wasm32")]
#[allow(non_camel_case_types)]
pub type wchar_t = u32;
pub type wchar_t = cfg_select! {
target_arch = "wasm32" => u32,
_ => libc::wchar_t,
};

/// Utf8 + state.ascii (+ PyUnicode_Kind in future)
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
Expand Down
36 changes: 17 additions & 19 deletions crates/host_env/src/crt_fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ mod c {

// this is basically what CPython has for Py_off_t; windows uses long long
// for offsets, other platforms just use off_t
#[cfg(not(windows))]
pub type Offset = c::off_t;
#[cfg(windows)]
pub type Offset = c::c_longlong;
pub type Offset = cfg_select! {
windows => c::c_longlong,
_ => c::off_t,
};

#[cfg(not(windows))]
pub type Raw = RawFd;
#[cfg(windows)]
pub type Raw = i32;
pub type Raw = cfg_select! {
windows => i32,
_ => RawFd,
};

#[inline]
fn cvt<I: num_traits::PrimInt>(ret: I) -> io::Result<I> {
Expand Down Expand Up @@ -341,18 +341,16 @@ pub fn ftruncate(fd: Borrowed<'_>, len: Offset) -> io::Result<()> {
let ret = unsafe { suppress_iph!(c::ftruncate(fd.as_raw(), len)) };
// On Windows, _chsize_s returns 0 on success, or a positive error code (errno value) on failure.
// On other platforms, ftruncate returns 0 on success, or -1 on failure with errno set.
#[cfg(windows)]
{
if ret != 0 {
// _chsize_s returns errno directly, convert to Windows error code
let winerror = crate::os::errno_to_winerror(ret);
return Err(io::Error::from_raw_os_error(winerror));
cfg_select! {
windows => {
if ret != 0 {
// _chsize_s returns errno directly, convert to Windows error code
let winerror = crate::os::errno_to_winerror(ret);
return Err(io::Error::from_raw_os_error(winerror));
}
}
}
#[cfg(not(windows))]
{
cvt(ret)?;
}
_ => cvt(ret)?,
};
Ok(())
}

Expand Down
90 changes: 27 additions & 63 deletions crates/stdlib/src/faulthandler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,30 +119,12 @@ mod decl {
// PUTS macro
#[cfg(any(unix, windows))]
fn puts(fd: i32, s: &str) {
let _ = unsafe {
#[cfg(windows)]
{
libc::write(fd, s.as_ptr() as *const libc::c_void, s.len() as u32)
}
#[cfg(not(windows))]
{
libc::write(fd, s.as_ptr() as *const libc::c_void, s.len())
}
};
puts_bytes(fd, s.as_bytes())
}

#[cfg(any(unix, windows))]
fn puts_bytes(fd: i32, s: &[u8]) {
let _ = unsafe {
#[cfg(windows)]
{
libc::write(fd, s.as_ptr() as *const libc::c_void, s.len() as u32)
}
#[cfg(not(windows))]
{
libc::write(fd, s.as_ptr() as *const libc::c_void, s.len())
}
};
let _ = unsafe { libc::write(fd, s.as_ptr().cast::<libc::c_void>(), s.len() as _) };
}

// _Py_DumpHexadecimal (traceback.c)
Expand All @@ -158,16 +140,7 @@ mod decl {
buf[2 + i] = HEX_CHARS[digit];
}

let _ = unsafe {
#[cfg(windows)]
{
libc::write(fd, buf.as_ptr() as *const libc::c_void, (2 + width) as u32)
}
#[cfg(not(windows))]
{
libc::write(fd, buf.as_ptr() as *const libc::c_void, 2 + width)
}
};
puts_bytes(fd, &buf[..2 + width]);
}

// _Py_DumpDecimal (traceback.c)
Expand All @@ -188,17 +161,7 @@ mod decl {
v /= 10;
}

let len = buf.len() - i;
let _ = unsafe {
#[cfg(windows)]
{
libc::write(fd, buf[i..].as_ptr() as *const libc::c_void, len as u32)
}
#[cfg(not(windows))]
{
libc::write(fd, buf[i..].as_ptr() as *const libc::c_void, len)
}
};
puts_bytes(fd, &buf[i..]);
}

/// Get current thread ID
Expand Down Expand Up @@ -857,30 +820,31 @@ mod decl {
drop(guard); // Release lock before I/O

// Timeout occurred, dump traceback
#[cfg(target_arch = "wasm32")]
let _ = (exit, fd, &header);

#[cfg(not(target_arch = "wasm32"))]
{
puts_bytes(fd, header.as_bytes());

// Use thread frame slots when threading is enabled (includes all threads).
// Fall back to live frame walking for non-threaded builds.
#[cfg(feature = "threading")]
{
for (tid, slot) in &thread_frame_slots {
let frames = slot.frames.lock();
dump_traceback_thread_frames(fd, *tid, false, &frames);
}
}
#[cfg(not(feature = "threading"))]
{
write_thread_id(fd, current_thread_id(), false);
dump_live_frames(fd);
cfg_select! {
target_arch = "wasm32" => {
let _ = (exit, fd, &header);
}
_ => {
puts_bytes(fd, header.as_bytes());

// Use thread frame slots when threading is enabled (includes all threads).
// Fall back to live frame walking for non-threaded builds.
cfg_select! {
feature = "threading" => {
for (tid, slot) in &thread_frame_slots {
let frames = slot.frames.lock();
dump_traceback_thread_frames(fd, *tid, false, &frames);
}
}
_ => {
write_thread_id(fd, current_thread_id(), false);
dump_live_frames(fd);
}
}

if exit {
rustpython_host_env::os::exit(1);
if exit {
rustpython_host_env::os::exit(1);
}
}
}

Expand Down
108 changes: 46 additions & 62 deletions crates/stdlib/src/openssl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1307,15 +1307,13 @@ mod _ssl {
#[pygetset]
fn num_tickets(&self, _vm: &VirtualMachine) -> PyResult<usize> {
// Only supported for TLS 1.3
#[cfg(ossl110)]
{
let ctx = self.ctx();
let num = unsafe { sys::SSL_CTX_get_num_tickets(ctx.as_ptr()) };
Ok(num)
}
#[cfg(not(ossl110))]
{
Ok(0)
cfg_select! {
ossl111 => {
let ctx = self.ctx();
let num = unsafe { sys::SSL_CTX_get_num_tickets(ctx.as_ptr()) };
Ok(num)
}
_ => Ok(0),
Comment on lines +1310 to +1316
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In OpenSSL, what minimum version introduced SSL_CTX_get_num_tickets and SSL_CTX_set_num_tickets?

💡 Result:

The minimum OpenSSL version that introduced both SSL_CTX_get_num_tickets and SSL_CTX_set_num_tickets is 1.1.1.

Citations:


🏁 Script executed:

# Check the actual code at the specified lines in openssl.rs
cd crates/stdlib/src && head -1350 openssl.rs | tail -100 | head -50

Repository: RustPython/RustPython

Length of output: 2008


🏁 Script executed:

# Find all usages of SSL_CTX_get_num_tickets and SSL_CTX_set_num_tickets
rg "SSL_CTX_(?:get|set)_num_tickets" crates/stdlib/src/

Repository: RustPython/RustPython

Length of output: 312


🏁 Script executed:

# Check for cfg_select macro definitions and gate patterns
rg "cfg_select|ossl110|ossl111" crates/stdlib/src/openssl.rs | head -40

Repository: RustPython/RustPython

Length of output: 1055


🏁 Script executed:

# Get exact lines around 1310-1316 and 1331-1342
sed -n '1305,1320p' crates/stdlib/src/openssl.rs
echo "---"
sed -n '1326,1345p' crates/stdlib/src/openssl.rs

Repository: RustPython/RustPython

Length of output: 1347


🏁 Script executed:

# Verify that ossl111 is used elsewhere for similar version-gated APIs to confirm the pattern
rg -A 3 'cfg_select.*ossl111 =>' crates/stdlib/src/openssl.rs | head -30

Repository: RustPython/RustPython

Length of output: 47


🏁 Script executed:

# Search for how ossl111 gate is used in cfg_select blocks
rg 'cfg_select!' crates/stdlib/src/openssl.rs -A 2 | grep -A 2 'ossl111'

Repository: RustPython/RustPython

Length of output: 154


Change version gates from ossl110 to ossl111 for SSL_CTX_get_num_tickets and SSL_CTX_set_num_tickets

SSL_CTX_get_num_tickets and SSL_CTX_set_num_tickets were introduced in OpenSSL 1.1.1, not 1.1.0. Using the ossl110 gate will cause build or link failures on OpenSSL 1.1.0 targets. Both occurrences must be updated to use ossl111.

Required fix
             cfg_select! {
-                ossl110 => {
+                ossl111 => {
                     let ctx = self.ctx();
                     let num = unsafe { sys::SSL_CTX_get_num_tickets(ctx.as_ptr()) };
                     Ok(num)
                 }
                 _ => Ok(0),
             }
             cfg_select! {
-                ossl110 => {
+                ossl111 => {
                     let ctx = self.builder();
                     let result = unsafe { sys::SSL_CTX_set_num_tickets(ctx.as_ptr(), value as usize) };
                     if result != 1 {
                         return Err(vm.new_value_error("failed to set num tickets."));
                     }
                     Ok(())
                 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cfg_select! {
ossl110 => {
let ctx = self.ctx();
let num = unsafe { sys::SSL_CTX_get_num_tickets(ctx.as_ptr()) };
Ok(num)
}
_ => Ok(0),
cfg_select! {
ossl111 => {
let ctx = self.ctx();
let num = unsafe { sys::SSL_CTX_get_num_tickets(ctx.as_ptr()) };
Ok(num)
}
_ => Ok(0),
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/stdlib/src/openssl.rs` around lines 1310 - 1316, Change the cfg gate
used where SSL_CTX_get_num_tickets and SSL_CTX_set_num_tickets are referenced
from ossl110 to ossl111: locate the cfg_select! blocks that wrap the calls to
sys::SSL_CTX_get_num_tickets and sys::SSL_CTX_set_num_tickets (references around
the methods using self.ctx() / ctx.as_ptr()) and replace the ossl110 arm with
ossl111 so the calls are only enabled for OpenSSL 1.1.1 and later; keep the
fallback arms (e.g., _ => Ok(0) or identical behavior) unchanged.

}
}
#[pygetset(setter)]
Expand All @@ -1330,19 +1328,19 @@ mod _ssl {
return Err(vm.new_value_error("SSLContext is not a server context."));
}

#[cfg(ossl110)]
{
let ctx = self.builder();
let result = unsafe { sys::SSL_CTX_set_num_tickets(ctx.as_ptr(), value as usize) };
if result != 1 {
return Err(vm.new_value_error("failed to set num tickets."));
cfg_select! {
ossl110 => {
let ctx = self.builder();
let result = unsafe { sys::SSL_CTX_set_num_tickets(ctx.as_ptr(), value as usize) };
if result != 1 {
return Err(vm.new_value_error("failed to set num tickets."));
}
Ok(())
}
_ => {
let _ = (value, vm);
Ok(())
}
Ok(())
}
#[cfg(not(ossl110))]
{
let _ = (value, vm);
Ok(())
}
}

Expand Down Expand Up @@ -1564,10 +1562,10 @@ mod _ssl {
) -> PyResult<Vec<PyObjectRef>> {
let binary_form = args.binary_form.unwrap_or(false);
let ctx = self.ctx();
#[cfg(ossl300)]
let certs = ctx.cert_store().all_certificates();
#[cfg(not(ossl300))]
let certs = ctx.cert_store().objects().iter().filter_map(|x| x.x509());
let certs = cfg_select! {
ossl300 => ctx.cert_store().all_certificates(),
_ => ctx.cert_store().objects().iter().filter_map(|x| x.x509()),
};
Comment thread
coderabbitai[bot] marked this conversation as resolved.

// Filter to only include CA certificates (Basic Constraints: CA=TRUE)
let certs = certs
Expand Down Expand Up @@ -2792,21 +2790,21 @@ mod _ssl {

#[pymethod]
fn verify_client_post_handshake(&self, vm: &VirtualMachine) -> PyResult<()> {
#[cfg(ossl111)]
{
let stream = self.connection.read();
let result = unsafe { SSL_verify_client_post_handshake(stream.ssl().as_ptr()) };
if result == 0 {
Err(convert_openssl_error(vm, openssl::error::ErrorStack::get()))
} else {
Ok(())
cfg_select! {
ossl111 => {
let stream = self.connection.read();
let result = unsafe { SSL_verify_client_post_handshake(stream.ssl().as_ptr()) };
if result == 0 {
Err(convert_openssl_error(vm, openssl::error::ErrorStack::get()))
} else {
Ok(())
}
}
_ => {
Err(vm.new_not_implemented_error(
"Post-handshake auth is not supported by your OpenSSL version.",
))
}
}
#[cfg(not(ossl111))]
{
Err(vm.new_not_implemented_error(
"Post-handshake auth is not supported by your OpenSSL version.",
))
}
}

Expand Down Expand Up @@ -3681,15 +3679,9 @@ mod _ssl {
impl PySslSession {
#[pygetset]
fn time(&self) -> i64 {
unsafe {
#[cfg(ossl330)]
{
sys::SSL_SESSION_get_time(self.session) as i64
}
#[cfg(not(ossl330))]
{
sys::SSL_SESSION_get_time(self.session) as i64
}
cfg_select! {
ossl330 => unsafe { sys::SSL_SESSION_get_time(self.session) as i64 },
_ => unsafe { sys::SSL_SESSION_get_time(self.session) as i64 },
}
}

Expand All @@ -3701,14 +3693,10 @@ mod _ssl {
#[pygetset]
fn ticket_lifetime_hint(&self) -> u64 {
// SSL_SESSION_get_ticket_lifetime_hint available in OpenSSL 1.1.0+
#[cfg(ossl110)]
{
unsafe { SSL_SESSION_get_ticket_lifetime_hint(self.session) as u64 }
}
#[cfg(not(ossl110))]
{
cfg_select! {
ossl110 => unsafe { SSL_SESSION_get_ticket_lifetime_hint(self.session) as u64 },
// Not available in older OpenSSL versions
0
_ => 0,
}
}

Expand All @@ -3725,14 +3713,10 @@ mod _ssl {
#[pygetset]
fn has_ticket(&self) -> bool {
// SSL_SESSION_has_ticket available in OpenSSL 1.1.0+
#[cfg(ossl110)]
{
unsafe { SSL_SESSION_has_ticket(self.session) != 0 }
}
#[cfg(not(ossl110))]
{
cfg_select! {
ossl110 => unsafe { SSL_SESSION_has_ticket(self.session) != 0 },
// Not available in older OpenSSL versions
false
_ => false,
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/stdlib/src/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3264,7 +3264,7 @@ mod _socket {
fn sock_from_raw(fileno: RawSocket, vm: &VirtualMachine) -> PyResult<Socket> {
let invalid = cfg_select! {
windows => fileno == INVALID_SOCKET,
_ => fileno < 0
_ => fileno < 0,
};
if invalid {
return Err(vm.new_value_error("negative file descriptor"));
Expand Down
Loading
Loading