diff --git a/CHANGELOG.md b/CHANGELOG.md index ca5cf9238f7..e7abf14e9fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Implement `IntoPy` for `&PathBuf` and `&OsString`. [#1721](https://github.com/PyO3/pyo3/pull/1712) +### Fixed + +- Fix crashes on PyPy due to incorrect definitions of `PyList_SET_ITEM`. [#1713](https://github.com/PyO3/pyo3/pull/1713) + ## [0.14.0] - 2021-07-03 ### Packaging diff --git a/src/ffi/cpython/listobject.rs b/src/ffi/cpython/listobject.rs index e0f583ad5c0..0489407850b 100644 --- a/src/ffi/cpython/listobject.rs +++ b/src/ffi/cpython/listobject.rs @@ -15,17 +15,20 @@ pub struct PyListObject { /// Macro, trading safety for speed #[inline] +#[cfg(not(PyPy))] pub unsafe fn PyList_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject { *(*(op as *mut PyListObject)).ob_item.offset(i as isize) } /// Macro, *only* to be used to fill in brand new lists #[inline] +#[cfg(not(PyPy))] pub unsafe fn PyList_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) { *(*(op as *mut PyListObject)).ob_item.offset(i as isize) = v; } #[inline] +#[cfg(not(PyPy))] pub unsafe fn PyList_GET_SIZE(op: *mut PyObject) -> Py_ssize_t { Py_SIZE(op) } diff --git a/src/ffi/listobject.rs b/src/ffi/listobject.rs index cc9ca0de7e9..79885bcff3e 100644 --- a/src/ffi/listobject.rs +++ b/src/ffi/listobject.rs @@ -52,4 +52,15 @@ extern "C" { pub fn PyList_Reverse(arg1: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyList_AsTuple")] pub fn PyList_AsTuple(arg1: *mut PyObject) -> *mut PyObject; + + // CPython macros exported as functions on PyPy + #[cfg(PyPy)] + #[cfg_attr(PyPy, link_name = "PyPyList_GET_ITEM")] + pub fn PyList_GET_ITEM(arg1: *mut PyObject, arg2: Py_ssize_t) -> *mut PyObject; + #[cfg(PyPy)] + #[cfg_attr(PyPy, link_name = "PyPyList_GET_SIZE")] + pub fn PyList_GET_SIZE(arg1: *mut PyObject) -> Py_ssize_t; + #[cfg(PyPy)] + #[cfg_attr(PyPy, link_name = "PyPyList_SET_ITEM")] + pub fn PyList_SET_ITEM(arg1: *mut PyObject, arg2: Py_ssize_t, arg3: *mut PyObject); } diff --git a/src/ffi/tupleobject.rs b/src/ffi/tupleobject.rs index fb38718950f..909eae2fce5 100644 --- a/src/ffi/tupleobject.rs +++ b/src/ffi/tupleobject.rs @@ -47,7 +47,7 @@ extern "C" { /// Macro, trading safety for speed #[inline] -#[cfg(not(Py_LIMITED_API))] +#[cfg(not(any(Py_LIMITED_API, PyPy)))] pub unsafe fn PyTuple_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject { *(*(op as *mut PyTupleObject)) .ob_item @@ -56,14 +56,14 @@ pub unsafe fn PyTuple_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObjec } #[inline] -#[cfg(not(Py_LIMITED_API))] +#[cfg(not(any(Py_LIMITED_API, PyPy)))] pub unsafe fn PyTuple_GET_SIZE(op: *mut PyObject) -> Py_ssize_t { Py_SIZE(op) } /// Macro, *only* to be used to fill in brand new tuples #[inline] -#[cfg(not(Py_LIMITED_API))] +#[cfg(not(any(Py_LIMITED_API, PyPy)))] pub unsafe fn PyTuple_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) { *(*(op as *mut PyTupleObject)) .ob_item diff --git a/src/types/tuple.rs b/src/types/tuple.rs index f48b7ce017d..1342ec408a8 100644 --- a/src/types/tuple.rs +++ b/src/types/tuple.rs @@ -26,9 +26,9 @@ impl PyTuple { unsafe { let ptr = ffi::PyTuple_New(len as Py_ssize_t); for (i, e) in elements_iter.enumerate() { - #[cfg(not(Py_LIMITED_API))] + #[cfg(not(any(Py_LIMITED_API, PyPy)))] ffi::PyTuple_SET_ITEM(ptr, i as Py_ssize_t, e.to_object(py).into_ptr()); - #[cfg(Py_LIMITED_API)] + #[cfg(any(Py_LIMITED_API, PyPy))] ffi::PyTuple_SetItem(ptr, i as Py_ssize_t, e.to_object(py).into_ptr()); } py.from_owned_ptr(ptr) @@ -43,9 +43,9 @@ impl PyTuple { /// Gets the length of the tuple. pub fn len(&self) -> usize { unsafe { - #[cfg(not(Py_LIMITED_API))] + #[cfg(not(any(Py_LIMITED_API, PyPy)))] let size = ffi::PyTuple_GET_SIZE(self.as_ptr()); - #[cfg(Py_LIMITED_API)] + #[cfg(any(Py_LIMITED_API, PyPy))] let size = ffi::PyTuple_Size(self.as_ptr()); // non-negative Py_ssize_t should always fit into Rust uint size as usize @@ -79,9 +79,9 @@ impl PyTuple { pub fn get_item(&self, index: usize) -> &PyAny { assert!(index < self.len()); unsafe { - #[cfg(not(Py_LIMITED_API))] + #[cfg(not(any(Py_LIMITED_API, PyPy)))] let item = ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t); - #[cfg(Py_LIMITED_API)] + #[cfg(any(Py_LIMITED_API, PyPy))] let item = ffi::PyTuple_GetItem(self.as_ptr(), index as Py_ssize_t); self.py().from_borrowed_ptr(item)