1 use crate::decode::BmpDecode;
2 use crate::structured::{merge_qrs, SplittedQr};
3 use crate::{QrCode, Version};
4
5 impl arbitrary::Arbitrary for QrCode {
arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self>6 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
7 let level = crate::EcLevel::arbitrary(u)?;
8 let version = crate::Version::arbitrary(u)?;
9 let data = <Vec<u8>>::arbitrary(u)?;
10 let qr_code = QrCode::with_version(data, version, level)
11 .map_err(|_| arbitrary::Error::IncorrectFormat)?;
12 Ok(qr_code)
13 }
14 }
15
16 #[derive(Debug)]
17 /// doc
18 pub struct QrCodeData {
19 /// qr
20 pub qr_code: QrCode,
21 /// data
22 pub data: Vec<u8>,
23 /// mul
24 pub mul_border: Option<(u8, u8)>,
25 }
26
27 impl QrCodeData {
28 /// used for fuzz tests
check(self)29 pub fn check(self) {
30 let crate::QrCodeData {
31 qr_code,
32 data,
33 mul_border,
34 } = self;
35 let base_bmp = qr_code.to_bmp();
36 let bmp = match mul_border {
37 None => base_bmp,
38 Some((mul, border)) => base_bmp
39 .mul(mul)
40 .and_then(|mul_bmp| mul_bmp.add_white_border(border))
41 .unwrap_or(base_bmp)
42 .normalize(),
43 };
44 let decoded = bmp.decode().unwrap();
45 assert_eq!(data, decoded);
46 }
47 }
48
49 impl arbitrary::Arbitrary for QrCodeData {
arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self>50 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
51 let level = crate::EcLevel::arbitrary(u)?;
52 let version = crate::Version::arbitrary(u)?;
53 let data = <Vec<u8>>::arbitrary(u)?;
54 let qr_code = QrCode::with_version(&data, version, level)
55 .map_err(|_| arbitrary::Error::IncorrectFormat)?;
56 let mul_border = u8::arbitrary(u)?;
57 let mul_border = if mul_border % 2 == 0 {
58 None
59 } else {
60 Some(((mul_border / 64) + 2, (mul_border % 64) + 1))
61 };
62
63 Ok(QrCodeData {
64 qr_code,
65 data,
66 mul_border,
67 })
68 }
69 }
70
71 impl arbitrary::Arbitrary for Version {
arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self>72 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
73 let v = u8::arbitrary(u)?;
74 match v {
75 1..=40 => Ok(Version::Normal(v as i16)),
76 //41..=44 => Ok(Version::Micro((v-40u8) as i16)), not supported for now
77 _ => Err(arbitrary::Error::IncorrectFormat),
78 }
79 }
80 }
81
82 /// split merge round-trip for fuzz testing
split_merge_rt(version: i16, bytes: Vec<u8>)83 pub fn split_merge_rt(version: i16, bytes: Vec<u8>) {
84 if let Ok(splitted_qr) = SplittedQr::new(bytes.clone(), version) {
85 if let Ok(qrs) = splitted_qr.split() {
86 //println!("qrs len:{}", qrs.len());
87 let mut vec = vec![];
88 for qr in qrs {
89 let decoded = qr.to_bmp().decode().unwrap();
90 vec.push(decoded);
91 }
92 if let Ok(merged) = merge_qrs(vec) {
93 assert_eq!(merged, bytes);
94 }
95 }
96 }
97 }
98
99 #[cfg(test)]
100 mod tests {
101 use crate::fuzz::split_merge_rt;
102
103 #[test]
test_fuzz_decode_check()104 fn test_fuzz_decode_check() {
105 use arbitrary::Arbitrary;
106 let data = include_bytes!(
107 "../fuzz/artifacts/decode_check/crash-045dc09e6d00cfd6d3b3e9a4cfe5835e410c5fd1"
108 );
109 let unstructured = arbitrary::Unstructured::new(&data[..]);
110 let qr_code_data = crate::QrCodeData::arbitrary_take_rest(unstructured).unwrap();
111 qr_code_data.check();
112 }
113
114 #[test]
test_fuzz_encode()115 fn test_fuzz_encode() {
116 let data = include_bytes!(
117 "../fuzz/artifacts/encode/crash-9ffe42701f80d18e9c114f1134b9d64045f7d5ce"
118 );
119 assert!(crate::QrCode::new(data).is_ok());
120 }
121
122 #[test]
test_fuzz_split_merge_rt()123 fn test_fuzz_split_merge_rt() {
124 use arbitrary::Arbitrary;
125 let data = include_bytes!(
126 "../fuzz/artifacts/split_merge_rt/crash-1e272488adbe45a04a14b1a2b848997ff64e1b74"
127 );
128 let unstructured = arbitrary::Unstructured::new(&data[..]);
129 let (version, bytes) = <(i16, Vec<u8>)>::arbitrary_take_rest(unstructured).unwrap();
130 split_merge_rt(version, bytes);
131 }
132 }
133