Skip to main content

bincode/features/serde/
untrusted.rs

1//! Explicit opt-in for an audited Serde deserializer and its nested graph.
2
3use super::{de_borrowed, de_owned, BorrowCompat, Compat};
4use crate::{
5    de::{BorrowUntrustedDecoder, UntrustedDecoder},
6    error::DecodeError,
7    BorrowDecodeUntrusted, DecodeUntrusted,
8};
9
10/// Opt in a Serde implementation to untrusted decoding.
11///
12/// Implementors must audit their entire Serde decoding graph, including custom
13/// visitors, allocations, and domain checks. Serde's own trait dispatch cannot
14/// enforce this recursively. Library containers opt in only when their contents
15/// do; there is no blanket implementation for arbitrary `Deserialize` types.
16///
17/// ```compile_fail
18/// #[derive(serde::Deserialize)]
19/// struct Ordinary(u8);
20/// let _ = bincode::serde::decode_from_slice_untrusted::<Ordinary, _>(&[1], bincode::config::standard());
21/// ```
22/// The same opt-in is required for Serde fields in a native untrusted derive:
23/// ```compile_fail
24/// #[derive(serde::Deserialize)]
25/// struct Ordinary(u8);
26/// #[derive(bincode::DecodeUntrusted)]
27/// struct External { #[bincode(with_serde)] value: Ordinary }
28/// ```
29pub trait DeserializeUntrusted<'de>: serde::Deserialize<'de> {}
30
31/// Explicitly opt in a Serde seed, including the graph it chooses to deserialize.
32///
33/// ```compile_fail
34/// struct Seed;
35/// impl<'de> serde::de::DeserializeSeed<'de> for Seed {
36///     type Value = u8;
37///     fn deserialize<D: serde::Deserializer<'de>>(self, d: D) -> Result<u8, D::Error> {
38///         serde::Deserialize::deserialize(d)
39///     }
40/// }
41/// let _ = bincode::serde::seed_decode_from_slice_untrusted(Seed, &[1], bincode::config::standard());
42/// ```
43pub trait DeserializeSeedUntrusted<'de>: serde::de::DeserializeSeed<'de> {}
44
45impl<'de, T: DeserializeUntrusted<'de>> DeserializeSeedUntrusted<'de>
46    for core::marker::PhantomData<T>
47{
48}
49
50impl<C, T: for<'de> DeserializeUntrusted<'de>> DecodeUntrusted<C> for Compat<T> {
51    fn decode_untrusted<D: UntrustedDecoder<Context = C>>(
52        decoder: &mut D,
53    ) -> Result<Self, DecodeError> {
54        T::deserialize(de_owned::SerdeDecoder {
55            de: decoder,
56            policy: super::de_policy::Untrusted,
57        })
58        .map(Compat)
59    }
60}
61impl<'de, C, T: for<'a> DeserializeUntrusted<'a>> BorrowDecodeUntrusted<'de, C> for Compat<T> {
62    fn borrow_decode_untrusted<D: BorrowUntrustedDecoder<'de, Context = C>>(
63        decoder: &mut D,
64    ) -> Result<Self, DecodeError> {
65        Self::decode_untrusted(decoder)
66    }
67}
68impl<'de, C, T: DeserializeUntrusted<'de>> BorrowDecodeUntrusted<'de, C> for BorrowCompat<T> {
69    fn borrow_decode_untrusted<D: BorrowUntrustedDecoder<'de, Context = C>>(
70        decoder: &mut D,
71    ) -> Result<Self, DecodeError> {
72        T::deserialize(de_borrowed::SerdeDecoder {
73            policy: super::de_policy::Untrusted,
74            de: decoder,
75            pd: core::marker::PhantomData,
76        })
77        .map(BorrowCompat)
78    }
79}
80
81macro_rules! leaf {
82    ($($ty:ty),* $(,)?) => {$(impl<'de> DeserializeUntrusted<'de> for $ty {})*};
83}
84leaf!(
85    (),
86    bool,
87    u8,
88    u16,
89    u32,
90    u64,
91    u128,
92    usize,
93    i8,
94    i16,
95    i32,
96    i64,
97    i128,
98    isize,
99    f32,
100    f64,
101    char,
102    core::time::Duration,
103    core::num::NonZeroU8,
104    core::num::NonZeroU16,
105    core::num::NonZeroU32,
106    core::num::NonZeroU64,
107    core::num::NonZeroU128,
108    core::num::NonZeroUsize,
109    core::num::NonZeroI8,
110    core::num::NonZeroI16,
111    core::num::NonZeroI32,
112    core::num::NonZeroI64,
113    core::num::NonZeroI128,
114    core::num::NonZeroIsize
115);
116impl<'de: 'a, 'a> DeserializeUntrusted<'de> for &'a str {}
117impl<'de: 'a, 'a> DeserializeUntrusted<'de> for &'a [u8] {}
118impl<'de, T: ?Sized> DeserializeUntrusted<'de> for core::marker::PhantomData<T> {}
119impl<'de, T: DeserializeUntrusted<'de>> DeserializeUntrusted<'de> for Option<T> {}
120impl<'de, T: DeserializeUntrusted<'de>, E: DeserializeUntrusted<'de>> DeserializeUntrusted<'de>
121    for Result<T, E>
122{
123}
124impl<'de, T: DeserializeUntrusted<'de>, const N: usize> DeserializeUntrusted<'de> for [T; N] where
125    [T; N]: serde::Deserialize<'de>
126{
127}
128
129macro_rules! tuple {
130    ($($t:ident),+) => {impl<'de,$($t:DeserializeUntrusted<'de>),+> DeserializeUntrusted<'de> for ($($t,)+) {}};
131}
132tuple!(A);
133tuple!(A, B);
134tuple!(A, B, C);
135tuple!(A, B, C, D);
136tuple!(A, B, C, D, E);
137tuple!(A, B, C, D, E, F);
138tuple!(A, B, C, D, E, F, G);
139tuple!(A, B, C, D, E, F, G, H);
140tuple!(A, B, C, D, E, F, G, H, I);
141tuple!(A, B, C, D, E, F, G, H, I, J);
142tuple!(A, B, C, D, E, F, G, H, I, J, K);
143tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
144tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
145tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
146tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
147tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
148
149#[cfg(feature = "alloc")]
150mod allocated {
151    use super::*;
152    use alloc::{
153        boxed::Box,
154        collections::{BTreeMap, BTreeSet, BinaryHeap, VecDeque},
155        string::String,
156        vec::Vec,
157    };
158    leaf!(String, Box<str>);
159    impl<'de, T: DeserializeUntrusted<'de>> DeserializeUntrusted<'de> for Vec<T> {}
160    impl<'de, T: DeserializeUntrusted<'de>> DeserializeUntrusted<'de> for Box<T> {}
161    impl<'de, T: DeserializeUntrusted<'de>> DeserializeUntrusted<'de> for Box<[T]> {}
162    impl<'de, T: DeserializeUntrusted<'de>> DeserializeUntrusted<'de> for VecDeque<T> {}
163    impl<'de, T: DeserializeUntrusted<'de> + Ord> DeserializeUntrusted<'de> for BinaryHeap<T> {}
164    impl<'de, T: DeserializeUntrusted<'de> + Ord> DeserializeUntrusted<'de> for BTreeSet<T> {}
165    impl<'de, K: DeserializeUntrusted<'de> + Ord, V: DeserializeUntrusted<'de>>
166        DeserializeUntrusted<'de> for BTreeMap<K, V>
167    {
168    }
169}
170#[cfg(feature = "std")]
171mod standard {
172    use super::*;
173    use std::{
174        collections::{HashMap, HashSet},
175        hash::{BuildHasher, Hash},
176        sync::{Mutex, RwLock},
177    };
178    leaf!(
179        std::time::SystemTime,
180        std::ffi::CString,
181        std::path::PathBuf,
182        std::net::IpAddr,
183        std::net::Ipv4Addr,
184        std::net::Ipv6Addr,
185        std::net::SocketAddr,
186        std::net::SocketAddrV4,
187        std::net::SocketAddrV6
188    );
189    impl<'de, T: DeserializeUntrusted<'de> + Eq + Hash, S: BuildHasher + Default>
190        DeserializeUntrusted<'de> for HashSet<T, S>
191    {
192    }
193    impl<
194            'de,
195            K: DeserializeUntrusted<'de> + Eq + Hash,
196            V: DeserializeUntrusted<'de>,
197            S: BuildHasher + Default,
198        > DeserializeUntrusted<'de> for HashMap<K, V, S>
199    {
200    }
201    impl<'de, T: DeserializeUntrusted<'de>> DeserializeUntrusted<'de> for Mutex<T> {}
202    impl<'de, T: DeserializeUntrusted<'de>> DeserializeUntrusted<'de> for RwLock<T> {}
203}