From 9a9b519bcbabee73f86be00182a90cd84f32d96b Mon Sep 17 00:00:00 2001 From: konstin Date: Sat, 30 Mar 2019 20:23:31 +0100 Subject: [PATCH] Mark PyTypeObject as unsafe --- CHANGELOG.md | 4 ++++ src/exceptions.rs | 4 ++-- src/type_object.rs | 7 +++++-- src/types/mod.rs | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 817d5371..18fb0d81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [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 ### Regressions diff --git a/src/exceptions.rs b/src/exceptions.rs index 5cd35487..989d39a8 100644 --- a/src/exceptions.rs +++ b/src/exceptions.rs @@ -88,7 +88,7 @@ macro_rules! import_exception { #[macro_export] macro_rules! import_exception_type_object { ($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> { // We can't use lazy_static here because raw pointers aren't Send 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() } } - impl PyTypeObject for $name { + unsafe impl PyTypeObject for $name { fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> { unsafe { std::ptr::NonNull::new_unchecked(ffi::$exc_name as *mut _) } } diff --git a/src/type_object.rs b/src/type_object.rs index 6fcc8a5a..c58274ac 100644 --- a/src/type_object.rs +++ b/src/type_object.rs @@ -230,7 +230,10 @@ pub trait PyObjectAlloc: PyTypeInfo + Sized { } /// 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 /// initialized exactly once and return it. fn init_type() -> NonNull; @@ -241,7 +244,7 @@ pub trait PyTypeObject { } } -impl PyTypeObject for T +unsafe impl PyTypeObject for T where T: PyTypeInfo + PyMethodsProtocol + PyObjectAlloc, { diff --git a/src/types/mod.rs b/src/types/mod.rs index f6e8a843..fb921026 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -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::PyTypeObject for $name { + unsafe impl<$($type_param,)*> $crate::type_object::PyTypeObject for $name { fn init_type() -> std::ptr::NonNull<$crate::ffi::PyTypeObject> { unsafe { std::ptr::NonNull::new_unchecked(::type_object() as *mut _)