Re: [PATCH 13/13] rust: sync: introduce `LockedBy`

From: Benno Lossin
Date: Thu Mar 30 2023 - 07:46:43 EST


On 30.03.23 13:28, Benno Lossin wrote:
> What happens if the the protected data `U` is a ZST? Then the address
> comparing will not work, since all ZST references have the same address.
> For example:
>
> struct Outer {
> mtx: Mutex<()>,
> inners: Vec<Inner>,
> }
>
> struct Inner {
> count: LockedBy<usize, ()>,
> }
>
> fn evil(inner: &Inner) {
> // can create two mutable references at the same time:
> let a = inner.count.access_mut(&mut ());
> let b = inner.count.access_mut(&mut ());
> core::mem::swap(a, b);
> }

Sorry the example I provided does not actually work, since `&mut ()`
refers to a place on the stack. I found a new example that shows ZSTs
are still problematic:

struct Outer {
mtx1: Mutex<()>,
mtx2: Mutex<()>,
inners: Vec<Inner>,
}

struct Inner {
count: LockedBy<usize, ()>,
}

fn new_inner(outer: &Outer) -> Inner {
Inner { count: LockedBy::new(&outer.mtx1, 0) }
}

fn evil(outer: &Outer) {
let inner = outer.inners.get(0).unwrap();
let mut guard1 = outer.mtx1.lock();
let mut guard2 = outer.mtx2.lock();
// The pointee of `guard1` and `guard2` have the same address.
let ref1 = inner.count.access_mut(&mut *guard1);
let ref2 = inner.count.access_mut(&mut *guard2);
mem::swap(ref1, ref2);
}

--
Cheers,
Benno