Skip to main content

email_message_wire/rfc822/
shared.rs

1/// Maximum input byte length accepted by [`super::parse_rfc822`]. 16 MiB is far
2/// above any practical RFC 5322 message including base64-inflated
3/// attachments; anything larger is treated as adversarial and rejected
4/// before allocation.
5pub const MAX_INPUT_BYTES: usize = 16 * 1024 * 1024;
6
7/// Maximum nesting depth for `multipart/*` parts during inbound parse.
8/// Real-world archive formats nest at most ~10 levels; 100 leaves
9/// generous headroom while preventing stack-overflow on adversarial
10/// input with deeply-nested multipart parts.
11pub const MAX_MULTIPART_DEPTH: usize = 100;
12
13/// Maximum number of sibling parts inside a single multipart body
14/// during inbound parse. Adversarial input could otherwise produce
15/// millions of empty parts (a "fan-out bomb") at one level deep.
16pub const MAX_MULTIPART_PARTS: usize = 1024;
17
18pub(super) const RFC5322_HARD_LINE_LEN: usize = 998;
19
20pub(super) const fn hex_val(byte: u8) -> Option<u8> {
21    match byte {
22        b'0'..=b'9' => Some(byte - b'0'),
23        b'A'..=b'F' => Some(byte - b'A' + 10),
24        b'a'..=b'f' => Some(byte - b'a' + 10),
25        _ => None,
26    }
27}
28
29pub(super) fn trim_lwsp_end(value: &[u8]) -> &[u8] {
30    let mut end = value.len();
31    while end > 0 && (value[end - 1] == b' ' || value[end - 1] == b'\t') {
32        end -= 1;
33    }
34
35    &value[..end]
36}