VYPR
Moderate severityNVD Advisory· Published Dec 31, 2020· Updated Aug 4, 2024

CVE-2020-35908

CVE-2020-35908

Description

An issue was discovered in the futures-util crate before 0.3.2 for Rust. FuturesUnordered can lead to data corruption because Sync is mishandled.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

CVE-2020-35908: Improper Sync implementation in futures-util's FuturesUnordered can cause data corruption in concurrent Rust programs.

Vulnerability

Overview

CVE-2020-35908 is a thread-safety vulnerability in the futures-util crate (part of the futures-rs library) for Rust, affecting versions prior to 0.3.2. The root cause is an improper implementation of the Sync trait on the FuturesUnordered type [1]. Specifically, after a refactoring that replaced RefCell with Cell for interior mutability of the len and head_all fields (in commit 47f3ccb), the existing Sync implementation was retained, although Cell provides no synchronization guarantees [4]. This violates Rust's thread-safety guarantees because Sync signals that a type is safe to share via shared references across threads, whereas FuturesUnordered does not perform any actual synchronization when mutating those fields (e.g., in the push method) [1][4].

Exploitation

Conditions

To exploit this vulnerability, an attacker must be able to construct a program that shares a FuturesUnordered instance across multiple threads using shared references. This typically requires local access to execute malicious code (CVSS attack vector: Local) and low privileges [1]. No user interaction is needed. The issue surfaces when concurrent, unsynchronized modifications to the FuturesUnordered's internal state are made, leading to data races [1][2].

Impact

An attacker exploiting this race condition can cause data corruption in internal data structures, ultimately leading to memory corruption [1]. Although confidentiality and integrity are not directly compromised, the impact on availability is rated High, as successful exploitation may result in crashes or unpredictable behavior [1]. The advisory classifies this as a memory-corruption and thread-safety vulnerability [1].

Mitigation

The vulnerability is fixed in futures-util version 0.3.2 [1][2]. Users should upgrade to at least that version. The fix involved removing the incorrect Sync implementation from FuturesUnordered, preventing its use across threads without explicit synchronization [1][4]. No workaround is available other than upgrading.

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
futures-utilcrates.io
>= 0.3.0, < 0.3.20.3.2

Affected products

2

Patches

1
b825f3079446

Stage 0.3.2

https://github.com/rust-lang/futures-rsTaylor CramerFeb 3, 2020via osv
12 files changed · +60 45
  • CHANGELOG.md+16 1 modified
    @@ -1,5 +1,20 @@
    -# 0.3.2 - 2020-??-??
    +# 0.3.2 - 2020-02-03
    +* Improved buffering performance of `SplitSink` (#1969)
    +* Added `select_biased!` macro (#1976)
    +* Added `hash_receiver` method to mpsc channel (#1962)
    +* Added `stream::try_unfold` (#1977)
    +* Fixed bug with zero-size buffers in vectored IO (#1998)
    +* `AtomicWaker::new()` is now `const fn` (#2007)
    +* Fixed bug between threadpool and user park/unparking (#2010)
    +* Added `stream::Peakable::peek` (#2021)
    +* Added `StreamExt::scan` (#2044)
    +* Added impl of `AsyncRead`/`Write` for `BufReader`/`Writer` (#2033)
    +* Added impl of `Spawn` and `LocalSpawn` for `Arc<impl Spawn` and `Rc<impl Spawn>` (#2039)
    +* Fixed `Sync` issues with `FuturesUnordered` (#2054)
     * Added `into_inner` method for `future::Ready` (#2055)
    +* Added `MappedMutexGuard` API (#2056)
    +* Mitigated starvation issues in `FuturesUnordered` (#2049)
    +* Added `TryFutureExt::map_ok_or_else` (#2058)
     
     # 0.3.1 - 2019-11-7
     * Fix signature of `LocalSpawn` trait (breaking change -- see #1959)
    
  • futures/Cargo.toml+10 10 modified
    @@ -1,7 +1,7 @@
     [package]
     name = "futures"
     edition = "2018"
    -version = "0.3.1"
    +version = "0.3.2"
     authors = ["Alex Crichton <alex@alexcrichton.com>"]
     license = "MIT OR Apache-2.0"
     readme = "../README.md"
    @@ -19,18 +19,18 @@ categories = ["asynchronous"]
     travis-ci = { repository = "rust-lang/futures-rs" }
     
     [dependencies]
    -futures-core = { path = "../futures-core", version = "0.3.1", default-features = false }
    -futures-task = { path = "../futures-task", version = "0.3.1", default-features = false }
    -futures-channel = { path = "../futures-channel", version = "0.3.1", default-features = false, features = ["sink"] }
    -futures-executor = { path = "../futures-executor", version = "0.3.1", default-features = false, optional = true }
    -futures-io = { path = "../futures-io", version = "0.3.1", default-features = false }
    -futures-sink = { path = "../futures-sink", version = "0.3.1", default-features = false }
    -futures-util = { path = "../futures-util", version = "0.3.1", default-features = false, features = ["sink"] }
    +futures-core = { path = "../futures-core", version = "0.3.2", default-features = false }
    +futures-task = { path = "../futures-task", version = "0.3.2", default-features = false }
    +futures-channel = { path = "../futures-channel", version = "0.3.2", default-features = false, features = ["sink"] }
    +futures-executor = { path = "../futures-executor", version = "0.3.2", default-features = false, optional = true }
    +futures-io = { path = "../futures-io", version = "0.3.2", default-features = false }
    +futures-sink = { path = "../futures-sink", version = "0.3.2", default-features = false }
    +futures-util = { path = "../futures-util", version = "0.3.2", default-features = false, features = ["sink"] }
     
     [dev-dependencies]
     pin-utils = "0.1.0-alpha.4"
    -futures-executor = { path = "../futures-executor", version = "0.3.1", features = ["thread-pool"] }
    -futures-test = { path = "../futures-test", version = "0.3.1" }
    +futures-executor = { path = "../futures-executor", version = "0.3.2", features = ["thread-pool"] }
    +futures-test = { path = "../futures-test", version = "0.3.2" }
     tokio = "0.1.11"
     assert_matches = "1.3.0"
     
    
  • futures-channel/Cargo.toml+5 5 modified
    @@ -1,7 +1,7 @@
     [package]
     name = "futures-channel"
     edition = "2018"
    -version = "0.3.1"
    +version = "0.3.2"
     authors = ["Alex Crichton <alex@alexcrichton.com>"]
     license = "MIT OR Apache-2.0"
     repository = "https://github.com/rust-lang/futures-rs"
    @@ -24,12 +24,12 @@ unstable = ["futures-core/unstable"]
     cfg-target-has-atomic = ["futures-core/cfg-target-has-atomic"]
     
     [dependencies]
    -futures-core = { path = "../futures-core", version = "0.3.1", default-features = false }
    -futures-sink = { path = "../futures-sink", version = "0.3.1", default-features = false, optional = true }
    +futures-core = { path = "../futures-core", version = "0.3.2", default-features = false }
    +futures-sink = { path = "../futures-sink", version = "0.3.2", default-features = false, optional = true }
     
     [dev-dependencies]
    -futures = { path = "../futures", version = "0.3.1", default-features = true }
    -futures-test = { path = "../futures-test", version = "0.3.1", default-features = true }
    +futures = { path = "../futures", version = "0.3.2", default-features = true }
    +futures-test = { path = "../futures-test", version = "0.3.2", default-features = true }
     
     [package.metadata.docs.rs]
     all-features = true
    
  • futures-core/Cargo.toml+2 2 modified
    @@ -1,7 +1,7 @@
     [package]
     name = "futures-core"
     edition = "2018"
    -version = "0.3.1"
    +version = "0.3.2"
     authors = ["Alex Crichton <alex@alexcrichton.com>"]
     license = "MIT OR Apache-2.0"
     repository = "https://github.com/rust-lang/futures-rs"
    @@ -25,7 +25,7 @@ cfg-target-has-atomic = []
     [dependencies]
     
     [dev-dependencies]
    -futures = { path = "../futures", version = "0.3.1" }
    +futures = { path = "../futures", version = "0.3.2" }
     
     [package.metadata.docs.rs]
     all-features = true
    
  • futures-executor/Cargo.toml+5 5 modified
    @@ -1,7 +1,7 @@
     [package]
     name = "futures-executor"
     edition = "2018"
    -version = "0.3.1"
    +version = "0.3.2"
     authors = ["Alex Crichton <alex@alexcrichton.com>"]
     license = "MIT OR Apache-2.0"
     repository = "https://github.com/rust-lang/futures-rs"
    @@ -17,13 +17,13 @@ std = ["futures-core/std", "futures-task/std", "futures-util/std"]
     thread-pool = ["std", "num_cpus"]
     
     [dependencies]
    -futures-core = { path = "../futures-core", version = "0.3.1", default-features = false }
    -futures-task = { path = "../futures-task", version = "0.3.1", default-features = false }
    -futures-util = { path = "../futures-util", version = "0.3.1", default-features = false }
    +futures-core = { path = "../futures-core", version = "0.3.2", default-features = false }
    +futures-task = { path = "../futures-task", version = "0.3.2", default-features = false }
    +futures-util = { path = "../futures-util", version = "0.3.2", default-features = false }
     num_cpus = { version = "1.8.0", optional = true }
     
     [dev-dependencies]
    -futures = { path = "../futures", version = "0.3.1" }
    +futures = { path = "../futures", version = "0.3.2" }
     
     [package.metadata.docs.rs]
     all-features = true
    
  • futures-io/Cargo.toml+1 1 modified
    @@ -1,7 +1,7 @@
     [package]
     name = "futures-io"
     edition = "2018"
    -version = "0.3.1"
    +version = "0.3.2"
     authors = ["Alex Crichton <alex@alexcrichton.com>"]
     license = "MIT OR Apache-2.0"
     repository = "https://github.com/rust-lang/futures-rs"
    
  • futures-macro/Cargo.toml+1 1 modified
    @@ -1,7 +1,7 @@
     [package]
     name = "futures-macro"
     edition = "2018"
    -version = "0.3.1"
    +version = "0.3.2"
     authors = ["Taylor Cramer <cramertj@google.com>", "Taiki Endo <te316e89@gmail.com>"]
     license = "MIT OR Apache-2.0"
     repository = "https://github.com/rust-lang/futures-rs"
    
  • futures-sink/Cargo.toml+1 1 modified
    @@ -1,7 +1,7 @@
     [package]
     name = "futures-sink"
     edition = "2018"
    -version = "0.3.1"
    +version = "0.3.2"
     authors = ["Alex Crichton <alex@alexcrichton.com>"]
     license = "MIT OR Apache-2.0"
     repository = "https://github.com/rust-lang/futures-rs"
    
  • futures-task/Cargo.toml+2 2 modified
    @@ -1,7 +1,7 @@
     [package]
     name = "futures-task"
     edition = "2018"
    -version = "0.3.1"
    +version = "0.3.2"
     authors = ["Alex Crichton <alex@alexcrichton.com>"]
     license = "MIT OR Apache-2.0"
     repository = "https://github.com/rust-lang/futures-rs"
    @@ -25,7 +25,7 @@ cfg-target-has-atomic = []
     [dependencies]
     
     [dev-dependencies]
    -futures = { path = "../futures", version = "0.3.1" }
    +futures = { path = "../futures", version = "0.3.2" }
     
     [package.metadata.docs.rs]
     all-features = true
    
  • futures-test/Cargo.toml+7 7 modified
    @@ -1,7 +1,7 @@
     [package]
     name = "futures-test"
     edition = "2018"
    -version = "0.3.1"
    +version = "0.3.2"
     authors = ["Wim Looman <wim@nemo157.com>"]
     license = "MIT OR Apache-2.0"
     repository = "https://github.com/rust-lang/futures-rs"
    @@ -12,15 +12,15 @@ Common utilities for testing components built off futures-rs.
     """
     
     [dependencies]
    -futures-core = { version = "0.3.1", path = "../futures-core", default-features = false }
    -futures-task = { version = "0.3.1", path = "../futures-task", default-features = false }
    -futures-io = { version = "0.3.1", path = "../futures-io", default-features = false }
    -futures-util = { version = "0.3.1", path = "../futures-util", default-features = false }
    -futures-executor = { version = "0.3.1", path = "../futures-executor", default-features = false }
    +futures-core = { version = "0.3.2", path = "../futures-core", default-features = false }
    +futures-task = { version = "0.3.2", path = "../futures-task", default-features = false }
    +futures-io = { version = "0.3.2", path = "../futures-io", default-features = false }
    +futures-util = { version = "0.3.2", path = "../futures-util", default-features = false }
    +futures-executor = { version = "0.3.2", path = "../futures-executor", default-features = false }
     pin-utils = { version = "0.1.0-alpha.4", default-features = false }
     
     [dev-dependencies]
    -futures = { version = "0.3.1", path = "../futures", default-features = false, features = ["std"] }
    +futures = { version = "0.3.2", path = "../futures", default-features = false, features = ["std"] }
     
     [features]
     default = ["std"]
    
  • futures-util/Cargo.toml+9 9 modified
    @@ -1,7 +1,7 @@
     [package]
     name = "futures-util"
     edition = "2018"
    -version = "0.3.1"
    +version = "0.3.2"
     authors = ["Alex Crichton <alex@alexcrichton.com>"]
     license = "MIT OR Apache-2.0"
     repository = "https://github.com/rust-lang/futures-rs"
    @@ -32,12 +32,12 @@ bilock = []
     read-initializer = ["io", "futures-io/read-initializer", "futures-io/unstable"]
     
     [dependencies]
    -futures-core = { path = "../futures-core", version = "0.3.1", default-features = false }
    -futures-task = { path = "../futures-task", version = "0.3.1", default-features = false }
    -futures-channel = { path = "../futures-channel", version = "0.3.1", default-features = false, features = ["std"], optional = true }
    -futures-io = { path = "../futures-io", version = "0.3.1", default-features = false, features = ["std"], optional = true }
    -futures-sink = { path = "../futures-sink", version = "0.3.1", default-features = false, optional = true }
    -futures-macro = { path = "../futures-macro", version = "0.3.1", default-features = false, optional = true }
    +futures-core = { path = "../futures-core", version = "0.3.2", default-features = false }
    +futures-task = { path = "../futures-task", version = "0.3.2", default-features = false }
    +futures-channel = { path = "../futures-channel", version = "0.3.2", default-features = false, features = ["std"], optional = true }
    +futures-io = { path = "../futures-io", version = "0.3.2", default-features = false, features = ["std"], optional = true }
    +futures-sink = { path = "../futures-sink", version = "0.3.2", default-features = false, optional = true }
    +futures-macro = { path = "../futures-macro", version = "0.3.2", default-features = false, optional = true }
     proc-macro-hack = { version = "0.5.9", optional = true }
     proc-macro-nested = { version = "0.1.2", optional = true }
     slab = { version = "0.4", optional = true }
    @@ -47,8 +47,8 @@ tokio-io = { version = "0.1.9", optional = true }
     pin-utils = "0.1.0-alpha.4"
     
     [dev-dependencies]
    -futures = { path = "../futures", version = "0.3.1", features = ["async-await"] }
    -futures-test = { path = "../futures-test", version = "0.3.1" }
    +futures = { path = "../futures", version = "0.3.2", features = ["async-await"] }
    +futures-test = { path = "../futures-test", version = "0.3.2" }
     tokio = "0.1.11"
     
     [package.metadata.docs.rs]
    
  • README.md+1 1 modified
    @@ -58,7 +58,7 @@ a `#[no_std]` environment, use:
     
     ```toml
     [dependencies]
    -futures = { version = "0.3.1", default-features = false }
    +futures = { version = "0.3.2", default-features = false }
     ```
     
     # License
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.