Skip to main content

vole_document/
limits.rs

1//! Centralized resource bounds.
2//!
3//! Every decode and encode path takes a [`Limits`]. Untrusted descriptors must
4//! be rejected *before* catastrophic work is performed, so all arithmetic on
5//! declared lengths and offsets is checked against these bounds and uses
6//! checked integer operations.
7
8/// Hard upper bounds applied while parsing and materializing a descriptor.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct Limits {
11    /// Maximum accepted source/descriptor input size.
12    pub max_input_bytes: u64,
13    /// Maximum reconstructed output size for a single materialization.
14    pub max_output_bytes: u64,
15    /// Maximum length of a single record payload.
16    pub max_record_len: u32,
17    /// Maximum number of records in a container.
18    pub max_record_count: u32,
19    /// Maximum number of distinct byte objects (`OBJECT` records).
20    pub max_object_count: u32,
21    /// Maximum number of DRA instructions in a reconstruction graph.
22    pub max_graph_ops: u32,
23    /// Maximum repeat count for a single `REPEAT_LAST` instruction.
24    pub max_repeat_count: u64,
25    /// Maximum number of symbols in a single entropy channel.
26    pub max_channel_symbols: u64,
27    /// Maximum number of distinct entropy models (`MODEL` records).
28    pub max_model_count: u32,
29    /// Maximum number of entropy channels (`ENTROPY_CHANNEL` records).
30    pub max_channel_count: u32,
31    /// Maximum encoded size of a single entropy model payload.
32    pub max_entropy_model_bytes: u32,
33    /// Maximum number of lexical spans produced for a PDF input.
34    pub max_pdf_spans: u32,
35}
36
37impl Limits {
38    /// The default archival limits: generous, but always finite.
39    pub const DEFAULT: Limits = Limits {
40        max_input_bytes: 1 << 40,  // 1 TiB
41        max_output_bytes: 1 << 40, // 1 TiB
42        max_record_len: 1 << 31,   // 2 GiB
43        max_record_count: 1 << 20, // ~1M records
44        max_object_count: 1 << 20,
45        max_graph_ops: 1 << 20,
46        max_repeat_count: 1 << 32,
47        max_channel_symbols: 1 << 40,
48        max_model_count: 1 << 16,
49        max_channel_count: 1 << 16,
50        max_entropy_model_bytes: 4096,
51        max_pdf_spans: 1 << 26,
52    };
53
54    /// Tight limits for hostile-input testing and fuzzing.
55    pub const STRICT: Limits = Limits {
56        max_input_bytes: 1 << 26,  // 64 MiB
57        max_output_bytes: 1 << 26, // 64 MiB
58        max_record_len: 1 << 24,   // 16 MiB
59        max_record_count: 1 << 16, // 65536
60        max_object_count: 1 << 16,
61        max_graph_ops: 1 << 16,
62        max_repeat_count: 1 << 24,
63        max_channel_symbols: 1 << 26,
64        max_model_count: 1 << 12,
65        max_channel_count: 1 << 12,
66        max_entropy_model_bytes: 4096,
67        max_pdf_spans: 1 << 16,
68    };
69}
70
71impl Default for Limits {
72    fn default() -> Self {
73        Limits::DEFAULT
74    }
75}