Coverage Report

Created: 2026-11-10 07:41

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
#include <GlobalParams.h>
7
8
// Recursive function to exercise structure tree parsing
9
static void exercise_structure_tree(PopplerStructureElementIter *iter)
10
52.9k
{
11
52.9k
    if (!iter) {
12
0
        return;
13
0
    }
14
15
168k
    do {
16
168k
        PopplerStructureElement *element = poppler_structure_element_iter_get_element(iter);
17
168k
        if (!element) {
18
0
            continue;
19
0
        }
20
21
        // Exercise all getter functions
22
168k
        (void)poppler_structure_element_get_kind(element);
23
24
        // These return gchar* that should be freed to prevent memory leaks
25
168k
        gchar *id = poppler_structure_element_get_id(element);
26
168k
        g_free(id);
27
28
168k
        gchar *title = poppler_structure_element_get_title(element);
29
168k
        g_free(title);
30
31
168k
        gchar *language = poppler_structure_element_get_language(element);
32
168k
        g_free(language);
33
34
168k
        gchar *abbreviation = poppler_structure_element_get_abbreviation(element);
35
168k
        g_free(abbreviation);
36
37
168k
        gchar *alt_text = poppler_structure_element_get_alt_text(element);
38
168k
        g_free(alt_text);
39
40
168k
        gchar *actual_text = poppler_structure_element_get_actual_text(element);
41
168k
        g_free(actual_text);
42
43
        // Check if it's content and test text extraction
44
168k
        if (poppler_structure_element_is_content(element)) {
45
            // Test non-recursive mode
46
109k
            gchar *text = poppler_structure_element_get_text(element, POPPLER_STRUCTURE_GET_TEXT_NONE);
47
109k
            g_free(text);
48
49
            // Test recursive mode
50
109k
            text = poppler_structure_element_get_text(element, POPPLER_STRUCTURE_GET_TEXT_RECURSIVE);
51
109k
            g_free(text);
52
109k
        }
53
54
        // Recurse into children
55
168k
        PopplerStructureElementIter *child_iter = poppler_structure_element_iter_get_child(iter);
56
168k
        if (child_iter) {
57
46.5k
            exercise_structure_tree(child_iter);
58
46.5k
            poppler_structure_element_iter_free(child_iter);
59
46.5k
        }
60
61
168k
        g_object_unref(element);
62
63
168k
    } while (poppler_structure_element_iter_next(iter));
64
52.9k
}
65
66
// Fuzzer entry point
67
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
68
8.32k
{
69
8.32k
    GlobalParamsIniter globalParamsIniter(nullptr);
70
8.32k
    globalParams->setErrQuiet(true);
71
72
8.32k
    GError *err = NULL;
73
74
    // Load document from fuzzer input
75
8.32k
    GBytes *bytes = g_bytes_new_static(data, size);
76
8.32k
    PopplerDocument *doc = poppler_document_new_from_bytes(bytes, NULL, &err);
77
8.32k
    g_bytes_unref(bytes);
78
79
8.32k
    if (doc == NULL) {
80
1.40k
        if (err) {
81
1.40k
            g_error_free(err);
82
1.40k
        }
83
1.40k
        return 0;
84
1.40k
    }
85
86
    // Try to create iterator - if it fails, no structure tree exists
87
6.92k
    PopplerStructureElementIter *root_iter = poppler_structure_element_iter_new(doc);
88
6.92k
    if (root_iter) {
89
6.31k
        exercise_structure_tree(root_iter);
90
6.31k
        poppler_structure_element_iter_free(root_iter);
91
6.31k
    }
92
93
6.92k
    g_object_unref(doc);
94
6.92k
    return 0;
95
8.32k
}