Skip to main content

deser_core/de/
limits.rs

1use alloc::vec::Vec;
2
3use crate::de::{Layer, LayerEvent, Next};
4use crate::error::{Error, ErrorKind};
5use crate::event::{Atom, Event};
6
7/// Limits the size of the deserialized data (a value of the
8/// [`Context`](crate::Context)).
9///
10/// Deser does not use the stack to process nested data, so deeply nested
11/// input cannot overflow the stack during deserialization.  Still it can
12/// be useful to limit the size of untrusted input, as the values that are
13/// deserialized might be processed recursively later, or to limit the
14/// memory used.  All limits are off by default.
15///
16/// The limits are configured in the context, for instance in the
17/// configuration of a format:
18///
19/// ```
20/// use deser::de::Limits;
21/// use deser::Context;
22///
23/// let config = deser_json::DeserializerConfig::builder()
24///     .context(Context::with(Limits::builder().max_depth(1).build()))
25///     .build();
26/// let err = config.from_str::<Vec<Vec<u32>>>("[[1]]").unwrap_err();
27/// assert_eq!(
28///     err.to_string(),
29///     "LimitExceeded: recursion limit exceeded at line 1 column 2"
30/// );
31/// ```
32///
33/// The [`DeserializeDriver`](crate::de::DeserializeDriver) enforces the
34/// limits of its context (see
35/// [`set_context`](crate::de::DeserializeDriver::set_context)).  They see
36/// the events as the sinks receive them, after all [`Layer`]s, so their
37/// errors have the context that layers add (for instance the path).
38#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
39pub struct Limits {
40    max_depth: Option<usize>,
41    max_events: Option<usize>,
42    max_items: Option<usize>,
43    max_len: Option<usize>,
44}
45
46impl Limits {
47    /// Creates limits that limit nothing.
48    pub const fn new() -> Limits {
49        Limits {
50            max_depth: None,
51            max_events: None,
52            max_items: None,
53            max_len: None,
54        }
55    }
56
57    /// Returns a builder for the limits (see [`LimitsBuilder`]).
58    pub const fn builder() -> LimitsBuilder {
59        LimitsBuilder::new()
60    }
61
62    /// Returns a builder that starts with these limits.
63    pub const fn into_builder(self) -> LimitsBuilder {
64        LimitsBuilder { value: self }
65    }
66
67    /// Limits the nesting depth of maps and sequences.
68    ///
69    /// With a depth of 1, maps and sequences cannot contain other maps and
70    /// sequences.
71    pub const fn set_max_depth(&mut self, depth: usize) {
72        self.max_depth = Some(depth);
73    }
74
75    /// Returns the limit of the nesting depth of maps and sequences.
76    pub const fn max_depth(&self) -> Option<usize> {
77        self.max_depth
78    }
79
80    /// Limits the total number of events.
81    ///
82    /// Every atom and every start and end of a map or sequence counts.
83    pub const fn set_max_events(&mut self, events: usize) {
84        self.max_events = Some(events);
85    }
86
87    /// Returns the limit of the total number of events.
88    pub const fn max_events(&self) -> Option<usize> {
89        self.max_events
90    }
91
92    /// Limits the number of items in a sequence and entries in a map.
93    pub const fn set_max_items(&mut self, items: usize) {
94        self.max_items = Some(items);
95    }
96
97    /// Returns the limit of the number of items in a sequence and entries
98    /// in a map.
99    pub const fn max_items(&self) -> Option<usize> {
100        self.max_items
101    }
102
103    /// Limits the length of strings and bytes (in bytes).
104    pub const fn set_max_len(&mut self, len: usize) {
105        self.max_len = Some(len);
106    }
107
108    /// Returns the limit of the length of strings and bytes (in bytes).
109    pub const fn max_len(&self) -> Option<usize> {
110        self.max_len
111    }
112
113    /// Returns `true` if nothing is limited.
114    pub(crate) const fn is_unlimited(&self) -> bool {
115        self.max_depth.is_none()
116            && self.max_events.is_none()
117            && self.max_items.is_none()
118            && self.max_len.is_none()
119    }
120}
121
122/// Builds [`Limits`].
123///
124/// The methods have the names of the setters of [`Limits`] (without `set_`).
125#[derive(Debug, Clone)]
126#[must_use]
127pub struct LimitsBuilder {
128    value: Limits,
129}
130
131impl LimitsBuilder {
132    /// Creates a builder that starts with the default.
133    pub const fn new() -> LimitsBuilder {
134        LimitsBuilder {
135            value: Limits::new(),
136        }
137    }
138
139    /// Limits the nesting depth of maps and sequences.
140    ///
141    /// See [`Limits::set_max_depth`].
142    pub const fn max_depth(mut self, depth: usize) -> LimitsBuilder {
143        self.value.set_max_depth(depth);
144        self
145    }
146
147    /// Limits the total number of events.
148    ///
149    /// See [`Limits::set_max_events`].
150    pub const fn max_events(mut self, events: usize) -> LimitsBuilder {
151        self.value.set_max_events(events);
152        self
153    }
154
155    /// Limits the number of items in a sequence and entries in a map.
156    ///
157    /// See [`Limits::set_max_items`].
158    pub const fn max_items(mut self, items: usize) -> LimitsBuilder {
159        self.value.set_max_items(items);
160        self
161    }
162
163    /// Limits the length of strings and bytes (in bytes).
164    ///
165    /// See [`Limits::set_max_len`].
166    pub const fn max_len(mut self, len: usize) -> LimitsBuilder {
167        self.value.set_max_len(len);
168        self
169    }
170
171    /// Returns the built [`Limits`].
172    pub const fn build(self) -> Limits {
173        self.value
174    }
175}
176
177impl Default for LimitsBuilder {
178    fn default() -> LimitsBuilder {
179        LimitsBuilder::new()
180    }
181}
182
183/// The layer that enforces [`Limits`] (installed by the driver).
184pub(crate) struct LimitsLayer {
185    limits: Limits,
186    events: usize,
187    // the number of items of the open containers if items are limited
188    items: Vec<(bool, usize)>,
189}
190
191impl LimitsLayer {
192    pub(crate) fn new(limits: Limits) -> LimitsLayer {
193        LimitsLayer {
194            limits,
195            events: 0,
196            items: Vec::new(),
197        }
198    }
199
200    /// Accounts for an item in the current container.
201    fn count_item(&mut self, is_map_key: bool) -> Result<(), Error> {
202        if let (Some(max), Some((is_map, count))) = (self.limits.max_items, self.items.last_mut())
203            && (!*is_map || is_map_key)
204        {
205            *count += 1;
206            if *count > max {
207                return Err(limit_error("too many items"));
208            }
209        }
210        Ok(())
211    }
212}
213
214#[cold]
215fn limit_error(msg: &'static str) -> Error {
216    Error::new(ErrorKind::LimitExceeded, msg)
217}
218
219impl Layer for LimitsLayer {
220    fn event<'de>(
221        &mut self,
222        event: LayerEvent<'_, 'de>,
223        next: &mut Next<'_, 'de>,
224    ) -> Result<(), Error> {
225        if let Some(max) = self.limits.max_events {
226            self.events += 1;
227            if self.events > max {
228                return Err(limit_error("too many events"));
229            }
230        }
231        let is_map_key = next.state().is_map_key();
232        match event.event() {
233            Event::MapStart(_) | Event::SeqStart(_) => {
234                if self
235                    .limits
236                    .max_depth
237                    .is_some_and(|max| next.state().depth() >= max)
238                {
239                    return Err(limit_error("recursion limit exceeded"));
240                }
241                self.count_item(is_map_key)?;
242                if self.limits.max_items.is_some() {
243                    self.items
244                        .push((matches!(event.event(), Event::MapStart(_)), 0));
245                }
246            }
247            Event::MapEnd | Event::SeqEnd => {
248                self.items.pop();
249            }
250            Event::Atom(atom) => {
251                if let Some(max) = self.limits.max_len {
252                    let len = match atom {
253                        Atom::Str(s) | Atom::Lexical(s) => s.len(),
254                        Atom::Bytes(b) => b.len(),
255                        _ => 0,
256                    };
257                    if len > max {
258                        return Err(limit_error("string or bytes too long"));
259                    }
260                }
261                self.count_item(is_map_key)?;
262            }
263        }
264        next.emit(event)
265    }
266}