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}