rlsp_yaml_parser/limits.rs
1// SPDX-License-Identifier: MIT
2
3/// Maximum combined block-collection nesting depth accepted from untrusted
4/// input.
5///
6/// This limit covers all open [`crate::Event::SequenceStart`] and
7/// [`crate::Event::MappingStart`] events combined. Using a unified limit prevents
8/// an attacker from nesting 512 sequences inside 512 mappings (total depth
9/// 1024) by exploiting separate per-type limits.
10///
11/// 512 is generous for all real-world YAML (Kubernetes / Helm documents are
12/// typically under 20 levels deep) and small enough that the explicit-stack
13/// overhead stays within a few KB.
14pub const MAX_COLLECTION_DEPTH: usize = 512;
15
16/// Maximum byte length of an anchor name accepted from untrusted input.
17///
18/// Maximum byte length of an anchor or alias name.
19///
20/// The YAML spec places no upper limit on anchor names, but scanning a name
21/// consisting of millions of valid `ns-anchor-char` bytes would exhaust CPU
22/// time without any heap allocation. This limit caps anchor and alias name
23/// scanning at 1 KiB — generous for all real-world YAML (Kubernetes names are
24/// typically under 64 bytes) while preventing degenerate-input stalls.
25///
26/// The limit is enforced by [`crate::parse_events`] for both `&name` (anchors) and
27/// `*name` (aliases). Exceeding it returns an [`crate::Error`], not a panic.
28pub const MAX_ANCHOR_NAME_BYTES: usize = 1024;
29
30/// Maximum byte length of a tag accepted from untrusted input.
31///
32/// The YAML spec places no upper limit on tag length, but scanning a tag
33/// consisting of millions of valid bytes would exhaust CPU time without any
34/// heap allocation. This limit caps tag scanning at 4 KiB — generous for all
35/// real-world YAML (standard tags like `tag:yaml.org,2002:str` are under 30
36/// bytes; custom namespace URIs are rarely over 200 bytes) while preventing
37/// degenerate-input stalls.
38///
39/// The limit applies to the raw scanned portion: the URI content between `<`
40/// and `>` for verbatim tags, or the suffix portion for shorthand tags.
41/// Exceeding it returns an [`crate::Error`], not a panic.
42pub const MAX_TAG_LEN: usize = 4096;
43
44/// Maximum byte length of a comment body accepted from untrusted input.
45///
46/// The YAML spec places no upper limit on comment length. With zero-copy
47/// `&'input str` slices, comment scanning itself allocates nothing, but
48/// character-by-character iteration over a very long comment line still burns
49/// CPU proportional to the line length. This limit matches `MAX_TAG_LEN` —
50/// comment-only files produce one `Comment` event per line (O(input size),
51/// acceptable) as long as individual lines are bounded.
52///
53/// Exceeding this limit returns an [`crate::Error`], not a panic or truncation.
54pub const MAX_COMMENT_LEN: usize = 4096;
55
56/// Maximum number of directives (`%YAML` + `%TAG` combined) per document.
57///
58/// Without this cap, an attacker could supply thousands of distinct `%TAG`
59/// directives, each allocating a `HashMap` entry, to exhaust heap memory.
60/// 64 is generous for all real-world YAML (the typical document has 0–2
61/// directives) while bounding per-document directive overhead.
62///
63/// Exceeding this limit returns an [`crate::Error`], not a panic.
64pub const MAX_DIRECTIVES_PER_DOC: usize = 64;
65
66/// Maximum byte length of a `%TAG` handle (e.g. `!foo!`) accepted from
67/// untrusted input.
68///
69/// Tag handles are short by design; a 256-byte cap is generous while
70/// preventing `DoS` via scanning very long handle strings.
71///
72/// Exceeding this limit returns an [`crate::Error`], not a panic.
73pub const MAX_TAG_HANDLE_BYTES: usize = 256;
74
75/// Maximum byte length of the fully-resolved tag string after prefix expansion.
76///
77/// When a shorthand tag `!foo!bar` is resolved against its `%TAG` prefix, the
78/// result is `prefix + suffix`. This cap prevents the resolved string from
79/// exceeding a safe bound even when the prefix and suffix are both at their
80/// individual limits. Reuses [`MAX_TAG_LEN`] so the bound is consistent with
81/// verbatim tag limits.
82///
83/// The check is performed before allocation; exceeding this limit returns an
84/// [`crate::Error`], not a panic.
85pub const MAX_RESOLVED_TAG_LEN: usize = MAX_TAG_LEN;