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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
//! Parse limits for all audio format parsers.
//!
//! Provides a unified [`ParseLimits`] configuration that caps memory
//! allocations during metadata parsing — regardless of which audio format
//! is being processed. Two independent ceilings are enforced:
//!
//! - **`max_tag_size`** — maximum bytes for an entire tag/metadata block
//! (text frames, comments, chapters, etc.).
//! - **`max_image_size`** — maximum bytes for a single embedded image
//! (cover art, booklet scans, etc.). This is intentionally separate
//! because high-resolution artwork can legitimately be very large.
//!
//! # Specification Compatibility
//!
//! The per-format constants and default limits are summarized below.
//! Note that some library ceilings are lower than the format specification
//! allows; use [`ParseLimits::permissive()`] for files near those limits:
//!
//! | Format | Effective parse ceiling | Spec ceiling |
//! |------------|----------------------------------|--------------------------|
//! | ID3v2 | 256 MB (2²⁸ − 1 synchsafe) | 256 MB (synchsafe) |
//! | FLAC | ~16 MB (2²⁴ − 1 per block) | ~16 MB (24-bit) |
//! | APEv2 | no hard limit | no hard spec limit |
//! | Vorbis | 10 MB per comment | ~4 GB (32-bit length) |
//! | MP4 | 256 MB (atom data buffer) | ~unlimited (64-bit ext.) |
//! | AIFF/WAVE | 256 MB (chunk data) | ~4 GB (32-bit size) |
//!
//! Separately, ASF saving uses a whole-file in-memory rewrite path guarded by
//! [`MAX_IN_MEMORY_WRITER_FILE`](crate::limits::MAX_IN_MEMORY_WRITER_FILE), currently 512 MiB.
//!
//! The default limits (8 MB tags / 16 MB images) are safe for untrusted
//! input. If you need to accept spec-legal files with very large metadata,
//! opt into [`ParseLimits::permissive()`] explicitly.
//!
//! # Usage
//!
//! The defaults are safe for most applications, including those that handle
//! untrusted uploads. Construct a `ParseLimits` value and pass it through
//! your parser pipeline, or rely on `ParseLimits::default()` for safe
//! defaults.
// ---------------------------------------------------------------------------
// Spec-derived reference constants (not enforced directly — used to document
// where the defaults come from)
// ---------------------------------------------------------------------------
/// ID3v2 maximum tag size: synchsafe 4-byte integer → 2²⁸ − 1 bytes.
pub const ID3V2_SPEC_MAX: u64 = - 1; // 268_435_455
/// FLAC maximum metadata block: 24-bit size field → 2²⁴ − 1 bytes.
pub const FLAC_SPEC_BLOCK_MAX: u64 = - 1; // 16_777_215
/// MP4 atom data buffer ceiling used by this library.
pub const MP4_ATOM_DATA_MAX: u64 = 256 * 1024 * 1024; // 256 MB
/// AIFF / WAVE chunk data ceiling used by this library.
pub const IFF_CHUNK_DATA_MAX: u64 = 256 * 1024 * 1024; // 256 MB
/// Vorbis comment maximum single comment length used by this library.
pub const VORBIS_COMMENT_MAX: u64 = 10 * 1024 * 1024; // 10 MB
/// Maximum file size accepted by whole-file in-memory writer operations.
///
/// Some writer-based save/clear paths need to buffer the complete file in
/// memory because the underlying transformation logic rewrites container
/// structures on a `Cursor`. This limit is intentionally separate from
/// `max_tag_size`: a large audio payload with tiny metadata should not be
/// rejected just because the tag-allocation budget is restrictive.
pub const MAX_IN_MEMORY_WRITER_FILE: u64 = 512 * 1024 * 1024; // 512 MB
// ---------------------------------------------------------------------------
// ParseLimits
// ---------------------------------------------------------------------------
/// Library-wide limits on metadata and image allocations during parsing.
///
/// Every format-specific parser checks these limits in addition to its own
/// format-level constraints. Construct an instance with [`Default::default()`]
/// for safe defaults, or use [`ParseLimits::permissive()`] for trusted media.
///
/// # Security
///
/// The default limits (8 MB tags / 16 MB images) are safe for processing
/// untrusted or user-uploaded content. They cover virtually all legitimate
/// media while preventing resource exhaustion from crafted files.
///
/// If you need to process trusted files that may have very large metadata
/// (up to the format spec ceilings), use [`ParseLimits::permissive()`]
/// explicitly.