Coverage Report

Created: 2025-07-12 06:48

/src/ttf-parser/fuzz/fuzz_targets/fuzz-aat.rs
Line
Count
Source
1
// Copyright 2025 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//      http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#![no_main]
16
17
use libfuzzer_sys::fuzz_target;
18
use std::num::NonZeroU16;
19
use ttf_parser::{GlyphId, apple_layout::Lookup};
20
21
161
fn u16_to_u8_vec(data: &[u16]) -> Vec<u8> {
22
161
    let mut u8_data = Vec::with_capacity(data.len() * 2);
23
617
    for &value in data {
24
456
        u8_data.push((value >> 8) as u8);
25
456
        u8_data.push(value as u8);
26
456
    }
27
161
    u8_data
28
161
}
29
30
fuzz_target!(|data: &[u8]| {
31
    // Skip this iteration if data not enough
32
    if data.len() < 4 {
33
        return;
34
    }
35
36
    let (format_data, rest) = data.split_at(2);
37
    let format = u16::from_be_bytes([format_data[0], format_data[1]]);
38
39
172
    let random_u16 = |data: &[u8], idx: usize| -> Option<u16> {
40
172
        if data.len() > idx + 1 {
41
161
            Some(u16::from_be_bytes([data[idx], data[idx + 1]]))
42
        } else {
43
11
            None
44
        }
45
172
    };
46
47
    let lookup_len = NonZeroU16::new(1).unwrap();
48
49
    // Use valid fromat 0 2 4 6 8 10 for fuzzing chioce
50
    match format {
51
        0 => {
52
            if let Some(value) = random_u16(rest, 0) {
53
                let lookup_data = u16_to_u8_vec(&[0, value]);
54
                if let Some(table) = Lookup::parse(lookup_len, &lookup_data) {
55
                    let _ = table.value(GlyphId(0));
56
                    let _ = table.value(GlyphId(1));
57
                }
58
            }
59
        }
60
        2 => {
61
            if let Some(segment_size) = random_u16(rest, 2) {
62
                let lookup_data = u16_to_u8_vec(&[2, segment_size, 1]);
63
                if let Some(table) = Lookup::parse(lookup_len, &lookup_data) {
64
                    let _ = table.value(GlyphId(118));
65
                    let _ = table.value(GlyphId(5));
66
                }
67
            }
68
        }
69
        4 => {
70
            if let Some(segment_size) = random_u16(rest, 2) {
71
                let lookup_data = u16_to_u8_vec(&[4, segment_size, 1]);
72
                if let Some(table) = Lookup::parse(lookup_len, &lookup_data) {
73
                    let _ = table.value(GlyphId(118));
74
                    let _ = table.value(GlyphId(7));
75
                }
76
            }
77
        }
78
        6 => {
79
            if let Some(segment_size) = random_u16(rest, 2) {
80
                let lookup_data = u16_to_u8_vec(&[6, segment_size]);
81
                if let Some(table) = Lookup::parse(lookup_len, &lookup_data) {
82
                    let _ = table.value(GlyphId(0));
83
                    let _ = table.value(GlyphId(10));
84
                }
85
            }
86
        }
87
        8 => {
88
            if let Some(glyph_count) = random_u16(rest, 2) {
89
                let lookup_data = u16_to_u8_vec(&[8, 0, glyph_count]);
90
                if let Some(table) = Lookup::parse(lookup_len, &lookup_data) {
91
                    let _ = table.value(GlyphId(0));
92
                    let _ = table.value(GlyphId(5));
93
                }
94
            }
95
        }
96
        10 => {
97
            if let Some(value_size) = random_u16(rest, 2) {
98
                let lookup_data = u16_to_u8_vec(&[10, value_size, 0]);
99
                if let Some(table) = Lookup::parse(lookup_len, &lookup_data) {
100
                    let _ = table.value(GlyphId(0));
101
                    let _ = table.value(GlyphId(1));
102
                }
103
            }
104
        }
105
        _ => {
106
          // Ignore invliad format of 1 3 5 7 9        
107
        }
108
    }
109
});