Coverage Report

Created: 2026-10-28 08:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/pdf/pdf_dict.c
Line
Count
Source
1
/* Copyright (C) 2018-2026 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
/* dictionary handling for the PDF interpreter */
17
#include "ghostpdf.h"
18
#include "pdf_types.h"
19
#include "pdf_deref.h"
20
#include "pdf_dict.h"
21
#include "pdf_stack.h"
22
#include "pdf_array.h"
23
#include "pdf_int.h"
24
#include "pdf_loop_detect.h"
25
#include "pdf_misc.h"
26
27
static int pdfi_dict_find(pdf_context *ctx, pdf_dict *d, const char *Key, bool sort);
28
static int pdfi_dict_find_key(pdf_context *ctx, pdf_dict *d, const pdf_name *Key, bool sort);
29
30
void pdfi_free_dict(pdf_obj *o)
31
11.6M
{
32
11.6M
    pdf_dict *d = (pdf_dict *)o;
33
11.6M
    int i;
34
#if DEBUG_DICT
35
    pdf_name *name;
36
#endif
37
38
111M
    for (i=0;i < d->entries;i++) {
39
#if DEBUG_DICT
40
        name = (pdf_name *)d->list[i].key;
41
#endif
42
99.4M
        if (d->list[i].value != NULL)
43
99.1M
            pdfi_countdown(d->list[i].value);
44
99.4M
        if (d->list[i].key != NULL)
45
99.1M
            pdfi_countdown(d->list[i].key);
46
99.4M
    }
47
11.6M
    gs_free_object(OBJ_MEMORY(d), d->list, "pdf interpreter free dictionary key/values");
48
11.6M
    gs_free_object(OBJ_MEMORY(d), d, "pdf interpreter free dictionary");
49
11.6M
}
50
51
/* Delete a key pair, either by specifying a char * or a pdf_name *
52
 */
53
static int pdfi_dict_delete_inner(pdf_context *ctx, pdf_dict *d, pdf_name *n, const char *str)
54
173k
{
55
173k
    int i = 0;
56
#if DEBUG_DICT
57
    pdf_name *name;
58
#endif
59
60
173k
    if (n != NULL)
61
8.65k
        i = pdfi_dict_find_key(ctx, d, (const pdf_name *)n, false);
62
164k
    else
63
164k
        i = pdfi_dict_find(ctx, d, str, false);
64
65
173k
    if (i < 0)
66
58
        return i;
67
68
173k
    pdfi_countdown(d->list[i].key);
69
173k
    pdfi_countdown(d->list[i].value);
70
173k
    d->entries--;
71
173k
    if (i != d->entries)
72
10.2k
        memmove(&d->list[i], &d->list[i+1], (d->entries - i) * sizeof(d->list[0]));
73
173k
    d->list[d->entries].key = NULL;
74
173k
    d->list[d->entries].value = NULL;
75
173k
    d->is_sorted = false;
76
173k
    return 0;
77
173k
}
78
79
int pdfi_dict_delete_pair(pdf_context *ctx, pdf_dict *d, pdf_name *n)
80
8.65k
{
81
8.65k
    return pdfi_dict_delete_inner(ctx, d, n, NULL);
82
8.65k
}
83
84
int pdfi_dict_delete(pdf_context *ctx, pdf_dict *d, const char *str)
85
164k
{
86
164k
    return pdfi_dict_delete_inner(ctx, d, NULL, str);
87
164k
}
88
89
/* This function is provided for symmetry with arrays, and in case we ever
90
 * want to change the behaviour of pdfi_dict_from_stack() and pdfi_dict_alloc()
91
 * similarly to the array behaviour, where we always have null PDF objects
92
 * rather than NULL pointers stored in the dictionary.
93
 */
94
int pdfi_dict_alloc(pdf_context *ctx, uint64_t size, pdf_dict **d)
95
11.6M
{
96
11.6M
    *d = NULL;
97
11.6M
    return pdfi_object_alloc(ctx, PDF_DICT, size, (pdf_obj **)d);
98
11.6M
}
99
100
static int pdfi_dict_name_from_string(pdf_context *ctx, pdf_string *s, pdf_name **n)
101
0
{
102
0
    int code = pdfi_object_alloc(ctx, PDF_NAME, s->length, (pdf_obj **)n);
103
0
    if (code >= 0) {
104
0
        memcpy((*n)->data, s->data, s->length);
105
0
        pdfi_countup(*n);
106
0
    }
107
0
    return code;
108
0
}
109
110
int pdfi_dict_from_stack(pdf_context *ctx, uint32_t indirect_num, uint32_t indirect_gen, bool convert_string_keys)
111
10.9M
{
112
10.9M
    uint64_t index = 0;
113
10.9M
    pdf_dict *d = NULL;
114
10.9M
    uint64_t i = 0;
115
10.9M
    int code;
116
#if DEBUG_DICT
117
    pdf_name *key;
118
#endif
119
120
10.9M
    code = pdfi_count_to_mark(ctx, &index);
121
10.9M
    if (code < 0) {
122
134k
        pdfi_clear_to_mark(ctx);
123
134k
        return code;
124
134k
    }
125
126
10.8M
    if (index & 1) {
127
209k
        pdfi_clear_to_mark(ctx);
128
209k
        return_error(gs_error_rangecheck);
129
209k
    }
130
131
10.5M
    code = pdfi_dict_alloc(ctx, index >> 1, &d);
132
10.5M
    if (code < 0) {
133
0
        pdfi_clear_to_mark(ctx);
134
0
        return code;
135
0
    }
136
137
10.5M
    d->entries = d->size;
138
139
62.8M
    while (index) {
140
52.3M
        i = (index / 2) - 1;
141
142
        /* In PDF keys are *required* to be names, so we ought to check that here */
143
52.3M
        if (pdfi_type_of((pdf_obj *)ctx->stack_top[-2]) == PDF_NAME) {
144
52.2M
            d->list[i].key = ctx->stack_top[-2];
145
52.2M
            pdfi_countup(d->list[i].key);
146
#if DEBUG_DICT
147
            key = (pdf_name *)d->list[i].key;
148
#endif
149
52.2M
            d->list[i].value = ctx->stack_top[-1];
150
52.2M
            pdfi_countup(d->list[i].value);
151
52.2M
        } else {
152
42.1k
            if (convert_string_keys && (pdfi_type_of((pdf_obj *)ctx->stack_top[-2]) == PDF_STRING)) {
153
0
                pdf_name *n;
154
0
                code = pdfi_dict_name_from_string(ctx, (pdf_string *)ctx->stack_top[-2], &n);
155
0
                if (code < 0) {
156
0
                    pdfi_free_dict((pdf_obj *)d);
157
0
                    pdfi_clear_to_mark(ctx);
158
0
                    return_error(gs_error_typecheck);
159
0
                }
160
0
                d->list[i].key = (pdf_obj *)n; /* pdfi_dict_name_from_string() sets refcnt to 1 */
161
0
                d->list[i].value = ctx->stack_top[-1];
162
0
                pdfi_countup(d->list[i].value);
163
0
            }
164
42.1k
            else {
165
42.1k
                pdfi_free_dict((pdf_obj *)d);
166
42.1k
                pdfi_clear_to_mark(ctx);
167
42.1k
                return_error(gs_error_typecheck);
168
42.1k
            }
169
42.1k
        }
170
171
52.2M
        pdfi_pop(ctx, 2);
172
52.2M
        index -= 2;
173
52.2M
    }
174
175
10.5M
    code = pdfi_clear_to_mark(ctx);
176
10.5M
    if (code < 0) {
177
0
        pdfi_free_dict((pdf_obj *)d);
178
0
        return code;
179
0
    }
180
181
10.5M
    if (ctx->args.pdfdebug)
182
0
        outprintf (ctx->memory, "\n >>\n");
183
184
10.5M
    d->indirect_num = indirect_num;
185
10.5M
    d->indirect_gen = indirect_gen;
186
187
10.5M
    code = pdfi_push(ctx, (pdf_obj *)d);
188
10.5M
    if (code < 0)
189
0
        pdfi_free_dict((pdf_obj *)d);
190
191
10.5M
    return code;
192
10.5M
}
193
194
/* Convenience routine for common case where there are two possible keys */
195
int
196
pdfi_dict_get2(pdf_context *ctx, pdf_dict *d, const char *Key1,
197
               const char *Key2, pdf_obj **o)
198
1.23M
{
199
1.23M
    int code;
200
201
    /* ISO 32000-2:2020 (PDF 2.0) - abbreviated names take precendence. Assume abbreviated names are shorter :-) */
202
1.23M
    if (strlen(Key1) < strlen(Key2)) {
203
0
        code = pdfi_dict_get(ctx, d, Key1, o);
204
0
        if (code == gs_error_undefined)
205
0
            code = pdfi_dict_get(ctx, d, Key2, o);
206
1.23M
    } else {
207
1.23M
        code = pdfi_dict_get(ctx, d, Key2, o);
208
1.23M
        if (code == gs_error_undefined)
209
1.02M
            code = pdfi_dict_get(ctx, d, Key1, o);
210
1.23M
    }
211
1.23M
    return code;
212
1.23M
}
213
214
static int pdfi_dict_compare_entry(const void *a, const void *b)
215
1.09G
{
216
1.09G
    pdf_name *key_a = (pdf_name *)((pdf_dict_entry *)a)->key, *key_b = (pdf_name *)((pdf_dict_entry *)b)->key;
217
218
1.09G
    if (key_a == NULL) {
219
531k
        if (key_b == NULL)
220
531k
            return 0;
221
0
        else
222
0
            return 1;
223
531k
    }
224
225
1.09G
    if (key_b == NULL)
226
105k
        return -1;
227
228
1.09G
    if (key_a->length != key_b->length)
229
347M
        return key_a->length - key_b->length;
230
231
745M
    return strncmp((const char *)key_a->data, (const char *)key_b->data, key_a->length);
232
1.09G
}
233
234
static int pdfi_dict_find_sorted(pdf_context *ctx, pdf_dict *d, const char *Key)
235
69.9M
{
236
69.9M
    int start = 0, end = d->size - 1, middle = 0, keylen = strlen(Key);
237
69.9M
    pdf_name *test_key;
238
239
599M
    while (start <= end) {
240
596M
        middle = start + (end - start) / 2;
241
596M
        test_key = (pdf_name *)d->list[middle].key;
242
243
        /* Sorting pushes unused key/values (NULL) to the end of the dictionary */
244
596M
        if (test_key == NULL) {
245
621k
            end = middle - 1;
246
621k
            continue;
247
621k
        }
248
249
596M
        if (test_key->length == keylen) {
250
380M
            int result = strncmp((const char *)test_key->data, Key, keylen);
251
252
380M
            if (result == 0)
253
66.9M
                return middle;
254
313M
            if (result < 0)
255
160M
                start = middle + 1;
256
152M
            else
257
152M
                end = middle - 1;
258
313M
        } else {
259
215M
            if (test_key->length < keylen)
260
85.9M
                start = middle + 1;
261
129M
            else
262
129M
                end = middle -1;
263
215M
        }
264
596M
    }
265
2.97M
    return gs_note_error(gs_error_undefined);
266
69.9M
}
267
268
static int pdfi_dict_find_unsorted(pdf_context *ctx, pdf_dict *d, const char *Key)
269
142M
{
270
142M
    int i;
271
142M
    pdf_name *t;
272
273
19.2G
    for (i=0;i< d->entries;i++) {
274
19.1G
        t = (pdf_name *)d->list[i].key;
275
276
19.1G
        if (t && pdfi_type_of(t) == PDF_NAME) {
277
19.1G
            if (pdfi_name_is((pdf_name *)t, Key)) {
278
53.5M
                return i;
279
53.5M
            }
280
19.1G
        }
281
19.1G
    }
282
142M
    return_error(gs_error_undefined);
283
142M
}
284
285
static int pdfi_dict_find(pdf_context *ctx, pdf_dict *d, const char *Key, bool sort)
286
212M
{
287
212M
    if (!d->is_sorted) {
288
142M
        if (d->entries > 32 && sort) {
289
311k
            qsort(d->list, d->size, sizeof(pdf_dict_entry), pdfi_dict_compare_entry);
290
311k
            d->is_sorted = true;
291
311k
            return pdfi_dict_find_sorted(ctx, d, Key);
292
311k
        } else
293
142M
            return pdfi_dict_find_unsorted(ctx, d, Key);
294
142M
    } else
295
69.6M
        return pdfi_dict_find_sorted(ctx, d, Key);
296
212M
}
297
298
static int pdfi_dict_find_key(pdf_context *ctx, pdf_dict *d, const pdf_name *Key, bool sort)
299
117M
{
300
117M
    char *Test = NULL;
301
117M
    int index = 0;
302
303
117M
    Test = (char *)gs_alloc_bytes(ctx->memory, (size_t)Key->length + 1, "pdfi_dict_find_key");
304
117M
    if (Test == NULL)
305
0
        return_error(gs_error_VMerror);
306
307
117M
    memcpy(Test, Key->data, Key->length);
308
117M
    Test[Key->length] = 0x00;
309
310
117M
    index = pdfi_dict_find(ctx, d, Test, sort);
311
312
117M
    gs_free_object(ctx->memory, Test, "pdfi_dict_find_key");
313
117M
    return index;
314
117M
}
315
316
/* The object returned by pdfi_dict_get has its reference count incremented by 1 to
317
 * indicate the reference now held by the caller, in **o.
318
 */
319
int pdfi_dict_get_common(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj **o, bool cache)
320
41.4M
{
321
41.4M
    int index = 0, code = 0;
322
323
41.4M
    *o = NULL;
324
325
41.4M
    if (pdfi_type_of(d) != PDF_DICT)
326
47.1k
        return_error(gs_error_typecheck);
327
328
41.4M
    index = pdfi_dict_find(ctx, d, Key, true);
329
41.4M
    if (index < 0)
330
9.06M
        return index;
331
332
32.3M
    if (pdfi_type_of(d->list[index].value) == PDF_INDIRECT) {
333
1.40M
        pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[index].value;
334
335
1.40M
        if (r->ref_object_num == d->object_num)
336
634
            return_error(gs_error_circular_reference);
337
338
1.40M
        if (cache)
339
1.40M
            code = pdfi_deref_loop_detect(ctx, r->ref_object_num, r->ref_generation_num, o);
340
0
        else
341
0
            code = pdfi_deref_loop_detect_nocache(ctx, r->ref_object_num, r->ref_generation_num, o);
342
1.40M
        if (code < 0)
343
446k
            return code;
344
        /* The file Bug690138.pdf has font dictionaries which contain ToUnicode keys where
345
         * the value is an indirect reference to the same font object. If we replace the
346
         * indirect reference in the dictionary with the font dictionary it becomes self
347
         * referencing and never counts down to 0, leading to a memory leak.
348
         * This is clearly an error, so flag it and don't replace the indirect reference.
349
         */
350
959k
        if ((*o) < (pdf_obj *)(uintptr_t)(TOKEN__LAST_KEY)) {
351
            /* "FAST" object, therefore can't be a problem. */
352
656
            pdfi_countdown(d->list[index].value);
353
656
            d->list[index].value = *o;
354
958k
        } else if ((*o)->object_num == 0 || (*o)->object_num != d->object_num) {
355
958k
            pdfi_countdown(d->list[index].value);
356
958k
            d->list[index].value = *o;
357
958k
        } else {
358
0
            code = pdfi_set_error_stop(ctx, gs_note_error(gs_error_undefinedresult), NULL, E_DICT_SELF_REFERENCE, "pdfi_dict_get", NULL);
359
0
            return code;
360
0
        }
361
959k
    }
362
31.8M
    *o = d->list[index].value;
363
31.8M
    pdfi_countup(*o);
364
365
31.8M
    return code;
366
32.3M
}
367
368
/* Get object from dict without resolving indirect references
369
 * Will inc refcnt by 1
370
 */
371
int pdfi_dict_get_no_deref(pdf_context *ctx, pdf_dict *d, const pdf_name *Key, pdf_obj **o)
372
78.0k
{
373
78.0k
    int index=0;
374
375
78.0k
    *o = NULL;
376
377
78.0k
    if (pdfi_type_of(d) != PDF_DICT)
378
0
        return_error(gs_error_typecheck);
379
380
78.0k
    index = pdfi_dict_find_key(ctx, d, Key, true);
381
78.0k
    if (index < 0)
382
0
        return index;
383
384
78.0k
    *o = d->list[index].value;
385
78.0k
    pdfi_countup(*o);
386
78.0k
    return 0;
387
78.0k
}
388
389
/* Get by pdf_name rather than by char *
390
 * The object returned by pdfi_dict_get has its reference count incremented by 1 to
391
 * indicate the reference now held by the caller, in **o.
392
 */
393
int pdfi_dict_get_by_key(pdf_context *ctx, pdf_dict *d, const pdf_name *Key, pdf_obj **o)
394
70.7M
{
395
70.7M
    int index=0, code = 0;
396
397
70.7M
    *o = NULL;
398
399
70.7M
    if (pdfi_type_of(d) != PDF_DICT)
400
227
        return_error(gs_error_typecheck);
401
402
70.7M
    index = pdfi_dict_find_key(ctx, d, Key, true);
403
70.7M
    if (index < 0)
404
3.86M
        return index;
405
406
66.8M
    if (pdfi_type_of(d->list[index].value) == PDF_INDIRECT) {
407
72.1k
        pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[index].value;
408
409
72.1k
        code = pdfi_deref_loop_detect(ctx, r->ref_object_num, r->ref_generation_num, o);
410
72.1k
        if (code < 0)
411
25.4k
            return code;
412
46.6k
        pdfi_countdown(d->list[index].value);
413
46.6k
        d->list[index].value = *o;
414
46.6k
    }
415
66.8M
    *o = d->list[index].value;
416
66.8M
    pdfi_countup(*o);
417
66.8M
    return 0;
418
66.8M
}
419
420
/* Get indirect reference without de-referencing it */
421
int pdfi_dict_get_ref(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_indirect_ref **o)
422
0
{
423
0
    int index=0;
424
425
0
    *o = NULL;
426
427
0
    if (pdfi_type_of(d) != PDF_DICT)
428
0
        return_error(gs_error_typecheck);
429
430
0
    index = pdfi_dict_find(ctx, d, Key, true);
431
0
    if (index < 0)
432
0
        return index;
433
434
0
    if (pdfi_type_of(d->list[index].value) == PDF_INDIRECT) {
435
0
        *o = (pdf_indirect_ref *)d->list[index].value;
436
0
        pdfi_countup(*o);
437
0
        return 0;
438
0
    } else {
439
0
        return_error(gs_error_typecheck);
440
0
    }
441
0
}
442
443
/* As per pdfi_dict_get(), but doesn't replace an indirect reference in a dictionary with a
444
 * new object. This is for Resources following, such as Do, where we will have to seek and
445
 * read the indirect object anyway, and we need to ensure that Form XObjects (for example)
446
 * don't have circular calls.
447
 *
448
 * Takes either strKey or nameKey param. Other will be NULL.
449
 */
450
static int pdfi_dict_get_no_store_R_inner(pdf_context *ctx, pdf_dict *d, const char *strKey,
451
                                          const pdf_name *nameKey, pdf_obj **o)
452
3.21M
{
453
3.21M
    int index=0, code = 0;
454
455
3.21M
    *o = NULL;
456
457
3.21M
    if (pdfi_type_of(d) != PDF_DICT)
458
0
        return_error(gs_error_typecheck);
459
460
3.21M
    if (strKey == NULL)
461
2.54M
        index = pdfi_dict_find_key(ctx, d, nameKey, true);
462
676k
    else
463
676k
        index = pdfi_dict_find(ctx, d, strKey, true);
464
465
3.21M
    if (index < 0)
466
122k
        return index;
467
468
3.09M
    if (pdfi_type_of(d->list[index].value) == PDF_INDIRECT) {
469
2.59M
        pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[index].value;
470
471
2.59M
        code = pdfi_dereference(ctx, r->ref_object_num, r->ref_generation_num, o);
472
2.59M
        if (code < 0)
473
1.08M
            return code;
474
2.59M
    } else {
475
502k
        *o = d->list[index].value;
476
502k
        pdfi_countup(*o);
477
502k
    }
478
2.01M
    return 0;
479
3.09M
}
480
481
/* Wrapper to pdfi_dict_no_store_R_inner(), takes a char * as Key */
482
int pdfi_dict_get_no_store_R(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj **o)
483
676k
{
484
676k
    return pdfi_dict_get_no_store_R_inner(ctx, d, Key, NULL, o);
485
676k
}
486
487
/* Wrapper to pdfi_dict_no_store_R_inner(), takes a pdf_name * as Key */
488
int pdfi_dict_get_no_store_R_key(pdf_context *ctx, pdf_dict *d, const pdf_name *Key, pdf_obj **o)
489
2.54M
{
490
2.54M
    return pdfi_dict_get_no_store_R_inner(ctx, d, NULL, Key, o);
491
2.54M
}
492
493
/* Convenience routine for common case where there are two possible keys */
494
int
495
pdfi_dict_get_type2(pdf_context *ctx, pdf_dict *d, const char *Key1, const char *Key2, pdf_obj_type type, pdf_obj **o)
496
0
{
497
0
    int code;
498
499
    /* ISO 32000-2:2020 (PDF 2.0) - abbreviated names take precendence. Assume abbreviated names are shorter :-) */
500
0
    if (strlen(Key1) < strlen(Key2)) {
501
0
        code = pdfi_dict_get_type(ctx, d, Key1, type, o);
502
0
        if (code == gs_error_undefined)
503
0
            code = pdfi_dict_get_type(ctx, d, Key2, type, o);
504
0
    } else {
505
0
        code = pdfi_dict_get_type(ctx, d, Key2, type, o);
506
0
        if (code == gs_error_undefined)
507
0
            code = pdfi_dict_get_type(ctx, d, Key1, type, o);
508
0
    }
509
0
    return code;
510
0
}
511
512
int pdfi_dict_get_type(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj_type type, pdf_obj **o)
513
20.3M
{
514
20.3M
    int code;
515
516
20.3M
    code = pdfi_dict_get(ctx, d, Key, o);
517
20.3M
    if (code < 0)
518
2.00M
        return code;
519
520
18.3M
    if (pdfi_type_of(*o) != type) {
521
18.1k
        pdfi_countdown(*o);
522
18.1k
        *o = NULL;
523
18.1k
        return_error(gs_error_typecheck);
524
18.1k
    }
525
18.3M
    return 0;
526
18.3M
}
527
528
int pdfi_dict_get_type_no_store_R(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj_type type, pdf_obj **o)
529
167
{
530
167
    int code;
531
532
167
    code = pdfi_dict_get_no_store_R(ctx, d, Key, o);
533
167
    if (code < 0)
534
16
        return code;
535
536
151
    if (pdfi_type_of(*o) != type) {
537
0
        pdfi_countdown(*o);
538
0
        *o = NULL;
539
0
        return_error(gs_error_typecheck);
540
0
    }
541
151
    return 0;
542
151
}
543
544
/* Convenience routine for common case where value has two possible keys */
545
int
546
pdfi_dict_get_int2(pdf_context *ctx, pdf_dict *d, const char *Key1,
547
                   const char *Key2, int64_t *i)
548
308k
{
549
308k
    int code;
550
551
    /* ISO 32000-2:2020 (PDF 2.0) - abbreviated names take precendence. Assume abbreviated names are shorter :-) */
552
308k
    if (strlen(Key1) < strlen(Key2)) {
553
0
        code = pdfi_dict_get_int(ctx, d, Key1, i);
554
0
        if (code == gs_error_undefined)
555
0
            code = pdfi_dict_get_int(ctx, d, Key2, i);
556
308k
    } else {
557
308k
        code = pdfi_dict_get_int(ctx, d, Key2, i);
558
308k
        if (code == gs_error_undefined)
559
103k
            code = pdfi_dict_get_int(ctx, d, Key1, i);
560
308k
    }
561
308k
    return code;
562
308k
}
563
564
int pdfi_dict_get_int(pdf_context *ctx, pdf_dict *d, const char *Key, int64_t *i)
565
6.78M
{
566
6.78M
    int code;
567
6.78M
    pdf_obj *n;
568
569
6.78M
    code = pdfi_dict_get(ctx, d, Key, &n);
570
6.78M
    if (code < 0)
571
1.22M
        return code;
572
5.56M
    code = pdfi_obj_to_int(ctx, n, i);
573
5.56M
    pdfi_countdown(n);
574
5.56M
    return code;
575
6.78M
}
576
577
/* Get an int from dict, and if undefined, return provided default */
578
int pdfi_dict_get_int_def(pdf_context *ctx, pdf_dict *d, const char *Key, int64_t *i,
579
                          int64_t def_val)
580
145k
{
581
145k
    int code;
582
583
145k
    code = pdfi_dict_get_int(ctx, d, Key, i);
584
145k
    if (code == gs_error_undefined) {
585
23.9k
        *i = def_val;
586
23.9k
        code = 0;
587
23.9k
    }
588
589
145k
    return code;
590
145k
}
591
592
/* Convenience routine for common case where value has two possible keys */
593
int
594
pdfi_dict_get_bool2(pdf_context *ctx, pdf_dict *d, const char *Key1,
595
                    const char *Key2, bool *val)
596
616k
{
597
616k
    int code;
598
599
    /* ISO 32000-2:2020 (PDF 2.0) - abbreviated names take precendence. Assume abbreviated names are shorter :-) */
600
616k
    if (strlen(Key1) < strlen(Key2)) {
601
0
        code = pdfi_dict_get_bool(ctx, d, Key1, val);
602
0
        if (code == gs_error_undefined)
603
0
            code = pdfi_dict_get_bool(ctx, d, Key2, val);
604
616k
    } else {
605
616k
        code = pdfi_dict_get_bool(ctx, d, Key2, val);
606
616k
        if (code == gs_error_undefined)
607
412k
            code = pdfi_dict_get_bool(ctx, d, Key1, val);
608
616k
    }
609
616k
    return code;
610
616k
}
611
612
int pdfi_dict_get_bool(pdf_context *ctx, pdf_dict *d, const char *Key, bool *val)
613
1.77M
{
614
1.77M
    int code;
615
1.77M
    pdf_obj *b;
616
617
1.77M
    code = pdfi_dict_get(ctx, d, Key, &b);
618
1.77M
    if (code < 0)
619
1.04M
        return code;
620
621
734k
    if (b == PDF_TRUE_OBJ) {
622
384k
        *val = 1;
623
384k
        return 0;
624
384k
    } else if (b == PDF_FALSE_OBJ) {
625
349k
        *val = 0;
626
349k
        return 0;
627
349k
    }
628
629
58
    pdfi_countdown(b);
630
631
58
    *val = 0; /* Be consistent at least! */
632
58
    return_error(gs_error_typecheck);
633
734k
}
634
635
int pdfi_dict_get_number2(pdf_context *ctx, pdf_dict *d, const char *Key1, const char *Key2, double *f)
636
618k
{
637
618k
    int code;
638
639
    /* ISO 32000-2:2020 (PDF 2.0) - abbreviated names take precendence. Assume abbreviated names are shorter :-) */
640
618k
    if (strlen(Key1) < strlen(Key2)) {
641
0
        code = pdfi_dict_get_number(ctx, d, Key1, f);
642
0
        if (code == gs_error_undefined)
643
0
            code = pdfi_dict_get_number(ctx, d, Key2, f);
644
618k
    } else {
645
618k
        code = pdfi_dict_get_number(ctx, d, Key2, f);
646
618k
        if (code == gs_error_undefined)
647
207k
            code = pdfi_dict_get_number(ctx, d, Key1, f);
648
618k
    }
649
618k
    return code;
650
618k
}
651
652
int pdfi_dict_get_number(pdf_context *ctx, pdf_dict *d, const char *Key, double *f)
653
2.71M
{
654
2.71M
    int code;
655
2.71M
    pdf_obj *o;
656
657
2.71M
    code = pdfi_dict_get(ctx, d, Key, &o);
658
2.71M
    if (code < 0)
659
1.09M
        return code;
660
1.62M
    code = pdfi_obj_to_real(ctx, o, f);
661
1.62M
    pdfi_countdown(o);
662
663
1.62M
    return code;
664
2.71M
}
665
666
/* convenience functions for retrieving arrys, see shadings and functions */
667
668
/* The 'fill' versions fill existing arrays, and need a size,
669
 * the 'make' versions allocate memory and fill it. Both varieties return the
670
 * number of entries on success. The fill Matrix utility expects to always
671
 * receive 6 values. The Domain function expects to receive an even number of
672
 * entries and each pair must have the second element larger than the first.
673
 */
674
int fill_domain_from_dict(pdf_context *ctx, float *parray, int size, pdf_dict *dict)
675
19.1k
{
676
19.1k
    int code, i;
677
19.1k
    pdf_array *a = NULL;
678
19.1k
    double f;
679
19.1k
    uint64_t array_size;
680
681
19.1k
    code = pdfi_dict_get(ctx, dict, "Domain", (pdf_obj **)&a);
682
19.1k
    if (code < 0)
683
6.14k
        return code;
684
13.0k
    if (pdfi_type_of(a) != PDF_ARRAY) {
685
0
        pdfi_countdown(a);
686
0
        return_error(gs_error_typecheck);
687
0
    }
688
13.0k
    array_size = pdfi_array_size(a);
689
13.0k
    if (array_size & 1 || array_size > size) {
690
7
        pdfi_countdown(a);
691
7
        return_error(gs_error_rangecheck);
692
7
    }
693
694
39.0k
    for (i=0;i< array_size;i++) {
695
26.0k
        code = pdfi_array_get_number(ctx, a, (uint64_t)i, &f);
696
26.0k
        if (code < 0) {
697
6
            pdfi_countdown(a);
698
6
            return_error(code);
699
6
        }
700
26.0k
        parray[i] = (float)f;
701
26.0k
    }
702
13.0k
    pdfi_countdown(a);
703
13.0k
    return array_size;
704
13.0k
}
705
706
int fill_float_array_from_dict(pdf_context *ctx, float *parray, int size, pdf_dict *dict, const char *Key)
707
20.7k
{
708
20.7k
    int code, i;
709
20.7k
    pdf_array *a = NULL;
710
20.7k
    double f;
711
20.7k
    uint64_t array_size;
712
713
20.7k
    code = pdfi_dict_get(ctx, dict, Key, (pdf_obj **)&a);
714
20.7k
    if (code < 0)
715
22
        return code;
716
20.7k
    if (pdfi_type_of(a) != PDF_ARRAY) {
717
0
        code = gs_note_error(gs_error_typecheck);
718
0
        goto exit;
719
0
    }
720
20.7k
    array_size = pdfi_array_size(a);
721
20.7k
    if (array_size > size) {
722
5
        code = gs_note_error(gs_error_rangecheck);
723
5
        goto exit;
724
5
    }
725
726
113k
    for (i=0; i< array_size; i++) {
727
92.4k
        code = pdfi_array_get_number(ctx, a, (uint64_t)i, &f);
728
92.4k
        if (code < 0)
729
11
            goto exit;
730
92.4k
        parray[i] = (float)f;
731
92.4k
    }
732
20.7k
    code = array_size;
733
20.7k
 exit:
734
20.7k
    pdfi_countdown(a);
735
20.7k
    return code;
736
20.7k
}
737
738
int fill_bool_array_from_dict(pdf_context *ctx, bool *parray, int size, pdf_dict *dict, const char *Key)
739
19.1k
{
740
19.1k
    int code, i;
741
19.1k
    pdf_array *a = NULL;
742
19.1k
    pdf_obj *o;
743
19.1k
    uint64_t array_size;
744
745
19.1k
    code = pdfi_dict_get(ctx, dict, Key, (pdf_obj **)&a);
746
19.1k
    if (code < 0)
747
377
        return code;
748
18.7k
    if (pdfi_type_of(a) != PDF_ARRAY) {
749
0
        pdfi_countdown(a);
750
0
        return_error(gs_error_typecheck);
751
0
    }
752
18.7k
    array_size = pdfi_array_size(a);
753
18.7k
    if (array_size > size)
754
0
        return_error(gs_error_rangecheck);
755
756
56.2k
    for (i=0;i< array_size;i++) {
757
37.5k
        code = pdfi_array_get(ctx, a, (uint64_t)i, (pdf_obj **)&o);
758
37.5k
        if (code < 0) {
759
0
            pdfi_countdown(a);
760
0
            return_error(code);
761
0
        }
762
37.5k
        if (o == PDF_TRUE_OBJ) {
763
36.6k
            parray[i] = 1;
764
36.6k
        } else if (o == PDF_FALSE_OBJ) {
765
914
            parray[i] = 0;
766
914
        } else {
767
7
            pdfi_countdown(o);
768
7
            pdfi_countdown(a);
769
7
            return_error(gs_error_typecheck);
770
7
        }
771
37.5k
    }
772
18.7k
    pdfi_countdown(a);
773
18.7k
    return array_size;
774
18.7k
}
775
776
int fill_matrix_from_dict(pdf_context *ctx, float *parray, pdf_dict *dict)
777
16
{
778
16
    int code, i;
779
16
    pdf_array *a = NULL;
780
16
    double f;
781
16
    uint64_t array_size;
782
783
16
    code = pdfi_dict_get(ctx, dict, "Matrix", (pdf_obj **)&a);
784
16
    if (code < 0)
785
16
        return code;
786
0
    if (pdfi_type_of(a) != PDF_ARRAY) {
787
0
        pdfi_countdown(a);
788
0
        return_error(gs_error_typecheck);
789
0
    }
790
0
    array_size = pdfi_array_size(a);
791
0
    if (array_size != 6) {
792
0
        pdfi_countdown(a);
793
0
        return_error(gs_error_rangecheck);
794
0
    }
795
796
0
    for (i=0; i< array_size; i++) {
797
0
        code = pdfi_array_get_number(ctx, a, (uint64_t)i, &f);
798
0
        if (code < 0) {
799
0
            pdfi_countdown(a);
800
0
            return_error(code);
801
0
        }
802
0
        parray[i] = (float)f;
803
0
    }
804
0
    pdfi_countdown(a);
805
0
    return array_size;
806
0
}
807
808
/* Returns < 0 for error or the number of entries allocated */
809
int pdfi_make_float_array_from_dict(pdf_context *ctx, float **parray, pdf_dict *dict, const char *Key)
810
299k
{
811
299k
    int code, i;
812
299k
    pdf_array *a = NULL;
813
299k
    float *arr = NULL;
814
299k
    double f;
815
299k
    uint64_t array_size;
816
817
299k
    *parray = NULL;
818
819
299k
    code = pdfi_dict_get(ctx, dict, Key, (pdf_obj **)&a);
820
299k
    if (code < 0)
821
58.1k
        return code;
822
241k
    if (pdfi_type_of(a) != PDF_ARRAY) {
823
0
        pdfi_countdown(a);
824
0
        return_error(gs_error_typecheck);
825
0
    }
826
241k
    array_size = pdfi_array_size(a);
827
828
241k
    arr = (float *)gs_alloc_byte_array(ctx->memory, array_size,
829
241k
                                       sizeof(float), "array_from_dict_key");
830
241k
    if (arr == NULL)
831
0
        return_error(gs_error_VMerror);
832
833
241k
    *parray = arr;
834
835
1.02M
    for (i=0;i< array_size;i++) {
836
785k
        code = pdfi_array_get_number(ctx, a, (uint64_t)i, &f);
837
785k
        if (code < 0) {
838
153
            gs_free_const_object(ctx->memory, arr, "float_array");
839
153
            *parray = NULL;
840
153
            pdfi_countdown(a);
841
153
            return_error(code);
842
153
        }
843
785k
        (*parray)[i] = (float)f;
844
785k
    }
845
241k
    pdfi_countdown(a);
846
241k
    return array_size;
847
241k
}
848
849
int pdfi_make_int_array_from_dict(pdf_context *ctx, int **parray, pdf_dict *dict, const char *Key)
850
21.8k
{
851
21.8k
    int code, i;
852
21.8k
    pdf_array *a = NULL;
853
21.8k
    int *arr = NULL;
854
21.8k
    pdf_num *o;
855
21.8k
    uint64_t array_size;
856
857
21.8k
    *parray = NULL;
858
859
21.8k
    code = pdfi_dict_get(ctx, dict, Key, (pdf_obj **)&a);
860
21.8k
    if (code < 0)
861
36
        return code;
862
21.8k
    if (pdfi_type_of(a) != PDF_ARRAY) {
863
0
        pdfi_countdown(a);
864
0
        return_error(gs_error_typecheck);
865
0
    }
866
21.8k
    array_size = pdfi_array_size(a);
867
21.8k
    arr = (int *)gs_alloc_byte_array(ctx->memory, array_size,
868
21.8k
                                     sizeof(int), "array_from_dict_key");
869
21.8k
    if (arr == NULL)
870
0
        return_error(gs_error_VMerror);
871
872
21.8k
    *parray = arr;
873
874
44.6k
    for (i=0;i< array_size;i++) {
875
22.8k
        code = pdfi_array_get_type(ctx, a, (uint64_t)i, PDF_INT, (pdf_obj **)&o);
876
22.8k
        if (code < 0) {
877
58
            gs_free_const_object(ctx->memory, arr, "int_array");
878
58
            *parray = NULL;
879
58
            pdfi_countdown(a);
880
58
            return_error(code);
881
58
        }
882
22.7k
        (*parray)[i] = (int)o->value.i;
883
22.7k
        pdfi_countdown(o);
884
22.7k
    }
885
21.7k
    pdfi_countdown(a);
886
21.7k
    return array_size;
887
21.8k
}
888
889
/* Put into dictionary with key as object -
890
   If the key already exists, we'll only replace it
891
   if "replace" is true.
892
*/
893
int pdfi_dict_put_obj(pdf_context *ctx, pdf_dict *d, pdf_obj *Key, pdf_obj *value, bool replace)
894
43.8M
{
895
43.8M
    int i;
896
43.8M
    pdf_dict_entry *new_list;
897
898
43.8M
    if (pdfi_type_of(d) != PDF_DICT)
899
0
        return_error(gs_error_typecheck);
900
901
43.8M
    if (pdfi_type_of(Key) != PDF_NAME)
902
0
        return_error(gs_error_typecheck);
903
904
    /* First, do we have a Key/value pair already ? */
905
43.8M
    i = pdfi_dict_find_key(ctx, d, (pdf_name *)Key, false);
906
43.8M
    if (i >= 0) {
907
75.1k
        if (d->list[i].value == value || replace == false)
908
            /* We already have this value stored with this key.... */
909
67.6k
            return 0;
910
7.46k
        pdfi_countdown(d->list[i].value);
911
7.46k
        d->list[i].value = value;
912
7.46k
        pdfi_countup(value);
913
7.46k
        return 0;
914
75.1k
    }
915
916
43.7M
    d->is_sorted = false;
917
918
    /* Nope, its a new Key */
919
43.7M
    if (d->size > d->entries) {
920
        /* We have a hole, find and use it */
921
18.7G
        for (i=0;i< d->size;i++) {
922
18.7G
            if (d->list[i].key == NULL) {
923
42.2M
                d->list[i].key = Key;
924
42.2M
                pdfi_countup(Key);
925
42.2M
                d->list[i].value = value;
926
42.2M
                pdfi_countup(value);
927
42.2M
                d->entries++;
928
42.2M
                return 0;
929
42.2M
            }
930
18.7G
        }
931
42.2M
    }
932
933
1.46M
    new_list = (pdf_dict_entry *)gs_alloc_bytes(ctx->memory, (size_t)(d->size + 1) * sizeof(pdf_dict_entry), "pdfi_dict_put reallocate dictionary key/values");
934
1.46M
    if (new_list == NULL) {
935
0
        return_error(gs_error_VMerror);
936
0
    }
937
1.46M
    if (d->size > 0)
938
1.30M
        memcpy(new_list, d->list, d->size * sizeof(pdf_dict_entry));
939
940
1.46M
    gs_free_object(ctx->memory, d->list, "pdfi_dict_put key/value reallocation");
941
942
1.46M
    d->list = new_list;
943
944
1.46M
    d->list[d->size].key = Key;
945
1.46M
    d->list[d->size].value = value;
946
1.46M
    d->size++;
947
1.46M
    d->entries++;
948
1.46M
    pdfi_countup(Key);
949
1.46M
    pdfi_countup(value);
950
951
1.46M
    return 0;
952
1.46M
}
953
954
/*
955
 * Be very cautious using this routine; it does not check to see if a key already exists
956
 * in a dictionary!. This is initially at least intended for use by the font code, to build
957
 * a CharStrings dictionary. We do that by adding each glyph individually with a name
958
 * created from a loop counter, so we know there cannot be any duplicates, and the time
959
 * taken to check that each of 64K names was unique was quite significant.
960
 * See bug #705534, the old PDF interpreter (nullpage, 72 dpi) runs this file in ~20 seconds
961
 * pdfi runs it in around 40 seconds. With this change it runs in around 3 seconds. THis is,
962
 * of course, an extreme example.
963
 */
964
int pdfi_dict_put_unchecked(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj *value)
965
3.27M
{
966
3.27M
    int i, code = 0;
967
3.27M
    pdf_dict_entry *new_list;
968
3.27M
    pdf_obj *key = NULL;
969
970
3.27M
    code = pdfi_name_alloc(ctx, (byte *)Key, strlen(Key), &key);
971
3.27M
    if (code < 0)
972
0
        return code;
973
3.27M
    pdfi_countup(key);
974
975
3.27M
    if (d->size > d->entries) {
976
3.27M
        int search_start = d->entries < 1 ? 0 : d->entries - 1;
977
3.27M
        do {
978
            /* We have a hole, find and use it */
979
6.54M
            for (i = search_start; i < d->size; i++) {
980
6.54M
                if (d->list[i].key == NULL) {
981
3.27M
                    d->list[i].key = key;
982
3.27M
                    d->list[i].value = value;
983
3.27M
                    pdfi_countup(value);
984
3.27M
                    d->entries++;
985
3.27M
                    return 0;
986
3.27M
                }
987
6.54M
            }
988
0
            if (search_start == 0) {
989
                /* This shouldn't ever happen, but just in case.... */
990
0
                break;
991
0
            }
992
0
            search_start = 0;
993
0
        } while(1);
994
3.27M
    }
995
996
0
    new_list = (pdf_dict_entry *)gs_alloc_bytes(ctx->memory, (size_t)(d->size + 1) * sizeof(pdf_dict_entry), "pdfi_dict_put reallocate dictionary key/values");
997
0
    if (new_list == NULL) {
998
0
        return_error(gs_error_VMerror);
999
0
    }
1000
0
    memcpy(new_list, d->list, d->size * sizeof(pdf_dict_entry));
1001
1002
0
    gs_free_object(ctx->memory, d->list, "pdfi_dict_put key/value reallocation");
1003
1004
0
    d->list = new_list;
1005
1006
0
    d->list[d->size].key = key;
1007
0
    d->list[d->size].value = value;
1008
0
    d->size++;
1009
0
    d->entries++;
1010
0
    pdfi_countup(value);
1011
1012
0
    return 0;
1013
0
}
1014
1015
/* Put into dictionary with key as string */
1016
int pdfi_dict_put(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj *value)
1017
2.33M
{
1018
2.33M
    int code;
1019
2.33M
    pdf_obj *key = NULL;
1020
1021
2.33M
    code = pdfi_name_alloc(ctx, (byte *)Key, strlen(Key), &key);
1022
2.33M
    if (code < 0)
1023
0
        return code;
1024
2.33M
    pdfi_countup(key);
1025
1026
2.33M
    code = pdfi_dict_put_obj(ctx, d, key, value, true);
1027
2.33M
    pdfi_countdown(key); /* get rid of extra ref */
1028
2.33M
    return code;
1029
2.33M
}
1030
1031
int pdfi_dict_put_int(pdf_context *ctx, pdf_dict *d, const char *key, int64_t value)
1032
1.98k
{
1033
1.98k
    int code;
1034
1.98k
    pdf_num *obj;
1035
1036
1.98k
    code = pdfi_object_alloc(ctx, PDF_INT, 0, (pdf_obj **)&obj);
1037
1.98k
    if (code < 0)
1038
0
        return code;
1039
1.98k
    obj->value.i = value;
1040
1041
1.98k
    return pdfi_dict_put(ctx, d, key, (pdf_obj *)obj);
1042
1.98k
}
1043
1044
int pdfi_dict_put_bool(pdf_context *ctx, pdf_dict *d, const char *key, bool value)
1045
4.42k
{
1046
4.42k
    pdf_obj *obj = (value ? PDF_TRUE_OBJ : PDF_FALSE_OBJ);
1047
1048
4.42k
    return pdfi_dict_put(ctx, d, key, obj);
1049
4.42k
}
1050
1051
int pdfi_dict_put_name(pdf_context *ctx, pdf_dict *d, const char *key, const char *name)
1052
0
{
1053
0
    int code;
1054
0
    pdf_obj *obj = NULL;
1055
1056
0
    code = pdfi_name_alloc(ctx, (byte *)name, strlen(name), &obj);
1057
0
    if (code < 0)
1058
0
        return code;
1059
0
    pdfi_countup(obj);
1060
1061
0
    code = pdfi_dict_put(ctx, d, key, obj);
1062
0
    pdfi_countdown(obj); /* get rid of extra ref */
1063
0
    return code;
1064
0
}
1065
1066
int pdfi_dict_copy(pdf_context *ctx, pdf_dict *target, pdf_dict *source)
1067
17.7k
{
1068
17.7k
    int i=0, code = 0;
1069
1070
83.8k
    for (i=0;i< source->entries;i++) {
1071
66.1k
        code = pdfi_dict_put_obj(ctx, target, source->list[i].key, source->list[i].value, true);
1072
66.1k
        if (code < 0)
1073
0
            return code;
1074
66.1k
        target->is_sorted = source->is_sorted;
1075
66.1k
    }
1076
17.7k
    return 0;
1077
17.7k
}
1078
1079
int pdfi_dict_known(pdf_context *ctx, pdf_dict *d, const char *Key, bool *known)
1080
52.9M
{
1081
52.9M
    int i;
1082
1083
52.9M
    if (pdfi_type_of(d) != PDF_DICT)
1084
3.06k
        return_error(gs_error_typecheck);
1085
1086
52.9M
    *known = false;
1087
52.9M
    i = pdfi_dict_find(ctx, d, Key, true);
1088
52.9M
    if (i >= 0)
1089
17.7M
        *known = true;
1090
1091
52.9M
    return 0;
1092
52.9M
}
1093
1094
int pdfi_dict_known_by_key(pdf_context *ctx, pdf_dict *d, pdf_name *Key, bool *known)
1095
99.5k
{
1096
99.5k
    int i;
1097
1098
99.5k
    if (pdfi_type_of(d) != PDF_DICT)
1099
0
        return_error(gs_error_typecheck);
1100
1101
99.5k
    *known = false;
1102
99.5k
    i = pdfi_dict_find_key(ctx, d, Key, true);
1103
99.5k
    if (i >= 0)
1104
89.9k
        *known = true;
1105
1106
99.5k
    return 0;
1107
99.5k
}
1108
1109
/* Tests if a Key is present in the dictionary, if it is, retrieves the value associated with the
1110
 * key. Returns < 0 for error, 0 if the key is not found > 0 if the key is present, and initialises
1111
 * the value in the arguments. Since this uses pdf_dict_get(), the returned value has its
1112
 * reference count incremented by 1, just like pdfi_dict_get().
1113
 */
1114
int pdfi_dict_knownget(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj **o)
1115
9.85M
{
1116
9.85M
    bool known = false;
1117
9.85M
    int code;
1118
1119
9.85M
    code = pdfi_dict_known(ctx, d, Key, &known);
1120
9.85M
    if (code < 0)
1121
568
        return code;
1122
1123
9.85M
    if (known == false)
1124
6.49M
        return 0;
1125
1126
3.36M
    code = pdfi_dict_get(ctx, d, Key, o);
1127
3.36M
    if (code < 0)
1128
61.6k
        return code;
1129
1130
3.29M
    return 1;
1131
3.36M
}
1132
1133
/* Like pdfi_dict_knownget() but allows the user to specify a type for the object that we get.
1134
 * returns < 0 for error (including typecheck if the object is not the requested type)
1135
 * 0 if the key is not found, or > 0 if the key was found and returned.
1136
 */
1137
int pdfi_dict_knownget_type(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj_type type, pdf_obj **o)
1138
26.8M
{
1139
26.8M
    bool known = false;
1140
26.8M
    int code;
1141
1142
26.8M
    code = pdfi_dict_known(ctx, d, Key, &known);
1143
26.8M
    if (code < 0)
1144
2.49k
        return code;
1145
1146
26.8M
    if (known == false)
1147
14.3M
        return 0;
1148
1149
12.5M
    code = pdfi_dict_get_type(ctx, d, Key, type, o);
1150
12.5M
    if (code < 0)
1151
319k
        return code;
1152
1153
12.1M
    return 1;
1154
12.5M
}
1155
1156
/* As above but don't store any dereferenced object. Used for Annots when we need the /Parent but
1157
 * storing that back to the annot would create a circulare reference to the page object
1158
 */
1159
int pdfi_dict_knownget_type_no_store_R(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj_type type, pdf_obj **o)
1160
167
{
1161
167
    bool known = false;
1162
167
    int code;
1163
1164
167
    code = pdfi_dict_known(ctx, d, Key, &known);
1165
167
    if (code < 0)
1166
0
        return code;
1167
1168
167
    if (known == false)
1169
0
        return 0;
1170
1171
167
    code = pdfi_dict_get_type_no_store_R(ctx, d, Key, type, o);
1172
167
    if (code < 0)
1173
16
        return code;
1174
1175
151
    return 1;
1176
167
}
1177
1178
int pdfi_dict_knownget_bool(pdf_context *ctx, pdf_dict *d, const char *Key, bool *b)
1179
12.5k
{
1180
12.5k
    bool known = false;
1181
12.5k
    int code;
1182
1183
12.5k
    code = pdfi_dict_known(ctx, d, Key, &known);
1184
12.5k
    if (code < 0)
1185
0
        return code;
1186
1187
12.5k
    if (known == false)
1188
7.23k
        return 0;
1189
1190
5.27k
    code = pdfi_dict_get_bool(ctx, d, Key, b);
1191
5.27k
    if (code < 0)
1192
0
        return code;
1193
1194
5.27k
    return 1;
1195
5.27k
}
1196
1197
/* Like pdfi_dict_knownget_type() but retrieves numbers (two possible types)
1198
 */
1199
int pdfi_dict_knownget_number(pdf_context *ctx, pdf_dict *d, const char *Key, double *f)
1200
2.18M
{
1201
2.18M
    bool known = false;
1202
2.18M
    int code;
1203
1204
2.18M
    code = pdfi_dict_known(ctx, d, Key, &known);
1205
2.18M
    if (code < 0)
1206
0
        return code;
1207
1208
2.18M
    if (known == false)
1209
2.07M
        return 0;
1210
1211
106k
    code = pdfi_dict_get_number(ctx, d, Key, f);
1212
106k
    if (code < 0)
1213
0
        return code;
1214
1215
106k
    return 1;
1216
106k
}
1217
1218
int pdfi_dict_next(pdf_context *ctx, pdf_dict *d, pdf_obj **Key, pdf_obj **Value, uint64_t *index)
1219
1.70M
{
1220
1.70M
    int code;
1221
1222
1.70M
    if (pdfi_type_of(d) != PDF_DICT)
1223
0
        return_error(gs_error_typecheck);
1224
1225
1.70M
    while (1) {
1226
1.70M
        if (*index >= d->entries) {
1227
144k
            *Key = NULL;
1228
144k
            *Value= NULL;
1229
144k
            return gs_error_undefined;
1230
144k
        }
1231
1232
        /* If we find NULL keys skip over them. This should never
1233
         * happen as we check the number of entries above, and we
1234
         * compact dictionaries on deletion of key/value pairs.
1235
         * This is a belt and braces check in case creation of the
1236
         * dictionary somehow ends up with NULL keys in the allocated
1237
         * section.
1238
         */
1239
1.55M
        *Key = d->list[*index].key;
1240
1.55M
        if (*Key == NULL) {
1241
0
            (*index)++;
1242
0
            continue;
1243
0
        }
1244
1245
1.55M
        if (pdfi_type_of(d->list[*index].value) == PDF_INDIRECT) {
1246
514k
            pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[*index].value;
1247
514k
            pdf_obj *o;
1248
1249
514k
            code = pdfi_dereference(ctx, r->ref_object_num, r->ref_generation_num, &o);
1250
514k
            if (code < 0) {
1251
218k
                if (code == gs_error_circular_reference) {
1252
                    /* Replace circular references with NULL objects to prevent future
1253
                     * circular dereferencing.
1254
                     */
1255
201
                    pdfi_countdown(d->list[*index].value);
1256
201
                    d->list[*index].value = PDF_NULL_OBJ;
1257
201
                }
1258
218k
                *Key = *Value = NULL;
1259
218k
                return code;
1260
218k
            }
1261
            /* The file Bug690138.pdf has font dictionaries which contain ToUnicode keys where
1262
             * the value is an indirect reference to the same font object. If we replace the
1263
             * indirect reference in the dictionary with the font dictionary it becomes self
1264
             * referencing and never counts down to 0, leading to a memory leak.
1265
             * This is clearly an error, so flag it and don't replace the indirect reference.
1266
             */
1267
296k
            if ((o) < (pdf_obj *)(uintptr_t)(TOKEN__LAST_KEY)) {
1268
                /* "FAST" object, therefore can't be a problem. */
1269
1.06k
                pdfi_countdown(d->list[*index].value);
1270
1.06k
                d->list[*index].value = o;
1271
295k
            } else if (o->object_num == 0 || o->object_num != d->object_num) {
1272
295k
                pdfi_countdown(d->list[*index].value);
1273
295k
                d->list[*index].value = o;
1274
295k
            } else {
1275
                /* Replace self references with NULL objects to prevent future
1276
                 * circular dereferencing.
1277
                 */
1278
5
                pdfi_countdown(d->list[*index].value);
1279
5
                d->list[*index].value = PDF_NULL_OBJ;
1280
5
                *Key = *Value = NULL;
1281
5
                code = pdfi_set_error_stop(ctx, gs_note_error(gs_error_undefinedresult), NULL, E_DICT_SELF_REFERENCE, "pdfi_dict_next", NULL);
1282
5
                return code;
1283
5
            }
1284
296k
            *Value = o;
1285
296k
            pdfi_countup(*Value);
1286
296k
            break;
1287
1.04M
        } else {
1288
1.04M
            *Value = d->list[*index].value;
1289
1.04M
            pdfi_countup(*Value);
1290
1.04M
            break;
1291
1.04M
        }
1292
1.55M
    }
1293
1294
1.34M
    pdfi_countup(*Key);
1295
1.34M
    (*index)++;
1296
1.34M
    return 0;
1297
1.70M
}
1298
1299
int pdfi_dict_next_no_store_R(pdf_context *ctx, pdf_dict *d, pdf_obj **Key, pdf_obj **Value, uint64_t *index)
1300
411k
{
1301
411k
    int code;
1302
1303
411k
    if (pdfi_type_of(d) != PDF_DICT)
1304
0
        return_error(gs_error_typecheck);
1305
1306
411k
    while (1) {
1307
411k
        if (*index >= d->entries) {
1308
0
            *Key = NULL;
1309
0
            *Value= NULL;
1310
0
            return gs_error_undefined;
1311
0
        }
1312
1313
        /* If we find NULL keys skip over them. This should never
1314
         * happen as we check the number of entries above, and we
1315
         * compact dictionaries on deletion of key/value pairs.
1316
         * This is a belt and braces check in case creation of the
1317
         * dictionary somehow ends up with NULL keys in the allocated
1318
         * section.
1319
         */
1320
411k
        *Key = d->list[*index].key;
1321
411k
        if (*Key == NULL) {
1322
0
            (*index)++;
1323
0
            continue;
1324
0
        }
1325
1326
411k
        if (pdfi_type_of(d->list[*index].value) == PDF_INDIRECT) {
1327
405k
            pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[*index].value;
1328
405k
            pdf_obj *o;
1329
1330
405k
            code = pdfi_dereference(ctx, r->ref_object_num, r->ref_generation_num, &o);
1331
405k
            if (code < 0) {
1332
57.2k
                *Key = *Value = NULL;
1333
57.2k
                return code;
1334
57.2k
            }
1335
348k
            *Value = o;
1336
348k
            break;
1337
405k
        } else {
1338
5.54k
            *Value = d->list[*index].value;
1339
5.54k
            pdfi_countup(*Value);
1340
5.54k
            break;
1341
5.54k
        }
1342
411k
    }
1343
1344
353k
    pdfi_countup(*Key);
1345
353k
    (*index)++;
1346
353k
    return 0;
1347
411k
}
1348
1349
int pdfi_dict_first(pdf_context *ctx, pdf_dict *d, pdf_obj **Key, pdf_obj **Value, uint64_t *index)
1350
551k
{
1351
551k
    uint64_t *i = index;
1352
1353
551k
    *i = 0;
1354
551k
    return pdfi_dict_next(ctx, d, Key, Value, index);
1355
551k
}
1356
1357
int pdfi_dict_first_no_store_R(pdf_context *ctx, pdf_dict *d, pdf_obj **Key, pdf_obj **Value, uint64_t *index)
1358
190k
{
1359
190k
    uint64_t *i = index;
1360
1361
190k
    *i = 0;
1362
190k
    return pdfi_dict_next_no_store_R(ctx, d, Key, Value, index);
1363
190k
}
1364
1365
int pdfi_dict_key_next(pdf_context *ctx, pdf_dict *d, pdf_obj **Key, uint64_t *index)
1366
67.8M
{
1367
67.8M
    uint64_t *i = index;
1368
1369
67.8M
    if (pdfi_type_of(d) != PDF_DICT)
1370
0
        return_error(gs_error_typecheck);
1371
1372
67.8M
    while (1) {
1373
67.8M
        if (*i >= d->entries) {
1374
105k
            *Key = NULL;
1375
105k
            return gs_error_undefined;
1376
105k
        }
1377
1378
67.7M
        *Key = d->list[*i].key;
1379
67.7M
        if (*Key == NULL) {
1380
0
            (*i)++;
1381
0
            continue;
1382
0
        }
1383
67.7M
        pdfi_countup(*Key);
1384
67.7M
        (*i)++;
1385
67.7M
        break;
1386
67.7M
    }
1387
67.7M
    return 0;
1388
67.8M
}
1389
1390
int pdfi_dict_key_first(pdf_context *ctx, pdf_dict *d, pdf_obj **Key, uint64_t *index)
1391
421k
{
1392
421k
    uint64_t *i = index;
1393
1394
421k
    *i = 0;
1395
421k
    return pdfi_dict_key_next(ctx, d, Key, index);
1396
421k
}
1397
1398
int pdfi_merge_dicts(pdf_context *ctx, pdf_dict *target, pdf_dict *source)
1399
204k
{
1400
204k
    int i, code;
1401
204k
    bool known = false;
1402
1403
303k
    for (i=0;i< source->entries;i++) {
1404
98.9k
        code = pdfi_dict_known_by_key(ctx, target, (pdf_name *)source->list[i].key, &known);
1405
98.9k
        if (code < 0)
1406
0
            return code;
1407
98.9k
        if (!known) {
1408
9.15k
            code = pdfi_dict_put_obj(ctx, target, source->list[i].key, source->list[i].value, true);
1409
9.15k
            if (code < 0)
1410
0
                return code;
1411
9.15k
        }
1412
98.9k
    }
1413
204k
    target->is_sorted = false;
1414
204k
    return 0;
1415
204k
}
1416
1417
/* Return Length of a stream, or 0 if it's not a stream
1418
 * Caches the Length
1419
 */
1420
int64_t pdfi_stream_length(pdf_context *ctx, pdf_stream *stream)
1421
466k
{
1422
466k
    int64_t Length = 0;
1423
466k
    int code;
1424
1425
466k
    if (pdfi_type_of(stream) != PDF_STREAM)
1426
0
        return 0;
1427
1428
466k
    if (stream->length_valid)
1429
254k
        return stream->Length;
1430
1431
211k
    code = pdfi_dict_get_int(ctx, stream->stream_dict, "Length", &Length);
1432
211k
    if (code < 0)
1433
210k
        Length = 0;
1434
1435
    /* Make sure Length is not negative... */
1436
211k
    if (Length < 0)
1437
0
        Length = 0;
1438
1439
    /* Cache it */
1440
211k
    stream->Length = Length;
1441
211k
    stream->length_valid = true;
1442
1443
211k
    return 0;
1444
466k
}
1445
1446
/* Safely get offset from a stream object.
1447
 * If it's not actually a stream, just return 0.
1448
 */
1449
gs_offset_t pdfi_stream_offset(pdf_context *ctx, pdf_stream *stream)
1450
2.70M
{
1451
2.70M
    if (pdfi_type_of(stream) != PDF_STREAM)
1452
78
        return 0;
1453
2.70M
    return stream->stream_offset;
1454
2.70M
}
1455
1456
pdf_stream *pdfi_stream_parent(pdf_context *ctx, pdf_stream *stream)
1457
919k
{
1458
919k
    if (pdfi_type_of(stream) != PDF_STREAM)
1459
42.7k
        return 0;
1460
876k
    return (pdf_stream *)stream->parent_obj;
1461
919k
}
1462
1463
void pdfi_set_stream_parent(pdf_context *ctx, pdf_stream *stream, pdf_stream *parent)
1464
488k
{
1465
    /* Ordinarily we would increment the reference count of the parent object here,
1466
     * because we are taking a new reference to it. But if we do that we will end up
1467
     * with circular references and will never count down and release the objects.
1468
     * This is because the parent object must have a Resources dictionary which
1469
     * references this stream, when we dereference the stream we store it in the
1470
     * Parent's Resources dictionary. So the parent points to the child, the child
1471
     * points to the parent and we always end up with a refcnt for each of 1. Since we
1472
     * only ever consult parent_obj in an illegal case we deal with this by not
1473
     * incrementing the reference count. To try and avoid any dangling references
1474
     * we clear the parent_obj when we finish executing the stream in
1475
     * pdfi_interpret_content_stream.
1476
     */
1477
488k
    stream->parent_obj = (pdf_obj *)parent;
1478
488k
}
1479
1480
void pdfi_clear_stream_parent(pdf_context *ctx, pdf_stream *stream)
1481
488k
{
1482
488k
    stream->parent_obj = NULL;
1483
488k
}
1484
1485
/* Get the dict from a pdf_obj, returns typecheck if it doesn't have one */
1486
int pdfi_dict_from_obj(pdf_context *ctx, pdf_obj *obj, pdf_dict **dict)
1487
88.9M
{
1488
88.9M
    *dict = NULL;
1489
88.9M
    switch (pdfi_type_of(obj)) {
1490
198k
        case PDF_DICT:
1491
198k
            *dict = (pdf_dict *)obj;
1492
198k
            break;
1493
88.7M
        case PDF_STREAM:
1494
88.7M
            *dict = ((pdf_stream *)obj)->stream_dict;
1495
88.7M
            break;
1496
649
        default:
1497
649
            return_error(gs_error_typecheck);
1498
88.9M
    }
1499
88.9M
    return 0;
1500
88.9M
}