Coverage Report

Created: 2022-04-16 11:23

/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
443k
{
33
443k
    os_ptr op = osp;
34
35
443k
    check_type(*op, t_integer);
36
443k
    if (op->value.intval < 0)
37
0
        return_error(gs_error_rangecheck);
38
443k
    return dict_create((uint) op->value.intval, op);
39
443k
}
40
41
/* <dict> maxlength <int> */
42
static int
43
zmaxlength(i_ctx_t *i_ctx_p)
44
400k
{
45
400k
    os_ptr op = osp;
46
47
400k
    check_type(*op, t_dictionary);
48
400k
    check_dict_read(*op);
49
400k
    make_int(op, dict_maxlength(op));
50
400k
    return 0;
51
400k
}
52
53
/* <dict> begin - */
54
int
55
zbegin(i_ctx_t *i_ctx_p)
56
1.29M
{
57
1.29M
    os_ptr op = osp;
58
59
1.29M
    check_type(*op, t_dictionary);
60
1.29M
    check_dict_read(*op);
61
1.29M
    if ( dsp == dstop ) {
62
0
        int code = ref_stack_extend(&d_stack, 1);
63
64
0
        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
0
    }
73
1.29M
    ++dsp;
74
1.29M
    ref_assign(dsp, op);
75
1.29M
    dict_set_top();
76
1.29M
    pop(1);
77
1.29M
    return 0;
78
1.29M
}
79
80
/* - end - */
81
int
82
zend(i_ctx_t *i_ctx_p)
83
1.29M
{
84
1.29M
    if (ref_stack_count_inline(&d_stack) == min_dstack_size) {
85
        /* We would underflow the d-stack. */
86
1
        return_error(gs_error_dictstackunderflow);
87
1
    }
88
1.29M
    while (dsp == dsbot) {
89
        /* We would underflow the current block. */
90
0
        ref_stack_pop_block(&d_stack);
91
0
    }
92
1.29M
    dsp--;
93
1.29M
    dict_set_top();
94
1.29M
    return 0;
95
1.29M
}
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
1.47M
{
105
1.47M
    os_ptr op = osp;
106
1.47M
    os_ptr op1 = op - 1;
107
1.47M
    ref *pvslot;
108
109
    /* The following combines a check_op(2) with a type check. */
110
1.47M
    switch (r_type(op1)) {
111
1.44M
        case t_name: {
112
            /* We can use the fast single-probe lookup here. */
113
1.44M
            uint nidx = name_index(imemory, op1);
114
1.44M
            uint htemp;
115
116
1.44M
            if_dict_find_name_by_index_top(nidx, htemp, pvslot) {
117
13.6k
                if (dtop_can_store(op))
118
13.6k
                    goto ra;
119
13.6k
            }
120
1.43M
            break;   /* handle all slower cases */
121
1.44M
            }
122
1.43M
        case t_null:
123
0
            return_error(gs_error_typecheck);
124
0
        case t__invalid:
125
0
            return_error(gs_error_stackunderflow);
126
1.47M
    }
127
    /*
128
     * Combine the check for a writable top dictionary with
129
     * the global/local store check.  See dstack.h for details.
130
     */
131
1.46M
    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
1.46M
    if (dict_find(dsp, op1, &pvslot) <= 0)
145
1.41M
        return idict_put(dsp, op1, op);
146
58.7k
ra:
147
58.7k
    if ((pvslot->tas.type_attrs & (&i_ctx_p->memory)->test_mask) == 0)
148
0
        alloc_save_change(idmemory, &dsp->value.pdict->values, (ref_packed *)pvslot, "dict_put(value)");
149
58.7k
    ref_assign_new_inline(pvslot,op);
150
151
58.7k
    return 0;
152
1.46M
}
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
1.30M
{
168
1.30M
    os_ptr op = osp;
169
1.30M
    ref *pvalue;
170
171
1.30M
    switch (r_type(op)) {
172
1.30M
        case t_name:
173
            /* Use the fast lookup. */
174
1.30M
            if ((pvalue = dict_find_name(op)) == 0)
175
0
                return_error(gs_error_undefined);
176
1.30M
            ref_assign(op, pvalue);
177
1.30M
            return 0;
178
0
        case t_null:
179
0
            return_error(gs_error_typecheck);
180
0
        case t__invalid:
181
0
            return_error(gs_error_stackunderflow);
182
0
        default: {
183
                /* Use an explicit loop. */
184
0
                uint size = ref_stack_count(&d_stack);
185
0
                uint i;
186
187
0
                for (i = 0; i < size; i++) {
188
0
                    ref *dp = ref_stack_index(&d_stack, i);
189
190
0
                    check_dict_read(*dp);
191
0
                    if (dict_find(dp, op, &pvalue) > 0) {
192
0
                        ref_assign(op, pvalue);
193
0
                        return 0;
194
0
                    }
195
0
                }
196
0
                return_error(gs_error_undefined);
197
0
            }
198
1.30M
    }
199
1.30M
}
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
128k
{
210
128k
    os_ptr op = osp;
211
128k
    os_ptr op1 = op - 1;
212
128k
    int code;
213
214
128k
    check_type(*op1, t_dictionary);
215
128k
    check_dict_write(*op1);
216
128k
    code = idict_undef(op1, op);
217
128k
    if (code < 0 && code != gs_error_undefined) /* ignore undefined error */
218
0
        return code;
219
128k
    pop(2);
220
128k
    return 0;
221
128k
}
222
223
/* <dict> <key> known <bool> */
224
static int
225
zknown(i_ctx_t *i_ctx_p)
226
1.43M
{
227
1.43M
    os_ptr op = osp;
228
1.43M
    register os_ptr op1 = op - 1;
229
1.43M
    ref *pvalue;
230
1.43M
    int code;
231
232
1.43M
    check_type(*op1, t_dictionary);
233
1.43M
    check_dict_read(*op1);
234
1.43M
    code = dict_find(op1, op, &pvalue);
235
1.43M
    switch (code) {
236
63.4k
    case gs_error_dictfull:
237
63.4k
        code = 0;
238
1.43M
    case 0: case 1:
239
1.43M
        break;
240
0
    default:
241
0
        return code;
242
1.43M
    }
243
1.43M
    make_bool(op1, code);
244
1.43M
    pop(1);
245
1.43M
    return 0;
246
1.43M
}
247
248
/* <key> where <dict> true */
249
/* <key> where false */
250
int
251
zwhere(i_ctx_t *i_ctx_p)
252
76.4k
{
253
76.4k
    os_ptr op = osp;
254
76.4k
    ref_stack_enum_t rsenum;
255
256
76.4k
    check_op(1);
257
76.4k
    ref_stack_enum_begin(&rsenum, &d_stack);
258
76.4k
    do {
259
76.4k
        const ref *const bot = rsenum.ptr;
260
76.4k
        const ref *pdref = bot + rsenum.size;
261
76.4k
        ref *pvalue;
262
76.4k
        int code;
263
264
292k
        while (pdref-- > bot) {
265
254k
            check_dict_read(*pdref);
266
254k
            code = dict_find(pdref, op, &pvalue);
267
254k
            if (code < 0 && code != gs_error_dictfull)
268
0
                return code;
269
254k
            if (code > 0) {
270
38.8k
                push(1);
271
38.8k
                ref_assign(op - 1, pdref);
272
38.8k
                make_true(op);
273
38.8k
                return 0;
274
38.8k
            }
275
254k
        }
276
76.4k
    } while (ref_stack_enum_next(&rsenum));
277
37.6k
    make_false(op);
278
37.6k
    return 0;
279
76.4k
}
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
9.56k
{
286
9.56k
    os_ptr op = osp;
287
9.56k
    os_ptr op1 = op - 1;
288
9.56k
    int code;
289
290
9.56k
    check_type(*op1, t_dictionary);
291
9.56k
    check_dict_read(*op1);
292
9.56k
    check_dict_write(*op);
293
9.56k
    if (!imemory->gs_lib_ctx->dict_auto_expand &&
294
9.56k
        (dict_length(op) != 0 || dict_maxlength(op) < dict_length(op1))
295
9.56k
        )
296
0
        return_error(gs_error_rangecheck);
297
9.56k
    code = idict_copy(op1, op);
298
9.56k
    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
9.56k
    if (!level2_enabled)
306
9.56k
        r_copy_attrs(dict_access_ref(op), a_write, dict_access_ref(op1));
307
9.56k
    ref_assign(op1, op);
308
9.56k
    pop(1);
309
9.56k
    return 0;
310
9.56k
}
311
312
/* - currentdict <dict> */
313
static int
314
zcurrentdict(i_ctx_t *i_ctx_p)
315
401k
{
316
401k
    os_ptr op = osp;
317
318
401k
    push(1);
319
401k
    ref_assign(op, dsp);
320
401k
    return 0;
321
401k
}
322
323
/* - countdictstack <int> */
324
static int
325
zcountdictstack(i_ctx_t *i_ctx_p)
326
706
{
327
706
    os_ptr op = osp;
328
706
    uint count = ref_stack_count(&d_stack);
329
330
706
    push(1);
331
706
    if (!level2_enabled)
332
0
        count--;   /* see dstack.h */
333
706
    make_int(op, count);
334
706
    return 0;
335
706
}
336
337
/* <array> dictstack <subarray> */
338
static int
339
zdictstack(i_ctx_t *i_ctx_p)
340
702
{
341
702
    os_ptr op = osp;
342
702
    uint count = ref_stack_count(&d_stack);
343
344
702
    if (!level2_enabled)
345
0
        count--;   /* see dstack.h */
346
702
    if (!r_is_array(op))
347
702
        return_op_typecheck(op);
348
702
    if (r_size(op) < count)
349
0
        return_error(gs_error_rangecheck);
350
702
    if (!r_has_type_attrs(op, t_array, a_write))
351
0
        return_error(gs_error_invalidaccess);
352
702
    return ref_stack_store(&d_stack, op, count, 0, 0, true, idmemory,
353
702
                           "dictstack");
354
702
}
355
356
/* - cleardictstack - */
357
static int
358
zcleardictstack(i_ctx_t *i_ctx_p)
359
1
{
360
1
    while (zend(i_ctx_p) >= 0)
361
1
        DO_NOTHING;
362
1
    return 0;
363
1
}
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
158k
{
372
158k
    uint count2 = ref_stack_counttomark(&o_stack);
373
158k
    ref rdict;
374
158k
    int code;
375
158k
    uint idx;
376
377
158k
    if (count2 == 0)
378
0
        return_error(gs_error_unmatchedmark);
379
158k
    count2--;
380
158k
    if ((count2 & 1) != 0)
381
0
        return_error(gs_error_rangecheck);
382
158k
    code = dict_create(count2 >> 1, &rdict);
383
158k
    if (code < 0)
384
0
        return code;
385
158k
    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
158k
    else {
396
       /* << /a 1 /a 2 >> => << /a 1 >>, i.e., */
397
       /* we must enter the keys in top-to-bottom order. */
398
6.40M
       for (idx = 0; idx < count2; idx += 2) {
399
6.24M
           code = idict_put(&rdict,
400
6.24M
                            ref_stack_index(&o_stack, idx + 1),
401
6.24M
                            ref_stack_index(&o_stack, idx));
402
6.24M
           if (code < 0) {         /* There's no way to free the dictionary -- too bad. */
403
0
               return code;
404
0
           }
405
6.24M
       }
406
158k
    }
407
158k
    ref_stack_pop(&o_stack, count2);
408
158k
    ref_assign(osp, &rdict);
409
158k
    return code;
410
158k
}
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
671
{
422
671
    os_ptr op = osp;
423
671
    os_ptr op1 = op - 1;
424
671
    int code;
425
426
671
    check_type(*op1, t_dictionary);
427
671
    check_dict_read(*op1);
428
671
    check_type(*op, t_dictionary);
429
    /*check_dict_write(*op);*/  /* see above */
430
    /* This is only recognized in Level 2 mode. */
431
671
    if (!imemory->gs_lib_ctx->dict_auto_expand)
432
0
        return_error(gs_error_undefined);
433
671
    code = idict_copy_new(op1, op);
434
671
    if (code < 0)
435
0
        return code;
436
671
    ref_assign(op1, op);
437
671
    pop(1);
438
671
    return 0;
439
671
}
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
369k
{
450
369k
    os_ptr op = osp;
451
452
369k
    check_type(op[-1], t_dictionary);
453
    /* Don't check_dict_write */
454
369k
    idict_undef(op - 1, op); /* ignore undefined error */
455
369k
    pop(2);
456
369k
    return 0;
457
369k
}
458
459
/* <dict> <key> .knownget <value> true */
460
/* <dict> <key> .knownget false */
461
static int
462
zknownget(i_ctx_t *i_ctx_p)
463
3.00M
{
464
3.00M
    os_ptr op = osp;
465
3.00M
    register os_ptr op1 = op - 1;
466
3.00M
    ref *pvalue;
467
468
3.00M
    check_type(*op1, t_dictionary);
469
3.00M
    check_dict_read(*op1);
470
3.00M
    if (dict_find(op1, op, &pvalue) <= 0) {
471
829k
        make_false(op1);
472
829k
        pop(1);
473
2.17M
    } else {
474
2.17M
        ref_assign(op1, pvalue);
475
2.17M
        make_true(op);
476
2.17M
    }
477
3.00M
    return 0;
478
3.00M
}
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
49.1k
{
500
49.1k
    os_ptr op = osp;
501
49.1k
    os_ptr op1 = op - 1;
502
49.1k
    uint new_size;
503
49.1k
    int code;
504
505
49.1k
    check_type(*op1, t_dictionary);
506
49.1k
    check_dict_write(*op1);
507
49.1k
    check_type(*op, t_integer);
508
49.1k
    if (op->value.intval < 0)
509
0
        return_error(gs_error_rangecheck);
510
49.1k
    new_size = (uint) op->value.intval;
511
49.1k
    if (dict_length(op - 1) > new_size)
512
0
        return_error(gs_error_dictfull);
513
49.1k
    code = idict_resize(op - 1, new_size);
514
49.1k
    if (code >= 0)
515
49.1k
        pop(2);
516
49.1k
    return code;
517
49.1k
}
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
};