From 33b8f6253fe18af5bc882cf885d68538c90dab62 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 23 Jul 2018 11:13:20 +0200 Subject: [PATCH 1/2] Don't use NonNull::dangling as sentinel value Instead, rely on alignment and use usize::MAX as sentinel. --- src/liballoc/rc.rs | 13 ++++++++----- src/liballoc/sync.rs | 13 +++++++++---- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index d76acb28df92b..b50bf5c15d5bb 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -258,6 +258,7 @@ use core::ops::Deref; use core::ops::CoerceUnsized; use core::ptr::{self, NonNull}; use core::convert::From; +use core::usize; use alloc::{Global, Alloc, Layout, box_free, handle_alloc_error}; use string::String; @@ -449,6 +450,8 @@ impl Rc { #[stable(feature = "rc_weak", since = "1.4.0")] pub fn downgrade(this: &Self) -> Weak { this.inc_weak(); + // Make sure we do not create a dangling Weak + debug_assert!(!is_dangling(this.ptr)); Weak { ptr: this.ptr } } @@ -1154,8 +1157,9 @@ impl From> for Rc<[T]> { pub struct Weak { // This is a `NonNull` to allow optimizing the size of this type in enums, // but it is not necessarily a valid pointer. - // `Weak::new` sets this to a dangling pointer so that it doesn’t need - // to allocate space on the heap. + // `Weak::new` sets this to `usize::MAX` so that it doesn’t need + // to allocate space on the heap. That's not a value a real poiner + // will ever have because RcBox has alignment at least 4. ptr: NonNull>, } @@ -1185,15 +1189,14 @@ impl Weak { #[stable(feature = "downgraded_weak", since = "1.10.0")] pub fn new() -> Weak { Weak { - ptr: NonNull::dangling(), + ptr: NonNull::new(usize::MAX as *mut RcBox).expect("MAX is not 0"), } } } pub(crate) fn is_dangling(ptr: NonNull) -> bool { let address = ptr.as_ptr() as *mut () as usize; - let align = align_of_val(unsafe { ptr.as_ref() }); - address == align + address == usize::MAX } impl Weak { diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 5def0237e7e71..4c14fef9b3183 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -238,8 +238,9 @@ impl, U: ?Sized> CoerceUnsized> for Arc {} pub struct Weak { // This is a `NonNull` to allow optimizing the size of this type in enums, // but it is not necessarily a valid pointer. - // `Weak::new` sets this to a dangling pointer so that it doesn’t need - // to allocate space on the heap. + // `Weak::new` sets this to `usize::MAX` so that it doesn’t need + // to allocate space on the heap. That's not a value a real poiner + // will ever have because RcBox has alignment at least 4. ptr: NonNull>, } @@ -442,7 +443,11 @@ impl Arc { // synchronize with the write coming from `is_unique`, so that the // events prior to that write happen before this read. match this.inner().weak.compare_exchange_weak(cur, cur + 1, Acquire, Relaxed) { - Ok(_) => return Weak { ptr: this.ptr }, + Ok(_) => { + // Make sure we do not create a dangling Weak + debug_assert!(!is_dangling(this.ptr)); + return Weak { ptr: this.ptr }; + } Err(old) => cur = old, } } @@ -1033,7 +1038,7 @@ impl Weak { #[stable(feature = "downgraded_weak", since = "1.10.0")] pub fn new() -> Weak { Weak { - ptr: NonNull::dangling(), + ptr: NonNull::new(usize::MAX as *mut ArcInner).expect("MAX is not 0"), } } } From a303741334baafa475632f23145695cba80ce8e7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 23 Jul 2018 12:53:37 +0200 Subject: [PATCH 2/2] typos --- src/liballoc/rc.rs | 4 ++-- src/liballoc/sync.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index b50bf5c15d5bb..be049eb6e5ef3 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -1158,8 +1158,8 @@ pub struct Weak { // This is a `NonNull` to allow optimizing the size of this type in enums, // but it is not necessarily a valid pointer. // `Weak::new` sets this to `usize::MAX` so that it doesn’t need - // to allocate space on the heap. That's not a value a real poiner - // will ever have because RcBox has alignment at least 4. + // to allocate space on the heap. That's not a value a real pointer + // will ever have because RcBox has alignment at least 2. ptr: NonNull>, } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 4c14fef9b3183..a00b6b4e435f0 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -239,8 +239,8 @@ pub struct Weak { // This is a `NonNull` to allow optimizing the size of this type in enums, // but it is not necessarily a valid pointer. // `Weak::new` sets this to `usize::MAX` so that it doesn’t need - // to allocate space on the heap. That's not a value a real poiner - // will ever have because RcBox has alignment at least 4. + // to allocate space on the heap. That's not a value a real pointer + // will ever have because RcBox has alignment at least 2. ptr: NonNull>, }