Skip to content

Commit

Permalink
Fix Bytes::is_unique when created from shared BytesMut (#718)
Browse files Browse the repository at this point in the history
The `is_unique` entry in the vtable for `Bytes` created from a shared
`BytesMut` just called the `shared_is_unique` function from the `bytes`
module. However, that function dereferences the `data` argument` as
`bytes::Shared`, but the actual underlying type is `bytes_mut::Shared`.
  • Loading branch information
zyxw59 committed Jul 12, 2024
1 parent ce8d8a0 commit 6b4b0ed
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/bytes_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1698,7 +1698,7 @@ unsafe fn rebuild_vec(ptr: *mut u8, mut len: usize, mut cap: usize, off: usize)
static SHARED_VTABLE: Vtable = Vtable {
clone: shared_v_clone,
to_vec: shared_v_to_vec,
is_unique: crate::bytes::shared_is_unique,
is_unique: shared_v_is_unique,
drop: shared_v_drop,
};

Expand Down Expand Up @@ -1732,6 +1732,12 @@ unsafe fn shared_v_to_vec(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> V
}
}

unsafe fn shared_v_is_unique(data: &AtomicPtr<()>) -> bool {
let shared = data.load(Ordering::Acquire);
let ref_count = (*shared.cast::<Shared>()).ref_count.load(Ordering::Relaxed);
ref_count == 1
}

unsafe fn shared_v_drop(data: &mut AtomicPtr<()>, _ptr: *const u8, _len: usize) {
data.with_mut(|shared| {
release_shared(*shared as *mut Shared);
Expand Down
9 changes: 9 additions & 0 deletions tests/test_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1172,3 +1172,12 @@ fn shared_is_unique() {
drop(b);
assert!(c.is_unique());
}

#[test]
fn mut_shared_is_unique() {
let mut b = BytesMut::from(LONG);
let c = b.split().freeze();
assert!(!c.is_unique());
drop(b);
assert!(c.is_unique());
}

0 comments on commit 6b4b0ed

Please sign in to comment.