Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/pdf/pdf_dict.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2018-2022 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
/* 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
6.76M
{
32
6.76M
    pdf_dict *d = (pdf_dict *)o;
33
6.76M
    int i;
34
#if DEBUG_DICT
35
    pdf_name *name;
36
#endif
37
38
55.5M
    for (i=0;i < d->entries;i++) {
39
#if DEBUG_DICT
40
        name = (pdf_name *)d->list[i].key;
41
#endif
42
48.8M
        if (d->list[i].value != NULL)
43
48.6M
            pdfi_countdown(d->list[i].value);
44
48.8M
        if (d->list[i].key != NULL)
45
48.6M
            pdfi_countdown(d->list[i].key);
46
48.8M
    }
47
6.76M
    gs_free_object(OBJ_MEMORY(d), d->list, "pdf interpreter free dictionary key/values");
48
6.76M
    gs_free_object(OBJ_MEMORY(d), d, "pdf interpreter free dictionary");
49
6.76M
}
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
168k
{
55
168k
    int i = 0;
56
#if DEBUG_DICT
57
    pdf_name *name;
58
#endif
59
60
168k
    if (n != NULL)
61
70.1k
        i = pdfi_dict_find_key(ctx, d, (const pdf_name *)n, false);
62
98.8k
    else
63
98.8k
        i = pdfi_dict_find(ctx, d, str, false);
64
65
168k
    if (i < 0)
66
2
        return i;
67
68
168k
    pdfi_countdown(d->list[i].key);
69
168k
    pdfi_countdown(d->list[i].value);
70
168k
    d->entries--;
71
168k
    if (i != d->entries)
72
78.2k
        memmove(&d->list[i], &d->list[i+1], (d->entries - i) * sizeof(d->list[0]));
73
168k
    d->list[d->entries].key = NULL;
74
168k
    d->list[d->entries].value = NULL;
75
168k
    d->is_sorted = false;
76
168k
    return 0;
77
168k
}
78
79
int pdfi_dict_delete_pair(pdf_context *ctx, pdf_dict *d, pdf_name *n)
80
70.1k
{
81
70.1k
    return pdfi_dict_delete_inner(ctx, d, n, NULL);
82
70.1k
}
83
84
int pdfi_dict_delete(pdf_context *ctx, pdf_dict *d, const char *str)
85
98.8k
{
86
98.8k
    return pdfi_dict_delete_inner(ctx, d, NULL, str);
87
98.8k
}
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
6.76M
{
96
6.76M
    *d = NULL;
97
6.76M
    return pdfi_object_alloc(ctx, PDF_DICT, size, (pdf_obj **)d);
98
6.76M
}
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
6.41M
{
112
6.41M
    uint64_t index = 0;
113
6.41M
    pdf_dict *d = NULL;
114
6.41M
    uint64_t i = 0;
115
6.41M
    int code;
116
#if DEBUG_DICT
117
    pdf_name *key;
118
#endif
119
120
6.41M
    code = pdfi_count_to_mark(ctx, &index);
121
6.41M
    if (code < 0) {
122
60.8k
        pdfi_clear_to_mark(ctx);
123
60.8k
        return code;
124
60.8k
    }
125
126
6.35M
    if (index & 1) {
127
48.1k
        pdfi_clear_to_mark(ctx);
128
48.1k
        return_error(gs_error_rangecheck);
129
48.1k
    }
130
131
6.30M
    code = pdfi_dict_alloc(ctx, index >> 1, &d);
132
6.30M
    if (code < 0) {
133
0
        pdfi_clear_to_mark(ctx);
134
0
        return code;
135
0
    }
136
137
6.30M
    d->entries = d->size;
138
139
37.1M
    while (index) {
140
30.8M
        i = (index / 2) - 1;
141
142
        /* In PDF keys are *required* to be names, so we ought to check that here */
143
30.8M
        if (pdfi_type_of((pdf_obj *)ctx->stack_top[-2]) == PDF_NAME) {
144
30.8M
            d->list[i].key = ctx->stack_top[-2];
145
30.8M
            pdfi_countup(d->list[i].key);
146
#if DEBUG_DICT
147
            key = (pdf_name *)d->list[i].key;
148
#endif
149
30.8M
            d->list[i].value = ctx->stack_top[-1];
150
30.8M
            pdfi_countup(d->list[i].value);
151
30.8M
        } else {
152
17.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
17.1k
            else {
165
17.1k
                pdfi_free_dict((pdf_obj *)d);
166
17.1k
                pdfi_clear_to_mark(ctx);
167
17.1k
                return_error(gs_error_typecheck);
168
17.1k
            }
169
17.1k
        }
170
171
30.8M
        pdfi_pop(ctx, 2);
172
30.8M
        index -= 2;
173
30.8M
    }
174
175
6.29M
    code = pdfi_clear_to_mark(ctx);
176
6.29M
    if (code < 0) {
177
0
        pdfi_free_dict((pdf_obj *)d);
178
0
        return code;
179
0
    }
180
181
6.29M
    if (ctx->args.pdfdebug)
182
6.29M
        dmprintf (ctx->memory, "\n >>\n");
183
184
6.29M
    d->indirect_num = indirect_num;
185
6.29M
    d->indirect_gen = indirect_gen;
186
187
6.29M
    code = pdfi_push(ctx, (pdf_obj *)d);
188
6.29M
    if (code < 0)
189
0
        pdfi_free_dict((pdf_obj *)d);
190
191
6.29M
    return code;
192
6.29M
}
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
211k
{
199
211k
    int code;
200
201
211k
    code = pdfi_dict_get(ctx, d, Key1, o);
202
211k
    if (code == gs_error_undefined)
203
113k
        code = pdfi_dict_get(ctx, d, Key2, o);
204
211k
    return code;
205
211k
}
206
207
static int pdfi_dict_compare_entry(const void *a, const void *b)
208
439M
{
209
439M
    pdf_name *key_a = (pdf_name *)((pdf_dict_entry *)a)->key, *key_b = (pdf_name *)((pdf_dict_entry *)b)->key;
210
211
439M
    if (key_a == NULL) {
212
194k
        if (key_b == NULL)
213
194k
            return 0;
214
0
        else
215
0
            return 1;
216
194k
    }
217
218
439M
    if (key_b == NULL)
219
40.9k
        return -1;
220
221
439M
    if (key_a->length != key_b->length)
222
141M
        return key_a->length - key_b->length;
223
224
297M
    return strncmp((const char *)key_a->data, (const char *)key_b->data, key_a->length);
225
439M
}
226
227
static int pdfi_dict_find_sorted(pdf_context *ctx, pdf_dict *d, const char *Key)
228
32.7M
{
229
32.7M
    int start = 0, end = d->size - 1, middle = 0, keylen = strlen(Key);
230
32.7M
    pdf_name *test_key;
231
232
281M
    while (start <= end) {
233
280M
        middle = start + (end - start) / 2;
234
280M
        test_key = (pdf_name *)d->list[middle].key;
235
236
        /* Sorting pushes unused key/values (NULL) to the end of the dictionary */
237
280M
        if (test_key == NULL) {
238
308k
            end = middle - 1;
239
308k
            continue;
240
308k
        }
241
242
280M
        if (test_key->length == keylen) {
243
181M
            int result = strncmp((const char *)test_key->data, Key, keylen);
244
245
181M
            if (result == 0)
246
31.5M
                return middle;
247
149M
            if (result < 0)
248
79.2M
                start = middle + 1;
249
70.2M
            else
250
70.2M
                end = middle - 1;
251
149M
        } else {
252
99.3M
            if (test_key->length < keylen)
253
39.4M
                start = middle + 1;
254
59.9M
            else
255
59.9M
                end = middle -1;
256
99.3M
        }
257
280M
    }
258
1.14M
    return gs_note_error(gs_error_undefined);
259
32.7M
}
260
261
static int pdfi_dict_find_unsorted(pdf_context *ctx, pdf_dict *d, const char *Key)
262
72.5M
{
263
72.5M
    int i;
264
72.5M
    pdf_name *t;
265
266
7.05G
    for (i=0;i< d->entries;i++) {
267
7.01G
        t = (pdf_name *)d->list[i].key;
268
269
7.01G
        if (t && pdfi_type_of(t) == PDF_NAME) {
270
7.01G
            if (pdfi_name_is((pdf_name *)t, Key)) {
271
31.9M
                return i;
272
31.9M
            }
273
7.01G
        }
274
7.01G
    }
275
72.5M
    return_error(gs_error_undefined);
276
72.5M
}
277
278
static int pdfi_dict_find(pdf_context *ctx, pdf_dict *d, const char *Key, bool sort)
279
105M
{
280
105M
    if (!d->is_sorted) {
281
72.6M
        if (d->entries > 32 && sort) {
282
127k
            qsort(d->list, d->size, sizeof(pdf_dict_entry), pdfi_dict_compare_entry);
283
127k
            d->is_sorted = true;
284
127k
            return pdfi_dict_find_sorted(ctx, d, Key);
285
127k
        } else
286
72.5M
            return pdfi_dict_find_unsorted(ctx, d, Key);
287
72.6M
    } else
288
32.5M
        return pdfi_dict_find_sorted(ctx, d, Key);
289
105M
}
290
291
static int pdfi_dict_find_key(pdf_context *ctx, pdf_dict *d, const pdf_name *Key, bool sort)
292
52.3M
{
293
52.3M
    char *Test = NULL;
294
52.3M
    int index = 0;
295
296
52.3M
    Test = (char *)gs_alloc_bytes(ctx->memory, Key->length + 1, "pdfi_dict_find_key");
297
52.3M
    if (Test == NULL)
298
0
        return_error(gs_error_VMerror);
299
300
52.3M
    memcpy(Test, Key->data, Key->length);
301
52.3M
    Test[Key->length] = 0x00;
302
303
52.3M
    index = pdfi_dict_find(ctx, d, Test, sort);
304
305
52.3M
    gs_free_object(ctx->memory, Test, "pdfi_dict_find_key");
306
52.3M
    return index;
307
52.3M
}
308
309
/* The object returned by pdfi_dict_get has its reference count incremented by 1 to
310
 * indicate the reference now held by the caller, in **o.
311
 */
312
int pdfi_dict_get_common(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj **o, bool cache)
313
21.7M
{
314
21.7M
    int index = 0, code = 0;
315
316
21.7M
    *o = NULL;
317
318
21.7M
    if (pdfi_type_of(d) != PDF_DICT)
319
10
        return_error(gs_error_typecheck);
320
321
21.7M
    index = pdfi_dict_find(ctx, d, Key, true);
322
21.7M
    if (index < 0)
323
2.35M
        return index;
324
325
19.4M
    if (pdfi_type_of(d->list[index].value) == PDF_INDIRECT) {
326
843k
        pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[index].value;
327
328
843k
        if (r->ref_object_num == d->object_num)
329
192
            return_error(gs_error_circular_reference);
330
331
843k
        if (cache)
332
843k
            code = pdfi_deref_loop_detect(ctx, r->ref_object_num, r->ref_generation_num, o);
333
0
        else
334
0
            code = pdfi_deref_loop_detect_nocache(ctx, r->ref_object_num, r->ref_generation_num, o);
335
843k
        if (code < 0)
336
158k
            return code;
337
        /* The file Bug690138.pdf has font dictionaries which contain ToUnicode keys where
338
         * the value is an indirect reference to the same font object. If we replace the
339
         * indirect reference in the dictionary with the font dictionary it becomes self
340
         * referencing and never counts down to 0, leading to a memory leak.
341
         * This is clearly an error, so flag it and don't replace the indirect reference.
342
         */
343
684k
        if ((*o) < (pdf_obj *)(uintptr_t)(TOKEN__LAST_KEY)) {
344
            /* "FAST" object, therefore can't be a problem. */
345
215
            pdfi_countdown(d->list[index].value);
346
215
            d->list[index].value = *o;
347
684k
        } else if ((*o)->object_num == 0 || (*o)->object_num != d->object_num) {
348
684k
            pdfi_countdown(d->list[index].value);
349
684k
            d->list[index].value = *o;
350
684k
        } else {
351
0
            pdfi_set_error(ctx, 0, NULL, E_DICT_SELF_REFERENCE, "pdfi_dict_get", NULL);
352
0
            return 0;
353
0
        }
354
684k
    }
355
19.2M
    *o = d->list[index].value;
356
19.2M
    pdfi_countup(*o);
357
358
19.2M
    return code;
359
19.4M
}
360
361
/* Get object from dict without resolving indirect references
362
 * Will inc refcnt by 1
363
 */
364
int pdfi_dict_get_no_deref(pdf_context *ctx, pdf_dict *d, const pdf_name *Key, pdf_obj **o)
365
503k
{
366
503k
    int index=0;
367
368
503k
    *o = NULL;
369
370
503k
    if (pdfi_type_of(d) != PDF_DICT)
371
0
        return_error(gs_error_typecheck);
372
373
503k
    index = pdfi_dict_find_key(ctx, d, Key, true);
374
503k
    if (index < 0)
375
0
        return index;
376
377
503k
    *o = d->list[index].value;
378
503k
    pdfi_countup(*o);
379
503k
    return 0;
380
503k
}
381
382
/* Get by pdf_name rather than by char *
383
 * The object returned by pdfi_dict_get has its reference count incremented by 1 to
384
 * indicate the reference now held by the caller, in **o.
385
 */
386
int pdfi_dict_get_by_key(pdf_context *ctx, pdf_dict *d, const pdf_name *Key, pdf_obj **o)
387
32.8M
{
388
32.8M
    int index=0, code = 0;
389
390
32.8M
    *o = NULL;
391
392
32.8M
    if (pdfi_type_of(d) != PDF_DICT)
393
32
        return_error(gs_error_typecheck);
394
395
32.8M
    index = pdfi_dict_find_key(ctx, d, Key, true);
396
32.8M
    if (index < 0)
397
909k
        return index;
398
399
31.9M
    if (pdfi_type_of(d->list[index].value) == PDF_INDIRECT) {
400
35.3k
        pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[index].value;
401
402
35.3k
        code = pdfi_deref_loop_detect(ctx, r->ref_object_num, r->ref_generation_num, o);
403
35.3k
        if (code < 0)
404
6.01k
            return code;
405
29.2k
        pdfi_countdown(d->list[index].value);
406
29.2k
        d->list[index].value = *o;
407
29.2k
    }
408
31.8M
    *o = d->list[index].value;
409
31.8M
    pdfi_countup(*o);
410
31.8M
    return 0;
411
31.9M
}
412
413
/* Get indirect reference without de-referencing it */
414
int pdfi_dict_get_ref(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_indirect_ref **o)
415
0
{
416
0
    int index=0;
417
418
0
    *o = NULL;
419
420
0
    if (pdfi_type_of(d) != PDF_DICT)
421
0
        return_error(gs_error_typecheck);
422
423
0
    index = pdfi_dict_find(ctx, d, Key, true);
424
0
    if (index < 0)
425
0
        return index;
426
427
0
    if (pdfi_type_of(d->list[index].value) == PDF_INDIRECT) {
428
0
        *o = (pdf_indirect_ref *)d->list[index].value;
429
0
        pdfi_countup(*o);
430
0
        return 0;
431
0
    } else {
432
0
        return_error(gs_error_typecheck);
433
0
    }
434
0
}
435
436
/* As per pdfi_dict_get(), but doesn't replace an indirect reference in a dictionary with a
437
 * new object. This is for Resources following, such as Do, where we will have to seek and
438
 * read the indirect object anyway, and we need to ensure that Form XObjects (for example)
439
 * don't have circular calls.
440
 *
441
 * Takes either strKey or nameKey param. Other will be NULL.
442
 */
443
static int pdfi_dict_get_no_store_R_inner(pdf_context *ctx, pdf_dict *d, const char *strKey,
444
                                          const pdf_name *nameKey, pdf_obj **o)
445
1.55M
{
446
1.55M
    int index=0, code = 0;
447
448
1.55M
    *o = NULL;
449
450
1.55M
    if (pdfi_type_of(d) != PDF_DICT)
451
0
        return_error(gs_error_typecheck);
452
453
1.55M
    if (strKey == NULL)
454
1.00M
        index = pdfi_dict_find_key(ctx, d, nameKey, true);
455
547k
    else
456
547k
        index = pdfi_dict_find(ctx, d, strKey, true);
457
458
1.55M
    if (index < 0)
459
128k
        return index;
460
461
1.42M
    if (pdfi_type_of(d->list[index].value) == PDF_INDIRECT) {
462
1.29M
        pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[index].value;
463
464
1.29M
        code = pdfi_dereference(ctx, r->ref_object_num, r->ref_generation_num, o);
465
1.29M
        if (code < 0)
466
265k
            return code;
467
1.29M
    } else {
468
129k
        *o = d->list[index].value;
469
129k
        pdfi_countup(*o);
470
129k
    }
471
1.15M
    return 0;
472
1.42M
}
473
474
/* Wrapper to pdfi_dict_no_store_R_inner(), takes a char * as Key */
475
int pdfi_dict_get_no_store_R(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj **o)
476
547k
{
477
547k
    return pdfi_dict_get_no_store_R_inner(ctx, d, Key, NULL, o);
478
547k
}
479
480
/* Wrapper to pdfi_dict_no_store_R_inner(), takes a pdf_name * as Key */
481
int pdfi_dict_get_no_store_R_key(pdf_context *ctx, pdf_dict *d, const pdf_name *Key, pdf_obj **o)
482
1.00M
{
483
1.00M
    return pdfi_dict_get_no_store_R_inner(ctx, d, NULL, Key, o);
484
1.00M
}
485
486
/* Convenience routine for common case where there are two possible keys */
487
int
488
pdfi_dict_get_type2(pdf_context *ctx, pdf_dict *d, const char *Key1, const char *Key2, pdf_obj_type type, pdf_obj **o)
489
0
{
490
0
    int code;
491
492
0
    code = pdfi_dict_get_type(ctx, d, Key1, type, o);
493
0
    if (code == gs_error_undefined)
494
0
        code = pdfi_dict_get_type(ctx, d, Key2, type, o);
495
0
    return code;
496
0
}
497
498
int pdfi_dict_get_type(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj_type type, pdf_obj **o)
499
10.2M
{
500
10.2M
    int code;
501
502
10.2M
    code = pdfi_dict_get(ctx, d, Key, o);
503
10.2M
    if (code < 0)
504
732k
        return code;
505
506
9.53M
    if (pdfi_type_of(*o) != type) {
507
38.9k
        pdfi_countdown(*o);
508
38.9k
        *o = NULL;
509
38.9k
        return_error(gs_error_typecheck);
510
38.9k
    }
511
9.49M
    return 0;
512
9.53M
}
513
514
/* Convenience routine for common case where value has two possible keys */
515
int
516
pdfi_dict_get_int2(pdf_context *ctx, pdf_dict *d, const char *Key1,
517
                   const char *Key2, int64_t *i)
518
52.8k
{
519
52.8k
    int code;
520
521
52.8k
    code = pdfi_dict_get_int(ctx, d, Key1, i);
522
52.8k
    if (code == gs_error_undefined)
523
8.23k
        code = pdfi_dict_get_int(ctx, d, Key2, i);
524
52.8k
    return code;
525
52.8k
}
526
527
int pdfi_dict_get_int(pdf_context *ctx, pdf_dict *d, const char *Key, int64_t *i)
528
4.97M
{
529
4.97M
    int code;
530
4.97M
    pdf_obj *n;
531
532
4.97M
    code = pdfi_dict_get(ctx, d, Key, &n);
533
4.97M
    if (code < 0)
534
215k
        return code;
535
4.75M
    code = pdfi_obj_to_int(ctx, n, i);
536
4.75M
    pdfi_countdown(n);
537
4.75M
    return code;
538
4.97M
}
539
540
/* Get an int from dict, and if undefined, return provided default */
541
int pdfi_dict_get_int_def(pdf_context *ctx, pdf_dict *d, const char *Key, int64_t *i,
542
                          int64_t def_val)
543
54.8k
{
544
54.8k
    int code;
545
546
54.8k
    code = pdfi_dict_get_int(ctx, d, Key, i);
547
54.8k
    if (code == gs_error_undefined) {
548
12.4k
        *i = def_val;
549
12.4k
        code = 0;
550
12.4k
    }
551
552
54.8k
    return code;
553
54.8k
}
554
555
/* Convenience routine for common case where value has two possible keys */
556
int
557
pdfi_dict_get_bool2(pdf_context *ctx, pdf_dict *d, const char *Key1,
558
                    const char *Key2, bool *val)
559
105k
{
560
105k
    int code;
561
562
105k
    code = pdfi_dict_get_bool(ctx, d, Key1, val);
563
105k
    if (code == gs_error_undefined)
564
83.8k
        code = pdfi_dict_get_bool(ctx, d, Key2, val);
565
105k
    return code;
566
105k
}
567
568
int pdfi_dict_get_bool(pdf_context *ctx, pdf_dict *d, const char *Key, bool *val)
569
690k
{
570
690k
    int code;
571
690k
    pdf_obj *b;
572
573
690k
    code = pdfi_dict_get(ctx, d, Key, &b);
574
690k
    if (code < 0)
575
330k
        return code;
576
577
360k
    if (b == PDF_TRUE_OBJ) {
578
122k
        *val = 1;
579
122k
        return 0;
580
237k
    } else if (b == PDF_FALSE_OBJ) {
581
237k
        *val = 0;
582
237k
        return 0;
583
237k
    }
584
585
214
    pdfi_countdown(b);
586
587
214
    *val = 0; /* Be consistent at least! */
588
214
    return_error(gs_error_typecheck);
589
360k
}
590
591
int pdfi_dict_get_number2(pdf_context *ctx, pdf_dict *d, const char *Key1, const char *Key2, double *f)
592
105k
{
593
105k
    int code;
594
595
105k
    code = pdfi_dict_get_number(ctx, d, Key1, f);
596
105k
    if (code == gs_error_undefined)
597
14.0k
        code = pdfi_dict_get_number(ctx, d, Key2, f);
598
105k
    return code;
599
105k
}
600
601
int pdfi_dict_get_number(pdf_context *ctx, pdf_dict *d, const char *Key, double *f)
602
955k
{
603
955k
    int code;
604
955k
    pdf_obj *o;
605
606
955k
    code = pdfi_dict_get(ctx, d, Key, &o);
607
955k
    if (code < 0)
608
315k
        return code;
609
639k
    code = pdfi_obj_to_real(ctx, o, f);
610
639k
    pdfi_countdown(o);
611
612
639k
    return code;
613
955k
}
614
615
/* convenience functions for retrieving arrys, see shadings and functions */
616
617
/* The 'fill' versions fill existing arrays, and need a size,
618
 * the 'make' versions allocate memory and fill it. Both varieties return the
619
 * number of entries on success. The fill Matrix utility expects to always
620
 * receive 6 values. The Domain function expects to receive an even number of
621
 * entries and each pair must have the second element larger than the first.
622
 */
623
int fill_domain_from_dict(pdf_context *ctx, float *parray, int size, pdf_dict *dict)
624
14.3k
{
625
14.3k
    int code, i;
626
14.3k
    pdf_array *a = NULL;
627
14.3k
    double f;
628
14.3k
    uint64_t array_size;
629
630
14.3k
    code = pdfi_dict_get(ctx, dict, "Domain", (pdf_obj **)&a);
631
14.3k
    if (code < 0)
632
6.74k
        return code;
633
7.62k
    if (pdfi_type_of(a) != PDF_ARRAY) {
634
0
        pdfi_countdown(a);
635
0
        return_error(gs_error_typecheck);
636
0
    }
637
7.62k
    array_size = pdfi_array_size(a);
638
7.62k
    if (array_size & 1 || array_size > size) {
639
1
        pdfi_countdown(a);
640
1
        return_error(gs_error_rangecheck);
641
1
    }
642
643
22.8k
    for (i=0;i< array_size;i++) {
644
15.2k
        code = pdfi_array_get_number(ctx, a, (uint64_t)i, &f);
645
15.2k
        if (code < 0) {
646
0
            pdfi_countdown(a);
647
0
            return_error(code);
648
0
        }
649
15.2k
        parray[i] = (float)f;
650
15.2k
    }
651
7.62k
    pdfi_countdown(a);
652
7.62k
    return array_size;
653
7.62k
}
654
655
int fill_float_array_from_dict(pdf_context *ctx, float *parray, int size, pdf_dict *dict, const char *Key)
656
14.9k
{
657
14.9k
    int code, i;
658
14.9k
    pdf_array *a = NULL;
659
14.9k
    double f;
660
14.9k
    uint64_t array_size;
661
662
14.9k
    code = pdfi_dict_get(ctx, dict, Key, (pdf_obj **)&a);
663
14.9k
    if (code < 0)
664
2
        return code;
665
14.9k
    if (pdfi_type_of(a) != PDF_ARRAY) {
666
0
        code = gs_note_error(gs_error_typecheck);
667
0
        goto exit;
668
0
    }
669
14.9k
    array_size = pdfi_array_size(a);
670
14.9k
    if (array_size > size) {
671
0
        code = gs_note_error(gs_error_rangecheck);
672
0
        goto exit;
673
0
    }
674
675
78.1k
    for (i=0; i< array_size; i++) {
676
63.1k
        code = pdfi_array_get_number(ctx, a, (uint64_t)i, &f);
677
63.1k
        if (code < 0)
678
2
            goto exit;
679
63.1k
        parray[i] = (float)f;
680
63.1k
    }
681
14.9k
    code = array_size;
682
14.9k
 exit:
683
14.9k
    pdfi_countdown(a);
684
14.9k
    return code;
685
14.9k
}
686
687
int fill_bool_array_from_dict(pdf_context *ctx, bool *parray, int size, pdf_dict *dict, const char *Key)
688
14.3k
{
689
14.3k
    int code, i;
690
14.3k
    pdf_array *a = NULL;
691
14.3k
    pdf_obj *o;
692
14.3k
    uint64_t array_size;
693
694
14.3k
    code = pdfi_dict_get(ctx, dict, Key, (pdf_obj **)&a);
695
14.3k
    if (code < 0)
696
83
        return code;
697
14.2k
    if (pdfi_type_of(a) != PDF_ARRAY) {
698
1
        pdfi_countdown(a);
699
1
        return_error(gs_error_typecheck);
700
1
    }
701
14.2k
    array_size = pdfi_array_size(a);
702
14.2k
    if (array_size > size)
703
0
        return_error(gs_error_rangecheck);
704
705
42.8k
    for (i=0;i< array_size;i++) {
706
28.5k
        code = pdfi_array_get(ctx, a, (uint64_t)i, (pdf_obj **)&o);
707
28.5k
        if (code < 0) {
708
0
            pdfi_countdown(a);
709
0
            return_error(code);
710
0
        }
711
28.5k
        if (o == PDF_TRUE_OBJ) {
712
28.3k
            parray[i] = 1;
713
28.3k
        } else if (o == PDF_FALSE_OBJ) {
714
157
            parray[i] = 0;
715
157
        } else {
716
0
            pdfi_countdown(o);
717
0
            pdfi_countdown(a);
718
0
            return_error(gs_error_typecheck);
719
0
        }
720
28.5k
    }
721
14.2k
    pdfi_countdown(a);
722
14.2k
    return array_size;
723
14.2k
}
724
725
int fill_matrix_from_dict(pdf_context *ctx, float *parray, pdf_dict *dict)
726
1
{
727
1
    int code, i;
728
1
    pdf_array *a = NULL;
729
1
    double f;
730
1
    uint64_t array_size;
731
732
1
    code = pdfi_dict_get(ctx, dict, "Matrix", (pdf_obj **)&a);
733
1
    if (code < 0)
734
1
        return code;
735
0
    if (pdfi_type_of(a) != PDF_ARRAY) {
736
0
        pdfi_countdown(a);
737
0
        return_error(gs_error_typecheck);
738
0
    }
739
0
    array_size = pdfi_array_size(a);
740
0
    if (array_size != 6) {
741
0
        pdfi_countdown(a);
742
0
        return_error(gs_error_rangecheck);
743
0
    }
744
745
0
    for (i=0; i< array_size; i++) {
746
0
        code = pdfi_array_get_number(ctx, a, (uint64_t)i, &f);
747
0
        if (code < 0) {
748
0
            pdfi_countdown(a);
749
0
            return_error(code);
750
0
        }
751
0
        parray[i] = (float)f;
752
0
    }
753
0
    pdfi_countdown(a);
754
0
    return array_size;
755
0
}
756
757
/* Returns < 0 for error or the number of entries allocated */
758
int pdfi_make_float_array_from_dict(pdf_context *ctx, float **parray, pdf_dict *dict, const char *Key)
759
162k
{
760
162k
    int code, i;
761
162k
    pdf_array *a = NULL;
762
162k
    float *arr = NULL;
763
162k
    double f;
764
162k
    uint64_t array_size;
765
766
162k
    *parray = NULL;
767
768
162k
    code = pdfi_dict_get(ctx, dict, Key, (pdf_obj **)&a);
769
162k
    if (code < 0)
770
37.4k
        return code;
771
124k
    if (pdfi_type_of(a) != PDF_ARRAY) {
772
0
        pdfi_countdown(a);
773
0
        return_error(gs_error_typecheck);
774
0
    }
775
124k
    array_size = pdfi_array_size(a);
776
777
124k
    arr = (float *)gs_alloc_byte_array(ctx->memory, array_size,
778
124k
                                       sizeof(float), "array_from_dict_key");
779
124k
    *parray = arr;
780
781
519k
    for (i=0;i< array_size;i++) {
782
395k
        code = pdfi_array_get_number(ctx, a, (uint64_t)i, &f);
783
395k
        if (code < 0) {
784
22
            gs_free_const_object(ctx->memory, arr, "float_array");
785
22
            *parray = NULL;
786
22
            pdfi_countdown(a);
787
22
            return_error(code);
788
22
        }
789
395k
        (*parray)[i] = (float)f;
790
395k
    }
791
124k
    pdfi_countdown(a);
792
124k
    return array_size;
793
124k
}
794
795
int pdfi_make_int_array_from_dict(pdf_context *ctx, int **parray, pdf_dict *dict, const char *Key)
796
12.6k
{
797
12.6k
    int code, i;
798
12.6k
    pdf_array *a = NULL;
799
12.6k
    int *arr = NULL;
800
12.6k
    pdf_num *o;
801
12.6k
    uint64_t array_size;
802
803
12.6k
    *parray = NULL;
804
805
12.6k
    code = pdfi_dict_get(ctx, dict, Key, (pdf_obj **)&a);
806
12.6k
    if (code < 0)
807
0
        return code;
808
12.6k
    if (pdfi_type_of(a) != PDF_ARRAY) {
809
0
        pdfi_countdown(a);
810
0
        return_error(gs_error_typecheck);
811
0
    }
812
12.6k
    array_size = pdfi_array_size(a);
813
12.6k
    arr = (int *)gs_alloc_byte_array(ctx->memory, array_size,
814
12.6k
                                     sizeof(int), "array_from_dict_key");
815
12.6k
    *parray = arr;
816
817
25.3k
    for (i=0;i< array_size;i++) {
818
12.7k
        code = pdfi_array_get_type(ctx, a, (uint64_t)i, PDF_INT, (pdf_obj **)&o);
819
12.7k
        if (code < 0) {
820
0
            gs_free_const_object(ctx->memory, arr, "int_array");
821
0
            *parray = NULL;
822
0
            pdfi_countdown(a);
823
0
            return_error(code);
824
0
        }
825
12.7k
        (*parray)[i] = (int)o->value.i;
826
12.7k
        pdfi_countdown(o);
827
12.7k
    }
828
12.6k
    pdfi_countdown(a);
829
12.6k
    return array_size;
830
12.6k
}
831
832
/* Put into dictionary with key as object -
833
   If the key already exists, we'll only replace it
834
   if "replace" is true.
835
*/
836
int pdfi_dict_put_obj(pdf_context *ctx, pdf_dict *d, pdf_obj *Key, pdf_obj *value, bool replace)
837
17.8M
{
838
17.8M
    int i;
839
17.8M
    pdf_dict_entry *new_list;
840
841
17.8M
    if (pdfi_type_of(d) != PDF_DICT)
842
0
        return_error(gs_error_typecheck);
843
844
17.8M
    if (pdfi_type_of(Key) != PDF_NAME)
845
0
        return_error(gs_error_typecheck);
846
847
    /* First, do we have a Key/value pair already ? */
848
17.8M
    i = pdfi_dict_find_key(ctx, d, (pdf_name *)Key, false);
849
17.8M
    if (i >= 0) {
850
14.5k
        if (d->list[i].value == value || replace == false)
851
            /* We already have this value stored with this key.... */
852
12.4k
            return 0;
853
2.12k
        pdfi_countdown(d->list[i].value);
854
2.12k
        d->list[i].value = value;
855
2.12k
        pdfi_countup(value);
856
2.12k
        return 0;
857
14.5k
    }
858
859
17.8M
    d->is_sorted = false;
860
861
    /* Nope, its a new Key */
862
17.8M
    if (d->size > d->entries) {
863
        /* We have a hole, find and use it */
864
6.80G
        for (i=0;i< d->size;i++) {
865
6.80G
            if (d->list[i].key == NULL) {
866
17.4M
                d->list[i].key = Key;
867
17.4M
                pdfi_countup(Key);
868
17.4M
                d->list[i].value = value;
869
17.4M
                pdfi_countup(value);
870
17.4M
                d->entries++;
871
17.4M
                return 0;
872
17.4M
            }
873
6.80G
        }
874
17.4M
    }
875
876
435k
    new_list = (pdf_dict_entry *)gs_alloc_bytes(ctx->memory, (d->size + 1) * sizeof(pdf_dict_entry), "pdfi_dict_put reallocate dictionary key/values");
877
435k
    if (new_list == NULL) {
878
0
        return_error(gs_error_VMerror);
879
0
    }
880
435k
    memcpy(new_list, d->list, d->size * sizeof(pdf_dict_entry));
881
882
435k
    gs_free_object(ctx->memory, d->list, "pdfi_dict_put key/value reallocation");
883
884
435k
    d->list = new_list;
885
886
435k
    d->list[d->size].key = Key;
887
435k
    d->list[d->size].value = value;
888
435k
    d->size++;
889
435k
    d->entries++;
890
435k
    pdfi_countup(Key);
891
435k
    pdfi_countup(value);
892
893
435k
    return 0;
894
435k
}
895
896
/*
897
 * Be very cautious using this routine; it does not check to see if a key already exists
898
 * in a dictionary!. This is initially at least intended for use by the font code, to build
899
 * a CharStrings dictionary. We do that by adding each glyph individually with a name
900
 * created from a loop counter, so we know there cannot be any duplicates, and the time
901
 * taken to check that each of 64K names was unique was quite significant.
902
 * See bug #705534, the old PDF interpreter (nullpage, 72 dpi) runs this file in ~20 seconds
903
 * pdfi runs it in around 40 seconds. With this change it runs in around 3 seconds. THis is,
904
 * of course, an extreme example.
905
 */
906
int pdfi_dict_put_unchecked(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj *value)
907
138k
{
908
138k
    int i, code = 0;
909
138k
    pdf_dict_entry *new_list;
910
138k
    pdf_obj *key = NULL;
911
912
138k
    code = pdfi_name_alloc(ctx, (byte *)Key, strlen(Key), &key);
913
138k
    if (code < 0)
914
0
        return code;
915
138k
    pdfi_countup(key);
916
917
138k
    if (d->size > d->entries) {
918
138k
        int search_start = d->entries < 1 ? 0 : d->entries - 1;
919
138k
        do {
920
            /* We have a hole, find and use it */
921
277k
            for (i = search_start; i < d->size; i++) {
922
277k
                if (d->list[i].key == NULL) {
923
138k
                    d->list[i].key = key;
924
138k
                    d->list[i].value = value;
925
138k
                    pdfi_countup(value);
926
138k
                    d->entries++;
927
138k
                    return 0;
928
138k
                }
929
277k
            }
930
0
            if (search_start == 0) {
931
                /* This shouldn't ever happen, but just in case.... */
932
0
                break;
933
0
            }
934
0
            search_start = 0;
935
0
        } while(1);
936
138k
    }
937
938
0
    new_list = (pdf_dict_entry *)gs_alloc_bytes(ctx->memory, (d->size + 1) * sizeof(pdf_dict_entry), "pdfi_dict_put reallocate dictionary key/values");
939
0
    if (new_list == NULL) {
940
0
        return_error(gs_error_VMerror);
941
0
    }
942
0
    memcpy(new_list, d->list, d->size * sizeof(pdf_dict_entry));
943
944
0
    gs_free_object(ctx->memory, d->list, "pdfi_dict_put key/value reallocation");
945
946
0
    d->list = new_list;
947
948
0
    d->list[d->size].key = key;
949
0
    d->list[d->size].value = value;
950
0
    d->size++;
951
0
    d->entries++;
952
0
    pdfi_countup(value);
953
954
0
    return 0;
955
0
}
956
957
/* Put into dictionary with key as string */
958
int pdfi_dict_put(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj *value)
959
785k
{
960
785k
    int code;
961
785k
    pdf_obj *key = NULL;
962
963
785k
    code = pdfi_name_alloc(ctx, (byte *)Key, strlen(Key), &key);
964
785k
    if (code < 0)
965
0
        return code;
966
785k
    pdfi_countup(key);
967
968
785k
    code = pdfi_dict_put_obj(ctx, d, key, value, true);
969
785k
    pdfi_countdown(key); /* get rid of extra ref */
970
785k
    return code;
971
785k
}
972
973
int pdfi_dict_put_int(pdf_context *ctx, pdf_dict *d, const char *key, int64_t value)
974
7.34k
{
975
7.34k
    int code;
976
7.34k
    pdf_num *obj;
977
978
7.34k
    code = pdfi_object_alloc(ctx, PDF_INT, 0, (pdf_obj **)&obj);
979
7.34k
    obj->value.i = value;
980
7.34k
    if (code < 0)
981
0
        return code;
982
983
7.34k
    return pdfi_dict_put(ctx, d, key, (pdf_obj *)obj);
984
7.34k
}
985
986
int pdfi_dict_put_bool(pdf_context *ctx, pdf_dict *d, const char *key, bool value)
987
1.08k
{
988
1.08k
    pdf_obj *obj = (value ? PDF_TRUE_OBJ : PDF_FALSE_OBJ);
989
990
1.08k
    return pdfi_dict_put(ctx, d, key, obj);
991
1.08k
}
992
993
int pdfi_dict_put_name(pdf_context *ctx, pdf_dict *d, const char *key, const char *name)
994
0
{
995
0
    int code;
996
0
    pdf_obj *obj = NULL;
997
998
0
    code = pdfi_name_alloc(ctx, (byte *)name, strlen(name), &obj);
999
0
    if (code < 0)
1000
0
        return code;
1001
0
    pdfi_countup(obj);
1002
1003
0
    code = pdfi_dict_put(ctx, d, key, obj);
1004
0
    pdfi_countdown(obj); /* get rid of extra ref */
1005
0
    return code;
1006
0
}
1007
1008
int pdfi_dict_copy(pdf_context *ctx, pdf_dict *target, pdf_dict *source)
1009
73.5k
{
1010
73.5k
    int i=0, code = 0;
1011
1012
698k
    for (i=0;i< source->entries;i++) {
1013
625k
        code = pdfi_dict_put_obj(ctx, target, source->list[i].key, source->list[i].value, true);
1014
625k
        if (code < 0)
1015
0
            return code;
1016
625k
        target->is_sorted = source->is_sorted;
1017
625k
    }
1018
73.5k
    return 0;
1019
73.5k
}
1020
1021
int pdfi_dict_known(pdf_context *ctx, pdf_dict *d, const char *Key, bool *known)
1022
30.5M
{
1023
30.5M
    int i;
1024
1025
30.5M
    if (pdfi_type_of(d) != PDF_DICT)
1026
970
        return_error(gs_error_typecheck);
1027
1028
30.5M
    *known = false;
1029
30.5M
    i = pdfi_dict_find(ctx, d, Key, true);
1030
30.5M
    if (i >= 0)
1031
10.0M
        *known = true;
1032
1033
30.5M
    return 0;
1034
30.5M
}
1035
1036
int pdfi_dict_known_by_key(pdf_context *ctx, pdf_dict *d, pdf_name *Key, bool *known)
1037
40.6k
{
1038
40.6k
    int i;
1039
1040
40.6k
    if (pdfi_type_of(d) != PDF_DICT)
1041
0
        return_error(gs_error_typecheck);
1042
1043
40.6k
    *known = false;
1044
40.6k
    i = pdfi_dict_find_key(ctx, d, Key, true);
1045
40.6k
    if (i >= 0)
1046
36.9k
        *known = true;
1047
1048
40.6k
    return 0;
1049
40.6k
}
1050
1051
/* Tests if a Key is present in the dictionary, if it is, retrieves the value associated with the
1052
 * key. Returns < 0 for error, 0 if the key is not found > 0 if the key is present, and initialises
1053
 * the value in the arguments. Since this uses pdf_dict_get(), the returned value has its
1054
 * reference count incremented by 1, just like pdfi_dict_get().
1055
 */
1056
int pdfi_dict_knownget(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj **o)
1057
5.90M
{
1058
5.90M
    bool known = false;
1059
5.90M
    int code;
1060
1061
5.90M
    code = pdfi_dict_known(ctx, d, Key, &known);
1062
5.90M
    if (code < 0)
1063
950
        return code;
1064
1065
5.90M
    if (known == false)
1066
3.02M
        return 0;
1067
1068
2.88M
    code = pdfi_dict_get(ctx, d, Key, o);
1069
2.88M
    if (code < 0)
1070
54.1k
        return code;
1071
1072
2.82M
    return 1;
1073
2.88M
}
1074
1075
/* Like pdfi_dict_knownget() but allows the user to specify a type for the object that we get.
1076
 * returns < 0 for error (including typecheck if the object is not the requested type)
1077
 * 0 if the key is not found, or > 0 if the key was found and returned.
1078
 */
1079
int pdfi_dict_knownget_type(pdf_context *ctx, pdf_dict *d, const char *Key, pdf_obj_type type, pdf_obj **o)
1080
14.0M
{
1081
14.0M
    bool known = false;
1082
14.0M
    int code;
1083
1084
14.0M
    code = pdfi_dict_known(ctx, d, Key, &known);
1085
14.0M
    if (code < 0)
1086
20
        return code;
1087
1088
14.0M
    if (known == false)
1089
7.85M
        return 0;
1090
1091
6.21M
    code = pdfi_dict_get_type(ctx, d, Key, type, o);
1092
6.21M
    if (code < 0)
1093
121k
        return code;
1094
1095
6.09M
    return 1;
1096
6.21M
}
1097
1098
int pdfi_dict_knownget_bool(pdf_context *ctx, pdf_dict *d, const char *Key, bool *b)
1099
2.01k
{
1100
2.01k
    bool known = false;
1101
2.01k
    int code;
1102
1103
2.01k
    code = pdfi_dict_known(ctx, d, Key, &known);
1104
2.01k
    if (code < 0)
1105
0
        return code;
1106
1107
2.01k
    if (known == false)
1108
1.47k
        return 0;
1109
1110
538
    code = pdfi_dict_get_bool(ctx, d, Key, b);
1111
538
    if (code < 0)
1112
0
        return code;
1113
1114
538
    return 1;
1115
538
}
1116
1117
/* Like pdfi_dict_knownget_type() but retrieves numbers (two possible types)
1118
 */
1119
int pdfi_dict_knownget_number(pdf_context *ctx, pdf_dict *d, const char *Key, double *f)
1120
2.14M
{
1121
2.14M
    bool known = false;
1122
2.14M
    int code;
1123
1124
2.14M
    code = pdfi_dict_known(ctx, d, Key, &known);
1125
2.14M
    if (code < 0)
1126
0
        return code;
1127
1128
2.14M
    if (known == false)
1129
2.07M
        return 0;
1130
1131
65.0k
    code = pdfi_dict_get_number(ctx, d, Key, f);
1132
65.0k
    if (code < 0)
1133
0
        return code;
1134
1135
65.0k
    return 1;
1136
65.0k
}
1137
1138
int pdfi_dict_next(pdf_context *ctx, pdf_dict *d, pdf_obj **Key, pdf_obj **Value, uint64_t *index)
1139
1.01M
{
1140
1.01M
    int code;
1141
1142
1.01M
    if (pdfi_type_of(d) != PDF_DICT)
1143
0
        return_error(gs_error_typecheck);
1144
1145
1.01M
    while (1) {
1146
1.01M
        if (*index >= d->entries) {
1147
64.7k
            *Key = NULL;
1148
64.7k
            *Value= NULL;
1149
64.7k
            return gs_error_undefined;
1150
64.7k
        }
1151
1152
        /* If we find NULL keys skip over them. This should never
1153
         * happen as we check the number of entries above, and we
1154
         * compact dictionaries on deletion of key/value pairs.
1155
         * This is a belt and braces check in case creation of the
1156
         * dictionary somehow ends up with NULL keys in the allocated
1157
         * section.
1158
         */
1159
947k
        *Key = d->list[*index].key;
1160
947k
        if (*Key == NULL) {
1161
0
            (*index)++;
1162
0
            continue;
1163
0
        }
1164
1165
947k
        if (pdfi_type_of(d->list[*index].value) == PDF_INDIRECT) {
1166
613k
            pdf_indirect_ref *r = (pdf_indirect_ref *)d->list[*index].value;
1167
613k
            pdf_obj *o;
1168
1169
613k
            code = pdfi_dereference(ctx, r->ref_object_num, r->ref_generation_num, &o);
1170
613k
            if (code < 0) {
1171
74.7k
                *Key = *Value = NULL;
1172
74.7k
                return code;
1173
74.7k
            }
1174
538k
            *Value = o;
1175
538k
            break;
1176
613k
        } else {
1177
334k
            *Value = d->list[*index].value;
1178
334k
            pdfi_countup(*Value);
1179
334k
            break;
1180
334k
        }
1181
947k
    }
1182
1183
872k
    pdfi_countup(*Key);
1184
872k
    (*index)++;
1185
872k
    return 0;
1186
1.01M
}
1187
1188
int pdfi_dict_first(pdf_context *ctx, pdf_dict *d, pdf_obj **Key, pdf_obj **Value, uint64_t *index)
1189
445k
{
1190
445k
    uint64_t *i = index;
1191
1192
445k
    *i = 0;
1193
445k
    return pdfi_dict_next(ctx, d, Key, Value, index);
1194
445k
}
1195
1196
int pdfi_dict_key_next(pdf_context *ctx, pdf_dict *d, pdf_obj **Key, uint64_t *index)
1197
36.4M
{
1198
36.4M
    uint64_t *i = index;
1199
1200
36.4M
    if (pdfi_type_of(d) != PDF_DICT)
1201
0
        return_error(gs_error_typecheck);
1202
1203
36.4M
    while (1) {
1204
36.4M
        if (*i >= d->entries) {
1205
209k
            *Key = NULL;
1206
209k
            return gs_error_undefined;
1207
209k
        }
1208
1209
36.2M
        *Key = d->list[*i].key;
1210
36.2M
        if (*Key == NULL) {
1211
0
            (*i)++;
1212
0
            continue;
1213
0
        }
1214
36.2M
        pdfi_countup(*Key);
1215
36.2M
        (*i)++;
1216
36.2M
        break;
1217
36.2M
    }
1218
36.2M
    return 0;
1219
36.4M
}
1220
1221
int pdfi_dict_key_first(pdf_context *ctx, pdf_dict *d, pdf_obj **Key, uint64_t *index)
1222
362k
{
1223
362k
    uint64_t *i = index;
1224
1225
362k
    *i = 0;
1226
362k
    return pdfi_dict_key_next(ctx, d, Key, index);
1227
362k
}
1228
1229
int pdfi_merge_dicts(pdf_context *ctx, pdf_dict *target, pdf_dict *source)
1230
89.2k
{
1231
89.2k
    int i, code;
1232
89.2k
    bool known = false;
1233
1234
129k
    for (i=0;i< source->entries;i++) {
1235
40.3k
        code = pdfi_dict_known_by_key(ctx, target, (pdf_name *)source->list[i].key, &known);
1236
40.3k
        if (code < 0)
1237
0
            return code;
1238
40.3k
        if (!known) {
1239
3.49k
            code = pdfi_dict_put_obj(ctx, target, source->list[i].key, source->list[i].value, true);
1240
3.49k
            if (code < 0)
1241
0
                return code;
1242
3.49k
        }
1243
40.3k
    }
1244
89.2k
    target->is_sorted = false;
1245
89.2k
    return 0;
1246
89.2k
}
1247
1248
/* Return Length of a stream, or 0 if it's not a stream
1249
 * Caches the Length
1250
 */
1251
int64_t pdfi_stream_length(pdf_context *ctx, pdf_stream *stream)
1252
151k
{
1253
151k
    int64_t Length = 0;
1254
151k
    int code;
1255
1256
151k
    if (pdfi_type_of(stream) != PDF_STREAM)
1257
0
        return 0;
1258
1259
151k
    if (stream->length_valid)
1260
142k
        return stream->Length;
1261
1262
8.80k
    code = pdfi_dict_get_int(ctx, stream->stream_dict, "Length", &Length);
1263
8.80k
    if (code < 0)
1264
8.66k
        Length = 0;
1265
1266
    /* Make sure Length is not negative... */
1267
8.80k
    if (Length < 0)
1268
0
        Length = 0;
1269
1270
    /* Cache it */
1271
8.80k
    stream->Length = Length;
1272
8.80k
    stream->length_valid = true;
1273
1274
8.80k
    return 0;
1275
151k
}
1276
1277
/* Safely get offset from a stream object.
1278
 * If it's not actually a stream, just return 0.
1279
 */
1280
gs_offset_t pdfi_stream_offset(pdf_context *ctx, pdf_stream *stream)
1281
2.22M
{
1282
2.22M
    if (pdfi_type_of(stream) != PDF_STREAM)
1283
0
        return 0;
1284
2.22M
    return stream->stream_offset;
1285
2.22M
}
1286
1287
pdf_stream *pdfi_stream_parent(pdf_context *ctx, pdf_stream *stream)
1288
309k
{
1289
309k
    if (pdfi_type_of(stream) != PDF_STREAM)
1290
16.3k
        return 0;
1291
293k
    return (pdf_stream *)stream->parent_obj;
1292
309k
}
1293
1294
void pdfi_set_stream_parent(pdf_context *ctx, pdf_stream *stream, pdf_stream *parent)
1295
306k
{
1296
    /* Ordinarily we would increment the reference count of the parent object here,
1297
     * because we are taking a new reference to it. But if we do that we will end up
1298
     * with circular references and will never count down and release the objects.
1299
     * This is because the parent object must have a Resources dictionary which
1300
     * references this stream, when we dereference the stream we store it in the
1301
     * Parent's Resources dictionary. So the parent points to the child, the child
1302
     * points to the parent and we always end up with a refcnt for each of 1. Since we
1303
     * only ever consult parent_obj in an illegal case we deal with this by not
1304
     * incrementing the reference count. To try and avoid any dangling references
1305
     * we clear the parent_obj when we finish executing the stream in
1306
     * pdfi_interpret_content_stream.
1307
     */
1308
306k
    stream->parent_obj = (pdf_obj *)parent;
1309
306k
}
1310
1311
void pdfi_clear_stream_parent(pdf_context *ctx, pdf_stream *stream)
1312
306k
{
1313
306k
    stream->parent_obj = NULL;
1314
306k
}
1315
1316
/* Get the dict from a pdf_obj, returns typecheck if it doesn't have one */
1317
int pdfi_dict_from_obj(pdf_context *ctx, pdf_obj *obj, pdf_dict **dict)
1318
49.4M
{
1319
49.4M
    *dict = NULL;
1320
49.4M
    switch (pdfi_type_of(obj)) {
1321
157k
        case PDF_DICT:
1322
157k
            *dict = (pdf_dict *)obj;
1323
157k
            break;
1324
49.3M
        case PDF_STREAM:
1325
49.3M
            *dict = ((pdf_stream *)obj)->stream_dict;
1326
49.3M
            break;
1327
791
        default:
1328
791
            return_error(gs_error_typecheck);
1329
49.4M
    }
1330
49.4M
    return 0;
1331
49.4M
}