From 73b4597dec5b4dd27b64a6a117945ced99ffe6c6 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Thu, 1 Sep 2022 16:01:48 +0530 Subject: [PATCH] fix(serde_v8): update bytes::Bytes layout assumptions (#15718) --- Cargo.lock | 4 ++-- serde_v8/Cargo.toml | 2 +- serde_v8/magic/rawbytes.rs | 24 ++++++++++++++++++++++++ serde_v8/magic/v8slice.rs | 13 +++++++++++++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4d3977088a..3d82df7c71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -398,9 +398,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "cache_control" diff --git a/serde_v8/Cargo.toml b/serde_v8/Cargo.toml index 3dc05912cc..dba85b240a 100644 --- a/serde_v8/Cargo.toml +++ b/serde_v8/Cargo.toml @@ -13,7 +13,7 @@ description = "Rust to V8 serialization and deserialization" path = "lib.rs" [dependencies] -bytes = "1" +bytes = "=1.2.1" derive_more = "0.99.17" serde = { version = "1.0.136", features = ["derive"] } serde_bytes = "0.11" diff --git a/serde_v8/magic/rawbytes.rs b/serde_v8/magic/rawbytes.rs index 4e41d313a5..b451437117 100644 --- a/serde_v8/magic/rawbytes.rs +++ b/serde_v8/magic/rawbytes.rs @@ -26,11 +26,25 @@ impl RawBytes { } } +// Validate some bytes::Bytes layout assumptions at compile time. +const _: () = { + assert!( + core::mem::size_of::() == core::mem::size_of::(), + ); + assert!( + core::mem::align_of::() == core::mem::align_of::(), + ); +}; + #[allow(unused)] pub(crate) struct Vtable { /// fn(data, ptr, len) pub clone: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> bytes::Bytes, /// fn(data, ptr, len) + /// + /// takes `Bytes` to value + pub to_vec: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> Vec, + /// fn(data, ptr, len) pub drop: unsafe fn(&mut AtomicPtr<()>, *const u8, usize), } @@ -55,6 +69,7 @@ mod tests { const STATIC_VTABLE: Vtable = Vtable { clone: static_clone, drop: static_drop, + to_vec: static_to_vec, }; unsafe fn static_clone( @@ -65,6 +80,15 @@ mod tests { from_static(std::slice::from_raw_parts(ptr, len)).into() } + unsafe fn static_to_vec( + _: &AtomicPtr<()>, + ptr: *const u8, + len: usize, + ) -> Vec { + let slice = std::slice::from_raw_parts(ptr, len); + slice.to_vec() + } + unsafe fn static_drop(_: &mut AtomicPtr<()>, _: *const u8, _: usize) { // nothing to drop for &'static [u8] } diff --git a/serde_v8/magic/v8slice.rs b/serde_v8/magic/v8slice.rs index 4772abd426..a1c01b888c 100644 --- a/serde_v8/magic/v8slice.rs +++ b/serde_v8/magic/v8slice.rs @@ -146,6 +146,7 @@ impl From for bytes::Bytes { const V8SLICE_VTABLE: rawbytes::Vtable = rawbytes::Vtable { clone: v8slice_clone, drop: v8slice_drop, + to_vec: v8slice_to_vec, }; unsafe fn v8slice_clone( @@ -161,6 +162,18 @@ unsafe fn v8slice_clone( rawbytes::RawBytes::new_raw(ptr, len, data.cast(), &V8SLICE_VTABLE) } +unsafe fn v8slice_to_vec( + data: &rawbytes::AtomicPtr<()>, + ptr: *const u8, + len: usize, +) -> Vec { + let rc = Rc::from_raw(*data as *const V8Slice); + std::mem::forget(rc); + // NOTE: `bytes::Bytes` does bounds checking so we trust its ptr, len inputs + // and must use them to allow cloning Bytes it has sliced + Vec::from_raw_parts(ptr as _, len, len) +} + unsafe fn v8slice_drop( data: &mut rawbytes::AtomicPtr<()>, _: *const u8,