Coverage Report

Created: 2026-09-14 06:18

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
0
{
28
0
    return CAIRO_STATUS_SUCCESS;
29
0
}
30
31
0
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
32
0
    if (size < 1) {
33
0
        return 0;
34
0
    }
35
36
0
    uint8_t backend_choice = data[0] % 4;
37
0
    const uint8_t *fuzz_data = data + 1;
38
0
    size_t fuzz_size = size - 1;
39
40
0
    cairo_surface_t *surface = NULL;
41
0
    cairo_device_t *device = NULL;
42
0
    cairo_status_t status;
43
44
0
    switch (backend_choice) {
45
0
        case 0: // PDF
46
0
            surface = cairo_pdf_surface_create_for_stream(_write_func, NULL, 500.0, 500.0);
47
0
            break;
48
0
        case 1: // PS
49
0
            surface = cairo_ps_surface_create_for_stream(_write_func, NULL, 595.0, 842.0); // A4
50
0
            break;
51
0
        case 2: // SVG
52
0
            surface = cairo_svg_surface_create_for_stream(_write_func, NULL, 500.0, 500.0);
53
0
            break;
54
0
        case 3: // Script
55
0
            device = cairo_script_create_for_stream(_write_func, NULL);
56
0
            if (cairo_device_status(device) == CAIRO_STATUS_SUCCESS) {
57
0
                surface = cairo_script_surface_create(device, CAIRO_CONTENT_COLOR_ALPHA, 400, 400);
58
0
            }
59
0
            break;
60
0
    }
61
62
0
    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
0
    cairo_t *cr = cairo_create(surface);
69
    
70
    // Backend specific exercises
71
0
    if (backend_choice == 0 && fuzz_size > 0) { // PDF specific
72
0
        char *buf = (char *) malloc(fuzz_size + 1);
73
0
        if (buf) {
74
0
            memcpy(buf, fuzz_data, fuzz_size);
75
0
            buf[fuzz_size] = '\0';
76
0
            cairo_pdf_surface_set_metadata(surface, CAIRO_PDF_METADATA_TITLE, buf);
77
0
            cairo_tag_begin(cr, buf, NULL);
78
0
            cairo_tag_end(cr, buf);
79
0
            free(buf);
80
0
        }
81
0
    }
82
83
0
    do_drawing(cr, fuzz_data, fuzz_size);
84
85
0
    if (backend_choice != 3) {
86
0
        cairo_show_page(cr);
87
0
    }
88
89
0
    cairo_destroy(cr);
90
0
    cairo_surface_finish(surface);
91
0
    cairo_surface_destroy(surface);
92
    
93
0
    if (device) {
94
0
        cairo_device_finish(device);
95
0
        cairo_device_destroy(device);
96
0
    }
97
98
0
    return 0;
99
0
}