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};
6use crate::ext::RawInput;
7
8/// Limits the size of the deserialized data (a value of the
9/// [`Context`](crate::Context)).
10///
11/// Deser does not use the stack to process nested data, so deeply nested
12/// input cannot overflow the stack during deserialization.  Still it can
13/// be useful to limit the size of untrusted input, as the values that are
14/// deserialized might be processed recursively later, or to limit the
15/// memory used.  All limits are off by default.
16///
17/// The limits are configured in the context, for instance in the
18/// configuration of a format:
19///
20/// ```
21/// use deser::de::Limits;
22/// use deser::Context;
23///
24/// let config = deser_json::DeserializerConfig::builder()
25///     .context(Context::with(Limits::builder().max_depth(1).build()))
26///     .build();
27/// let err = config.from_str::<Vec<Vec<u32>>>("[[1]]").unwrap_err();
28/// assert_eq!(
29///     err.to_string(),
30///     "LimitExceeded: recursion limit exceeded at line 1 column 2"
31/// );
32/// ```
33///
34/// The [`DeserializeDriver`](crate::de::DeserializeDriver) enforces the
35/// limits of its context (see
36/// [`set_context`](crate::de::DeserializeDriver::set_context)).  They see
37/// the events as the sinks receive them, after all [`Layer`]s, so their
38/// errors have the context that layers add (for instance the path).
39/// Raw values are checked against their encoded contents: their containers,
40/// atoms and string or byte payloads count, rather than a single opaque atom.
41#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
42pub struct Limits {
43    max_depth: Option<usize>,
44    max_events: Option<usize>,
45    max_items: Option<usize>,
46    max_len: Option<usize>,
47}
48
49impl Limits {
50    /// Creates limits that limit nothing.
51    pub const fn new() -> Limits {
52        Limits {
53            max_depth: None,
54            max_events: None,
55            max_items: None,
56            max_len: None,
57        }
58    }
59
60    /// Returns a builder for the limits (see [`LimitsBuilder`]).
61    pub const fn builder() -> LimitsBuilder {
62        LimitsBuilder::new()
63    }
64
65    /// Returns a builder that starts with these limits.
66    pub const fn into_builder(self) -> LimitsBuilder {
67        LimitsBuilder { value: self }
68    }
69
70    /// Limits the nesting depth of maps and sequences.
71    ///
72    /// With a depth of 1, maps and sequences cannot contain other maps and
73    /// sequences.
74    pub const fn set_max_depth(&mut self, depth: usize) {
75        self.max_depth = Some(depth);
76    }
77
78    /// Returns the limit of the nesting depth of maps and sequences.
79    pub const fn max_depth(&self) -> Option<usize> {
80        self.max_depth
81    }
82
83    /// Limits the total number of events.
84    ///
85    /// Every atom and every start and end of a map or sequence counts.
86    pub const fn set_max_events(&mut self, events: usize) {
87        self.max_events = Some(events);
88    }
89
90    /// Returns the limit of the total number of events.
91    pub const fn max_events(&self) -> Option<usize> {
92        self.max_events
93    }
94
95    /// Limits the number of items in a sequence and entries in a map.
96    pub const fn set_max_items(&mut self, items: usize) {
97        self.max_items = Some(items);
98    }
99
100    /// Returns the limit of the number of items in a sequence and entries
101    /// in a map.
102    pub const fn max_items(&self) -> Option<usize> {
103        self.max_items
104    }
105
106    /// Limits the length of strings and bytes (in bytes), including the
107    /// original text of values whose type was inferred from text.
108    pub const fn set_max_len(&mut self, len: usize) {
109        self.max_len = Some(len);
110    }
111
112    /// Returns the limit of the length of strings and bytes (in bytes).
113    pub const fn max_len(&self) -> Option<usize> {
114        self.max_len
115    }
116
117    /// Returns `true` if nothing is limited.
118    pub(crate) const fn is_unlimited(&self) -> bool {
119        self.max_depth.is_none()
120            && self.max_events.is_none()
121            && self.max_items.is_none()
122            && self.max_len.is_none()
123    }
124}
125
126/// Builds [`Limits`].
127///
128/// The methods have the names of the setters of [`Limits`] (without `set_`).
129#[derive(Debug, Clone)]
130#[must_use]
131pub struct LimitsBuilder {
132    value: Limits,
133}
134
135impl LimitsBuilder {
136    /// Creates a builder that starts with the default.
137    pub const fn new() -> LimitsBuilder {
138        LimitsBuilder {
139            value: Limits::new(),
140        }
141    }
142
143    /// Limits the nesting depth of maps and sequences.
144    ///
145    /// See [`Limits::set_max_depth`].
146    pub const fn max_depth(mut self, depth: usize) -> LimitsBuilder {
147        self.value.set_max_depth(depth);
148        self
149    }
150
151    /// Limits the total number of events.
152    ///
153    /// See [`Limits::set_max_events`].
154    pub const fn max_events(mut self, events: usize) -> LimitsBuilder {
155        self.value.set_max_events(events);
156        self
157    }
158
159    /// Limits the number of items in a sequence and entries in a map.
160    ///
161    /// See [`Limits::set_max_items`].
162    pub const fn max_items(mut self, items: usize) -> LimitsBuilder {
163        self.value.set_max_items(items);
164        self
165    }
166
167    /// Limits the length of strings and bytes (in bytes).
168    ///
169    /// See [`Limits::set_max_len`].
170    pub const fn max_len(mut self, len: usize) -> LimitsBuilder {
171        self.value.set_max_len(len);
172        self
173    }
174
175    /// Returns the built [`Limits`].
176    pub const fn build(self) -> Limits {
177        self.value
178    }
179}
180
181impl Default for LimitsBuilder {
182    fn default() -> LimitsBuilder {
183        LimitsBuilder::new()
184    }
185}
186
187/// Checks the events inside a raw value without delivering them to sinks.
188///
189/// Format scanners use this to account for the encoded structure without
190/// converting its numbers or interpreting its tags.
191#[doc(hidden)]
192pub struct RawLimits {
193    limits: Limits,
194    events: usize,
195    depth: usize,
196    // map or sequence, number of items, whether the next item is a map key
197    items: Vec<(bool, usize, bool)>,
198}
199
200impl RawLimits {
201    pub(crate) fn new(limits: Limits, events: usize, depth: usize) -> Self {
202        Self {
203            limits,
204            events,
205            depth,
206            items: Vec::new(),
207        }
208    }
209
210    /// Accounts for an encoded event.  Numeric atoms can be replaced by null.
211    pub fn event(&mut self, event: Event<'_>) -> Result<(), Error> {
212        self.events += 1;
213        if self.limits.max_events.is_some_and(|max| self.events > max) {
214            return Err(limit_error("too many events"));
215        }
216        if !matches!(event, Event::MapEnd | Event::SeqEnd)
217            && let Some((is_map, count, key)) = self.items.last_mut()
218        {
219            if !*is_map || *key {
220                *count += 1;
221                if self.limits.max_items.is_some_and(|max| *count > max) {
222                    return Err(limit_error("too many items"));
223                }
224            }
225            *key = !*key;
226        }
227        match event {
228            Event::MapStart(_) | Event::SeqStart(_) => {
229                if self.limits.max_depth.is_some_and(|max| self.depth >= max) {
230                    return Err(limit_error("recursion limit exceeded"));
231                }
232                self.depth += 1;
233                self.items
234                    .push((matches!(event, Event::MapStart(_)), 0, true));
235            }
236            Event::MapEnd | Event::SeqEnd => {
237                self.depth -= 1;
238                self.items.pop();
239            }
240            Event::Atom(atom) => {
241                let len = atom_len(&atom);
242                if self.limits.max_len.is_some_and(|max| len > max) {
243                    return Err(limit_error("string or bytes too long"));
244                }
245            }
246        }
247        Ok(())
248    }
249}
250
251/// The layer that enforces [`Limits`] (installed by the driver).
252pub(crate) struct LimitsLayer {
253    limits: Limits,
254    events: usize,
255    // the number of items of the open containers if items are limited
256    items: Vec<(bool, usize)>,
257}
258
259impl LimitsLayer {
260    pub(crate) fn new(limits: Limits) -> LimitsLayer {
261        LimitsLayer {
262            limits,
263            events: 0,
264            items: Vec::new(),
265        }
266    }
267
268    /// Accounts for an item in the current container.
269    fn count_item(&mut self, is_map_key: bool) -> Result<(), Error> {
270        if let (Some(max), Some((is_map, count))) = (self.limits.max_items, self.items.last_mut())
271            && (!*is_map || is_map_key)
272        {
273            *count += 1;
274            if *count > max {
275                return Err(limit_error("too many items"));
276            }
277        }
278        Ok(())
279    }
280}
281
282fn atom_len(atom: &Atom<'_>) -> usize {
283    match atom {
284        Atom::Str(s) | Atom::Lexical(s) => s.len(),
285        Atom::Bytes(b) => b.len(),
286        Atom::Implicit(value) => value.text().len(),
287        _ => 0,
288    }
289}
290
291#[cold]
292fn limit_error(msg: &'static str) -> Error {
293    Error::new(ErrorKind::LimitExceeded, msg)
294}
295
296impl Layer for LimitsLayer {
297    fn event<'de>(
298        &mut self,
299        event: LayerEvent<'_, 'de>,
300        next: &mut Next<'_, 'de>,
301    ) -> Result<(), Error> {
302        if let Event::Atom(Atom::Ext(ext)) = event.event()
303            && let Some(input) = ext.downcast_value_ref::<RawInput>()
304        {
305            self.count_item(next.state().is_map_key())?;
306            let mut limits = RawLimits::new(self.limits, self.events, next.state().depth());
307            input.check_limits(&mut limits)?;
308            self.events = limits.events;
309            return next.emit(event);
310        }
311        if let Some(max) = self.limits.max_events {
312            self.events += 1;
313            if self.events > max {
314                return Err(limit_error("too many events"));
315            }
316        }
317        let is_map_key = next.state().is_map_key();
318        match event.event() {
319            Event::MapStart(_) | Event::SeqStart(_) => {
320                if self
321                    .limits
322                    .max_depth
323                    .is_some_and(|max| next.state().depth() >= max)
324                {
325                    return Err(limit_error("recursion limit exceeded"));
326                }
327                self.count_item(is_map_key)?;
328                if self.limits.max_items.is_some() {
329                    self.items
330                        .push((matches!(event.event(), Event::MapStart(_)), 0));
331                }
332            }
333            Event::MapEnd | Event::SeqEnd => {
334                self.items.pop();
335            }
336            Event::Atom(atom) => {
337                if let Some(max) = self.limits.max_len {
338                    let len = atom_len(atom);
339                    if len > max {
340                        return Err(limit_error("string or bytes too long"));
341                    }
342                }
343                self.count_item(is_map_key)?;
344            }
345        }
346        next.emit(event)
347    }
348}