Coverage Report

Created: 2025-06-24 07:01

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