Coverage Report

Created: 2026-09-28 08:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/poppler/glib/tests/fuzzing/structured_text_fuzzer.cc
Line
Count
Source
1
// Fuzzer for PDF structured text parser
2
3
#include <stdint.h>
4
#include <stdlib.h>
5
#include <poppler.h>
6
7
// Recursive function to exercise structure tree parsing
8
static void exercise_structure_tree(PopplerStructureElementIter *iter)
9
60.3k
{
10
60.3k
    if (!iter) {
11
0
        return;
12
0
    }
13
14
181k
    do {
15
181k
        PopplerStructureElement *element = poppler_structure_element_iter_get_element(iter);
16
181k
        if (!element) {
17
0
            continue;
18
0
        }
19
20
        // Exercise all getter functions
21
181k
        (void)poppler_structure_element_get_kind(element);
22
23
        // These return gchar* that should be freed to prevent memory leaks
24
181k
        gchar *id = poppler_structure_element_get_id(element);
25
181k
        g_free(id);
26
27
181k
        gchar *title = poppler_structure_element_get_title(element);
28
181k
        g_free(title);
29
30
181k
        gchar *language = poppler_structure_element_get_language(element);
31
181k
        g_free(language);
32
33
181k
        gchar *abbreviation = poppler_structure_element_get_abbreviation(element);
34
181k
        g_free(abbreviation);
35
36
181k
        gchar *alt_text = poppler_structure_element_get_alt_text(element);
37
181k
        g_free(alt_text);
38
39
181k
        gchar *actual_text = poppler_structure_element_get_actual_text(element);
40
181k
        g_free(actual_text);
41
42
        // Check if it's content and test text extraction
43
181k
        if (poppler_structure_element_is_content(element)) {
44
            // Test non-recursive mode
45
115k
            gchar *text = poppler_structure_element_get_text(element, POPPLER_STRUCTURE_GET_TEXT_NONE);
46
115k
            g_free(text);
47
48
            // Test recursive mode
49
115k
            text = poppler_structure_element_get_text(element, POPPLER_STRUCTURE_GET_TEXT_RECURSIVE);
50
115k
            g_free(text);
51
115k
        }
52
53
        // Recurse into children
54
181k
        PopplerStructureElementIter *child_iter = poppler_structure_element_iter_get_child(iter);
55
181k
        if (child_iter) {
56
53.5k
            exercise_structure_tree(child_iter);
57
53.5k
            poppler_structure_element_iter_free(child_iter);
58
53.5k
        }
59
60
181k
        g_object_unref(element);
61
62
181k
    } while (poppler_structure_element_iter_next(iter));
63
60.3k
}
64
65
// Fuzzer entry point
66
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
67
9.23k
{
68
9.23k
    GError *err = NULL;
69
70
    // Load document from fuzzer input
71
9.23k
    GBytes *bytes = g_bytes_new_static(data, size);
72
9.23k
    PopplerDocument *doc = poppler_document_new_from_bytes(bytes, NULL, &err);
73
9.23k
    g_bytes_unref(bytes);
74
75
9.23k
    if (doc == NULL) {
76
1.65k
        if (err) {
77
1.65k
            g_error_free(err);
78
1.65k
        }
79
1.65k
        return 0;
80
1.65k
    }
81
82
    // Try to create iterator - if it fails, no structure tree exists
83
7.57k
    PopplerStructureElementIter *root_iter = poppler_structure_element_iter_new(doc);
84
7.57k
    if (root_iter) {
85
6.87k
        exercise_structure_tree(root_iter);
86
6.87k
        poppler_structure_element_iter_free(root_iter);
87
6.87k
    }
88
89
7.57k
    g_object_unref(doc);
90
7.57k
    return 0;
91
9.23k
}