Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/psi/zdict.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2021 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
17
/* Dictionary operators */
18
#include "ghost.h"
19
#include "oper.h"
20
#include "iddict.h"
21
#include "dstack.h"
22
#include "ilevel.h"   /* for [count]dictstack */
23
#include "iname.h"    /* for dict_find_name */
24
#include "ipacked.h"    /* for inline dict lookup */
25
#include "ivmspace.h"
26
#include "store.h"
27
#include "iscan.h"              /* for SCAN_PDF_RULES */
28
29
/* <int> dict <dict> */
30
int
31
zdict(i_ctx_t *i_ctx_p)
32
39.3M
{
33
39.3M
    os_ptr op = osp;
34
35
39.3M
    check_type(*op, t_integer);
36
39.3M
    if (op->value.intval < 0)
37
13
        return_error(gs_error_rangecheck);
38
39.3M
    return dict_create((uint) op->value.intval, op);
39
39.3M
}
40
41
/* <dict> maxlength <int> */
42
static int
43
zmaxlength(i_ctx_t *i_ctx_p)
44
52.8M
{
45
52.8M
    os_ptr op = osp;
46
47
52.8M
    check_type(*op, t_dictionary);
48
52.8M
    check_dict_read(*op);
49
52.8M
    make_int(op, dict_maxlength(op));
50
52.8M
    return 0;
51
52.8M
}
52
53
/* <dict> begin - */
54
int
55
zbegin(i_ctx_t *i_ctx_p)
56
170M
{
57
170M
    os_ptr op = osp;
58
59
170M
    check_type(*op, t_dictionary);
60
170M
    check_dict_read(*op);
61
170M
    if ( dsp == dstop ) {
62
101
        int code = ref_stack_extend(&d_stack, 1);
63
64
101
        if ( code < 0 ) {
65
0
            if (code == gs_error_dictstackoverflow) {
66
                /* Adobe doesn't restore the operand that caused stack */
67
                /* overflow. We do the same to match CET 20-02-02      */
68
0
                pop(1);
69
0
            }
70
0
            return code;
71
0
        }
72
101
    }
73
170M
    ++dsp;
74
170M
    ref_assign(dsp, op);
75
170M
    dict_set_top();
76
170M
    pop(1);
77
170M
    return 0;
78
170M
}
79
80
/* - end - */
81
int
82
zend(i_ctx_t *i_ctx_p)
83
170M
{
84
170M
    if (ref_stack_count_inline(&d_stack) == min_dstack_size) {
85
        /* We would underflow the d-stack. */
86
462
        return_error(gs_error_dictstackunderflow);
87
462
    }
88
170M
    while (dsp == dsbot) {
89
        /* We would underflow the current block. */
90
26
        ref_stack_pop_block(&d_stack);
91
26
    }
92
170M
    dsp--;
93
170M
    dict_set_top();
94
170M
    return 0;
95
170M
}
96
97
/* <key> <value> def - */
98
/*
99
 * We make this into a separate procedure because
100
 * the interpreter will almost always call it directly.
101
 */
102
int
103
zop_def(i_ctx_t *i_ctx_p)
104
285M
{
105
285M
    os_ptr op = osp;
106
285M
    os_ptr op1 = op - 1;
107
285M
    ref *pvslot;
108
109
    /* The following combines a check_op(2) with a type check. */
110
285M
    switch (r_type(op1)) {
111
280M
        case t_name: {
112
            /* We can use the fast single-probe lookup here. */
113
280M
            uint nidx = name_index(imemory, op1);
114
280M
            uint htemp;
115
116
280M
            if_dict_find_name_by_index_top(nidx, htemp, pvslot) {
117
1.78M
                if (dtop_can_store(op))
118
1.78M
                    goto ra;
119
1.78M
            }
120
278M
            break;   /* handle all slower cases */
121
280M
            }
122
278M
        case t_null:
123
1
            return_error(gs_error_typecheck);
124
22
        case t__invalid:
125
22
            return_error(gs_error_stackunderflow);
126
285M
    }
127
    /*
128
     * Combine the check for a writable top dictionary with
129
     * the global/local store check.  See dstack.h for details.
130
     */
131
284M
    if (!dtop_can_store(op)) {
132
0
        check_dict_write(*dsp);
133
        /*
134
         * If the dictionary is writable, the problem must be
135
         * an invalid store.
136
         */
137
0
        return_error(gs_error_invalidaccess);
138
0
    }
139
    /*
140
     * Save a level of procedure call in the common (redefinition)
141
     * case.  With the current interfaces, we pay a double lookup
142
     * in the uncommon case.
143
     */
144
284M
    if (dict_find(dsp, op1, &pvslot) <= 0)
145
274M
        return idict_put(dsp, op1, op);
146
11.1M
ra:
147
11.1M
    if ((pvslot->tas.type_attrs & (&i_ctx_p->memory)->test_mask) == 0)
148
24.8k
        alloc_save_change(idmemory, &dsp->value.pdict->values, (ref_packed *)pvslot, "dict_put(value)");
149
11.1M
    ref_assign_new_inline(pvslot,op);
150
151
11.1M
    return 0;
152
284M
}
153
int
154
zdef(i_ctx_t *i_ctx_p)
155
0
{
156
0
    int code = zop_def(i_ctx_p);
157
158
0
    if (code >= 0) {
159
0
        pop(2);
160
0
    }
161
0
    return code;
162
0
}
163
164
/* <key> load <value> */
165
static int
166
zload(i_ctx_t *i_ctx_p)
167
170M
{
168
170M
    os_ptr op = osp;
169
170M
    ref *pvalue;
170
171
170M
    switch (r_type(op)) {
172
170M
        case t_name:
173
            /* Use the fast lookup. */
174
170M
            if ((pvalue = dict_find_name(op)) == 0)
175
8
                return_error(gs_error_undefined);
176
170M
            ref_assign(op, pvalue);
177
170M
            return 0;
178
0
        case t_null:
179
0
            return_error(gs_error_typecheck);
180
11
        case t__invalid:
181
11
            return_error(gs_error_stackunderflow);
182
26
        default: {
183
                /* Use an explicit loop. */
184
26
                uint size = ref_stack_count(&d_stack);
185
26
                uint i;
186
187
101
                for (i = 0; i < size; i++) {
188
76
                    ref *dp = ref_stack_index(&d_stack, i);
189
190
76
                    check_dict_read(*dp);
191
76
                    if (dict_find(dp, op, &pvalue) > 0) {
192
1
                        ref_assign(op, pvalue);
193
1
                        return 0;
194
1
                    }
195
76
                }
196
26
                return_error(gs_error_undefined);
197
26
            }
198
170M
    }
199
170M
}
200
201
/* get - implemented in zgeneric.c */
202
203
/* put - implemented in zgeneric.c */
204
205
/* <dict> <key> .undef - */
206
/* <dict> <key> undef - */
207
static int
208
zundef(i_ctx_t *i_ctx_p)
209
17.7M
{
210
17.7M
    os_ptr op = osp;
211
17.7M
    os_ptr op1 = op - 1;
212
17.7M
    int code;
213
214
17.7M
    check_type(*op1, t_dictionary);
215
17.7M
    check_dict_write(*op1);
216
17.7M
    code = idict_undef(op1, op);
217
17.7M
    if (code < 0 && code != gs_error_undefined) /* ignore undefined error */
218
0
        return code;
219
17.7M
    pop(2);
220
17.7M
    return 0;
221
17.7M
}
222
223
/* <dict> <key> known <bool> */
224
static int
225
zknown(i_ctx_t *i_ctx_p)
226
198M
{
227
198M
    os_ptr op = osp;
228
198M
    register os_ptr op1 = op - 1;
229
198M
    ref *pvalue;
230
198M
    int code;
231
232
198M
    check_type(*op1, t_dictionary);
233
198M
    check_dict_read(*op1);
234
198M
    code = dict_find(op1, op, &pvalue);
235
198M
    switch (code) {
236
9.79M
    case gs_error_dictfull:
237
9.79M
        code = 0;
238
198M
    case 0: case 1:
239
198M
        break;
240
0
    default:
241
0
        return code;
242
198M
    }
243
198M
    make_bool(op1, code);
244
198M
    pop(1);
245
198M
    return 0;
246
198M
}
247
248
/* <key> where <dict> true */
249
/* <key> where false */
250
int
251
zwhere(i_ctx_t *i_ctx_p)
252
8.74M
{
253
8.74M
    os_ptr op = osp;
254
8.74M
    ref_stack_enum_t rsenum;
255
256
8.74M
    check_op(1);
257
8.74M
    ref_stack_enum_begin(&rsenum, &d_stack);
258
8.74M
    do {
259
8.74M
        const ref *const bot = rsenum.ptr;
260
8.74M
        const ref *pdref = bot + rsenum.size;
261
8.74M
        ref *pvalue;
262
8.74M
        int code;
263
264
29.8M
        while (pdref-- > bot) {
265
26.1M
            check_dict_read(*pdref);
266
26.1M
            code = dict_find(pdref, op, &pvalue);
267
26.1M
            if (code < 0 && code != gs_error_dictfull)
268
0
                return code;
269
26.1M
            if (code > 0) {
270
5.03M
                push(1);
271
5.03M
                ref_assign(op - 1, pdref);
272
5.03M
                make_true(op);
273
5.03M
                return 0;
274
5.03M
            }
275
26.1M
        }
276
8.74M
    } while (ref_stack_enum_next(&rsenum));
277
3.71M
    make_false(op);
278
3.71M
    return 0;
279
8.74M
}
280
281
/* copy for dictionaries -- called from zcopy in zgeneric.c. */
282
/* Only the type of *op has been checked. */
283
int
284
zcopy_dict(i_ctx_t *i_ctx_p)
285
1.24M
{
286
1.24M
    os_ptr op = osp;
287
1.24M
    os_ptr op1 = op - 1;
288
1.24M
    int code;
289
290
1.24M
    check_type(*op1, t_dictionary);
291
1.24M
    check_dict_read(*op1);
292
1.24M
    check_dict_write(*op);
293
1.24M
    if (!imemory->gs_lib_ctx->dict_auto_expand &&
294
1.24M
        (dict_length(op) != 0 || dict_maxlength(op) < dict_length(op1))
295
1.24M
        )
296
0
        return_error(gs_error_rangecheck);
297
1.24M
    code = idict_copy(op1, op);
298
1.24M
    if (code < 0)
299
0
        return code;
300
    /*
301
     * In Level 1 systems, we must copy the access attributes too.
302
     * The only possible effect this can have is to make the
303
     * copy read-only if the original dictionary is read-only.
304
     */
305
1.24M
    if (!level2_enabled)
306
1.24M
        r_copy_attrs(dict_access_ref(op), a_write, dict_access_ref(op1));
307
1.24M
    ref_assign(op1, op);
308
1.24M
    pop(1);
309
1.24M
    return 0;
310
1.24M
}
311
312
/* - currentdict <dict> */
313
static int
314
zcurrentdict(i_ctx_t *i_ctx_p)
315
53.2M
{
316
53.2M
    os_ptr op = osp;
317
318
53.2M
    push(1);
319
53.2M
    ref_assign(op, dsp);
320
53.2M
    return 0;
321
53.2M
}
322
323
/* - countdictstack <int> */
324
static int
325
zcountdictstack(i_ctx_t *i_ctx_p)
326
139k
{
327
139k
    os_ptr op = osp;
328
139k
    uint count = ref_stack_count(&d_stack);
329
330
139k
    push(1);
331
139k
    if (!level2_enabled)
332
0
        count--;   /* see dstack.h */
333
139k
    make_int(op, count);
334
139k
    return 0;
335
139k
}
336
337
/* <array> dictstack <subarray> */
338
static int
339
zdictstack(i_ctx_t *i_ctx_p)
340
137k
{
341
137k
    os_ptr op = osp;
342
137k
    uint count = ref_stack_count(&d_stack);
343
344
137k
    if (!level2_enabled)
345
0
        count--;   /* see dstack.h */
346
137k
    if (!r_is_array(op))
347
137k
        return_op_typecheck(op);
348
137k
    if (r_size(op) < count)
349
0
        return_error(gs_error_rangecheck);
350
137k
    if (!r_has_type_attrs(op, t_array, a_write))
351
0
        return_error(gs_error_invalidaccess);
352
137k
    return ref_stack_store(&d_stack, op, count, 0, 0, true, idmemory,
353
137k
                           "dictstack");
354
137k
}
355
356
/* - cleardictstack - */
357
static int
358
zcleardictstack(i_ctx_t *i_ctx_p)
359
437
{
360
452
    while (zend(i_ctx_p) >= 0)
361
437
        DO_NOTHING;
362
437
    return 0;
363
437
}
364
365
/* ------ Extensions ------ */
366
367
/* -mark- <key0> <value0> <key1> <value1> ... .dicttomark <dict> */
368
/* This is the Level 2 >> operator. */
369
static int
370
zdicttomark(i_ctx_t *i_ctx_p)
371
28.7M
{
372
28.7M
    uint count2 = ref_stack_counttomark(&o_stack);
373
28.7M
    ref rdict;
374
28.7M
    int code;
375
28.7M
    uint idx;
376
377
28.7M
    if (count2 == 0)
378
23
        return_error(gs_error_unmatchedmark);
379
28.7M
    count2--;
380
28.7M
    if ((count2 & 1) != 0)
381
14
        return_error(gs_error_rangecheck);
382
28.7M
    code = dict_create(count2 >> 1, &rdict);
383
28.7M
    if (code < 0)
384
0
        return code;
385
28.7M
    if ((i_ctx_p->scanner_options & SCAN_PDF_RULES) != 0) {
386
0
       for (idx = count2; idx > 0; idx -= 2) {
387
0
           code = idict_put(&rdict,
388
0
                            ref_stack_index(&o_stack, idx - 1),
389
0
                            ref_stack_index(&o_stack, idx - 2));
390
0
           if (code < 0) {         /* There's no way to free the dictionary -- too bad. */
391
0
               return code;
392
0
           }
393
0
       }
394
0
    }
395
28.7M
    else {
396
       /* << /a 1 /a 2 >> => << /a 1 >>, i.e., */
397
       /* we must enter the keys in top-to-bottom order. */
398
893M
       for (idx = 0; idx < count2; idx += 2) {
399
864M
           code = idict_put(&rdict,
400
864M
                            ref_stack_index(&o_stack, idx + 1),
401
864M
                            ref_stack_index(&o_stack, idx));
402
864M
           if (code < 0) {         /* There's no way to free the dictionary -- too bad. */
403
0
               return code;
404
0
           }
405
864M
       }
406
28.7M
    }
407
28.7M
    ref_stack_pop(&o_stack, count2);
408
28.7M
    ref_assign(osp, &rdict);
409
28.7M
    return code;
410
28.7M
}
411
412
/* <dict1> <dict2> .forcecopynew <dict2> */
413
/*
414
 * This operator is a special-purpose accelerator for use by 'restore' (see
415
 * gs_dps1.ps).  Note that this operator does *not* require that dict2 be
416
 * writable.  Hence it is in the same category of "dangerous" operators as
417
 * .forceput and .forceundef.
418
 */
419
static int
420
zforcecopynew(i_ctx_t *i_ctx_p)
421
72.0k
{
422
72.0k
    os_ptr op = osp;
423
72.0k
    os_ptr op1 = op - 1;
424
72.0k
    int code;
425
426
72.0k
    check_type(*op1, t_dictionary);
427
72.0k
    check_dict_read(*op1);
428
72.0k
    check_type(*op, t_dictionary);
429
    /*check_dict_write(*op);*/  /* see above */
430
    /* This is only recognized in Level 2 mode. */
431
72.0k
    if (!imemory->gs_lib_ctx->dict_auto_expand)
432
0
        return_error(gs_error_undefined);
433
72.0k
    code = idict_copy_new(op1, op);
434
72.0k
    if (code < 0)
435
0
        return code;
436
72.0k
    ref_assign(op1, op);
437
72.0k
    pop(1);
438
72.0k
    return 0;
439
72.0k
}
440
441
/* <dict> <key> .forceundef - */
442
/*
443
 * This forces an "undef" even if the dictionary is not writable.
444
 * Like .forceput, it is meant to be used only in a few special situations,
445
 * and should not be accessible by name after initialization.
446
 */
447
static int
448
zforceundef(i_ctx_t *i_ctx_p)
449
48.3M
{
450
48.3M
    os_ptr op = osp;
451
452
48.3M
    check_type(op[-1], t_dictionary);
453
    /* Don't check_dict_write */
454
48.3M
    idict_undef(op - 1, op); /* ignore undefined error */
455
48.3M
    pop(2);
456
48.3M
    return 0;
457
48.3M
}
458
459
/* <dict> <key> .knownget <value> true */
460
/* <dict> <key> .knownget false */
461
static int
462
zknownget(i_ctx_t *i_ctx_p)
463
395M
{
464
395M
    os_ptr op = osp;
465
395M
    register os_ptr op1 = op - 1;
466
395M
    ref *pvalue;
467
468
395M
    check_type(*op1, t_dictionary);
469
395M
    check_dict_read(*op1);
470
395M
    if (dict_find(op1, op, &pvalue) <= 0) {
471
91.0M
        make_false(op1);
472
91.0M
        pop(1);
473
304M
    } else {
474
304M
        ref_assign(op1, pvalue);
475
304M
        make_true(op);
476
304M
    }
477
395M
    return 0;
478
395M
}
479
480
/* <dict> <key> .knownundef <bool> */
481
static int
482
zknownundef(i_ctx_t *i_ctx_p)
483
0
{
484
0
    os_ptr op = osp;
485
0
    os_ptr op1 = op - 1;
486
0
    int code;
487
488
0
    check_type(*op1, t_dictionary);
489
0
    check_dict_write(*op1);
490
0
    code = idict_undef(op1, op);
491
0
    make_bool(op1, code == 0);
492
0
    pop(1);
493
0
    return 0;
494
0
}
495
496
/* <dict> <int> .setmaxlength - */
497
static int
498
zsetmaxlength(i_ctx_t *i_ctx_p)
499
6.42M
{
500
6.42M
    os_ptr op = osp;
501
6.42M
    os_ptr op1 = op - 1;
502
6.42M
    uint new_size;
503
6.42M
    int code;
504
505
6.42M
    check_type(*op1, t_dictionary);
506
6.42M
    check_dict_write(*op1);
507
6.42M
    check_type(*op, t_integer);
508
6.42M
    if (op->value.intval < 0)
509
0
        return_error(gs_error_rangecheck);
510
6.42M
    new_size = (uint) op->value.intval;
511
6.42M
    if (dict_length(op - 1) > new_size)
512
0
        return_error(gs_error_dictfull);
513
6.42M
    code = idict_resize(op - 1, new_size);
514
6.42M
    if (code >= 0)
515
6.42M
        pop(2);
516
6.42M
    return code;
517
6.42M
}
518
519
/* ------ Initialization procedure ------ */
520
521
/* We need to split the table because of the 16-element limit. */
522
const op_def zdict1_op_defs[] = {
523
    {"0cleardictstack", zcleardictstack},
524
    {"1begin", zbegin},
525
    {"0countdictstack", zcountdictstack},
526
    {"0currentdict", zcurrentdict},
527
    {"2def", zdef},
528
    {"1dict", zdict},
529
    {"0dictstack", zdictstack},
530
    {"0end", zend},
531
    {"2known", zknown},
532
    {"1load", zload},
533
    {"1maxlength", zmaxlength},
534
    {"2.undef", zundef},  /* we need this even in Level 1 */
535
    {"1where", zwhere},
536
    op_def_end(0)
537
};
538
const op_def zdict2_op_defs[] = {
539
                /* Extensions */
540
    {"1.dicttomark", zdicttomark},
541
    {"2.forcecopynew", zforcecopynew},
542
    {"2.forceundef", zforceundef},
543
    {"2.knownget", zknownget},
544
    {"1.knownundef", zknownundef},
545
    {"2.setmaxlength", zsetmaxlength},
546
        /*
547
         * In Level 2, >> is a synonym for .dicttomark, and undef for
548
         * .undef.  By giving the former their own entries, they will not be
549
         * "eq" to .dicttomark and .undef, but that doesn't matter, since
550
         * we're doing this only for the sake of Adobe- compatible error
551
         * stacks.
552
         */
553
    op_def_begin_level2(),
554
    {"1>>", zdicttomark},
555
    {"2undef", zundef},
556
    op_def_end(0)
557
};