about summary refs log tree commit diff
path: root/src/libstd/sync/mpsc/sync.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-09-03 11:24:01 -0700
committerGitHub <noreply@github.com>2016-09-03 11:24:01 -0700
commit49e9bfdbf24d5cb3cb2b3b7c103fded4682d88cc (patch)
treed127376c1be4101e36b189ee6016a940d27b8bf8 /src/libstd/sync/mpsc/sync.rs
parentd748fa6ecccf6f5b4c7ae4abee0a2d206b165de2 (diff)
parent899c2891e6be24100db723f2b5464969bcebe0f0 (diff)
downloadrust-49e9bfdbf24d5cb3cb2b3b7c103fded4682d88cc.tar.gz
rust-49e9bfdbf24d5cb3cb2b3b7c103fded4682d88cc.zip
Auto merge of #36104 - KiChjang:issue-35847, r=brson
Fix illegal instruction caused by overflow in channel cloning

Fixes #35847.

r? @alexcrichton
Diffstat (limited to 'src/libstd/sync/mpsc/sync.rs')
-rw-r--r--src/libstd/sync/mpsc/sync.rs13
1 files changed, 12 insertions, 1 deletions
diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs
index 9985daaba8f..1d16e002a2b 100644
--- a/src/libstd/sync/mpsc/sync.rs
+++ b/src/libstd/sync/mpsc/sync.rs
@@ -36,6 +36,8 @@
 pub use self::Failure::*;
 use self::Blocker::*;
 
+use core::intrinsics::abort;
+use core::isize;
 use core::mem;
 use core::ptr;
 
@@ -45,6 +47,8 @@ use sync::mpsc::select::StartResult::{self, Installed, Abort};
 use sync::{Mutex, MutexGuard};
 use time::Instant;
 
+const MAX_REFCOUNT: usize = (isize::MAX) as usize;
+
 pub struct Packet<T> {
     /// Only field outside of the mutex. Just done for kicks, but mainly because
     /// the other shared channel already had the code implemented
@@ -350,7 +354,14 @@ impl<T> Packet<T> {
     // Prepares this shared packet for a channel clone, essentially just bumping
     // a refcount.
     pub fn clone_chan(&self) {
-        self.channels.fetch_add(1, Ordering::SeqCst);
+        let old_count = self.channels.fetch_add(1, Ordering::SeqCst);
+
+        // See comments on Arc::clone() on why we do this (for `mem::forget`).
+        if old_count > MAX_REFCOUNT {
+            unsafe {
+                abort();
+            }
+        }
     }
 
     pub fn drop_chan(&self) {