about summary refs log tree commit diff
path: root/src/liballoc
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2018-07-23 11:13:20 +0200
committerRalf Jung <post@ralfj.de>2018-07-23 11:31:55 +0200
commit33b8f6253fe18af5bc882cf885d68538c90dab62 (patch)
treef28bafed0cc0a842fe6cecc9ca4e7b7373d5246b /src/liballoc
parent210d61f05c8c2f9e58f167eb28ab9d8bbef4968b (diff)
downloadrust-33b8f6253fe18af5bc882cf885d68538c90dab62.tar.gz
rust-33b8f6253fe18af5bc882cf885d68538c90dab62.zip
Don't use NonNull::dangling as sentinel value
Instead, rely on alignment and use usize::MAX as sentinel.
Diffstat (limited to 'src/liballoc')
-rw-r--r--src/liballoc/rc.rs13
-rw-r--r--src/liballoc/sync.rs13
2 files changed, 17 insertions, 9 deletions
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index d76acb28df9..b50bf5c15d5 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<T: ?Sized> Rc<T> {
     #[stable(feature = "rc_weak", since = "1.4.0")]
     pub fn downgrade(this: &Self) -> Weak<T> {
         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<T> From<Vec<T>> for Rc<[T]> {
 pub struct Weak<T: ?Sized> {
     // 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<RcBox<T>>,
 }
 
@@ -1185,15 +1189,14 @@ impl<T> Weak<T> {
     #[stable(feature = "downgraded_weak", since = "1.10.0")]
     pub fn new() -> Weak<T> {
         Weak {
-            ptr: NonNull::dangling(),
+            ptr: NonNull::new(usize::MAX as *mut RcBox<T>).expect("MAX is not 0"),
         }
     }
 }
 
 pub(crate) fn is_dangling<T: ?Sized>(ptr: NonNull<T>) -> 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<T: ?Sized> Weak<T> {
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index 5def0237e7e..4c14fef9b31 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -238,8 +238,9 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
 pub struct Weak<T: ?Sized> {
     // 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<ArcInner<T>>,
 }
 
@@ -442,7 +443,11 @@ impl<T: ?Sized> Arc<T> {
             // 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<T> Weak<T> {
     #[stable(feature = "downgraded_weak", since = "1.10.0")]
     pub fn new() -> Weak<T> {
         Weak {
-            ptr: NonNull::dangling(),
+            ptr: NonNull::new(usize::MAX as *mut ArcInner<T>).expect("MAX is not 0"),
         }
     }
 }