1 #![allow(clippy::cast_lossless, clippy::cast_possible_wrap)]
2 
3 use indoc::indoc;
4 use serde::serde_if_integer128;
5 use serde_derive::Deserialize;
6 use serde_yaml::Value;
7 use std::collections::BTreeMap;
8 use std::fmt::Debug;
9 
test_de<T>(yaml: &str, expected: &T) where T: serde::de::DeserializeOwned + PartialEq + Debug,10 fn test_de<T>(yaml: &str, expected: &T)
11 where
12     T: serde::de::DeserializeOwned + PartialEq + Debug,
13 {
14     let deserialized: T = serde_yaml::from_str(yaml).unwrap();
15     assert_eq!(*expected, deserialized);
16 
17     serde_yaml::from_str::<serde_yaml::Value>(yaml).unwrap();
18     serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
19 }
20 
test_de_seed<T, S>(yaml: &str, seed: S, expected: &T) where T: PartialEq + Debug, S: for<'de> serde::de::DeserializeSeed<'de, Value = T>,21 fn test_de_seed<T, S>(yaml: &str, seed: S, expected: &T)
22 where
23     T: PartialEq + Debug,
24     S: for<'de> serde::de::DeserializeSeed<'de, Value = T>,
25 {
26     let deserialized: T = serde_yaml::seed::from_str_seed(yaml, seed).unwrap();
27     assert_eq!(*expected, deserialized);
28 
29     serde_yaml::from_str::<serde_yaml::Value>(yaml).unwrap();
30     serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap();
31 }
32 
33 #[test]
test_alias()34 fn test_alias() {
35     let yaml = indoc! {"
36         ---
37         first:
38           &alias
39           1
40         second:
41           *alias
42         third: 3
43     "};
44     let mut expected = BTreeMap::new();
45     {
46         expected.insert(String::from("first"), 1);
47         expected.insert(String::from("second"), 1);
48         expected.insert(String::from("third"), 3);
49     }
50     test_de(&yaml, &expected);
51 }
52 
53 #[test]
test_option()54 fn test_option() {
55     #[derive(Deserialize, PartialEq, Debug)]
56     struct Data {
57         a: Option<f64>,
58         b: Option<String>,
59         c: Option<bool>,
60     }
61     let yaml = indoc! {"
62         ---
63         b:
64         c: true
65     "};
66     let expected = Data {
67         a: None,
68         b: None,
69         c: Some(true),
70     };
71     test_de(&yaml, &expected);
72 }
73 
74 #[test]
test_option_alias()75 fn test_option_alias() {
76     #[derive(Deserialize, PartialEq, Debug)]
77     struct Data {
78         a: Option<f64>,
79         b: Option<String>,
80         c: Option<bool>,
81         d: Option<f64>,
82         e: Option<String>,
83         f: Option<bool>,
84     }
85     let yaml = indoc! {"
86         ---
87         none_f:
88           &none_f
89           ~
90         none_s:
91           &none_s
92           ~
93         none_b:
94           &none_b
95           ~
96 
97         some_f:
98           &some_f
99           1.0
100         some_s:
101           &some_s
102           x
103         some_b:
104           &some_b
105           true
106 
107         a: *none_f
108         b: *none_s
109         c: *none_b
110         d: *some_f
111         e: *some_s
112         f: *some_b
113     "};
114     let expected = Data {
115         a: None,
116         b: None,
117         c: None,
118         d: Some(1.0),
119         e: Some("x".to_owned()),
120         f: Some(true),
121     };
122     test_de(&yaml, &expected);
123 }
124 
125 #[test]
test_enum_alias()126 fn test_enum_alias() {
127     #[derive(Deserialize, PartialEq, Debug)]
128     enum E {
129         A,
130         B(u8, u8),
131     }
132     #[derive(Deserialize, PartialEq, Debug)]
133     struct Data {
134         a: E,
135         b: E,
136     }
137     let yaml = indoc! {"
138         ---
139         aref:
140           &aref
141           A
142         bref:
143           &bref
144           B:
145             - 1
146             - 2
147 
148         a: *aref
149         b: *bref
150     "};
151     let expected = Data {
152         a: E::A,
153         b: E::B(1, 2),
154     };
155     test_de(&yaml, &expected);
156 }
157 
158 #[test]
test_enum_tag()159 fn test_enum_tag() {
160     #[derive(Deserialize, PartialEq, Debug)]
161     enum E {
162         A(String),
163         B(String),
164     }
165     #[derive(Deserialize, PartialEq, Debug)]
166     struct Data {
167         a: E,
168         b: E,
169     }
170     let yaml = indoc! {"
171         ---
172         a: !A foo
173         b: !B bar
174     "};
175     let expected = Data {
176         a: E::A("foo".into()),
177         b: E::B("bar".into()),
178     };
179     test_de(&yaml, &expected);
180 }
181 
182 #[test]
test_number_as_string()183 fn test_number_as_string() {
184     #[derive(Deserialize, PartialEq, Debug)]
185     struct Num {
186         value: String,
187     }
188     let yaml = indoc! {"
189         ---
190         # Cannot be represented as u128
191         value: 340282366920938463463374607431768211457
192     "};
193     let expected = Num {
194         value: "340282366920938463463374607431768211457".to_owned(),
195     };
196     test_de(&yaml, &expected);
197 }
198 
199 serde_if_integer128! {
200     #[test]
201     fn test_i128_big() {
202         let expected: i128 = ::std::i64::MIN as i128 - 1;
203         let yaml = indoc! {"
204             ---
205             -9223372036854775809
206         "};
207         assert_eq!(expected, serde_yaml::from_str::<i128>(&yaml).unwrap());
208     }
209 
210     #[test]
211     fn test_u128_big() {
212         let expected: u128 = ::std::u64::MAX as u128 + 1;
213         let yaml = indoc! {"
214             ---
215             18446744073709551616
216         "};
217         assert_eq!(expected, serde_yaml::from_str::<u128>(&yaml).unwrap());
218     }
219 }
220 
221 #[test]
test_number_alias_as_string()222 fn test_number_alias_as_string() {
223     #[derive(Deserialize, PartialEq, Debug)]
224     struct Num {
225         version: String,
226         value: String,
227     }
228     let yaml = indoc! {"
229         ---
230         version: &a 1.10
231         value: *a
232     "};
233     let expected = Num {
234         version: "1.10".to_owned(),
235         value: "1.10".to_owned(),
236     };
237     test_de(&yaml, &expected);
238 }
239 
240 #[test]
test_de_mapping()241 fn test_de_mapping() {
242     #[derive(Debug, Deserialize, PartialEq)]
243     struct Data {
244         pub substructure: serde_yaml::Mapping,
245     }
246     let yaml = indoc! {"
247         ---
248         substructure:
249           a: 'foo'
250           b: 'bar'
251     "};
252 
253     let mut expected = Data {
254         substructure: serde_yaml::Mapping::new(),
255     };
256     expected.substructure.insert(
257         serde_yaml::Value::String("a".to_owned()),
258         serde_yaml::Value::String("foo".to_owned()),
259     );
260     expected.substructure.insert(
261         serde_yaml::Value::String("b".to_owned()),
262         serde_yaml::Value::String("bar".to_owned()),
263     );
264 
265     test_de(&yaml, &expected);
266 }
267 
268 #[test]
test_bomb()269 fn test_bomb() {
270     #[derive(Debug, Deserialize, PartialEq)]
271     struct Data {
272         expected: String,
273     }
274 
275     // This would deserialize an astronomical number of elements if we were
276     // vulnerable.
277     let yaml = indoc! {"
278         ---
279         a: &a ~
280         b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
281         c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
282         d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
283         e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
284         f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
285         g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
286         h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
287         i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
288         j: &j [*i,*i,*i,*i,*i,*i,*i,*i,*i]
289         k: &k [*j,*j,*j,*j,*j,*j,*j,*j,*j]
290         l: &l [*k,*k,*k,*k,*k,*k,*k,*k,*k]
291         m: &m [*l,*l,*l,*l,*l,*l,*l,*l,*l]
292         n: &n [*m,*m,*m,*m,*m,*m,*m,*m,*m]
293         o: &o [*n,*n,*n,*n,*n,*n,*n,*n,*n]
294         p: &p [*o,*o,*o,*o,*o,*o,*o,*o,*o]
295         q: &q [*p,*p,*p,*p,*p,*p,*p,*p,*p]
296         r: &r [*q,*q,*q,*q,*q,*q,*q,*q,*q]
297         s: &s [*r,*r,*r,*r,*r,*r,*r,*r,*r]
298         t: &t [*s,*s,*s,*s,*s,*s,*s,*s,*s]
299         u: &u [*t,*t,*t,*t,*t,*t,*t,*t,*t]
300         v: &v [*u,*u,*u,*u,*u,*u,*u,*u,*u]
301         w: &w [*v,*v,*v,*v,*v,*v,*v,*v,*v]
302         x: &x [*w,*w,*w,*w,*w,*w,*w,*w,*w]
303         y: &y [*x,*x,*x,*x,*x,*x,*x,*x,*x]
304         z: &z [*y,*y,*y,*y,*y,*y,*y,*y,*y]
305         expected: string
306     "};
307 
308     let expected = Data {
309         expected: "string".to_owned(),
310     };
311 
312     assert_eq!(expected, serde_yaml::from_str::<Data>(&yaml).unwrap());
313 }
314 
315 #[test]
test_numbers()316 fn test_numbers() {
317     let cases = [
318         ("0xF0", "240"),
319         ("+0xF0", "240"),
320         ("-0xF0", "-240"),
321         ("0o70", "56"),
322         ("+0o70", "56"),
323         ("-0o70", "-56"),
324         ("0b10", "2"),
325         ("+0b10", "2"),
326         ("-0b10", "-2"),
327         ("127", "127"),
328         ("+127", "127"),
329         ("-127", "-127"),
330         (".inf", ".inf"),
331         (".Inf", ".inf"),
332         (".INF", ".inf"),
333         ("-.inf", "-.inf"),
334         ("-.Inf", "-.inf"),
335         ("-.INF", "-.inf"),
336         (".nan", ".nan"),
337         (".NaN", ".nan"),
338         (".NAN", ".nan"),
339         ("0.1", "0.1"),
340     ];
341     for &(yaml, expected) in &cases {
342         let value = serde_yaml::from_str::<Value>(yaml).unwrap();
343         match value {
344             Value::Number(number) => assert_eq!(number.to_string(), expected),
345             _ => panic!("expected number"),
346         }
347     }
348 }
349 
350 #[test]
test_stateful()351 fn test_stateful() {
352     struct Seed(i64);
353 
354     impl<'de> serde::de::DeserializeSeed<'de> for Seed {
355         type Value = i64;
356         fn deserialize<D>(self, deserializer: D) -> Result<i64, D::Error>
357         where
358             D: serde::de::Deserializer<'de>,
359         {
360             struct Visitor(i64);
361             impl<'de> serde::de::Visitor<'de> for Visitor {
362                 type Value = i64;
363 
364                 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
365                     write!(formatter, "an integer")
366                 }
367 
368                 fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<i64, E> {
369                     Ok(v * self.0)
370                 }
371 
372                 fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<i64, E> {
373                     Ok(v as i64 * self.0)
374                 }
375             }
376 
377             deserializer.deserialize_any(Visitor(self.0))
378         }
379     }
380 
381     let cases = [("3", 5, 15), ("6", 7, 42), ("-5", 9, -45)];
382     for &(yaml, seed, expected) in &cases {
383         test_de_seed(yaml, Seed(seed), &expected);
384     }
385 }
386