1mod chunk;
23pub mod format;
24mod head;
25mod value;
26
27pub use format::CborFmt;
28pub use head::{
29 BreakFmt, CborHead, CborHeadFmt, CborHeadValue, CborInitial, CborInitialFmt, MajorType, BREAK,
30};
31pub use value::{CborArray, CborBytes, CborFloat, CborMap, CborText, CborValue, CborValueSpec};
32
33pub const MAX_RECURSION_DEPTH: usize = 30;
35
36#[cfg(test)]
37mod tests {
38 use super::*;
39 use crate::core::exec::{ByteLen, Parser, Prepare, SerializerExt};
40 use alloc::borrow::ToOwned;
41
42 const GENERAL: bool = false;
43 const DETERMINISTIC: bool = true;
44
45 #[test]
46 fn rfc8949_major_types_conformance() {
47 let format = CborFmt::<GENERAL>;
48
49 assert_eq!(format.parse(&&[0x00][..]), Ok((1, CborValue::Integer(0))));
51 assert_eq!(format.parse(&&[0x17][..]), Ok((1, CborValue::Integer(23))));
52 assert_eq!(format.parse(&&[0x18, 0x18][..]), Ok((2, CborValue::Integer(24))));
53 assert_eq!(format.parse(&&[0x19, 0x01, 0x00][..]), Ok((3, CborValue::Integer(256))));
54 assert_eq!(
55 format.parse(&&[0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]),
56 Ok((9, CborValue::Integer(u64::MAX as i128)))
57 );
58
59 assert_eq!(format.parse(&&[0x20][..]), Ok((1, CborValue::Integer(-1))));
61 assert_eq!(format.parse(&&[0x37][..]), Ok((1, CborValue::Integer(-24))));
62 assert_eq!(format.parse(&&[0x38, 0x18][..]), Ok((2, CborValue::Integer(-25))));
63 assert_eq!(format.parse(&&[0x39, 0x03, 0xe7][..]), Ok((3, CborValue::Integer(-1000))));
64 assert_eq!(
65 format.parse(&&[0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]),
66 Ok((9, CborValue::Integer(-1i128 - u64::MAX as i128)))
67 );
68
69 let raw_bytes = [0x44, 0x01, 0x02, 0x03, 0x04];
71 let (consumed, parsed) = format.parse(&&raw_bytes[..]).unwrap();
72 assert_eq!(consumed, 5);
73 match parsed {
74 CborValue::Bytes(CborBytes::Definite(slice)) => {
75 assert_eq!(slice, &[1, 2, 3, 4]);
76 assert_eq!(slice.as_ptr(), raw_bytes[1..].as_ptr());
77 }
78 _ => panic!("expected definite byte string"),
79 }
80
81 let raw_text = [0x63, 0xe6, 0xb0, 0xb4]; let (consumed, parsed) = format.parse(&&raw_text[..]).unwrap();
84 assert_eq!(consumed, 4);
85 match parsed {
86 CborValue::Text(CborText::Definite(s)) => {
87 assert_eq!(s, "水");
88 assert_eq!(s.as_ptr(), raw_text[1..].as_ptr());
89 }
90 _ => panic!("expected definite text string"),
91 }
92
93 assert_eq!(format.parse(&&[0x80][..]), Ok((1, CborValue::Array(vec![]))));
95 assert_eq!(
96 format.parse(&&[0x82, 0x01, 0x02][..]),
97 Ok((3, CborValue::Array(vec![CborValue::Integer(1), CborValue::Integer(2)])))
98 );
99
100 assert_eq!(format.parse(&&[0xa0][..]), Ok((1, CborValue::Map(vec![]))));
102 assert_eq!(
103 format.parse(&&[0xa1, 0x61, b'a', 0x01][..]),
104 Ok((
105 4,
106 CborValue::Map(vec![(
107 CborValue::Text(CborText::Definite("a")),
108 CborValue::Integer(1)
109 )])
110 ))
111 );
112
113 assert_eq!(
115 format.parse(&&[0xc0, 0x60][..]),
116 Ok((2, CborValue::Tag(0, alloc::boxed::Box::new(CborValue::Text(CborText::Definite(""))))))
117 );
118
119 assert_eq!(format.parse(&&[0xf4][..]), Ok((1, CborValue::Bool(false))));
121 assert_eq!(format.parse(&&[0xf5][..]), Ok((1, CborValue::Bool(true))));
122 assert_eq!(format.parse(&&[0xf6][..]), Ok((1, CborValue::Null)));
123 assert_eq!(format.parse(&&[0xf7][..]), Ok((1, CborValue::Undefined)));
124 assert_eq!(format.parse(&&[0xf0][..]), Ok((1, CborValue::Simple(16))));
125 assert_eq!(format.parse(&&[0xf8, 0x20][..]), Ok((2, CborValue::Simple(32))));
126 assert_eq!(format.parse(&&[0xf9, 0x3c, 0x00][..]), Ok((3, CborValue::Float(CborFloat::F16(0x3c00)))));
127 assert_eq!(format.parse(&&[0xfa, 0x47, 0xc3, 0x50, 0x00][..]), Ok((5, CborValue::Float(CborFloat::F32(0x47c35000)))));
128 assert_eq!(format.parse(&&[0xfb, 0x3f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), Ok((9, CborValue::Float(CborFloat::F64(0x3ff8000000000000)))));
129 }
130
131 #[test]
132 fn indefinite_streaming_and_chunk_security() {
133 let format = CborFmt::<GENERAL>;
134
135 let byte_chunks = [0x5f, 0x42, 0x01, 0x02, 0x41, 0x03, 0xff];
137 assert_eq!(
138 format.parse(&&byte_chunks[..]),
139 Ok((byte_chunks.len(), CborValue::Bytes(CborBytes::Indefinite(vec![1, 2, 3]))))
140 );
141
142 let text_chunks = [0x7f, 0x62, b'h', b'i', 0x61, b'!', 0xff];
143 assert_eq!(
144 format.parse(&&text_chunks[..]),
145 Ok((text_chunks.len(), CborValue::Text(CborText::Indefinite("hi!".to_owned()))))
146 );
147
148 let array = [0x9f, 0x01, 0x02, 0xff];
150 assert_eq!(
151 format.parse(&&array[..]),
152 Ok((array.len(), CborValue::Array(vec![CborValue::Integer(1), CborValue::Integer(2)])))
153 );
154
155 let map = [0xbf, 0x61, b'k', 0x01, 0xff];
156 assert_eq!(
157 format.parse(&&map[..]),
158 Ok((
159 map.len(),
160 CborValue::Map(vec![(
161 CborValue::Text(CborText::Definite("k")),
162 CborValue::Integer(1)
163 )])
164 ))
165 );
166
167 assert!(format.parse(&&[0x5f, 0x5f, 0x41, 0x01, 0xff, 0xff][..]).is_err());
170
171 assert!(format.parse(&&[0x5f, 0x61, b'x', 0xff][..]).is_err());
173 assert!(format.parse(&&[0x7f, 0x41, 0x01, 0xff][..]).is_err());
174 assert!(format.parse(&&[0x5f, 0x01, 0xff][..]).is_err());
175
176 let split_utf8 = [0x7f, 0x61, 0xc2, 0x61, 0xa2, 0xff];
178 assert!(format.parse(&&split_utf8[..]).is_err());
179
180 assert!(format.parse(&&[0xbf, 0x01, 0xff][..]).is_err());
182
183 assert!(format.parse(&&[0xff][..]).is_err());
185 assert!(format.parse(&&[0x81, 0xff][..]).is_err());
186 }
187
188 #[test]
189 fn deterministic_dcbor_vs_general_cbor() {
190 let det = CborFmt::<DETERMINISTIC>;
191 let gen = CborFmt::<GENERAL>;
192
193 let non_minimal_uint = [0x18, 0x17];
195 assert!(det.parse(&&non_minimal_uint[..]).is_err());
196 assert_eq!(gen.parse(&&non_minimal_uint[..]), Ok((2, CborValue::Integer(23))));
197
198 let non_minimal_neg = [0x38, 0x17];
200 assert!(det.parse(&&non_minimal_neg[..]).is_err());
201 assert_eq!(gen.parse(&&non_minimal_neg[..]), Ok((2, CborValue::Integer(-24))));
202
203 let non_minimal_bstr_len = [0x58, 0x01, 0xaa];
205 assert!(det.parse(&&non_minimal_bstr_len[..]).is_err());
206 assert!(gen.parse(&&non_minimal_bstr_len[..]).is_ok());
207
208 let non_minimal_tag = [0xd8, 0x01, 0x00];
210 assert!(det.parse(&&non_minimal_tag[..]).is_err());
211 assert!(gen.parse(&&non_minimal_tag[..]).is_ok());
212
213 assert!(det.parse(&&[0x5f, 0x41, 0x01, 0xff][..]).is_err());
215 assert!(det.parse(&&[0x7f, 0x61, b'a', 0xff][..]).is_err());
216 assert!(det.parse(&&[0x9f, 0x01, 0xff][..]).is_err());
217 assert!(det.parse(&&[0xbf, 0x01, 0x02, 0xff][..]).is_err());
218 }
219
220 #[test]
221 fn truncation_and_malformed_input_robustness() {
222 let format = CborFmt::<GENERAL>;
223
224 assert!(format.parse(&&[0x18][..]).is_err());
226 assert!(format.parse(&&[0x19, 0x01][..]).is_err());
227 assert!(format.parse(&&[0x1a, 0x00, 0x01][..]).is_err());
228 assert!(format.parse(&&[0x1b, 0x00, 0x00, 0x00, 0x01][..]).is_err());
229
230 assert!(format.parse(&&[0x45, 0x01, 0x02, 0x03][..]).is_err()); assert!(format.parse(&&[0x65, b'a', b'b'][..]).is_err()); assert!(format.parse(&&[0x83, 0x01, 0x02][..]).is_err()); assert!(format.parse(&&[0xa1, 0x01][..]).is_err()); assert!(format.parse(&&[0x9f, 0x01, 0x02][..]).is_err());
240 assert!(format.parse(&&[0x5f, 0x41, 0x01][..]).is_err());
241
242 assert!(format.parse(&&[0x1c][..]).is_err());
244 assert!(format.parse(&&[0x1d][..]).is_err());
245 assert!(format.parse(&&[0x1e][..]).is_err());
246 }
247
248 #[test]
249 fn recursion_depth_limit_defense() {
250 let deeply_nested = [0x81, 0x81, 0x81, 0x81, 0x01];
252
253 let format_deep = CborFmt::<GENERAL, 6>;
255 assert!(format_deep.parse(&&deeply_nested[..]).is_ok());
256
257 let format_shallow = CborFmt::<GENERAL, 3>;
259 assert!(format_shallow.parse(&&deeply_nested[..]).is_err());
260 }
261
262 #[test]
263 fn serialization_and_roundtrip_invariants() {
264 let format = CborFmt::<DETERMINISTIC, 8>;
265
266 let value = CborValue::Map(vec![
267 (
268 CborValue::Integer(1),
269 CborValue::Array(vec![CborValue::Bool(true), CborValue::Null]),
270 ),
271 (
272 CborValue::Text(CborText::Definite("tag")),
273 CborValue::Tag(42, alloc::boxed::Box::new(CborValue::Integer(100))),
274 ),
275 ]);
276
277 let len = format.prepare(&value).unwrap();
279 assert_eq!(format.length(&value), len);
280
281 let mut buffer = vec![0u8; len];
283 format.serialize(&value, buffer.as_mut_slice());
284
285 assert_eq!(format.parse(&&buffer[..]), Ok((len, value)));
287
288 let gen_format = CborFmt::<GENERAL, 8>;
290 let indefinite_bytes = CborValue::Bytes(CborBytes::Indefinite(vec![1, 2, 3]));
291 let len = gen_format.prepare(&indefinite_bytes).unwrap();
292 let mut buffer = vec![0u8; len];
293 gen_format.serialize(&indefinite_bytes, buffer.as_mut_slice());
294 assert_eq!(buffer, [0x43, 0x01, 0x02, 0x03]);
295 }
296}