aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Ben Kimock <kimockb@gmail.com> 2022-04-06 10:59:20 -0400
committerGravatar GitHub <noreply@github.com> 2022-04-06 16:59:20 +0200
commit724476982b35f094b59d160ecc02c042082ac604 (patch)
treee001e4f702e7418f15d83df60a3d13bc606e5a89 /src
parent9e6edd18d297ec1b1bf9e01b1fce7a52eacdd8cc (diff)
downloadbytes-724476982b35f094b59d160ecc02c042082ac604.tar.gz
bytes-724476982b35f094b59d160ecc02c042082ac604.tar.zst
bytes-724476982b35f094b59d160ecc02c042082ac604.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/bytes.rs23
1 files changed, 18 insertions, 5 deletions
diff --git a/src/bytes.rs b/src/bytes.rs
index 753bb5c..24c2137 100644
--- a/src/bytes.rs
+++ b/src/bytes.rs
@@ -2,7 +2,13 @@ use core::iter::FromIterator;
use core::ops::{Deref, RangeBounds};
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;
#[allow(unused)]
@@ -941,11 +947,18 @@ unsafe fn rebuild_boxed_slice(buf: *mut u8, offset: *const u8, len: usize) -> Bo
// ===== impl SharedVtable =====
struct Shared {
- // holds vec for drop, but otherwise doesnt access it
- _vec: Vec<u8>,
+ // Holds arguments to dealloc upon Drop, but otherwise doesn't use them
+ buf: *mut u8,
+ cap: usize,
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.
// This is a necessary invariant since we depend on allocating `Shared` a
// 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
// `Arc`, those three fields still are the components of the
// vector.
- let vec = rebuild_boxed_slice(buf, offset, len).into_vec();
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
// for the new clone that will be returned from
// `shallow_clone`.