/src/bson-rust/fuzz/fuzz_targets/encoding.rs
Line | Count | Source (jump to first uncovered line) |
1 | | #![no_main] |
2 | | use bson::{ |
3 | | raw::{RawDocument, RawDocumentBuf}, |
4 | | Bson, |
5 | | Document, |
6 | | }; |
7 | | use libfuzzer_sys::fuzz_target; |
8 | | |
9 | 15.0k | fn compare_docs(doc1: &Document, doc2: &Document) -> bool { |
10 | 15.0k | if doc1.len() != doc2.len() { |
11 | 0 | return false; |
12 | 15.0k | } |
13 | 181k | for (key, value) in doc1 { |
14 | 165k | if let Some(val2) = doc2.get(key) { |
15 | 165k | if !compare_values(value, val2) { |
16 | 0 | return false; |
17 | 165k | } |
18 | | } else { |
19 | 0 | return false; |
20 | | } |
21 | | } |
22 | 15.0k | true |
23 | 15.0k | } |
24 | | |
25 | 227k | fn compare_values(val1: &Bson, val2: &Bson) -> bool { |
26 | 227k | match (val1, val2) { |
27 | 7.96k | (Bson::Double(d1), Bson::Double(d2)) => (d1.is_nan() && d2.is_nan()) || d1 == d2, |
28 | 10.6k | (Bson::Document(doc1), Bson::Document(doc2)) => compare_docs(doc1, doc2), |
29 | 7.39k | (Bson::Array(arr1), Bson::Array(arr2)) => { |
30 | 7.39k | if arr1.len() != arr2.len() { |
31 | 0 | return false; |
32 | 7.39k | } |
33 | 61.1k | for (subval1, subval2) in std::iter::zip(arr1, arr2) { |
34 | 61.1k | if !compare_values(subval1, subval2) { |
35 | 0 | return false; |
36 | 61.1k | } |
37 | | } |
38 | 7.39k | true |
39 | | } |
40 | 1.95k | (Bson::JavaScriptCodeWithScope(jsc1), Bson::JavaScriptCodeWithScope(jsc2)) => { |
41 | 1.95k | jsc1.code == jsc2.code && compare_docs(&jsc1.scope, &jsc2.scope) |
42 | | } |
43 | 199k | (v1, v2) => v1 == v2, |
44 | | } |
45 | 227k | } |
46 | | |
47 | | fuzz_target!(|input: &[u8]| { |
48 | | if let Ok(rawdoc) = RawDocument::decode_from_bytes(&input) { |
49 | | if let Ok(doc) = Document::try_from(rawdoc) { |
50 | | let out = RawDocumentBuf::try_from(&doc).unwrap(); |
51 | | let out_bytes = out.as_bytes(); |
52 | | if input != out_bytes { |
53 | | let reencoded = RawDocument::decode_from_bytes(&out_bytes).unwrap(); |
54 | | let reencoded_doc = Document::try_from(reencoded).unwrap(); |
55 | | // Ensure that the re-encoded document is the same as the original document, the |
56 | | // bytes can differ while still resulting in the same Document. |
57 | | if !compare_docs(&doc, &reencoded_doc) { |
58 | | panic!( |
59 | | "Reencoded document is not the same as the original document: {:?} != {:?}", |
60 | | doc, reencoded_doc |
61 | | ); |
62 | | } |
63 | | } |
64 | | } |
65 | | } |
66 | | }); |