Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/pdf/pdf_loop_detect.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2018-2022 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
/* code for handling circular references */
17
18
#include "pdf_int.h"
19
#include "pdf_loop_detect.h"
20
21
static int pdfi_init_loop_detector(pdf_context *ctx)
22
3.88M
{
23
3.88M
    if (ctx->loop_detection) {
24
0
        dbgmprintf(ctx->memory, "Attempt to initialise loop detector while one is in operation\n");
25
0
        return_error(gs_error_unknownerror);
26
0
    }
27
28
3.88M
    ctx->loop_detection = (uint64_t *)gs_alloc_bytes(ctx->memory, INITIAL_LOOP_TRACKER_SIZE * sizeof (uint64_t), "allocate loop tracking array");
29
3.88M
    if (ctx->loop_detection == NULL)
30
0
        return_error(gs_error_VMerror);
31
32
3.88M
    ctx->loop_detection_entries = 0;
33
3.88M
    ctx->loop_detection_size = INITIAL_LOOP_TRACKER_SIZE;
34
3.88M
    return 0;
35
3.88M
}
36
37
static int pdfi_free_loop_detector(pdf_context *ctx)
38
3.88M
{
39
3.88M
    if (ctx->loop_detection == NULL) {
40
0
        dbgmprintf(ctx->memory, "Attempt to free loop detector without initialising it\n");
41
0
        return 0;
42
0
    }
43
3.88M
    if (ctx->loop_detection != NULL)
44
3.88M
        gs_free_object(ctx->memory, ctx->loop_detection, "Free array for loop tracking");
45
3.88M
    ctx->loop_detection_entries = 0;
46
3.88M
    ctx->loop_detection_size = 0;
47
3.88M
    ctx->loop_detection = NULL;
48
49
3.88M
    return 0;
50
3.88M
}
51
52
int pdfi_loop_detector_add_object(pdf_context *ctx, uint64_t object)
53
11.9M
{
54
11.9M
    if (ctx->loop_detection == NULL) {
55
0
        dbgmprintf(ctx->memory, "Attempt to use loop detector without initialising it\n");
56
0
        return 0;
57
0
    }
58
59
11.9M
    if (ctx->loop_detection_entries == ctx->loop_detection_size) {
60
0
        uint64_t *New;
61
62
0
        New = (uint64_t *)gs_alloc_bytes(ctx->memory, (ctx->loop_detection_size + INITIAL_LOOP_TRACKER_SIZE) * sizeof (uint64_t), "re-allocate loop tracking array");
63
0
        if (New == NULL) {
64
0
            return_error(gs_error_VMerror);
65
0
        }
66
0
        memcpy(New, ctx->loop_detection, ctx->loop_detection_entries * sizeof(uint64_t));
67
0
        gs_free_object(ctx->memory, ctx->loop_detection, "Free array for loop tracking");
68
0
        ctx->loop_detection_size += INITIAL_LOOP_TRACKER_SIZE;
69
0
        ctx->loop_detection = New;
70
0
    }
71
11.9M
    ctx->loop_detection[ctx->loop_detection_entries++] = object;
72
11.9M
    return 0;
73
11.9M
}
74
75
bool pdfi_loop_detector_check_object(pdf_context *ctx, uint64_t object)
76
4.15M
{
77
4.15M
    int i = 0;
78
79
4.15M
    if (ctx->loop_detection == NULL) {
80
40
        dbgmprintf(ctx->memory, "Attempt to use loop detector without initialising it\n");
81
40
        return 0;
82
40
    }
83
84
10.9M
    for (i=0;i < ctx->loop_detection_entries;i++) {
85
6.83M
        if (ctx->loop_detection[i] == object) {
86
21.5k
            char info_string[256];
87
21.5k
            gs_snprintf(info_string, sizeof(info_string), "Error! circular reference to object %"PRIu64" detected.\n", object);
88
21.5k
            pdfi_set_error(ctx, 0, NULL, E_PDF_CIRCULARREF, "pdfi_loop_detector_check_object", info_string);
89
21.5k
            return true;
90
21.5k
        }
91
6.83M
    }
92
4.13M
    return false;
93
4.15M
}
94
95
int pdfi_loop_detector_mark(pdf_context *ctx)
96
7.32M
{
97
7.32M
    int code = 0;
98
99
7.32M
    if (ctx->loop_detection == NULL) {
100
3.88M
        code = pdfi_init_loop_detector(ctx);
101
3.88M
        if (code < 0)
102
0
            return code;
103
3.88M
    }
104
105
7.32M
    return pdfi_loop_detector_add_object(ctx, 0);
106
7.32M
}
107
108
int pdfi_loop_detector_cleartomark(pdf_context *ctx)
109
7.32M
{
110
7.32M
    if (ctx->loop_detection == NULL) {
111
610
        dbgmprintf(ctx->memory, "Attempt to use loop detector without initialising it\n");
112
610
        return 0;
113
610
    }
114
115
11.9M
    while (ctx->loop_detection[--ctx->loop_detection_entries] != 0) {
116
4.61M
        ctx->loop_detection[ctx->loop_detection_entries] = 0;
117
4.61M
    }
118
    /* FIXME - potential optimisation
119
     * Instead of freeing the loop detection array every tiome we are done with it
120
     * and then reallocating a new one next time we need one, we could just keep
121
     * the existing (empty) array. I suspect this would provide a small performance
122
     * improvement.
123
     */
124
7.32M
    if (ctx->loop_detection_entries == 0)
125
3.88M
        pdfi_free_loop_detector(ctx);
126
7.32M
    return 0;
127
7.32M
}