Skip to content

Commit 00dcea6

Browse files
committed
channel: unbounded: minimal testcase for null pointer dereference
Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
1 parent 4cc0ab5 commit 00dcea6

File tree

2 files changed

+23
-0
lines changed

2 files changed

+23
-0
lines changed

crossbeam-channel/src/flavors/list.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ impl<T> Channel<T> {
236236
.compare_exchange(block, new, Ordering::Release, Ordering::Relaxed)
237237
.is_ok()
238238
{
239+
std::thread::sleep(std::time::Duration::from_secs(2));
239240
self.head.block.store(new, Ordering::Release);
240241
block = new;
241242
} else {

crossbeam-channel/tests/list.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,28 @@ fn ms(ms: u64) -> Duration {
1616
Duration::from_millis(ms)
1717
}
1818

19+
#[test]
20+
fn gh_971() {
21+
let (s1, r) = unbounded::<u64>();
22+
let s2 = s1.clone();
23+
24+
// This thread will sleep for 2000ms at the critical moment
25+
let t1 = thread::spawn(move || assert!(s1.send(42).is_err()));
26+
27+
// Give some time for thread 1 to reach the critical state
28+
thread::sleep(Duration::from_millis(100));
29+
// Send another value which see the tail is not null and will just advance the tail offset to 1
30+
// and write the value.
31+
s2.send(42).unwrap();
32+
33+
// Now drop the receiver which will attempt to drop a message by reading it since head != tail
34+
// but head is still a null pointer because the thread t1 is still preempted leading to a
35+
// segfault.
36+
drop(r);
37+
38+
t1.join().unwrap();
39+
}
40+
1941
#[test]
2042
fn smoke() {
2143
let (s, r) = unbounded();

0 commit comments

Comments
 (0)