Skip to main content

reliakit_json/
limits.rs

1//! Explicit resource limits for parsing untrusted JSON.
2
3/// Resource limits enforced while parsing.
4///
5/// Limits bound *logical* decoded data (counts and byte lengths), not exact
6/// allocator memory — real heap use also depends on `String`/`Vec` capacity and
7/// the platform. Parsing untrusted input should always go through limits;
8/// [`crate::parse`] applies [`JsonLimits::new`] by default.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct JsonLimits {
11    /// Maximum size of the whole input, in bytes.
12    pub max_input_bytes: usize,
13    /// Maximum nesting depth of arrays and objects.
14    pub max_depth: usize,
15    /// Maximum decoded size of a single string value, in bytes.
16    pub max_string_bytes: usize,
17    /// Maximum decoded size of a single object key, in bytes.
18    pub max_key_bytes: usize,
19    /// Maximum length of a single number token, in bytes.
20    pub max_number_bytes: usize,
21    /// Maximum number of items in a single array.
22    pub max_array_items: usize,
23    /// Maximum number of members in a single object.
24    pub max_object_members: usize,
25    /// Maximum total number of values (nodes) in the document.
26    pub max_total_nodes: usize,
27    /// Maximum total decoded string bytes across the whole document.
28    pub max_total_decoded_string_bytes: usize,
29}
30
31impl JsonLimits {
32    /// The default limits: conservative values suitable for untrusted input.
33    ///
34    /// `1 MiB` input, depth `64`, `256 KiB` per string, `16 KiB` per key,
35    /// `256` bytes per number, `100_000` array items / object members,
36    /// `200_000` total nodes, `1 MiB` total decoded string bytes.
37    pub const fn new() -> Self {
38        Self {
39            max_input_bytes: 1 << 20,
40            max_depth: 64,
41            max_string_bytes: 256 << 10,
42            max_key_bytes: 16 << 10,
43            max_number_bytes: 256,
44            max_array_items: 100_000,
45            max_object_members: 100_000,
46            max_total_nodes: 200_000,
47            max_total_decoded_string_bytes: 1 << 20,
48        }
49    }
50
51    /// A tighter profile for small, low-trust payloads (e.g. tokens, webhooks).
52    ///
53    /// `64 KiB` input, depth `32`, `16 KiB` per string, `1 KiB` per key,
54    /// `64` bytes per number, `4_096` array items / object members,
55    /// `16_384` total nodes, `64 KiB` total decoded string bytes.
56    pub const fn conservative() -> Self {
57        Self {
58            max_input_bytes: 64 << 10,
59            max_depth: 32,
60            max_string_bytes: 16 << 10,
61            max_key_bytes: 1 << 10,
62            max_number_bytes: 64,
63            max_array_items: 4_096,
64            max_object_members: 4_096,
65            max_total_nodes: 16_384,
66            max_total_decoded_string_bytes: 64 << 10,
67        }
68    }
69
70    /// A looser profile for larger trusted documents. Still explicit and finite.
71    ///
72    /// `64 MiB` input, depth `128`, `16 MiB` per string, `256 KiB` per key,
73    /// `1_024` bytes per number, `5_000_000` array items / object members,
74    /// `10_000_000` total nodes, `64 MiB` total decoded string bytes.
75    pub const fn permissive() -> Self {
76        Self {
77            max_input_bytes: 64 << 20,
78            max_depth: 128,
79            max_string_bytes: 16 << 20,
80            max_key_bytes: 256 << 10,
81            max_number_bytes: 1_024,
82            max_array_items: 5_000_000,
83            max_object_members: 5_000_000,
84            max_total_nodes: 10_000_000,
85            max_total_decoded_string_bytes: 64 << 20,
86        }
87    }
88
89    /// Sets [`max_depth`](Self::max_depth).
90    pub const fn with_max_depth(mut self, value: usize) -> Self {
91        self.max_depth = value;
92        self
93    }
94
95    /// Sets [`max_input_bytes`](Self::max_input_bytes).
96    pub const fn with_max_input_bytes(mut self, value: usize) -> Self {
97        self.max_input_bytes = value;
98        self
99    }
100
101    /// Sets [`max_string_bytes`](Self::max_string_bytes).
102    pub const fn with_max_string_bytes(mut self, value: usize) -> Self {
103        self.max_string_bytes = value;
104        self
105    }
106
107    /// Sets [`max_total_nodes`](Self::max_total_nodes).
108    pub const fn with_max_total_nodes(mut self, value: usize) -> Self {
109        self.max_total_nodes = value;
110        self
111    }
112}
113
114impl Default for JsonLimits {
115    fn default() -> Self {
116        Self::new()
117    }
118}