Closed
Description
Similar to the issue fixed in #27174, these two methods do not account for overflow, causing use-after-frees in extremely contrived situations on machines with 32-bit usize
s.
Both of these examples exhibit the erroneous behavior when compiled and run with -C opt-level=3 --target=i686-unknown-linux-gnu
:
downgrade.rs
:
use std::sync::Arc;
fn main() {
let a = Arc::new("42".to_owned());
for _ in 0..std::usize::MAX - 2 {
let w = Arc::downgrade(&a); // add 1 to the weak count
std::mem::forget(w); // avoid decrementing the weak count
}
// the weak count is now `std::usize::MAX - 1`
{
let w = Arc::downgrade(&a); // add 1 to the weak count
let x = w.clone(); // add 1 to the weak count so it wraps to 0
drop(w); // drop `w`, deallocating the underlying `String`
drop(x); // drop `x`, trying to deallocate the same `String`
}
}
upgrade.rs
:
use std::sync::Arc;
fn main() {
let a = Arc::new("42".to_owned());
let w = Arc::downgrade(&a);
for _ in 0..std::usize::MAX - 1 {
let b = w.upgrade(); // add 1 to the strong count
std::mem::forget(b); // avoid decrementing the strong count
}
// the strong count is now `std::usize::MAX`
{
let b = w.upgrade().unwrap(); // add 1 to the strong count so it wraps to 0
let c = b.clone(); // add 1 to the strong count so it is 1
drop(c); // drop `c`, dropping the underlying `String`
}
println!("{:?}", a); // accesses the dropped `String`
}
Note that I've been working on a general consolidation of both reference-counted types at https://github.com/apasel422/ref_count.
Metadata
Metadata
Assignees
Labels
Area: Atomics, barriers, and sync primitivesCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics.Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness