Skip to content

fmt::Arguments is Send+Sync regardless of its captured arguments #45197

Closed
@cuviper

Description

@cuviper
Member

fmt::Arguments<'a> is only parameterized on lifetime. The types of the captured arguments are erased in the contained [ArgumentV1<'a>]. Nothing restricts the Arguments aggregate from being Send or Sync, so by OIBIT it's both. Thus this compiles:

fn send<T: Send>(_: T) {}
fn sync<T: Sync>(_: T) {}

fn main() {
    // `Cell` is not `Sync`, so `&Cell` is neither `Sync` nor `Send`,
    // yet `std::fmt::Arguments` forgets this...
    let c = std::cell::Cell::new(42);
    send(format_args!("{:?}", c));
    sync(format_args!("{:?}", c));
}

I'm not sure if there are any realistic ways to accidentally abuse this, but here's a deliberate example. The spawned thread will read the Cell through the arguments, even while the main thread modifies it.

extern crate crossbeam;

use std::io::Write;
use std::cell::Cell;

fn main() {
    let c = Cell::new(1);
    threader(&c, format_args!("{:?}\n", c));
}

fn threader(c: &Cell<i32>, a: std::fmt::Arguments) {
    crossbeam::scope(|scope| {
        let delay = std::time::Duration::from_millis(100);
        
        let guard = scope.spawn(move || {
            for _ in 0..10 {
                std::thread::sleep(delay);
                std::io::stdout().write_fmt(a).unwrap();
            }
        });
        
        for _ in 0..10 {
            std::thread::sleep(delay);
            c.set(c.get() * 2);
        }
        
        guard.join();
    });
}

playground

Activity

added a commit that references this issue on Oct 11, 2017
787f9f4
reopened this on Oct 11, 2017
added
I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness
on Oct 11, 2017
added
T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.
on Oct 11, 2017
added a commit that references this issue on Nov 22, 2017

Auto merge of #45198 - oli-obk:fmt_args, r=sfackler

1dc0b57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-highHigh priorityT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @steveklabnik@cuviper@alexcrichton@bstrie@sfackler

        Issue actions

          `fmt::Arguments` is `Send+Sync` regardless of its captured arguments · Issue #45197 · rust-lang/rust