diff options
author | 2019-12-17 13:23:15 -0800 | |
---|---|---|
committer | 2019-12-17 13:23:15 -0800 | |
commit | c7cf71618071933eac2c18471427d30e6a630af5 (patch) | |
tree | eb467f28b5bc5b60c427cea7675d08d487301969 /tests/test_bytes_odd_alloc.rs | |
parent | 8ae3bb2104fda9a02d55ac5635974ca1b5a49ebb (diff) | |
download | bytes-c7cf71618071933eac2c18471427d30e6a630af5.tar.gz bytes-c7cf71618071933eac2c18471427d30e6a630af5.tar.zst bytes-c7cf71618071933eac2c18471427d30e6a630af5.zip |
Fix Bytes when Vec pointer's LSB is set (#346)
This separates the `SharedVtable` into 3:
- `PromotableEvenVtable`: The original `SharedVtable`, which will
promote the `Vec` to `Shared` on the first clone, and is selected when
the `Vec`'s pointer has the LSB unset.
- `PromotableOddVtable`: Similar to the `PromotableEvenVtable`, but
selected when the `Vec`'s pointer has the LSB set. This vtable differs
in the masking used when reconstructing the `Vec`.
- `SharedVtable`: This no longer checks if its current kind is `VEC` or
`ARC`, and is only created by the "promotable" vtables.
This also adds a test using an "odd" global allocator that purposefully
bumps all pointers with alignment of 1.
Closes #343
Diffstat (limited to 'tests/test_bytes_odd_alloc.rs')
-rw-r--r-- | tests/test_bytes_odd_alloc.rs | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/tests/test_bytes_odd_alloc.rs b/tests/test_bytes_odd_alloc.rs new file mode 100644 index 0000000..01e51ea --- /dev/null +++ b/tests/test_bytes_odd_alloc.rs @@ -0,0 +1,67 @@ +//! Test using `Bytes` with an allocator that hands out "odd" pointers for +//! vectors (pointers where the LSB is set). + +use std::alloc::{GlobalAlloc, Layout, System}; +use std::ptr; + +use bytes::Bytes; + +#[global_allocator] +static ODD: Odd = Odd; + +struct Odd; + +unsafe impl GlobalAlloc for Odd { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + if layout.align() == 1 && layout.size() > 0 { + // Allocate slightly bigger so that we can offset the pointer by 1 + let size = layout.size() + 1; + let new_layout = match Layout::from_size_align(size, 1) { + Ok(layout) => layout, + Err(_err) => return ptr::null_mut(), + }; + let ptr = System.alloc(new_layout); + if !ptr.is_null() { + let ptr = ptr.offset(1); + ptr + } else { + ptr + } + } else { + System.alloc(layout) + } + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + if layout.align() == 1 && layout.size() > 0 { + let size = layout.size() + 1; + let new_layout = match Layout::from_size_align(size, 1) { + Ok(layout) => layout, + Err(_err) => std::process::abort(), + }; + System.dealloc(ptr.offset(-1), new_layout); + } else { + System.alloc(layout); + } + } +} + +#[test] +fn sanity_check_odd_allocator() { + let vec = vec![33u8; 1024]; + let p = vec.as_ptr() as usize; + assert!(p & 0x1 == 0x1, "{:#b}", p); +} + +#[test] +fn test_bytes_from_vec_drop() { + let vec = vec![33u8; 1024]; + let _b = Bytes::from(vec); +} + +#[test] +fn test_bytes_clone_drop() { + let vec = vec![33u8; 1024]; + let b1 = Bytes::from(vec); + let _b2 = b1.clone(); +} |