Coverage Report

Created: 2026-10-17 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fuzz/multi_surface_fuzzer.c
Line
Count
Source
1
// Copyright 2026 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
#include <cairo.h>
16
#include <cairo-pdf.h>
17
#include <cairo-ps.h>
18
#include <cairo-svg.h>
19
#include <cairo-script.h>
20
#include <stdint.h>
21
#include <stdlib.h>
22
#include <string.h>
23
#include "common_drawing.h"
24
25
static cairo_status_t
26
_write_func (void *closure, const uint8_t *data, unsigned int length)
27
1.25M
{
28
1.25M
    return CAIRO_STATUS_SUCCESS;
29
1.25M
}
30
31
11.3k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
32
11.3k
    if (size < 1) {
33
0
        return 0;
34
0
    }
35
36
11.3k
    uint8_t backend_choice = data[0] % 4;
37
11.3k
    const uint8_t *fuzz_data = data + 1;
38
11.3k
    size_t fuzz_size = size - 1;
39
40
11.3k
    cairo_surface_t *surface = NULL;
41
11.3k
    cairo_device_t *device = NULL;
42
11.3k
    cairo_status_t status;
43
44
11.3k
    switch (backend_choice) {
45
1.33k
        case 0: // PDF
46
1.33k
            surface = cairo_pdf_surface_create_for_stream(_write_func, NULL, 500.0, 500.0);
47
1.33k
            break;
48
8.45k
        case 1: // PS
49
8.45k
            surface = cairo_ps_surface_create_for_stream(_write_func, NULL, 595.0, 842.0); // A4
50
8.45k
            break;
51
653
        case 2: // SVG
52
653
            surface = cairo_svg_surface_create_for_stream(_write_func, NULL, 500.0, 500.0);
53
653
            break;
54
927
        case 3: // Script
55
927
            device = cairo_script_create_for_stream(_write_func, NULL);
56
927
            if (cairo_device_status(device) == CAIRO_STATUS_SUCCESS) {
57
927
                surface = cairo_script_surface_create(device, CAIRO_CONTENT_COLOR_ALPHA, 400, 400);
58
927
            }
59
927
            break;
60
11.3k
    }
61
62
11.3k
    if (!surface || cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
63
0
        if (surface) cairo_surface_destroy(surface);
64
0
        if (device) cairo_device_destroy(device);
65
0
        return 0;
66
0
    }
67
68
11.3k
    cairo_t *cr = cairo_create(surface);
69
    
70
    // Backend specific exercises
71
11.3k
    if (backend_choice == 0 && fuzz_size > 0) { // PDF specific
72
1.32k
        char *buf = (char *) malloc(fuzz_size + 1);
73
1.32k
        if (buf) {
74
1.32k
            memcpy(buf, fuzz_data, fuzz_size);
75
1.32k
            buf[fuzz_size] = '\0';
76
1.32k
            cairo_pdf_surface_set_metadata(surface, CAIRO_PDF_METADATA_TITLE, buf);
77
1.32k
            cairo_tag_begin(cr, buf, NULL);
78
1.32k
            cairo_tag_end(cr, buf);
79
1.32k
            free(buf);
80
1.32k
        }
81
1.32k
    }
82
83
11.3k
    do_drawing(cr, fuzz_data, fuzz_size);
84
85
11.3k
    if (backend_choice != 3) {
86
10.4k
        cairo_show_page(cr);
87
10.4k
    }
88
89
11.3k
    cairo_destroy(cr);
90
11.3k
    cairo_surface_finish(surface);
91
11.3k
    cairo_surface_destroy(surface);
92
    
93
11.3k
    if (device) {
94
927
        cairo_device_finish(device);
95
927
        cairo_device_destroy(device);
96
927
    }
97
98
11.3k
    return 0;
99
11.3k
}