Coverage Report

Created: 2026-05-23 06:40

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