object_lang/limits.rs
1//! Budgets that bound the work and memory a reader spends on untrusted input.
2
3/// Budgets for reading untrusted files.
4///
5/// Every reader checks its input against these before allocating for it. Section data,
6/// symbol records, and relocation records are also bounded by the input itself (a
7/// reader copies at most as many bytes of section data as the file holds, however its
8/// headers overlap), so the budgets that matter most are the ones on names: a hostile
9/// file can point many symbols at one long string, and only `max_name_bytes` stops that
10/// from multiplying.
11///
12/// The defaults sit far above what compilers produce and far below what would exhaust
13/// a machine. The struct is `#[non_exhaustive]`: start from [`Limits::default`] and
14/// change fields.
15///
16/// | Field | Default | Bounds |
17/// |---|---|---|
18/// | `max_sections` | 1,048,576 | section headers |
19/// | `max_symbols` | 16,777,216 | symbol table entries |
20/// | `max_relocations` | 67,108,864 | relocation records, all sections together |
21/// | `max_name_len` | 65,536 bytes | one section or symbol name |
22/// | `max_name_bytes` | 268,435,456 bytes (256 MiB) | all names together, as copied out |
23///
24/// # Examples
25///
26/// ```
27/// use object_lang::{Architecture, Limits, Object, ReadError, Section, SectionKind};
28///
29/// let mut obj = Object::relocatable(Architecture::X86_64);
30/// obj.add_section(Section::new(".text", SectionKind::Text));
31/// obj.add_section(Section::new(".data", SectionKind::Data));
32/// let bytes = object_lang::elf::write(&obj)?;
33///
34/// let mut limits = Limits::default();
35/// limits.max_sections = 3;
36/// assert_eq!(
37/// object_lang::elf::read_with_limits(&bytes, &limits),
38/// Err(ReadError::LimitExceeded { limit: "max_sections" }),
39/// );
40/// # Ok::<(), object_lang::WriteError>(())
41/// ```
42#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
43#[non_exhaustive]
44pub struct Limits {
45 /// The most section headers a file may have.
46 pub max_sections: u32,
47 /// The most entries a symbol table may have.
48 pub max_symbols: u32,
49 /// The most relocation records, over all sections.
50 pub max_relocations: u64,
51 /// The longest a single name may be, in bytes.
52 pub max_name_len: u32,
53 /// The most name bytes copied out of the file, over all names.
54 pub max_name_bytes: u64,
55}
56
57impl Limits {
58 /// The default budgets, as a constant.
59 ///
60 /// # Examples
61 ///
62 /// ```
63 /// use object_lang::Limits;
64 ///
65 /// assert_eq!(Limits::DEFAULT, Limits::default());
66 /// ```
67 pub const DEFAULT: Limits = Limits {
68 max_sections: 1 << 20,
69 max_symbols: 1 << 24,
70 max_relocations: 1 << 26,
71 max_name_len: 1 << 16,
72 max_name_bytes: 1 << 28,
73 };
74}
75
76impl Default for Limits {
77 fn default() -> Self {
78 Limits::DEFAULT
79 }
80}