Skip to content

Commit

Permalink
Fix illegal instruction caused by overflow in channel cloning
Browse files Browse the repository at this point in the history
  • Loading branch information
KiChjang committed Aug 29, 2016
1 parent e4791e0 commit 899c289
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 4 deletions.
15 changes: 12 additions & 3 deletions src/libstd/sync/mpsc/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
pub use self::Failure::*;

use core::cmp;
use core::intrinsics::abort;
use core::isize;

use sync::atomic::{AtomicUsize, AtomicIsize, AtomicBool, Ordering};
Expand All @@ -34,6 +35,7 @@ use time::Instant;

const DISCONNECTED: isize = isize::MIN;
const FUDGE: isize = 1024;
const MAX_REFCOUNT: usize = (isize::MAX) as usize;
#[cfg(test)]
const MAX_STEALS: isize = 5;
#[cfg(not(test))]
Expand All @@ -46,7 +48,7 @@ pub struct Packet<T> {
to_wake: AtomicUsize, // SignalToken for wake up

// The number of channels which are currently using this packet.
channels: AtomicIsize,
channels: AtomicUsize,

// See the discussion in Port::drop and the channel send methods for what
// these are used for
Expand All @@ -72,7 +74,7 @@ impl<T> Packet<T> {
cnt: AtomicIsize::new(0),
steals: 0,
to_wake: AtomicUsize::new(0),
channels: AtomicIsize::new(2),
channels: AtomicUsize::new(2),
port_dropped: AtomicBool::new(false),
sender_drain: AtomicIsize::new(0),
select_lock: Mutex::new(()),
Expand Down Expand Up @@ -340,7 +342,14 @@ impl<T> Packet<T> {
// Prepares this shared packet for a channel clone, essentially just bumping
// a refcount.
pub fn clone_chan(&mut 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();
}
}
}

// Decrement the reference count on a channel. This is called whenever a
Expand Down
13 changes: 12 additions & 1 deletion src/libstd/sync/mpsc/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
pub use self::Failure::*;
use self::Blocker::*;

use core::intrinsics::abort;
use core::isize;
use core::mem;
use core::ptr;

Expand All @@ -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
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 899c289

Please sign in to comment.