Coverage Report

Created: 2025-06-10 07:27

/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
145k
{
29
145k
    return (strlen(str) == pcs->size &&
30
145k
            !strncmp(str, (const char *)pcs->data, pcs->size));
31
145k
}
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
317k
{
38
317k
    gs_param_string ens;
39
317k
    int code = param_read_name(plist, param_name, &ens);
40
41
317k
    switch (code) {
42
237k
        case 1:
43
237k
            return ecode;
44
80.0k
        case 0:
45
80.0k
            {
46
80.0k
                int i;
47
48
112k
                for (i = 0; pnames[i] != 0; ++i)
49
112k
                    if (gs_param_string_eq(&ens, pnames[i])) {
50
80.0k
                        *pvalue = i;
51
80.0k
                        return 0;
52
80.0k
                    }
53
80.0k
            }
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
317k
    }
60
0
    return ecode;
61
317k
}
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
21.6k
{
68
21.6k
    int code;
69
70
21.6k
    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
10.8k
        case 0:
75
21.6k
        case 1:
76
21.6k
            break;
77
21.6k
    }
78
21.6k
    return ecode;
79
21.6k
}
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
43.3k
{
86
43.3k
    int code;
87
88
43.3k
    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
0
        case 0:
93
43.3k
        case 1:
94
43.3k
            break;
95
43.3k
    }
96
43.3k
    return ecode;
97
43.3k
}
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
54.1k
{
121
54.1k
    gs_param_enumerator_t key_enum;
122
54.1k
    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
54.1k
    bool copy_persists = plto->memory == plfrom->memory;
128
54.1k
    int code;
129
130
54.1k
    param_init_enumerator(&key_enum);
131
238k
    while ((code = param_get_next_key(plfrom, &key_enum, &key)) == 0) {
132
184k
        char string_key[256]; /* big enough for any reasonable key */
133
184k
        gs_param_typed_value value;
134
184k
        gs_param_collection_type_t coll_type;
135
184k
        gs_param_typed_value copy;
136
137
184k
        if (key.size > sizeof(string_key) - 1) {
138
0
            code = gs_note_error(gs_error_rangecheck);
139
0
            break;
140
0
        }
141
184k
        memcpy(string_key, key.data, key.size);
142
184k
        string_key[key.size] = 0;
143
184k
        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
184k
        gs_param_list_set_persistent_keys(plto, false);
153
184k
        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
86.6k
        case gs_param_type_int_array:
182
86.6k
            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
86.6k
        ca:
189
184k
        default:
190
184k
            code = param_write_typed(plto, string_key, &value);
191
184k
        }
192
184k
        if (code < 0)
193
0
            break;
194
184k
    }
195
54.1k
    return code;
196
54.1k
}