From 904ac08c77c6ffd71a8c00875c5d3f078206e58d Mon Sep 17 00:00:00 2001 From: "William R. Fraser" Date: Wed, 23 Feb 2022 00:04:29 -0800 Subject: [PATCH] FuturesUnordered: fix partial iteration The IntoIter impl advances the head pointer every iteration, but this breaks the linked list invariant that the head's prev should be null. If the iteration is not done to completion, on subsequent drop, FuturesUnordered::unlink relies on this broken invariant and ends up panicking. The fix is to maintain the `head->prev == null` invariant while iterating. --- futures-util/src/stream/futures_unordered/iter.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/futures-util/src/stream/futures_unordered/iter.rs b/futures-util/src/stream/futures_unordered/iter.rs index 04db5ee753..010b79655f 100644 --- a/futures-util/src/stream/futures_unordered/iter.rs +++ b/futures-util/src/stream/futures_unordered/iter.rs @@ -2,6 +2,7 @@ use super::task::Task; use super::FuturesUnordered; use core::marker::PhantomData; use core::pin::Pin; +use core::ptr; use core::sync::atomic::Ordering::Relaxed; /// Mutable iterator over all futures in the unordered set. @@ -58,6 +59,7 @@ impl Iterator for IntoIter { // valid `next_all` checks can be skipped. let next = (**task).next_all.load(Relaxed); *task = next; + *(**task).prev_all.get() = ptr::null_mut(); self.len -= 1; Some(future) }