diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a0947af853b..0ba29605c02 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -299,8 +299,7 @@ jobs: target/release/rustpython -m test -j 1 --slowest --fail-env-changed -v -x ${{ env.PLATFORM_INDEPENDENT_TESTS }} ${{ env.WINDOWS_SKIPS }} timeout-minutes: 45 - - if: runner.os != 'Windows' - name: check that --install-pip succeeds + - name: check that --install-pip succeeds run: | mkdir site-packages target/release/rustpython --install-pip ensurepip --user @@ -309,11 +308,10 @@ jobs: run: | target/release/rustpython -m ensurepip target/release/rustpython -c "import pip" - - if: runner.os != 'Windows' - name: Check if pip inside venv is functional + - name: Check if pip inside venv is functional run: | target/release/rustpython -m venv testvenv - testvenv/bin/rustpython -m pip install wheel + testvenv/bin/rustpython -m pip install flask - name: Check whats_left is not broken run: python -I whats_left.py diff --git a/crates/vm/src/stdlib/ctypes.rs b/crates/vm/src/stdlib/ctypes.rs index 9b922230431..83143aa4a0c 100644 --- a/crates/vm/src/stdlib/ctypes.rs +++ b/crates/vm/src/stdlib/ctypes.rs @@ -579,7 +579,9 @@ pub(crate) mod _ctypes { vm: &VirtualMachine, ) -> PyResult { // Default mode: RTLD_NOW | RTLD_LOCAL, always force RTLD_NOW - let mode = load_flags.unwrap_or(libc::RTLD_NOW | libc::RTLD_LOCAL) | libc::RTLD_NOW; + let mode = load_flags + .map(|m| m | libc::RTLD_NOW) + .unwrap_or(libc::RTLD_NOW | libc::RTLD_LOCAL); match name { Some(name) => { @@ -641,6 +643,13 @@ pub(crate) mod _ctypes { name: crate::builtins::PyStrRef, vm: &VirtualMachine, ) -> PyResult { + // Validate the handle exists in the library cache before calling dlsym + let cache = library::libcache().read(); + if cache.get_lib(handle).is_none() { + return Err(vm.new_os_error("invalid library handle")); + } + drop(cache); + let symbol_name = std::ffi::CString::new(name.as_str()) .map_err(|_| vm.new_value_error("symbol name contains null byte"))?; diff --git a/crates/vm/src/stdlib/ctypes/library.rs b/crates/vm/src/stdlib/ctypes/library.rs index 7512ce29d8a..cbab950632c 100644 --- a/crates/vm/src/stdlib/ctypes/library.rs +++ b/crates/vm/src/stdlib/ctypes/library.rs @@ -6,7 +6,9 @@ use std::ffi::OsStr; use std::fmt; #[cfg(unix)] -use libloading::os::unix::Library as UnixLibrary; +use libloading::os::unix::Library as OsLibrary; +#[cfg(windows)] +use libloading::os::windows::Library as OsLibrary; pub struct SharedLibrary { pub(crate) lib: PyMutex>, @@ -33,7 +35,7 @@ impl SharedLibrary { ) -> Result { Ok(SharedLibrary { lib: PyMutex::new(Some(unsafe { - UnixLibrary::open(Some(name.as_ref()), mode)?.into() + OsLibrary::open(Some(name.as_ref()), mode)?.into() })), }) } @@ -42,19 +44,39 @@ impl SharedLibrary { #[cfg(unix)] pub fn from_raw_handle(handle: *mut libc::c_void) -> SharedLibrary { SharedLibrary { - lib: PyMutex::new(Some(unsafe { UnixLibrary::from_raw(handle).into() })), + lib: PyMutex::new(Some(unsafe { OsLibrary::from_raw(handle).into() })), } } /// Get the underlying OS handle (HMODULE on Windows, dlopen handle on Unix) + #[cfg(unix)] pub fn get_pointer(&self) -> usize { - let lib_lock = self.lib.lock(); - if let Some(l) = &*lib_lock { - // libloading::Library internally stores the OS handle directly - // On Windows: HMODULE (*mut c_void) - // On Unix: *mut c_void from dlopen - // We use transmute_copy to read the handle without consuming the Library - unsafe { std::mem::transmute_copy::(l) } + let mut lib_lock = self.lib.lock(); + if let Some(lib) = lib_lock.take() { + // Use official libloading API: convert to platform-specific type, + // extract raw handle, then reconstruct + let unix_lib: OsLibrary = lib.into(); + let handle = unix_lib.into_raw(); + // Reconstruct the library from the raw handle and put it back + *lib_lock = Some(unsafe { OsLibrary::from_raw(handle) }.into()); + handle as usize + } else { + 0 + } + } + + /// Get the underlying OS handle (HMODULE on Windows, dlopen handle on Unix) + #[cfg(windows)] + pub fn get_pointer(&self) -> usize { + let mut lib_lock = self.lib.lock(); + if let Some(lib) = lib_lock.take() { + // Use official libloading API: convert to platform-specific type, + // extract raw handle, then reconstruct + let win_lib: OsLibrary = lib.into(); + let handle = win_lib.into_raw(); + // Reconstruct the library from the raw handle and put it back + *lib_lock = Some(unsafe { OsLibrary::from_raw(handle) }.into()); + handle as usize } else { 0 }