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}