Coverage Report

Created: 2026-04-12 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bson-rust/fuzz/fuzz_targets/encoding.rs
Line
Count
Source
1
#![no_main]
2
use bson::{
3
    raw::{RawDocument, RawDocumentBuf},
4
    Bson,
5
    Document,
6
};
7
use libfuzzer_sys::fuzz_target;
8
9
28.3k
fn compare_docs(doc1: &Document, doc2: &Document) -> bool {
10
28.3k
    if doc1.len() != doc2.len() {
11
0
        return false;
12
28.3k
    }
13
275k
    for (key, value) in doc1 {
14
246k
        if let Some(val2) = doc2.get(key) {
15
246k
            if !compare_values(value, val2) {
16
0
                return false;
17
246k
            }
18
        } else {
19
0
            return false;
20
        }
21
    }
22
28.3k
    true
23
28.3k
}
24
25
555k
fn compare_values(val1: &Bson, val2: &Bson) -> bool {
26
555k
    match (val1, val2) {
27
10.2k
        (Bson::Double(d1), Bson::Double(d2)) => (d1.is_nan() && d2.is_nan()) || d1 == d2,
28
17.3k
        (Bson::Document(doc1), Bson::Document(doc2)) => compare_docs(doc1, doc2),
29
10.5k
        (Bson::Array(arr1), Bson::Array(arr2)) => {
30
10.5k
            if arr1.len() != arr2.len() {
31
0
                return false;
32
10.5k
            }
33
308k
            for (subval1, subval2) in std::iter::zip(arr1, arr2) {
34
308k
                if !compare_values(subval1, subval2) {
35
0
                    return false;
36
308k
                }
37
            }
38
10.5k
            true
39
        }
40
8.32k
        (Bson::JavaScriptCodeWithScope(jsc1), Bson::JavaScriptCodeWithScope(jsc2)) => {
41
8.32k
            jsc1.code == jsc2.code && compare_docs(&jsc1.scope, &jsc2.scope)
42
        }
43
509k
        (v1, v2) => v1 == v2,
44
    }
45
555k
}
46
47
fuzz_target!(|input: &[u8]| {
48
    if let Ok(rawdoc) = RawDocument::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::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
});