1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//! Format handlers.
//!
//! Organised by **file format, not by dependency**: someone looking for how WebP is handled
//! opens `webp.rs`. If the crate underneath a handler is ever swapped, the change stops at
//! that module boundary and nothing else in the tree moves. A module must never be named
//! after the crate it wraps.
//!
//! # Why handlers take a slice and return a buffer
//!
//! `docs/ARCHITECTURE.md` §3 sketched this trait over a `ReadSeek`. Phase 1 refines it to
//! `&[u8]` in and `Vec<u8>` out, recorded as ADR-0017. Two reasons:
//!
//! - **Output must be verified before it can reach the disk.** The verification pass
//! (`docs/ARCHITECTURE.md` §1) re-inspects what the handler produced and fails if metadata
//! survived. Streaming straight to the destination would mean unverified — possibly
//! partially-sanitised — bytes had already been written by the time the check ran, which is
//! exactly the outcome the fail-closed rule exists to prevent.
//! - **A slice makes the panic-freedom lints enforceable.** Seek-driven parsing spreads
//! bounds checking across every read; a slice concentrates it in
//! [`crate::bytes::Reader`], where `indexing_slicing` and `arithmetic_side_effects` can be
//! denied and actually mean something (ADR-0006).
//!
//! The cost is that a file is held in memory, which is why ingest is bounded before a handler
//! ever sees it ([`crate::io::Limits`]).
use crateFormat;
use crateResult;
use crate;
pub
pub
pub
/// Sanitised bytes and an account of what was done to produce them.
/// Ceilings a handler applies while parsing.
///
/// Separate from [`crate::io::Limits`], which bounds how much is *read*. These bound what a
/// parser will do with what it read — the difference between refusing a 4 GB file and
/// refusing a 4 KB file that describes four billion objects.
/// What a caller wants from a strip.
/// Detection, reporting, and removal for one file format.
///
/// Implementations sit directly on attacker-controlled bytes and must uphold the invariants
/// in `docs/ARCHITECTURE.md` §3: `inspect` never mutates, nothing panics, failure is total
/// rather than partial, resources are bounded, the payload is preserved, and anything `strip`
/// claims to remove is something `inspect` can detect — without which the verification pass
/// would be checking nothing.