mirror of
https://github.com/tokio-rs/bytes.git
synced 2026-08-25 00:00:22 +02:00
Fix aliasing in Clone by using a raw pointer (#523)
Previously, this code produced a &mut[u8] and a Box<[u8]> to the shared allocation upon cloning it. If the underlying allocation were actually shared, such as through a &[u8] from the Deref impl, creating either of these types incorrectly asserted uniqueness of the allocation. This fixes the example in #522, but Miri still does not pass on this test suite with -Zmiri-tag-raw-pointers because Miri does not currently understand int to pointer casts.
This commit is contained in:
+18
-5
@@ -2,7 +2,13 @@ use core::iter::FromIterator;
|
|||||||
use core::ops::{Deref, RangeBounds};
|
use core::ops::{Deref, RangeBounds};
|
||||||
use core::{cmp, fmt, hash, mem, ptr, slice, usize};
|
use core::{cmp, fmt, hash, mem, ptr, slice, usize};
|
||||||
|
|
||||||
use alloc::{borrow::Borrow, boxed::Box, string::String, vec::Vec};
|
use alloc::{
|
||||||
|
alloc::{dealloc, Layout},
|
||||||
|
borrow::Borrow,
|
||||||
|
boxed::Box,
|
||||||
|
string::String,
|
||||||
|
vec::Vec,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::buf::IntoIter;
|
use crate::buf::IntoIter;
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
@@ -941,11 +947,18 @@ unsafe fn rebuild_boxed_slice(buf: *mut u8, offset: *const u8, len: usize) -> Bo
|
|||||||
// ===== impl SharedVtable =====
|
// ===== impl SharedVtable =====
|
||||||
|
|
||||||
struct Shared {
|
struct Shared {
|
||||||
// holds vec for drop, but otherwise doesnt access it
|
// Holds arguments to dealloc upon Drop, but otherwise doesn't use them
|
||||||
_vec: Vec<u8>,
|
buf: *mut u8,
|
||||||
|
cap: usize,
|
||||||
ref_cnt: AtomicUsize,
|
ref_cnt: AtomicUsize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for Shared {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe { dealloc(self.buf, Layout::from_size_align(self.cap, 1).unwrap()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Assert that the alignment of `Shared` is divisible by 2.
|
// Assert that the alignment of `Shared` is divisible by 2.
|
||||||
// This is a necessary invariant since we depend on allocating `Shared` a
|
// This is a necessary invariant since we depend on allocating `Shared` a
|
||||||
// shared object to implicitly carry the `KIND_ARC` flag in its pointer.
|
// shared object to implicitly carry the `KIND_ARC` flag in its pointer.
|
||||||
@@ -1006,9 +1019,9 @@ unsafe fn shallow_clone_vec(
|
|||||||
// updated and since the buffer hasn't been promoted to an
|
// updated and since the buffer hasn't been promoted to an
|
||||||
// `Arc`, those three fields still are the components of the
|
// `Arc`, those three fields still are the components of the
|
||||||
// vector.
|
// vector.
|
||||||
let vec = rebuild_boxed_slice(buf, offset, len).into_vec();
|
|
||||||
let shared = Box::new(Shared {
|
let shared = Box::new(Shared {
|
||||||
_vec: vec,
|
buf,
|
||||||
|
cap: (offset as usize - buf as usize) + len,
|
||||||
// Initialize refcount to 2. One for this reference, and one
|
// Initialize refcount to 2. One for this reference, and one
|
||||||
// for the new clone that will be returned from
|
// for the new clone that will be returned from
|
||||||
// `shallow_clone`.
|
// `shallow_clone`.
|
||||||
|
|||||||
Reference in New Issue
Block a user