Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PyWeakref_GetRef and use it in weakref wrappers. #4528

Merged
merged 9 commits into from
Oct 2, 2024
2 changes: 2 additions & 0 deletions newsfragments/4528.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* Added bindings for `pyo3_ffi::PyWeakref_GetRef` on Python 3.13 and newer and
`py03_ffi::compat::PyWeakref_GetRef` for older Python versions.
7 changes: 7 additions & 0 deletions newsfragments/4528.removed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
* Removed the `get_object_borrowed`, `upgrade_borrowed`, `upgrade_borrowed_as`,
`upgrade_borrowed_as_unchecked`, `upgrade_borrowed_as_exact` methods of
`PyWeakref` and `PyWeakrefProxy`. These returned borrowed references to weakly
referenced data, and in principle if the GIL is released the last strong
reference could be released, allowing a possible use-after-free error. If you
are using these functions, you should change to the equivalent function that
returns a `Bound<'py, T>` reference.
33 changes: 33 additions & 0 deletions pyo3-ffi/src/compat/py_3_13.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,36 @@ compat_function!(
Py_XNewRef(PyImport_AddModule(name))
}
);

compat_function!(
originally_defined_for(Py_3_13);

#[inline]
pub unsafe fn PyWeakref_GetRef(
reference: *mut crate::PyObject,
pobj: *mut *mut crate::PyObject,
) -> std::os::raw::c_int {
use crate::{
compat::Py_NewRef, PyErr_SetString, PyExc_TypeError, PyWeakref_Check,
PyWeakref_GetObject, Py_None,
};

if !reference.is_null() && PyWeakref_Check(reference) == 0 {
*pobj = std::ptr::null_mut();
PyErr_SetString(PyExc_TypeError, c_str!("expected a weakref").as_ptr());
return -1;
}
let obj = PyWeakref_GetObject(reference);
if obj.is_null() {
// SystemError if reference is NULL
*pobj = std::ptr::null_mut();
return -1;
}
if obj == Py_None() {
*pobj = std::ptr::null_mut();
return 0;
}
*pobj = Py_NewRef(obj);
1
}
);
9 changes: 8 additions & 1 deletion pyo3-ffi/src/weakrefobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,12 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyWeakref_NewProxy")]
pub fn PyWeakref_NewProxy(ob: *mut PyObject, callback: *mut PyObject) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyWeakref_GetObject")]
pub fn PyWeakref_GetObject(_ref: *mut PyObject) -> *mut PyObject;
#[cfg_attr(
Py_3_13,
deprecated(note = "deprecated since Python 3.13. Use `PyWeakref_GetRef` instead.")
)]
pub fn PyWeakref_GetObject(reference: *mut PyObject) -> *mut PyObject;
#[cfg(Py_3_13)]
#[cfg_attr(PyPy, link_name = "PyPyWeakref_GetRef")]
pub fn PyWeakref_GetRef(reference: *mut PyObject, pobj: *mut *mut PyObject) -> c_int;
}
Loading
Loading