Skip to content

BitVec and BitBox are Sync for any BitStore, including Cell #314

Description

@fereidani

Hey, I've found this while scanning the top 5000 downloaded crates with my UB static analyzer.

src/vec/traits.rs:397 and src/boxed/traits.rs:379:

unsafe impl<T, O> Sync for BitVec<T, O>
where
	T: BitStore,
	O: BitOrder,
{
}

There is no T: Sync bound, and Cell<u8> is a shipped BitStore (src/store.rs:159). So safe code can build a BitVec<Cell<u8>, Lsb0>, share it with another thread because the type claims Sync, call the safe as_raw_slice(&self) on both threads, and write through the &[Cell<u8>] from both. That is a plain data race.

use bitvec::prelude::*;
use std::cell::Cell;
use std::sync::{Arc, Barrier};
use std::thread;

#[test]
fn two_threads_write_one_cell() {
    let bv: BitVec<Cell<u8>, Lsb0> = BitVec::from_element(Cell::new(0u8));
    let bv: &'static BitVec<Cell<u8>, Lsb0> = Box::leak(Box::new(bv));

    let barrier = Arc::new(Barrier::new(2));
    let other = barrier.clone();

    let h = thread::spawn(move || {
        let raw = bv.as_raw_slice();
        other.wait();
        raw[0].set(1);
    });

    let raw = bv.as_raw_slice();
    barrier.wait();
    raw[0].set(2);
    h.join().unwrap();
}
$ cargo +nightly miri test

test two_threads_write_one_cell ... error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `unnamed-2` and (2) retag write of type `u8` on thread `two_threads_wri` at alloc41122
   --> library/core/src/cell.rs:516:31
    |
516 |         mem::replace(unsafe { &mut *self.value.get() }, val)
    |                               ^^^^^^^^^^^^^^^^^^^^^^ (2) just happened here
help: and (1) occurred earlier here
   --> tests/bitvec.rs:17:9
    |
 17 |         raw[0].set(1);
    |         ^^^^^^^^^^^^^

Fix would be to add T: Sync to both Sync impls (and T: Send to the matching Send impls). The Cell and unsynchronized BitStore types then stop being Sync, which is the intent.

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions