1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//! Configuration for Automorph behavior.
//!
//! This module provides configuration options that can be set globally or per-thread.
//!
//! # Collection Size Limits
//!
//! By default, Automorph limits collections to `DEFAULT_MAX_COLLECTION_SIZE` (10 million)
//! elements to prevent memory exhaustion from malicious documents.
//!
//! You can override this limit globally or for a specific scope:
//!
//! ```rust
//! use automorph::config;
//!
//! // Set a global limit (affects all threads until changed)
//! config::set_max_collection_size(1_000_000);
//!
//! // Or use a scoped limit that automatically restores the previous value
//! config::with_max_collection_size(100, || {
//! // Within this closure, max collection size is 100
//! // After the closure returns, the previous limit is restored
//! });
//! ```
use Cell;
/// Default maximum number of elements allowed when loading collections.
/// This prevents memory exhaustion from malicious documents that claim
/// to have billions of elements.
///
/// Default value: 10,000,000 elements
pub const DEFAULT_MAX_COLLECTION_SIZE: usize = 10_000_000;
thread_local!
/// Gets the current maximum collection size limit.
///
/// This returns the thread-local limit if set, otherwise the default limit.
///
/// # Example
///
/// ```rust
/// use automorph::config;
///
/// let limit = config::max_collection_size();
/// assert_eq!(limit, config::DEFAULT_MAX_COLLECTION_SIZE);
/// ```
/// Sets the maximum collection size limit for the current thread.
///
/// This affects all subsequent collection loads on this thread until changed.
///
/// # Arguments
///
/// * `size` - The new maximum collection size. Set to `usize::MAX` to disable the limit.
///
/// # Example
///
/// ```rust
/// use automorph::config;
///
/// // Allow larger collections
/// config::set_max_collection_size(100_000_000);
///
/// // Or disable the limit entirely (use with caution!)
/// config::set_max_collection_size(usize::MAX);
/// ```
///
/// # Safety
///
/// Setting a very high or unlimited value (`usize::MAX`) may expose your application
/// to denial-of-service attacks if loading untrusted documents.
/// Executes a closure with a temporary collection size limit.
///
/// The previous limit is automatically restored after the closure returns,
/// even if it panics.
///
/// # Arguments
///
/// * `size` - The temporary maximum collection size
/// * `f` - The closure to execute with the temporary limit
///
/// # Example
///
/// ```rust
/// use automorph::config;
///
/// // Temporarily allow very small collections (e.g., for testing)
/// config::with_max_collection_size(10, || {
/// // In this scope, collections are limited to 10 elements
/// });
/// // Previous limit is restored here
/// ```