aboutsummaryrefslogtreecommitdiffstats
path: root/fuzz/src/main.rs
blob: d1967fcceb4b310d9e6b6a29f60c64f2b28e0860 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#[path = "../../tests/helpers/mod.rs"]
mod helpers;

fn check_full(vt_base: &vt100::Screen, empty: &vt100::Screen, idx: usize) {
    let mut input = vec![];
    input.extend(vt_base.state_formatted());
    input.extend(vt_base.bells_diff(empty));
    let mut vt_full = vt100::Parser::default();
    vt_full.process(&input);
    assert!(
        helpers::compare_screens(vt_full.screen(), vt_base),
        "{}: full:\n{}",
        idx,
        helpers::format_bytes(&input),
    );
}

fn check_diff_empty(
    vt_base: &vt100::Screen,
    empty: &vt100::Screen,
    idx: usize,
) {
    let mut input = vec![];
    input.extend(vt_base.state_diff(empty));
    input.extend(vt_base.bells_diff(empty));
    let mut vt_diff_empty = vt100::Parser::default();
    vt_diff_empty.process(&input);
    assert!(
        helpers::compare_screens(vt_diff_empty.screen(), vt_base),
        "{}: diff-empty:\n{}",
        idx,
        helpers::format_bytes(&input),
    );
}

fn check_diff(
    vt_base: &vt100::Screen,
    vt_diff: &mut vt100::Parser,
    prev: &vt100::Screen,
    empty: &vt100::Screen,
    idx: usize,
) {
    let mut input = vec![];
    input.extend(vt_base.state_diff(prev));
    input.extend(vt_base.bells_diff(empty));
    vt_diff.process(&input);
    assert!(
        helpers::compare_screens(vt_diff.screen(), vt_base),
        "{}: diff:\n{}",
        idx,
        helpers::format_bytes(&input),
    );
}

fn check_rows(vt_base: &vt100::Screen, empty: &vt100::Screen, idx: usize) {
    let mut input = vec![];
    let mut wrapped = false;
    for (idx, row) in vt_base.rows_formatted(0, 80).enumerate() {
        input.extend(b"\x1b[m");
        if !wrapped {
            input.extend(format!("\x1b[{}H", idx + 1).as_bytes());
        }
        input.extend(&row);
        wrapped = vt_base.row_wrapped(idx.try_into().unwrap());
    }
    input.extend(&vt_base.cursor_state_formatted());
    input.extend(&vt_base.attributes_formatted());
    input.extend(&vt_base.input_mode_formatted());
    input.extend(&vt_base.title_formatted());
    input.extend(&vt_base.bells_diff(empty));
    let mut vt_rows = vt100::Parser::default();
    vt_rows.process(&input);
    assert!(
        helpers::compare_screens(vt_rows.screen(), vt_base),
        "{}: rows:\n{}",
        idx,
        helpers::format_bytes(&input),
    );
}

fn main() {
    afl::fuzz!(|data: &[u8]| {
        let mut vt_base = vt100::Parser::default();
        let mut vt_diff = vt100::Parser::default();
        let mut prev_screen = vt_base.screen().clone();
        let empty_screen = vt100::Parser::default().screen().clone();
        for (idx, byte) in data.iter().enumerate() {
            vt_base.process(&[*byte]);

            check_full(vt_base.screen(), &empty_screen, idx);
            check_diff_empty(vt_base.screen(), &empty_screen, idx);
            check_diff(
                vt_base.screen(),
                &mut vt_diff,
                &prev_screen,
                &empty_screen,
                idx,
            );
            check_rows(vt_base.screen(), &empty_screen, idx);

            prev_screen = vt_base.screen().clone();
        }
    });
}