• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![allow(clippy::zero_sized_map_values)]
2 
3 use indoc::indoc;
4 use serde::de::Deserialize;
5 #[cfg(not(miri))]
6 use serde::de::{SeqAccess, Visitor};
7 use serde_derive::{Deserialize, Serialize};
8 use serde_yaml::value::{Tag, TaggedValue};
9 use serde_yaml::{Deserializer, Value};
10 #[cfg(not(miri))]
11 use std::collections::BTreeMap;
12 #[cfg(not(miri))]
13 use std::fmt;
14 use std::fmt::Debug;
15 
test_error<'de, T>(yaml: &'de str, expected: &str) where T: Deserialize<'de> + Debug,16 fn test_error<'de, T>(yaml: &'de str, expected: &str)
17 where
18     T: Deserialize<'de> + Debug,
19 {
20     let result = serde_yaml::from_str::<T>(yaml);
21     assert_eq!(expected, result.unwrap_err().to_string());
22 
23     let mut deserializer = Deserializer::from_str(yaml);
24     if let Some(first_document) = deserializer.next() {
25         if deserializer.next().is_none() {
26             let result = T::deserialize(first_document);
27             assert_eq!(expected, result.unwrap_err().to_string());
28         }
29     }
30 }
31 
32 #[test]
test_scan_error()33 fn test_scan_error() {
34     let yaml = ">\n@";
35     let expected = "found character that cannot start any token at line 2 column 1, while scanning for the next token";
36     test_error::<Value>(yaml, expected);
37 }
38 
39 #[test]
test_incorrect_type()40 fn test_incorrect_type() {
41     let yaml = indoc! {"
42         ---
43         str
44     "};
45     let expected = "invalid type: string \"str\", expected i16 at line 2 column 1";
46     test_error::<i16>(yaml, expected);
47 }
48 
49 #[test]
test_incorrect_nested_type()50 fn test_incorrect_nested_type() {
51     #[derive(Deserialize, Debug)]
52     pub struct A {
53         pub b: Vec<B>,
54     }
55     #[derive(Deserialize, Debug)]
56     pub enum B {
57         C(C),
58     }
59     #[derive(Deserialize, Debug)]
60     pub struct C {
61         pub d: bool,
62     }
63     let yaml = indoc! {"
64         b:
65           - !C
66             d: fase
67     "};
68     let expected = "b[0].d: invalid type: string \"fase\", expected a boolean at line 3 column 8";
69     test_error::<A>(yaml, expected);
70 }
71 
72 #[test]
test_empty()73 fn test_empty() {
74     let expected = "EOF while parsing a value";
75     test_error::<String>("", expected);
76 }
77 
78 #[test]
test_missing_field()79 fn test_missing_field() {
80     #[derive(Deserialize, Debug)]
81     pub struct Basic {
82         pub v: bool,
83         pub w: bool,
84     }
85     let yaml = indoc! {"
86         ---
87         v: true
88     "};
89     let expected = "missing field `w` at line 2 column 1";
90     test_error::<Basic>(yaml, expected);
91 }
92 
93 #[test]
test_unknown_anchor()94 fn test_unknown_anchor() {
95     let yaml = indoc! {"
96         ---
97         *some
98     "};
99     let expected = "unknown anchor at line 2 column 1";
100     test_error::<String>(yaml, expected);
101 }
102 
103 #[test]
test_ignored_unknown_anchor()104 fn test_ignored_unknown_anchor() {
105     #[derive(Deserialize, Debug)]
106     pub struct Wrapper {
107         pub c: (),
108     }
109     let yaml = indoc! {"
110         b: [*a]
111         c: ~
112     "};
113     let expected = "unknown anchor at line 1 column 5";
114     test_error::<Wrapper>(yaml, expected);
115 }
116 
117 #[test]
test_bytes()118 fn test_bytes() {
119     let expected = "serialization and deserialization of bytes in YAML is not implemented";
120     test_error::<&[u8]>("...", expected);
121 }
122 
123 #[test]
test_two_documents()124 fn test_two_documents() {
125     let yaml = indoc! {"
126         ---
127         0
128         ---
129         1
130     "};
131     let expected = "deserializing from YAML containing more than one document is not supported";
132     test_error::<usize>(yaml, expected);
133 }
134 
135 #[test]
test_second_document_syntax_error()136 fn test_second_document_syntax_error() {
137     let yaml = indoc! {"
138         ---
139         0
140         ---
141         ]
142     "};
143 
144     let mut de = Deserializer::from_str(yaml);
145     let first_doc = de.next().unwrap();
146     let result = <usize as serde::Deserialize>::deserialize(first_doc);
147     assert_eq!(0, result.unwrap());
148 
149     let second_doc = de.next().unwrap();
150     let result = <usize as serde::Deserialize>::deserialize(second_doc);
151     let expected =
152         "did not find expected node content at line 4 column 1, while parsing a block node";
153     assert_eq!(expected, result.unwrap_err().to_string());
154 }
155 
156 #[test]
test_missing_enum_tag()157 fn test_missing_enum_tag() {
158     #[derive(Deserialize, Debug)]
159     pub enum E {
160         V(usize),
161     }
162     let yaml = indoc! {r#"
163         "V": 16
164         "other": 32
165     "#};
166     let expected = "invalid type: map, expected a YAML tag starting with '!'";
167     test_error::<E>(yaml, expected);
168 }
169 
170 #[test]
test_serialize_nested_enum()171 fn test_serialize_nested_enum() {
172     #[derive(Serialize, Debug)]
173     pub enum Outer {
174         Inner(Inner),
175     }
176     #[derive(Serialize, Debug)]
177     pub enum Inner {
178         Newtype(usize),
179         Tuple(usize, usize),
180         Struct { x: usize },
181     }
182 
183     let expected = "serializing nested enums in YAML is not supported yet";
184 
185     let e = Outer::Inner(Inner::Newtype(0));
186     let error = serde_yaml::to_string(&e).unwrap_err();
187     assert_eq!(error.to_string(), expected);
188 
189     let e = Outer::Inner(Inner::Tuple(0, 0));
190     let error = serde_yaml::to_string(&e).unwrap_err();
191     assert_eq!(error.to_string(), expected);
192 
193     let e = Outer::Inner(Inner::Struct { x: 0 });
194     let error = serde_yaml::to_string(&e).unwrap_err();
195     assert_eq!(error.to_string(), expected);
196 
197     let e = Value::Tagged(Box::new(TaggedValue {
198         tag: Tag::new("Outer"),
199         value: Value::Tagged(Box::new(TaggedValue {
200             tag: Tag::new("Inner"),
201             value: Value::Null,
202         })),
203     }));
204     let error = serde_yaml::to_string(&e).unwrap_err();
205     assert_eq!(error.to_string(), expected);
206 }
207 
208 #[test]
test_deserialize_nested_enum()209 fn test_deserialize_nested_enum() {
210     #[derive(Deserialize, Debug)]
211     pub enum Outer {
212         Inner(Inner),
213     }
214     #[derive(Deserialize, Debug)]
215     pub enum Inner {
216         Variant(Vec<usize>),
217     }
218 
219     let yaml = indoc! {"
220         ---
221         !Inner []
222     "};
223     let expected = "deserializing nested enum in Outer::Inner from YAML is not supported yet at line 2 column 1";
224     test_error::<Outer>(yaml, expected);
225 
226     let yaml = indoc! {"
227         ---
228         !Variant []
229     "};
230     let expected = "unknown variant `Variant`, expected `Inner`";
231     test_error::<Outer>(yaml, expected);
232 
233     let yaml = indoc! {"
234         ---
235         !Inner !Variant []
236     "};
237     let expected = "deserializing nested enum in Outer::Inner from YAML is not supported yet at line 2 column 1";
238     test_error::<Outer>(yaml, expected);
239 }
240 
241 #[test]
test_variant_not_a_seq()242 fn test_variant_not_a_seq() {
243     #[derive(Deserialize, Debug)]
244     pub enum E {
245         V(usize),
246     }
247     let yaml = indoc! {"
248         ---
249         !V
250         value: 0
251     "};
252     let expected = "invalid type: map, expected usize at line 2 column 1";
253     test_error::<E>(yaml, expected);
254 }
255 
256 #[test]
test_struct_from_sequence()257 fn test_struct_from_sequence() {
258     #[derive(Deserialize, Debug)]
259     pub struct Struct {
260         pub x: usize,
261         pub y: usize,
262     }
263     let yaml = indoc! {"
264         [0, 0]
265     "};
266     let expected = "invalid type: sequence, expected struct Struct";
267     test_error::<Struct>(yaml, expected);
268 }
269 
270 #[test]
test_bad_bool()271 fn test_bad_bool() {
272     let yaml = indoc! {"
273         ---
274         !!bool str
275     "};
276     let expected = "invalid value: string \"str\", expected a boolean at line 2 column 1";
277     test_error::<bool>(yaml, expected);
278 }
279 
280 #[test]
test_bad_int()281 fn test_bad_int() {
282     let yaml = indoc! {"
283         ---
284         !!int str
285     "};
286     let expected = "invalid value: string \"str\", expected an integer at line 2 column 1";
287     test_error::<i64>(yaml, expected);
288 }
289 
290 #[test]
test_bad_float()291 fn test_bad_float() {
292     let yaml = indoc! {"
293         ---
294         !!float str
295     "};
296     let expected = "invalid value: string \"str\", expected a float at line 2 column 1";
297     test_error::<f64>(yaml, expected);
298 }
299 
300 #[test]
test_bad_null()301 fn test_bad_null() {
302     let yaml = indoc! {"
303         ---
304         !!null str
305     "};
306     let expected = "invalid value: string \"str\", expected null at line 2 column 1";
307     test_error::<()>(yaml, expected);
308 }
309 
310 #[test]
test_short_tuple()311 fn test_short_tuple() {
312     let yaml = indoc! {"
313         ---
314         [0, 0]
315     "};
316     let expected = "invalid length 2, expected a tuple of size 3 at line 2 column 1";
317     test_error::<(u8, u8, u8)>(yaml, expected);
318 }
319 
320 #[test]
test_long_tuple()321 fn test_long_tuple() {
322     let yaml = indoc! {"
323         ---
324         [0, 0, 0]
325     "};
326     let expected = "invalid length 3, expected sequence of 2 elements at line 2 column 1";
327     test_error::<(u8, u8)>(yaml, expected);
328 }
329 
330 #[test]
test_invalid_scalar_type()331 fn test_invalid_scalar_type() {
332     #[derive(Deserialize, Debug)]
333     pub struct S {
334         pub x: [i32; 1],
335     }
336 
337     let yaml = "x: ''\n";
338     let expected = "x: invalid type: string \"\", expected an array of length 1 at line 1 column 4";
339     test_error::<S>(yaml, expected);
340 }
341 
342 #[cfg(not(miri))]
343 #[test]
test_infinite_recursion_objects()344 fn test_infinite_recursion_objects() {
345     #[derive(Deserialize, Debug)]
346     pub struct S {
347         pub x: Option<Box<S>>,
348     }
349 
350     let yaml = "&a {'x': *a}";
351     let expected = "recursion limit exceeded";
352     test_error::<S>(yaml, expected);
353 }
354 
355 #[cfg(not(miri))]
356 #[test]
test_infinite_recursion_arrays()357 fn test_infinite_recursion_arrays() {
358     #[derive(Deserialize, Debug)]
359     pub struct S(pub usize, pub Option<Box<S>>);
360 
361     let yaml = "&a [0, *a]";
362     let expected = "recursion limit exceeded";
363     test_error::<S>(yaml, expected);
364 }
365 
366 #[cfg(not(miri))]
367 #[test]
test_infinite_recursion_newtype()368 fn test_infinite_recursion_newtype() {
369     #[derive(Deserialize, Debug)]
370     pub struct S(pub Option<Box<S>>);
371 
372     let yaml = "&a [*a]";
373     let expected = "recursion limit exceeded";
374     test_error::<S>(yaml, expected);
375 }
376 
377 #[cfg(not(miri))]
378 #[test]
test_finite_recursion_objects()379 fn test_finite_recursion_objects() {
380     #[derive(Deserialize, Debug)]
381     pub struct S {
382         pub x: Option<Box<S>>,
383     }
384 
385     let yaml = "{'x':".repeat(1_000) + &"}".repeat(1_000);
386     let expected = "recursion limit exceeded at line 1 column 641";
387     test_error::<S>(&yaml, expected);
388 }
389 
390 #[cfg(not(miri))]
391 #[test]
test_finite_recursion_arrays()392 fn test_finite_recursion_arrays() {
393     #[derive(Deserialize, Debug)]
394     pub struct S(pub usize, pub Option<Box<S>>);
395 
396     let yaml = "[0, ".repeat(1_000) + &"]".repeat(1_000);
397     let expected = "recursion limit exceeded at line 1 column 513";
398     test_error::<S>(&yaml, expected);
399 }
400 
401 #[cfg(not(miri))]
402 #[test]
test_billion_laughs()403 fn test_billion_laughs() {
404     #[derive(Debug)]
405     struct X;
406 
407     impl<'de> Deserialize<'de> for X {
408         fn deserialize<D>(deserializer: D) -> Result<X, D::Error>
409         where
410             D: serde::Deserializer<'de>,
411         {
412             impl<'de> Visitor<'de> for X {
413                 type Value = X;
414 
415                 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
416                     formatter.write_str("exponential blowup")
417                 }
418 
419                 fn visit_unit<E>(self) -> Result<X, E> {
420                     Ok(X)
421                 }
422 
423                 fn visit_seq<S>(self, mut seq: S) -> Result<X, S::Error>
424                 where
425                     S: SeqAccess<'de>,
426                 {
427                     while let Some(X) = seq.next_element()? {}
428                     Ok(X)
429                 }
430             }
431 
432             deserializer.deserialize_any(X)
433         }
434     }
435 
436     let yaml = indoc! {"
437         a: &a ~
438         b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
439         c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
440         d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
441         e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
442         f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
443         g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
444         h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
445         i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
446     "};
447     let expected = "repetition limit exceeded";
448     test_error::<BTreeMap<String, X>>(yaml, expected);
449 }
450 
451 #[test]
test_duplicate_keys()452 fn test_duplicate_keys() {
453     let yaml = indoc! {"
454         ---
455         thing: true
456         thing: false
457     "};
458     let expected = "duplicate entry with key \"thing\" at line 2 column 1";
459     test_error::<Value>(yaml, expected);
460 
461     let yaml = indoc! {"
462         ---
463         null: true
464         ~: false
465     "};
466     let expected = "duplicate entry with null key at line 2 column 1";
467     test_error::<Value>(yaml, expected);
468 
469     let yaml = indoc! {"
470         ---
471         99: true
472         99: false
473     "};
474     let expected = "duplicate entry with key 99 at line 2 column 1";
475     test_error::<Value>(yaml, expected);
476 
477     let yaml = indoc! {"
478         ---
479         {}: true
480         {}: false
481     "};
482     let expected = "duplicate entry in YAML map at line 2 column 1";
483     test_error::<Value>(yaml, expected);
484 }
485