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
151
152
153
154
//! Deserialization-Trust-Boundary family — the admitting-specimens.
//!
//! The affinity-pair exhibits (ADR-039 §C worth-multiplier) for the two
//! build-now members:
//! - [`antigen::stdlib::deserialization::DeserializeWithoutDenyUnknownFields`]
//! — a `Deserialize` struct without the tight-junction (binds) + a sibling
//! that sets `deny_unknown_fields` (spared).
//! - [`antigen::stdlib::deserialization::UnboundedDeserialization`] — a
//! `from_reader` call (binds) + a bounded `.take(limit)` sibling (spared).
//!
//! Run:
//!
//! ```sh
//! cargo run --example deserialization --package antigen
//! cargo run --bin cargo-antigen -- antigen scan --root antigen/examples
//! ```
//!
//! Note: both siblings of each pair are `#[presents]`-marked (to teach the
//! affinity-pair), so audit lists *both* — the safe sibling is "spared" by the
//! *fingerprint* (it doesn't bind), not made to disappear from the console. To
//! *read* the fingerprint's bind/spare side by side, see the guard tests
//! `antigen/tests/stdlib_family_fingerprints.rs`
//! (`unbounded_deserialization_binds_from_reader_call` beside
//! `unbounded_deserialization_spares_from_slice_namesake`).
//!
//! ## BIOSAFETY NOTE
//!
//! The "bad" paths are toy stand-ins exhibiting the call/attribute shape the
//! fingerprints match — not production code. The `Deserialize` derives are
//! commented stand-ins (no `serde` dependency in the example crate); the
//! fingerprint anchors on the `#[derive(...)]`/`#[serde(...)]` token shape and
//! the `from_reader` call token, which the scanner reads syntactically.
use ;
// ---------------------------------------------------------------------------
// Member 1 — DeserializeWithoutDenyUnknownFields
// ---------------------------------------------------------------------------
/// A `#[derive(Deserialize)]` type with no `#[serde(deny_unknown_fields)]` —
/// unknown input fields are silently dropped (leaky gut at the trust boundary).
;
/// BAD (the bind): a config struct that derives `Deserialize` but does NOT set
/// `deny_unknown_fields` — an unknown `is_admin` smuggled in the payload is
/// silently dropped instead of rejected.
///
/// `derives("Deserialize")` matches AND `not(serde_arg("deny_unknown_fields"))`
/// matches (the arg is absent) → the `all_of` **binds**.
// In real code: #[derive(serde::Deserialize)] with no #[serde(deny_unknown_fields)].
/// GOOD (the spare): the same shape, but `#[serde(deny_unknown_fields)]` IS set
/// — unknown fields are rejected at the boundary (the tight-junction).
///
/// `not(serde_arg("deny_unknown_fields"))` does NOT match (the arg is present)
/// → the `all_of` is **spared**.
// In real code: #[derive(serde::Deserialize)] #[serde(deny_unknown_fields)].
// ---------------------------------------------------------------------------
// Member 2 — UnboundedDeserialization
// ---------------------------------------------------------------------------
/// A byte/reader-source deserialization with no size/depth limit — a `DoS`
/// surface (stack exhaustion on deeply-nested input).
;
/// Toy stand-in for a deserialization entrypoint — keeps the `from_reader`
/// call-shape the fingerprint anchors on without a `serde` dependency.
/// UNADDRESSED (the bind): deserializes from a reader with NO `.take(limit)`
/// bound — a non-terminating / huge stream blows the stack or allocates
/// unboundedly. `body_calls("from_reader")` matches → **binds**, and there is no
/// witness, so it is an unaddressed presentation (the real `DoS` surface).
/// DEFENDED (surface fires, witness spares at audit): the SAME `from_reader`
/// surface — so it **still fires** the fingerprint — but the byte source is
/// bounded with `.take(limit)`, the std-documented anti-`DoS` defense. The
/// `#[defended_by]` test below proves the bound; audit observes the circuit and
/// marks this site defended. The surface-flag / witness-proof split: the
/// fingerprint flags the surface, the witness proves the defense — we do NOT
/// fingerprint-spare the capped form (a `not(take)` guard would silently suppress
/// real `DoS` sites whenever an unrelated `Iterator::take` appeared, a silent
/// false-negative that breaks the named tier's promise).
/// Witness: proves `load_bounded` caps its reader with `.take(limit)`.
/// `#[defended_by]` declares this test's intent toward the failure-class; audit
/// observes that the circuit covers the bounded site.