Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/psi/zusparam.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
/* User and system parameter operators */
18
#include "memory_.h"
19
#include "string_.h"
20
#include "ghost.h"
21
#include "oper.h"
22
#include "gscdefs.h"
23
#include "gsstruct.h"   /* for gxht.h */
24
#include "gsfont.h"   /* for user params */
25
#include "gxht.h"   /* for user params */
26
#include "gsutil.h"
27
#include "estack.h"
28
#include "ialloc.h"   /* for imemory for status */
29
#include "icontext.h"   /* for set_user_params prototype */
30
#include "idict.h"
31
#include "idparam.h"
32
#include "iparam.h"
33
#include "dstack.h"
34
#include "iname.h"
35
#include "itoken.h"
36
#include "iutil2.h"
37
#include "ivmem2.h"
38
#include "store.h"
39
#include "gsnamecl.h"
40
#include "igstate.h"
41
#include "gscms.h"
42
#include "gsicc_manage.h"
43
#include "gsparamx.h"
44
#include "gx.h"
45
#include "gxgstate.h"
46
#include "gslibctx.h"
47
#include "ichar.h"
48
49
/* The (global) font directory */
50
extern gs_font_dir *ifont_dir;  /* in zfont.c */
51
52
/* Define an individual user or system parameter. */
53
/* Eventually this will be made public. */
54
#define param_def_common\
55
    const char *pname
56
57
typedef struct param_def_s {
58
    param_def_common;
59
} param_def_t;
60
61
typedef struct size_t_param_def_s {
62
    param_def_common;
63
    size_t min_value, max_value;
64
    size_t (*current)(i_ctx_t *);
65
    int (*set)(i_ctx_t *, size_t);
66
} size_t_param_def_t;
67
68
typedef struct i64_param_def_s {
69
    param_def_common;
70
    int64_t min_value, max_value;
71
    int64_t (*current)(i_ctx_t *);
72
    int (*set)(i_ctx_t *, int64_t);
73
} i64_param_def_t;
74
75
typedef struct long_param_def_s {
76
    param_def_common;
77
    long min_value, max_value;
78
    long (*current)(i_ctx_t *);
79
    int (*set)(i_ctx_t *, long);
80
} long_param_def_t;
81
82
#if ARCH_SIZEOF_LONG > ARCH_SIZEOF_INT
83
#  define MAX_UINT_PARAM max_uint
84
#  define MIN_INT_PARAM min_int
85
#else
86
#  define MAX_UINT_PARAM max_long
87
#  define MIN_INT_PARAM min_long
88
#endif
89
90
typedef struct bool_param_def_s {
91
    param_def_common;
92
    bool (*current)(i_ctx_t *);
93
    int (*set)(i_ctx_t *, bool);
94
} bool_param_def_t;
95
96
typedef struct string_param_def_s {
97
    param_def_common;
98
    void (*current)(i_ctx_t *, gs_param_string *);
99
    int (*set)(i_ctx_t *, gs_param_string *);
100
} string_param_def_t;
101
102
/* Define a parameter set (user or system). */
103
typedef struct param_set_s {
104
    const size_t_param_def_t *size_t_defs;
105
    uint size_t_count;
106
    const i64_param_def_t *i64_defs;
107
    uint i64_count;
108
    const long_param_def_t *long_defs;
109
    uint long_count;
110
    const bool_param_def_t *bool_defs;
111
    uint bool_count;
112
    const string_param_def_t *string_defs;
113
    uint string_count;
114
} param_set;
115
116
/* Forward references */
117
static int setparams(i_ctx_t *, gs_param_list *, const param_set *);
118
static int currentparams(i_ctx_t *, const param_set *);
119
static int currentparam1(i_ctx_t *, const param_set *);
120
121
/* ------ Passwords ------ */
122
123
/* <string|int> .checkpassword <0|1|2> */
124
static int
125
zcheckpassword(i_ctx_t *i_ctx_p)
126
0
{
127
0
    os_ptr op = osp;
128
0
    ref params[2];
129
0
    array_param_list list;
130
0
    gs_param_list *const plist = (gs_param_list *)&list;
131
0
    int result = 0;
132
0
    int code = name_ref(imemory, (const byte *)"Password", 8, &params[0], 0);
133
0
    password pass;
134
135
0
    if (code < 0)
136
0
        return code;
137
0
    check_op(1);
138
0
    params[1] = *op;
139
0
    array_param_list_read(&list, params, 2, NULL, false, iimemory);
140
0
    if (dict_read_password(&pass, systemdict, "StartJobPassword") >= 0 &&
141
0
        param_check_password(plist, &pass) == 0
142
0
        )
143
0
        result = 1;
144
0
    if (dict_read_password(&pass, systemdict, "SystemParamsPassword") >= 0 &&
145
0
        param_check_password(plist, &pass) == 0
146
0
        )
147
0
        result = 2;
148
0
    iparam_list_release(&list);
149
0
    make_int(op, result);
150
0
    return 0;
151
0
}
152
153
/* ------ System parameters ------ */
154
155
/* Integer values */
156
static long
157
current_BuildTime(i_ctx_t *i_ctx_p)
158
812k
{
159
812k
    return gs_buildtime;
160
812k
}
161
162
/* we duplicate this definition here instead of including bfont.h and
163
   all its dependencies */
164
165
7.37M
#define ifont_dir (gs_lib_ctx_get_interp_instance(imemory)->font_dir)
166
167
static long
168
current_MaxFontCache(i_ctx_t *i_ctx_p)
169
812k
{
170
812k
    return gs_currentcachesize(ifont_dir);
171
812k
}
172
static int
173
set_MaxFontCache(i_ctx_t *i_ctx_p, long val)
174
0
{
175
    /* Changing the cache params clears the "pairs" cache, which
176
       causes a crash if the in use font/matrix pair disappears
177
       during a text operation. So don't allow that to happen.
178
     */
179
0
    if (op_show_find(i_ctx_p) != NULL)
180
0
        return_error(gs_error_invalidaccess);
181
0
    return gs_setcachesize(igs, ifont_dir,
182
0
                           (uint)(val < 0 ? 0 : val > max_uint ? max_uint :
183
0
                                   val));
184
0
}
185
static long
186
current_CurFontCache(i_ctx_t *i_ctx_p)
187
812k
{
188
812k
    uint cstat[7];
189
190
812k
    gs_cachestatus(ifont_dir, cstat);
191
812k
    return cstat[0];
192
812k
}
193
194
/* Even though size_t is unsigned, PostScript limits this to signed range */
195
static size_t
196
current_MaxGlobalVM(i_ctx_t *i_ctx_p)
197
812k
{
198
812k
    gs_memory_gc_status_t stat;
199
812k
    size_t val;
200
201
812k
    gs_memory_gc_status(iimemory_global, &stat);
202
    /* RJW: This seems very supicious to me. I get that in CPSI
203
     * mode the max_vm figure needs to be kept to 32bit mode, but
204
     * surely clipping it should be correct, rather than truncating
205
     * it? i.e. min(stat.max_vm, 0x7fffffff) */
206
812k
    if (gs_currentcpsimode(imemory))
207
0
        return stat.max_vm & 0x7fffffff;
208
    /* else clamp at the maximum positive value for the size_t size signed integer */
209
812k
    val = min(stat.max_vm, MAX_VM_THRESHOLD);
210
812k
    return val;
211
812k
}
212
213
/* Even though size_t is unsigned, PostScript limits this to signed range */
214
static int
215
set_MaxGlobalVM(i_ctx_t *i_ctx_p, size_t val)
216
0
{
217
0
    gs_memory_gc_status_t stat;
218
219
0
    gs_memory_gc_status(iimemory_global, &stat);
220
0
    stat.max_vm = val;
221
0
    gs_memory_set_gc_status(iimemory_global, &stat);
222
0
    return 0;
223
0
}
224
static long
225
current_Revision(i_ctx_t *i_ctx_p)
226
812k
{
227
812k
    return gs_revision;
228
812k
}
229
230
static long
231
current_PageCount(i_ctx_t *i_ctx_p)
232
812k
{
233
812k
    gx_device *dev = gs_currentdevice(igs);
234
235
812k
    if ((*dev_proc(dev, get_page_device))(dev) != 0)
236
324k
        if (dev->ShowpageCount > i_ctx_p->nv_page_count)
237
0
          i_ctx_p->nv_page_count = dev->ShowpageCount;
238
812k
    return 1000 + i_ctx_p->nv_page_count; /* Add 1000 to imitate NV memory */
239
812k
}
240
241
static const size_t_param_def_t system_size_t_params[] =
242
{
243
    /* Extensions */
244
    {"MaxGlobalVM", MIN_VM_THRESHOLD, MAX_VM_THRESHOLD, current_MaxGlobalVM, set_MaxGlobalVM}
245
};
246
247
static const long_param_def_t system_long_params[] =
248
{
249
    {"BuildTime", min_long, max_long, current_BuildTime, NULL},
250
    {"MaxFontCache", 0, MAX_UINT_PARAM, current_MaxFontCache, set_MaxFontCache},
251
    {"CurFontCache", 0, MAX_UINT_PARAM, current_CurFontCache, NULL},
252
    {"Revision", min_long, max_long, current_Revision, NULL},
253
    {"PageCount", min_long, max_long, current_PageCount, NULL}
254
};
255
256
/* Boolean values */
257
static bool
258
current_ByteOrder(i_ctx_t *i_ctx_p)
259
974k
{
260
974k
    return !ARCH_IS_BIG_ENDIAN;
261
974k
}
262
static const bool_param_def_t system_bool_params[] =
263
{
264
    {"ByteOrder", current_ByteOrder, NULL}
265
};
266
267
/* String values */
268
static void
269
current_RealFormat(i_ctx_t *i_ctx_p, gs_param_string * pval)
270
974k
{
271
974k
#if ARCH_FLOATS_ARE_IEEE
272
974k
    static const char *const rfs = "IEEE";
273
#else
274
    static const char *const rfs = "not IEEE";
275
#endif
276
277
974k
    pval->data = (const byte *)rfs;
278
974k
    pval->size = strlen(rfs);
279
974k
    pval->persistent = true;
280
974k
}
281
282
static const string_param_def_t system_string_params[] =
283
{
284
    {"RealFormat", current_RealFormat, NULL},
285
};
286
287
/* The system parameter set */
288
static const param_set system_param_set =
289
{
290
    system_size_t_params, countof(system_size_t_params),
291
    NULL, 0,  /* No i64 params for systemparams (yet) */
292
    system_long_params, countof(system_long_params),
293
    system_bool_params, countof(system_bool_params),
294
    system_string_params, countof(system_string_params)
295
};
296
297
/* <dict> .setsystemparams - */
298
static int
299
zsetsystemparams(i_ctx_t *i_ctx_p)
300
0
{
301
0
    os_ptr op = osp;
302
0
    int code;
303
0
    dict_param_list list;
304
0
    gs_param_list *const plist = (gs_param_list *)&list;
305
0
    password pass;
306
307
0
    check_op(1);
308
0
    check_type(*op, t_dictionary);
309
0
    code = dict_param_list_read(&list, op, NULL, false, iimemory);
310
0
    if (code < 0)
311
0
        return code;
312
0
    code = dict_read_password(&pass, systemdict, "SystemParamsPassword");
313
0
    if (code < 0)
314
0
        return code;
315
0
    code = param_check_password(plist, &pass);
316
0
    if (code != 0) {
317
0
        if (code > 0)
318
0
            code = gs_note_error(gs_error_invalidaccess);
319
0
        goto out;
320
0
    }
321
0
    code = param_read_password(plist, "StartJobPassword", &pass);
322
0
    switch (code) {
323
0
        default:    /* invalid */
324
0
            goto out;
325
0
        case 1:   /* missing */
326
0
            break;
327
0
        case 0:
328
0
            code = dict_write_password(&pass, systemdict,
329
0
                                       "StartJobPassword",
330
0
                                       ! i_ctx_p->LockFilePermissions);
331
0
            if (code < 0)
332
0
                goto out;
333
0
    }
334
0
    code = param_read_password(plist, "SystemParamsPassword", &pass);
335
0
    switch (code) {
336
0
        default:    /* invalid */
337
0
            goto out;
338
0
        case 1:   /* missing */
339
0
            break;
340
0
        case 0:
341
0
            code = dict_write_password(&pass, systemdict,
342
0
                                       "SystemParamsPassword",
343
0
                                       ! i_ctx_p->LockFilePermissions);
344
0
            if (code < 0)
345
0
                goto out;
346
0
    }
347
348
0
    code = setparams(i_ctx_p, plist, &system_param_set);
349
0
  out:
350
0
    iparam_list_release(&list);
351
0
    if (code < 0)
352
0
        return code;
353
0
    pop(1);
354
0
    return 0;
355
0
}
356
357
/* - .currentsystemparams <name1> <value1> ... */
358
static int
359
zcurrentsystemparams(i_ctx_t *i_ctx_p)
360
812k
{
361
812k
    return currentparams(i_ctx_p, &system_param_set);
362
812k
}
363
364
/* <name> .getsystemparam <value> */
365
static int
366
zgetsystemparam(i_ctx_t *i_ctx_p)
367
324k
{
368
324k
    return currentparam1(i_ctx_p, &system_param_set);
369
324k
}
370
371
/* ------ User parameters ------ */
372
373
/* Integer values */
374
static long
375
current_JobTimeout(i_ctx_t *i_ctx_p)
376
649k
{
377
649k
    return 0;
378
649k
}
379
static int
380
set_JobTimeout(i_ctx_t *i_ctx_p, long val)
381
543k
{
382
543k
    return 0;
383
543k
}
384
static long
385
current_MaxFontItem(i_ctx_t *i_ctx_p)
386
812k
{
387
812k
    return gs_currentcacheupper(ifont_dir);
388
812k
}
389
static int
390
set_MaxFontItem(i_ctx_t *i_ctx_p, long val)
391
868k
{
392
868k
    return gs_setcacheupper(ifont_dir, val);
393
868k
}
394
static long
395
current_MinFontCompress(i_ctx_t *i_ctx_p)
396
812k
{
397
812k
    return gs_currentcachelower(ifont_dir);
398
812k
}
399
static int
400
set_MinFontCompress(i_ctx_t *i_ctx_p, long val)
401
868k
{
402
868k
    return gs_setcachelower(ifont_dir, val);
403
868k
}
404
static long
405
current_MaxOpStack(i_ctx_t *i_ctx_p)
406
649k
{
407
649k
    return ref_stack_max_count(&o_stack);
408
649k
}
409
static int
410
set_MaxOpStack(i_ctx_t *i_ctx_p, long val)
411
705k
{
412
705k
    return ref_stack_set_max_count(&o_stack, val);
413
705k
}
414
static long
415
current_MaxDictStack(i_ctx_t *i_ctx_p)
416
649k
{
417
649k
    return ref_stack_max_count(&d_stack);
418
649k
}
419
static int
420
set_MaxDictStack(i_ctx_t *i_ctx_p, long val)
421
705k
{
422
705k
    return ref_stack_set_max_count(&d_stack, val);
423
705k
}
424
static long
425
current_MaxExecStack(i_ctx_t *i_ctx_p)
426
649k
{
427
649k
    return ref_stack_max_count(&e_stack);
428
649k
}
429
static int
430
set_MaxExecStack(i_ctx_t *i_ctx_p, long val)
431
705k
{
432
705k
    return ref_stack_set_max_count(&e_stack, val);
433
705k
}
434
static size_t
435
current_MaxLocalVM(i_ctx_t *i_ctx_p)
436
649k
{
437
649k
    gs_memory_gc_status_t stat;
438
649k
    size_t val;
439
440
649k
    gs_memory_gc_status(iimemory_local, &stat);
441
    /* RJW: This seems very supicious to me. I get that in CPSI
442
     * mode the max_vm figure needs to be kept to 32bit mode, but
443
     * surely clipping it should be correct, rather than truncating
444
     * it? i.e. min(stat.max_vm, 0x7fffffff) */
445
649k
    if (gs_currentcpsimode(imemory))
446
0
        return stat.max_vm & 0x7fffffff;
447
    /* else clamp at the maximun positive value for the size_t size signed integer */
448
649k
    val = min(stat.max_vm, MAX_VM_THRESHOLD);
449
649k
    return val;
450
649k
}
451
/* Even though size_t is unsigned, PostScript limits this to signed range */
452
static int
453
set_MaxLocalVM(i_ctx_t *i_ctx_p, size_t val)
454
543k
{
455
543k
    gs_memory_gc_status_t stat;
456
457
543k
    gs_memory_gc_status(iimemory_local, &stat);
458
543k
    stat.max_vm = val;
459
543k
    gs_memory_set_gc_status(iimemory_local, &stat);
460
543k
    return 0;
461
543k
}
462
static long
463
current_VMReclaim(i_ctx_t *i_ctx_p)
464
812k
{
465
812k
    gs_memory_gc_status_t gstat, lstat;
466
467
812k
    gs_memory_gc_status(iimemory_global, &gstat);
468
812k
    gs_memory_gc_status(iimemory_local, &lstat);
469
812k
    return (!gstat.enabled ? -2 : !lstat.enabled ? -1 : 0);
470
812k
}
471
static int64_t
472
current_VMThreshold(i_ctx_t *i_ctx_p)
473
812k
{
474
812k
    gs_memory_gc_status_t stat;
475
476
812k
    gs_memory_gc_status(iimemory_local, &stat);
477
812k
    return stat.vm_threshold;
478
812k
}
479
static long
480
current_WaitTimeout(i_ctx_t *i_ctx_p)
481
649k
{
482
649k
    return 0;
483
649k
}
484
static int
485
set_WaitTimeout(i_ctx_t *i_ctx_p, long val)
486
543k
{
487
543k
    return 0;
488
543k
}
489
static long
490
current_MinScreenLevels(i_ctx_t *i_ctx_p)
491
649k
{
492
649k
    return gs_currentminscreenlevels(imemory);
493
649k
}
494
static int
495
set_MinScreenLevels(i_ctx_t *i_ctx_p, long val)
496
543k
{
497
543k
    gs_setminscreenlevels(imemory, (uint) val);
498
543k
    return 0;
499
543k
}
500
static long
501
current_AlignToPixels(i_ctx_t *i_ctx_p)
502
649k
{
503
649k
    return gs_currentaligntopixels(ifont_dir);
504
649k
}
505
static int
506
set_AlignToPixels(i_ctx_t *i_ctx_p, long val)
507
543k
{
508
543k
    gs_setaligntopixels(ifont_dir, (uint)val);
509
543k
    return 0;
510
543k
}
511
static long
512
current_GridFitTT(i_ctx_t *i_ctx_p)
513
649k
{
514
649k
    return gs_currentgridfittt(ifont_dir);
515
649k
}
516
static int
517
set_GridFitTT(i_ctx_t *i_ctx_p, long val)
518
543k
{
519
543k
    gs_setgridfittt(ifont_dir, (uint)val);
520
543k
    return 0;
521
543k
}
522
523
#undef ifont_dir
524
525
static void
526
current_devicen_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
527
649k
{
528
649k
    gs_currentdevicenicc(igs, pval);
529
649k
}
530
531
static int
532
set_devicen_profile_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
533
543k
{
534
543k
    return gs_setdevicenprofileicc(igs, pval);
535
543k
}
536
537
static void
538
current_default_gray_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
539
649k
{
540
649k
    gs_currentdefaultgrayicc(igs, pval);
541
649k
}
542
543
static int
544
set_default_gray_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
545
543k
{
546
543k
    return gs_setdefaultgrayicc(igs, pval);
547
543k
}
548
549
static void
550
current_icc_directory(i_ctx_t *i_ctx_p, gs_param_string * pval)
551
649k
{
552
649k
    gs_currenticcdirectory(igs, pval);
553
649k
}
554
555
static int
556
set_icc_directory(i_ctx_t *i_ctx_p, gs_param_string * pval)
557
543k
{
558
543k
    return gs_seticcdirectory(igs, pval);
559
543k
}
560
561
static void
562
current_srcgtag_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
563
649k
{
564
649k
    gs_currentsrcgtagicc(igs, pval);
565
649k
}
566
567
static int
568
set_srcgtag_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
569
543k
{
570
543k
    return gs_setsrcgtagicc(igs, pval);
571
543k
}
572
573
static void
574
current_default_rgb_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
575
649k
{
576
649k
    gs_currentdefaultrgbicc(igs, pval);
577
649k
}
578
579
static int
580
set_default_rgb_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
581
543k
{
582
543k
    return gs_setdefaultrgbicc(igs, pval);
583
543k
}
584
585
static void
586
current_named_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
587
649k
{
588
649k
    gs_currentnamedicc(igs, pval);
589
649k
}
590
591
static int
592
set_named_profile_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
593
543k
{
594
543k
    return gs_setnamedprofileicc(igs, pval);
595
543k
}
596
597
static void
598
current_default_cmyk_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
599
649k
{
600
649k
    gs_currentdefaultcmykicc(igs, pval);
601
649k
}
602
603
static int
604
set_default_cmyk_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
605
543k
{
606
543k
    return gs_setdefaultcmykicc(igs, pval);
607
543k
}
608
609
static void
610
current_lab_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
611
649k
{
612
649k
    gs_currentlabicc(igs, pval);
613
649k
}
614
615
static int
616
set_lab_icc(i_ctx_t *i_ctx_p, gs_param_string * pval)
617
543k
{
618
543k
    return gs_setlabicc(igs, pval);
619
543k
}
620
621
static const size_t_param_def_t user_size_t_params[] =
622
{
623
    {"MaxLocalVM", MIN_VM_THRESHOLD, MAX_VM_THRESHOLD, current_MaxLocalVM, set_MaxLocalVM}
624
};
625
626
static const i64_param_def_t user_i64_params[] =
627
{
628
    {"VMThreshold", -1, MAX_VM_THRESHOLD, current_VMThreshold, set_vm_threshold},
629
};
630
631
static const long_param_def_t user_long_params[] =
632
{
633
    {"JobTimeout", 0, MAX_UINT_PARAM,
634
     current_JobTimeout, set_JobTimeout},
635
    {"MaxFontItem", MIN_INT_PARAM, MAX_UINT_PARAM,
636
     current_MaxFontItem, set_MaxFontItem},
637
    {"MinFontCompress", MIN_INT_PARAM, MAX_UINT_PARAM,
638
     current_MinFontCompress, set_MinFontCompress},
639
    {"MaxOpStack", -1, max_long,
640
     current_MaxOpStack, set_MaxOpStack},
641
    {"MaxDictStack", -1, max_long,
642
     current_MaxDictStack, set_MaxDictStack},
643
    {"MaxExecStack", -1, max_long,
644
     current_MaxExecStack, set_MaxExecStack},
645
    {"VMReclaim", -2, 0,
646
     current_VMReclaim, set_vm_reclaim},
647
    {"WaitTimeout", 0, MAX_UINT_PARAM,
648
     current_WaitTimeout, set_WaitTimeout},
649
    /* Extensions */
650
    {"MinScreenLevels", 0, MAX_UINT_PARAM,
651
     current_MinScreenLevels, set_MinScreenLevels},
652
    {"AlignToPixels", 0, 1,
653
     current_AlignToPixels, set_AlignToPixels},
654
    {"GridFitTT", 0, 3,
655
     current_GridFitTT, set_GridFitTT}
656
};
657
658
/* Note that string objects that are maintained as user params must be
659
   either allocated in non-gc memory or be a constant in the executable.
660
   The problem stems from the way userparams are retained during garbage
661
   collection in a param_list (collected by currentuserparams).  For
662
   some reason this param_list does not get the pointers to strings relocated
663
   during the GC. Note that the param_dict itself is correctly updated by reloc,
664
   it is just the pointers to the strings in the param_list that are not traced
665
   and updated. An example of this includes the ICCProfilesDir, which sets a
666
   string in the icc_manager. When a reclaim occurs, the string is relocated
667
   (when in non-gc memory and when it is noted to the gc with the proper object
668
   descriptor).  Then if a set_icc_directory occurs, the user params pointer has
669
   NOT been updated and validation problems will occur. */
670
static const string_param_def_t user_string_params[] =
671
{
672
    {"DefaultGrayProfile", current_default_gray_icc, set_default_gray_icc},
673
    {"DefaultRGBProfile", current_default_rgb_icc, set_default_rgb_icc},
674
    {"DefaultCMYKProfile", current_default_cmyk_icc, set_default_cmyk_icc},
675
    {"NamedProfile", current_named_icc, set_named_profile_icc},
676
    {"ICCProfilesDir", current_icc_directory, set_icc_directory},
677
    {"LabProfile", current_lab_icc, set_lab_icc},
678
    {"DeviceNProfile", current_devicen_icc, set_devicen_profile_icc},
679
    {"SourceObjectICC", current_srcgtag_icc, set_srcgtag_icc}
680
};
681
682
/* Boolean values */
683
static bool
684
current_AccurateScreens(i_ctx_t *i_ctx_p)
685
649k
{
686
649k
    return gs_currentaccuratescreens(imemory);
687
649k
}
688
static int
689
set_AccurateScreens(i_ctx_t *i_ctx_p, bool val)
690
543k
{
691
543k
    gs_setaccuratescreens(imemory, val);
692
543k
    return 0;
693
543k
}
694
/* Boolean values */
695
static bool
696
current_OverrideICC(i_ctx_t *i_ctx_p)
697
649k
{
698
649k
    return gs_currentoverrideicc(igs);
699
649k
}
700
static int
701
set_OverrideICC(i_ctx_t *i_ctx_p, bool val)
702
543k
{
703
543k
    gs_setoverrideicc(igs, val);
704
543k
    return 0;
705
543k
}
706
static bool
707
current_LockFilePermissions(i_ctx_t *i_ctx_p)
708
649k
{
709
649k
    return i_ctx_p->LockFilePermissions;
710
649k
}
711
static int
712
set_LockFilePermissions(i_ctx_t *i_ctx_p, bool val)
713
543k
{
714
    /* allow locking even if already locked */
715
543k
    if (i_ctx_p->LockFilePermissions && !val)
716
0
        return_error(gs_error_invalidaccess);
717
543k
    i_ctx_p->LockFilePermissions = val;
718
543k
    return 0;
719
543k
}
720
static bool
721
current_RenderTTNotdef(i_ctx_t *i_ctx_p)
722
649k
{
723
649k
    return i_ctx_p->RenderTTNotdef;
724
649k
}
725
static int
726
set_RenderTTNotdef(i_ctx_t *i_ctx_p, bool val)
727
543k
{
728
543k
    i_ctx_p->RenderTTNotdef = val;
729
543k
    return 0;
730
543k
}
731
static const bool_param_def_t user_bool_params[] =
732
{
733
    {"AccurateScreens", current_AccurateScreens, set_AccurateScreens},
734
    {"LockFilePermissions", current_LockFilePermissions, set_LockFilePermissions},
735
    {"RenderTTNotdef", current_RenderTTNotdef, set_RenderTTNotdef},
736
    {"OverrideICC", current_OverrideICC, set_OverrideICC}
737
};
738
739
/* The user parameter set */
740
static const param_set user_param_set =
741
{
742
    user_size_t_params, countof(user_size_t_params),
743
    user_i64_params, countof(user_i64_params),
744
    user_long_params, countof(user_long_params),
745
    user_bool_params, countof(user_bool_params),
746
    user_string_params, countof(user_string_params)
747
};
748
749
/* <dict> .setuserparams - */
750
/* We break this out for use when switching contexts. */
751
int
752
set_user_params(i_ctx_t *i_ctx_p, const ref *paramdict)
753
4.44M
{
754
4.44M
    dict_param_list list;
755
4.44M
    int code;
756
757
4.44M
    check_type(*paramdict, t_dictionary);
758
4.44M
    code = dict_param_list_read(&list, paramdict, NULL, false, iimemory);
759
4.44M
    if (code < 0)
760
1
        return code;
761
4.44M
    code = setparams(i_ctx_p, (gs_param_list *)&list, &user_param_set);
762
4.44M
    iparam_list_release(&list);
763
4.44M
    return code;
764
4.44M
}
765
static int
766
zsetuserparams(i_ctx_t *i_ctx_p)
767
3.94M
{
768
3.94M
    os_ptr op = osp;
769
3.94M
    int code;
770
771
3.94M
    check_op(1);
772
3.94M
    code = set_user_params(i_ctx_p, op);
773
3.94M
    if (code >= 0) {
774
        /* Update cached scanner options. */
775
3.94M
        i_ctx_p->scanner_options =
776
3.94M
            ztoken_scanner_options(op, i_ctx_p->scanner_options);
777
3.94M
        pop(1);
778
3.94M
    }
779
3.94M
    return code;
780
3.94M
}
781
782
/* - .currentuserparams <name1> <value1> ... */
783
static int
784
zcurrentuserparams(i_ctx_t *i_ctx_p)
785
649k
{
786
649k
    return currentparams(i_ctx_p, &user_param_set);
787
649k
}
788
789
/* <name> .getuserparam <value> */
790
static int
791
zgetuserparam(i_ctx_t *i_ctx_p)
792
649k
{
793
649k
    return currentparam1(i_ctx_p, &user_param_set);
794
649k
}
795
796
/* ------ Initialization procedure ------ */
797
798
const op_def zusparam_op_defs[] =
799
{
800
        /* User and system parameters are accessible even in Level 1 */
801
        /* (if this is a Level 2 system). */
802
    {"0.currentsystemparams", zcurrentsystemparams},
803
    {"0.currentuserparams", zcurrentuserparams},
804
    {"1.getsystemparam", zgetsystemparam},
805
    {"1.getuserparam", zgetuserparam},
806
    {"1.setsystemparams", zsetsystemparams},
807
    {"1.setuserparams", zsetuserparams},
808
        /* The rest of the operators are defined only in Level 2. */
809
    op_def_begin_level2(),
810
    {"1.checkpassword", zcheckpassword},
811
    op_def_end(0)
812
};
813
814
/* ------ Internal procedures ------ */
815
816
/* Set the values of a parameter set from a parameter list. */
817
/* We don't attempt to back out if anything fails. */
818
static int
819
setparams(i_ctx_t *i_ctx_p, gs_param_list * plist, const param_set * pset)
820
4.44M
{
821
4.44M
    int code;
822
4.44M
    unsigned int i;
823
824
8.88M
    for (i = 0; i < pset->size_t_count; i++) {
825
4.44M
        const size_t_param_def_t *pdef = &pset->size_t_defs[i];
826
4.44M
        size_t val;
827
828
4.44M
        if (pdef->set == NULL)
829
0
            continue;
830
4.44M
        code = param_read_size_t(plist, pdef->pname, &val);
831
4.44M
        switch (code) {
832
0
            default:    /* invalid */
833
0
                return code;
834
3.89M
            case 1:   /* missing */
835
3.89M
                break;
836
543k
            case 0:
837
543k
                if (val < pdef->min_value || val > pdef->max_value)
838
0
                    return_error(gs_error_rangecheck);
839
543k
                code = (*pdef->set)(i_ctx_p, val);
840
543k
                if (code < 0)
841
0
                    return code;
842
4.44M
        }
843
4.44M
    }
844
845
8.88M
    for (i = 0; i < pset->i64_count; i++) {
846
4.44M
        const i64_param_def_t *pdef = &pset->i64_defs[i];
847
4.44M
        int64_t val;
848
849
4.44M
        if (pdef->set == NULL)
850
0
            continue;
851
4.44M
        code = param_read_i64(plist, pdef->pname, &val);
852
4.44M
        switch (code) {
853
0
            default:    /* invalid */
854
0
                return code;
855
3.57M
            case 1:   /* missing */
856
3.57M
                break;
857
868k
            case 0:
858
868k
                if (val < pdef->min_value || val > pdef->max_value)
859
0
                    return_error(gs_error_rangecheck);
860
868k
                code = (*pdef->set)(i_ctx_p, val);
861
868k
                if (code < 0)
862
0
                    return code;
863
4.44M
        }
864
4.44M
    }
865
866
53.3M
    for (i = 0; i < pset->long_count; i++) {
867
48.8M
        const long_param_def_t *pdef = &pset->long_defs[i];
868
48.8M
        long val;
869
870
48.8M
        if (pdef->set == NULL)
871
0
            continue;
872
48.8M
        code = param_read_long(plist, pdef->pname, &val);
873
48.8M
        switch (code) {
874
9
            default:    /* invalid */
875
9
                return code;
876
41.4M
            case 1:   /* missing */
877
41.4M
                break;
878
7.43M
            case 0:
879
7.43M
                if (val < pdef->min_value || val > pdef->max_value)
880
6
                    return_error(gs_error_rangecheck);
881
7.43M
                code = (*pdef->set)(i_ctx_p, val);
882
7.43M
                if (code < 0)
883
0
                    return code;
884
48.8M
        }
885
48.8M
    }
886
22.2M
    for (i = 0; i < pset->bool_count; i++) {
887
17.7M
        const bool_param_def_t *pdef = &pset->bool_defs[i];
888
17.7M
        bool val;
889
890
17.7M
        if (pdef->set == NULL)
891
0
            continue;
892
17.7M
        code = param_read_bool(plist, pdef->pname, &val);
893
17.7M
        if (code == 0)
894
2.17M
            code = (*pdef->set)(i_ctx_p, val);
895
17.7M
        if (code < 0)
896
0
            return code;
897
17.7M
    }
898
899
39.9M
    for (i = 0; i < pset->string_count; i++) {
900
35.5M
        const string_param_def_t *pdef = &pset->string_defs[i];
901
35.5M
        gs_param_string val;
902
903
35.5M
        if (pdef->set == NULL)
904
0
            continue;
905
35.5M
        code = param_read_string(plist, pdef->pname, &val);
906
35.5M
        switch (code) {
907
0
            default:    /* invalid */
908
0
                return code;
909
31.1M
            case 1:   /* missing */
910
31.1M
                break;
911
4.34M
            case 0:
912
4.34M
                code = (*pdef->set)(i_ctx_p, &val);
913
4.34M
                if (code < 0)
914
0
                    return code;
915
35.5M
        }
916
35.5M
    }
917
918
4.44M
    return 0;
919
4.44M
}
920
921
/* Get the current values of a parameter set to the stack. */
922
static bool
923
pname_matches(const char *pname, const ref * psref)
924
41.5M
{
925
41.5M
    return
926
41.5M
        (psref == 0 ||
927
41.5M
         !bytes_compare((const byte *)pname, strlen(pname),
928
18.8M
                        psref->value.const_bytes, r_size(psref)));
929
41.5M
}
930
static int
931
current_param_list(i_ctx_t *i_ctx_p, const param_set * pset,
932
                   const ref * psref /*t_string */ )
933
2.43M
{
934
2.43M
    stack_param_list list;
935
2.43M
    gs_param_list *const plist = (gs_param_list *)&list;
936
2.43M
    int code = 0;
937
2.43M
    unsigned int i;
938
939
2.43M
    stack_param_list_write(&list, &o_stack, NULL, iimemory);
940
941
4.87M
    for (i = 0; i < pset->size_t_count; i++) {
942
2.43M
        const char *pname = pset->size_t_defs[i].pname;
943
944
2.43M
        if (pname_matches(pname, psref)) {
945
1.46M
            size_t val = (*pset->size_t_defs[i].current)(i_ctx_p);
946
947
1.46M
            code = param_write_size_t(plist, pname, &val);
948
1.46M
            if (code < 0)
949
0
                return code;
950
1.46M
        }
951
2.43M
    }
952
3.73M
    for (i = 0; i < pset->i64_count; i++) {
953
1.29M
        const char *pname = pset->i64_defs[i].pname;
954
955
1.29M
        if (pname_matches(pname, psref)) {
956
812k
            int64_t val = (*pset->i64_defs[i].current)(i_ctx_p);
957
958
812k
            code = param_write_i64(plist, pname, &val);
959
812k
            if (code < 0)
960
0
                return code;
961
812k
        }
962
1.29M
    }
963
22.4M
    for (i = 0; i < pset->long_count; i++) {
964
19.9M
        const char *pname = pset->long_defs[i].pname;
965
966
19.9M
        if (pname_matches(pname, psref)) {
967
11.6M
            long val = (*pset->long_defs[i].current)(i_ctx_p);
968
969
11.6M
            code = param_write_long(plist, pname, &val);
970
11.6M
            if (code < 0)
971
0
                return code;
972
11.6M
        }
973
19.9M
    }
974
8.77M
    for (i = 0; i < pset->bool_count; i++) {
975
6.33M
        const char *pname = pset->bool_defs[i].pname;
976
977
6.33M
        if (pname_matches(pname, psref)) {
978
3.57M
            bool val = (*pset->bool_defs[i].current)(i_ctx_p);
979
980
3.57M
            code = param_write_bool(plist, pname, &val);
981
3.57M
            if (code < 0)
982
0
                return code;
983
3.57M
        }
984
6.33M
    }
985
13.9M
    for (i = 0; i < pset->string_count; i++) {
986
11.5M
        const char *pname = pset->string_defs[i].pname;
987
988
11.5M
        if (pname_matches(pname, psref)) {
989
6.17M
            gs_param_string val;
990
991
6.17M
            (*pset->string_defs[i].current)(i_ctx_p, &val);
992
6.17M
            code = param_write_string(plist, pname, &val);
993
6.17M
            if (code < 0)
994
0
                return code;
995
6.17M
        }
996
11.5M
    }
997
2.43M
    if (psref) {
998
        /*
999
         * Scanner options can be read, but only individually by .getuserparam.
1000
         * This avoids putting them into userparams, and being affected by save/restore.
1001
         */
1002
974k
        const char *pname;
1003
974k
        bool val;
1004
974k
        int code;
1005
1006
974k
        switch (ztoken_get_scanner_option(psref, i_ctx_p->scanner_options, &pname)) {
1007
0
            case 0:
1008
0
                code = param_write_null(plist, pname);
1009
0
                break;
1010
0
            case 1:
1011
0
                val = true;
1012
0
                code = param_write_bool(plist, pname, &val);
1013
0
                break;
1014
974k
            default:
1015
974k
                code = 0;
1016
974k
                break;
1017
974k
        }
1018
974k
        if (code < 0)
1019
0
            return code;
1020
974k
    }
1021
2.43M
    return code;
1022
2.43M
}
1023
1024
/* Get the current values of a parameter set to the stack. */
1025
static int
1026
currentparams(i_ctx_t *i_ctx_p, const param_set * pset)
1027
1.46M
{
1028
1.46M
    return current_param_list(i_ctx_p, pset, NULL);
1029
1.46M
}
1030
1031
/* Get the value of a single parameter to the stack, or signal an error. */
1032
static int
1033
currentparam1(i_ctx_t *i_ctx_p, const param_set * pset)
1034
974k
{
1035
974k
    os_ptr op = osp;
1036
974k
    ref sref;
1037
974k
    int code;
1038
1039
974k
    check_type(*op, t_name);
1040
974k
    check_ostack(2);
1041
974k
    name_string_ref(imemory, (const ref *)op, &sref);
1042
974k
    code = current_param_list(i_ctx_p, pset, &sref);
1043
974k
    if (code < 0)
1044
0
        return code;
1045
974k
    if (osp == op)
1046
0
        return_error(gs_error_undefined);
1047
    /* We know osp == op + 2. */
1048
974k
    ref_assign(op, op + 2);
1049
974k
    pop(2);
1050
974k
    return code;
1051
974k
}