Coverage Report

Created: 2025-06-10 07:24

/src/ghostpdl/base/gsparamx.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 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.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Extended parameter dictionary utilities */
18
#include "string_.h"
19
#include "gserrors.h"
20
#include "gstypes.h"
21
#include "gsmemory.h"
22
#include "gsparam.h"
23
#include "gsparamx.h"
24
25
/* Compare a C string and a gs_param_string. */
26
bool
27
gs_param_string_eq(const gs_param_string * pcs, const char *str)
28
325k
{
29
325k
    return (strlen(str) == pcs->size &&
30
325k
            !strncmp(str, (const char *)pcs->data, pcs->size));
31
325k
}
32
33
/* Put an enumerated value. */
34
int
35
param_put_enum(gs_param_list * plist, gs_param_name param_name,
36
               int *pvalue, const char *const pnames[], int ecode)
37
1.26M
{
38
1.26M
    gs_param_string ens;
39
1.26M
    int code = param_read_name(plist, param_name, &ens);
40
41
1.26M
    switch (code) {
42
1.10M
        case 1:
43
1.10M
            return ecode;
44
157k
        case 0:
45
157k
            {
46
157k
                int i;
47
48
281k
                for (i = 0; pnames[i] != 0; ++i)
49
281k
                    if (gs_param_string_eq(&ens, pnames[i])) {
50
157k
                        *pvalue = i;
51
157k
                        return 0;
52
157k
                    }
53
157k
            }
54
0
            code = gs_error_rangecheck;
55
            /* fall through */
56
0
        default:
57
0
            ecode = code;
58
0
            param_signal_error(plist, param_name, code);
59
1.26M
    }
60
0
    return ecode;
61
1.26M
}
62
63
/* Put a Boolean value. */
64
int
65
param_put_bool(gs_param_list * plist, gs_param_name param_name,
66
               bool * pval, int ecode)
67
105k
{
68
105k
    int code;
69
70
105k
    switch (code = param_read_bool(plist, param_name, pval)) {
71
0
        default:
72
0
            ecode = code;
73
0
            param_signal_error(plist, param_name, ecode);
74
14.7k
        case 0:
75
105k
        case 1:
76
105k
            break;
77
105k
    }
78
105k
    return ecode;
79
105k
}
80
81
/* Put an integer value. */
82
int
83
param_put_int(gs_param_list * plist, gs_param_name param_name,
84
              int *pval, int ecode)
85
210k
{
86
210k
    int code;
87
88
210k
    switch (code = param_read_int(plist, param_name, pval)) {
89
0
        default:
90
0
            ecode = code;
91
0
            param_signal_error(plist, param_name, ecode);
92
5.00k
        case 0:
93
210k
        case 1:
94
210k
            break;
95
210k
    }
96
210k
    return ecode;
97
210k
}
98
99
/* Put a long value. */
100
int
101
param_put_long(gs_param_list * plist, gs_param_name param_name,
102
               long *pval, int ecode)
103
0
{
104
0
    int code;
105
106
0
    switch (code = param_read_long(plist, param_name, pval)) {
107
0
        default:
108
0
            ecode = code;
109
0
            param_signal_error(plist, param_name, ecode);
110
0
        case 0:
111
0
        case 1:
112
0
            break;
113
0
    }
114
0
    return ecode;
115
0
}
116
117
/* Copy one parameter list to another, recursively if necessary. */
118
int
119
param_list_copy(gs_param_list *plto, gs_param_list *plfrom)
120
1.51M
{
121
1.51M
    gs_param_enumerator_t key_enum;
122
1.51M
    gs_param_key_t key;
123
    /*
124
     * If plfrom and plto use different allocators, we must copy
125
     * aggregate values even if they are "persistent".
126
     */
127
1.51M
    bool copy_persists = plto->memory == plfrom->memory;
128
1.51M
    int code;
129
130
1.51M
    param_init_enumerator(&key_enum);
131
7.29M
    while ((code = param_get_next_key(plfrom, &key_enum, &key)) == 0) {
132
5.77M
        char string_key[256]; /* big enough for any reasonable key */
133
5.77M
        gs_param_typed_value value;
134
5.77M
        gs_param_collection_type_t coll_type;
135
5.77M
        gs_param_typed_value copy;
136
137
5.77M
        if (key.size > sizeof(string_key) - 1) {
138
0
            code = gs_note_error(gs_error_rangecheck);
139
0
            break;
140
0
        }
141
5.77M
        memcpy(string_key, key.data, key.size);
142
5.77M
        string_key[key.size] = 0;
143
5.77M
        if ((code = param_read_typed(plfrom, string_key, &value)) != 0) {
144
0
            code = (code > 0 ? gs_note_error(gs_error_unknownerror) : code);
145
0
            break;
146
0
        }
147
        /* We used to use 'key.persistent' to determine whether we needed to copy the
148
         * key (by setting persistent_keys in the param list to false), but that isn't
149
         * correct! We are going to use the heap buffer 'string_key', not the original
150
         * key, and since that's on the heap it is NOT persistent....
151
         */
152
5.77M
        gs_param_list_set_persistent_keys(plto, false);
153
5.77M
        switch (value.type) {
154
0
        case gs_param_type_dict:
155
0
            coll_type = gs_param_collection_dict_any;
156
0
            goto cc;
157
0
        case gs_param_type_dict_int_keys:
158
0
            coll_type = gs_param_collection_dict_int_keys;
159
0
            goto cc;
160
0
        case gs_param_type_array:
161
0
            coll_type = gs_param_collection_array;
162
0
        cc:
163
0
            copy.value.d.size = value.value.d.size;
164
            /* FIXME: RJW: I suspect that this will go wrong, if size == 0.
165
             * We should probably spot size == 0 and break. */
166
0
            if ((code = param_begin_write_collection(plto, string_key,
167
0
                                                     &copy.value.d,
168
0
                                                     coll_type)) < 0 ||
169
0
                (code = param_list_copy(copy.value.d.list,
170
0
                                        value.value.d.list)) < 0 ||
171
0
                (code = param_end_write_collection(plto, string_key,
172
0
                                                   &copy.value.d)) < 0)
173
0
                break;
174
0
            code = param_end_read_collection(plfrom, string_key,
175
0
                                             &value.value.d);
176
0
            break;
177
0
        case gs_param_type_string:
178
0
            value.value.s.persistent &= copy_persists; goto ca;
179
0
        case gs_param_type_name:
180
0
            value.value.n.persistent &= copy_persists; goto ca;
181
2.43M
        case gs_param_type_int_array:
182
2.43M
            value.value.ia.persistent &= copy_persists; goto ca;
183
0
        case gs_param_type_float_array:
184
0
            value.value.fa.persistent &= copy_persists; goto ca;
185
0
        case gs_param_type_string_array:
186
0
            value.value.sa.persistent &= copy_persists;
187
            /* fall through */
188
2.43M
        ca:
189
5.77M
        default:
190
5.77M
            code = param_write_typed(plto, string_key, &value);
191
5.77M
        }
192
5.77M
        if (code < 0)
193
0
            break;
194
5.77M
    }
195
1.51M
    return code;
196
1.51M
}