Skip to content

arc::Weak::upgrade does not account for overflow #30031

Closed
@apasel422

Description

@apasel422

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 usizes.

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

No one assigned

    Labels

    A-atomicArea: Atomics, barriers, and sync primitivesE-easyCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.I-crashIssue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions