///|
/// Resource limits applied before allocating or recursively parsing content.
pub(all) struct ResourceLimits {
max_input_bytes : Int
max_header_bytes : Int
max_header_line_bytes : Int
max_header_count : Int
max_depth : Int
max_entities : Int
max_leaf_body_bytes : Int
max_decoded_leaf_bytes : Int
max_total_decoded_bytes : Int
max_parameter_count : Int
max_boundary_bytes : Int
max_diagnostics : Int
} derive(Debug, Eq)
///|
/// Conservative defaults suitable for untrusted messages in ordinary tools.
pub fn ResourceLimits::secure_defaults() -> ResourceLimits {
{
max_input_bytes: 32 * 1024 * 1024,
max_header_bytes: 256 * 1024,
max_header_line_bytes: 998,
max_header_count: 256,
max_depth: 16,
max_entities: 1000,
max_leaf_body_bytes: 16 * 1024 * 1024,
max_decoded_leaf_bytes: 16 * 1024 * 1024,
max_total_decoded_bytes: 64 * 1024 * 1024,
max_parameter_count: 128,
max_boundary_bytes: 70,
max_diagnostics: 256,
}
}
///|
/// Tighter settings for small webhook or edge-function payloads.
pub fn ResourceLimits::edge_defaults() -> ResourceLimits {
{
max_input_bytes: 4 * 1024 * 1024,
max_header_bytes: 64 * 1024,
max_header_line_bytes: 998,
max_header_count: 128,
max_depth: 8,
max_entities: 128,
max_leaf_body_bytes: 2 * 1024 * 1024,
max_decoded_leaf_bytes: 2 * 1024 * 1024,
max_total_decoded_bytes: 8 * 1024 * 1024,
max_parameter_count: 64,
max_boundary_bytes: 70,
max_diagnostics: 128,
}
}
///|
/// Validate limit relationships before parsing attacker-controlled input.
pub fn ResourceLimits::validate(self : ResourceLimits) -> Unit raise MimeError {
let values = [
("max_input_bytes", self.max_input_bytes),
("max_header_bytes", self.max_header_bytes),
("max_header_line_bytes", self.max_header_line_bytes),
("max_header_count", self.max_header_count),
("max_depth", self.max_depth),
("max_entities", self.max_entities),
("max_leaf_body_bytes", self.max_leaf_body_bytes),
("max_decoded_leaf_bytes", self.max_decoded_leaf_bytes),
("max_total_decoded_bytes", self.max_total_decoded_bytes),
("max_parameter_count", self.max_parameter_count),
("max_boundary_bytes", self.max_boundary_bytes),
("max_diagnostics", self.max_diagnostics),
]
for item in values {
let (name, value) = item
if value <= 0 {
raise InvalidArgument(name + " must be greater than zero")
}
}
if self.max_header_bytes > self.max_input_bytes {
raise InvalidArgument("max_header_bytes must not exceed max_input_bytes")
}
if self.max_leaf_body_bytes > self.max_input_bytes {
raise InvalidArgument("max_leaf_body_bytes must not exceed max_input_bytes")
}
if self.max_decoded_leaf_bytes > self.max_total_decoded_bytes {
raise InvalidArgument(
"max_decoded_leaf_bytes must not exceed max_total_decoded_bytes",
)
}
}