Coverage Report

Created: 2025-07-11 06:43

/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
});