Skip to content

Commit 43ea0b5

Browse files
authored
feat(io): fix ancillary API to avoid UB (#737)
* feat(io): new AncillaryBuf::build() API * fix(io): redo new AncillaryBuilder API * fix(io): address CR issues * fix(io): fix API to avoid UB * fix(io): gate libc::in_pktinfo for Linux/Android * fix(io): replace with Pod, fix hirarchy and docs * fix(io,quic): fix decode_data(), propagate error * fix(quic): unsafe union access on Windows * chore(quic): use helpful panic message * fix(io): enable bytemuck:min_const_generics
1 parent 3ee37ca commit 43ea0b5

11 files changed

Lines changed: 696 additions & 122 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ compio-quic = { path = "./compio-quic", version = "0.7.0", default-features = fa
4040
compio-ws = { path = "./compio-ws", version = "0.3.0", default-features = false }
4141

4242
bytes = "1.7.1"
43+
bytemuck = "1.25.0"
4344
cfg_aliases = "0.2.1"
4445
cfg-if = "1.0.0"
4546
compio-send-wrapper = "0.7.0"

compio-io/Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ cfg-if = { workspace = true, optional = true }
2020
thiserror = { workspace = true, optional = true }
2121
serde = { version = "1.0.219", optional = true }
2222
serde_json = { version = "1.0.140", optional = true }
23+
bytemuck = { workspace = true, optional = true, features = ["min_const_generics"] }
2324

2425
[target.'cfg(unix)'.dependencies]
2526
libc = { workspace = true, optional = true }
@@ -30,7 +31,6 @@ windows-sys = { workspace = true, optional = true, features = [
3031
] }
3132

3233
[dev-dependencies]
33-
aligned-array = "1.0.1"
3434
tokio = { workspace = true, features = ["macros", "rt"] }
3535
serde = { version = "1.0.219", features = ["derive"] }
3636
futures-executor = "0.3.30"
@@ -58,3 +58,7 @@ required-features = ["compat"]
5858
[[test]]
5959
name = "framed"
6060
required-features = ["codec-serde-json"]
61+
62+
[[test]]
63+
name = "ancillary"
64+
required-features = ["ancillary"]
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//! Extension module for automatic [`AncillaryData`] implementation via
2+
//! bytemuck.
3+
//!
4+
//! See [`BitwiseAncillaryData`] for details.
5+
6+
use std::mem::MaybeUninit;
7+
8+
pub use bytemuck::{Pod, Zeroable};
9+
10+
use super::{AncillaryData, CodecError, copy_from_bytes, copy_to_bytes};
11+
12+
/// Marker trait to enable automatic `AncillaryData` implementation via
13+
/// bytemuck.
14+
///
15+
/// Types that implement this trait (which requires [`bytemuck::Pod`]) will
16+
/// automatically implement [`AncillaryData`] using a simple byte-wise
17+
/// encoding/decoding.
18+
///
19+
/// # Example
20+
///
21+
/// ```
22+
/// use compio_io::ancillary::bytemuck_ext;
23+
///
24+
/// #[derive(Clone, Copy)]
25+
/// #[repr(C)]
26+
/// struct MyType {
27+
/// value: u32,
28+
/// }
29+
///
30+
/// unsafe impl bytemuck_ext::Zeroable for MyType {}
31+
/// unsafe impl bytemuck_ext::Pod for MyType {}
32+
/// impl bytemuck_ext::BitwiseAncillaryData for MyType {}
33+
///
34+
/// // Now MyType automatically implements AncillaryData
35+
/// ```
36+
pub trait BitwiseAncillaryData: Pod {}
37+
38+
impl<T: BitwiseAncillaryData> AncillaryData for T {
39+
fn encode(&self, buffer: &mut [MaybeUninit<u8>]) -> Result<(), CodecError> {
40+
unsafe { copy_to_bytes(self, buffer) }
41+
}
42+
43+
fn decode(buffer: &[u8]) -> Result<Self, CodecError> {
44+
unsafe { copy_from_bytes(buffer) }
45+
}
46+
}
47+
48+
macro_rules! impl_bytemuck_marker {
49+
($($t:ty),* $(,)?) => {
50+
$(
51+
impl BitwiseAncillaryData for $t {}
52+
)*
53+
};
54+
}
55+
56+
impl_bytemuck_marker!(
57+
(),
58+
u8,
59+
u16,
60+
u32,
61+
u64,
62+
u128,
63+
usize,
64+
i8,
65+
i16,
66+
i32,
67+
i64,
68+
i128,
69+
isize,
70+
f32,
71+
f64,
72+
);
73+
74+
impl<T: BitwiseAncillaryData, const N: usize> BitwiseAncillaryData for [T; N] {}

0 commit comments

Comments
 (0)