Mark PyTypeObject as unsafe

This commit is contained in:
konstin 2019-03-30 20:23:31 +01:00
parent 9f2afbc3cc
commit 9a9b519bcb
4 changed files with 12 additions and 5 deletions

View File

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased] ## [Unreleased]
## Fixed
* `type_object::PyTypeObject` has been marked unsafe because breaking the contract `type_object::PyTypeObject::init_type` can lead to UB.
## [0.6.0] - 2018-03-28 ## [0.6.0] - 2018-03-28
### Regressions ### Regressions

View File

@ -88,7 +88,7 @@ macro_rules! import_exception {
#[macro_export] #[macro_export]
macro_rules! import_exception_type_object { macro_rules! import_exception_type_object {
($module: expr, $name: ident) => { ($module: expr, $name: ident) => {
impl $crate::type_object::PyTypeObject for $name { unsafe impl $crate::type_object::PyTypeObject for $name {
fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> { fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> {
// We can't use lazy_static here because raw pointers aren't Send // We can't use lazy_static here because raw pointers aren't Send
static TYPE_OBJECT_ONCE: ::std::sync::Once = ::std::sync::Once::new(); static TYPE_OBJECT_ONCE: ::std::sync::Once = ::std::sync::Once::new();
@ -221,7 +221,7 @@ macro_rules! impl_native_exception (
PyErr::new::<$name, V>(args).into() PyErr::new::<$name, V>(args).into()
} }
} }
impl PyTypeObject for $name { unsafe impl PyTypeObject for $name {
fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> { fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> {
unsafe { std::ptr::NonNull::new_unchecked(ffi::$exc_name as *mut _) } unsafe { std::ptr::NonNull::new_unchecked(ffi::$exc_name as *mut _) }
} }

View File

@ -230,7 +230,10 @@ pub trait PyObjectAlloc: PyTypeInfo + Sized {
} }
/// Python object types that have a corresponding type object. /// Python object types that have a corresponding type object.
pub trait PyTypeObject { ///
/// This trait is marked unsafe because not fulfilling the contract for [PyTypeObject::init_type]
/// leads to UB
pub unsafe trait PyTypeObject {
/// This function must make sure that the corresponding type object gets /// This function must make sure that the corresponding type object gets
/// initialized exactly once and return it. /// initialized exactly once and return it.
fn init_type() -> NonNull<ffi::PyTypeObject>; fn init_type() -> NonNull<ffi::PyTypeObject>;
@ -241,7 +244,7 @@ pub trait PyTypeObject {
} }
} }
impl<T> PyTypeObject for T unsafe impl<T> PyTypeObject for T
where where
T: PyTypeInfo + PyMethodsProtocol + PyObjectAlloc, T: PyTypeInfo + PyMethodsProtocol + PyObjectAlloc,
{ {

View File

@ -117,7 +117,7 @@ macro_rules! pyobject_native_type_convert(
impl<$($type_param,)*> $crate::type_object::PyObjectAlloc for $name {} impl<$($type_param,)*> $crate::type_object::PyObjectAlloc for $name {}
impl<$($type_param,)*> $crate::type_object::PyTypeObject for $name { unsafe impl<$($type_param,)*> $crate::type_object::PyTypeObject for $name {
fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> { fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> {
unsafe { unsafe {
std::ptr::NonNull::new_unchecked(<Self as $crate::type_object::PyTypeInfo>::type_object() as *mut _) std::ptr::NonNull::new_unchecked(<Self as $crate::type_object::PyTypeInfo>::type_object() as *mut _)