Coverage Report

Created: 2026-08-08 08:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/pdf/pdf_obj.c
Line
Count
Source
1
/* Copyright (C) 2020-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
#include "ghostpdf.h"
17
#include "pdf_stack.h"
18
#include "pdf_array.h"
19
#include "pdf_dict.h"
20
#include "pdf_obj.h"
21
#include "pdf_cmap.h"
22
#include "pdf_font.h"
23
#include "pdf_deref.h" /* for replace_cache_entry() */
24
#include "pdf_mark.h"
25
#include "pdf_file.h" /* for pdfi_stream_to_buffer() */
26
#include "pdf_loop_detect.h"
27
#include "stream.h"
28
29
/***********************************************************************************/
30
/* Functions to create the various kinds of 'PDF objects', Created objects have a  */
31
/* reference count of 0. Composite objects (dictionaries, arrays, strings) use the */
32
/* 'size' argument to create an object with the correct numbr of entries or of the */
33
/* requested size. Simple objects (integers etc) ignore this parameter.            */
34
/* Objects do not get their data assigned, that's up to the caller, but we do      */
35
/* set the length or size fields for composite objects.                             */
36
37
int pdfi_object_alloc(pdf_context *ctx, pdf_obj_type type, unsigned int size, pdf_obj **obj)
38
638M
{
39
638M
    int bytes = 0;
40
638M
    int code = 0;
41
42
638M
    switch(type) {
43
11.7M
        case PDF_ARRAY_MARK:
44
22.1M
        case PDF_DICT_MARK:
45
22.4M
        case PDF_PROC_MARK:
46
22.4M
            bytes = sizeof(pdf_obj);
47
22.4M
            break;
48
159M
        case PDF_INT:
49
281M
        case PDF_REAL:
50
281M
            bytes = sizeof(pdf_num);
51
281M
            break;
52
59.9M
        case PDF_STRING:
53
284M
        case PDF_NAME:
54
284M
            bytes = sizeof(pdf_string) + size - PDF_NAME_DECLARED_LENGTH;
55
284M
            break;
56
35.6k
        case PDF_BUFFER:
57
35.6k
            bytes = sizeof(pdf_buffer);
58
35.6k
            break;
59
11.6M
        case PDF_ARRAY:
60
11.6M
            bytes = sizeof(pdf_array);
61
11.6M
            break;
62
10.6M
        case PDF_DICT:
63
10.6M
            bytes = sizeof(pdf_dict);
64
10.6M
            break;
65
13.5M
        case PDF_INDIRECT:
66
13.5M
            bytes = sizeof(pdf_indirect_ref);
67
13.5M
            break;
68
13.4M
        case PDF_KEYWORD:
69
13.4M
            bytes = sizeof(pdf_keyword) + size - PDF_NAME_DECLARED_LENGTH;
70
13.4M
            break;
71
        /* The following aren't PDF object types, but are objects we either want to
72
         * reference count, or store on the stack.
73
         */
74
0
        case PDF_XREF_TABLE:
75
0
            bytes = sizeof(xref_table_t);
76
0
            break;
77
901k
        case PDF_STREAM:
78
901k
            bytes = sizeof(pdf_stream);
79
901k
            break;
80
0
        case PDF_NULL:
81
0
        case PDF_BOOL:
82
0
        default:
83
0
            code = gs_note_error(gs_error_typecheck);
84
0
            goto error_out;
85
638M
    }
86
638M
    *obj = (pdf_obj *)gs_alloc_bytes(ctx->memory, bytes, "pdfi_object_alloc");
87
638M
    if (*obj == NULL) {
88
0
        code = gs_note_error(gs_error_VMerror);
89
0
        goto error_out;
90
0
    }
91
92
638M
    memset(*obj, 0x00, bytes);
93
638M
    (*obj)->ctx = ctx;
94
638M
    (*obj)->type = type;
95
96
638M
    switch(type) {
97
/*      PDF_NULL and PDF_BOOL are now handled as special (not allocated) data types
98
        and we will return an error in the switch above if we get a call to allocate
99
        one of these. Having the cases isn't harmful but Coverity complains of dead
100
        code, so commenting these out to silence Coverity while preserving the old
101
        semantics to indicate what's happening.
102
        case PDF_NULL:
103
        case PDF_BOOL: */
104
105
159M
        case PDF_INT:
106
281M
        case PDF_REAL:
107
295M
        case PDF_INDIRECT:
108
307M
        case PDF_ARRAY_MARK:
109
317M
        case PDF_DICT_MARK:
110
317M
        case PDF_PROC_MARK:
111
317M
            break;
112
13.4M
        case PDF_KEYWORD:
113
73.3M
        case PDF_STRING:
114
297M
        case PDF_NAME:
115
297M
            ((pdf_string *)*obj)->length = size;
116
297M
            break;
117
35.6k
        case PDF_BUFFER:
118
35.6k
            {
119
35.6k
                pdf_buffer *b = (pdf_buffer *)*obj;
120
               /* NOTE: size can be 0 if the caller wants to allocate the data area itself
121
                */
122
35.6k
                if (size > 0) {
123
0
                    b->data = gs_alloc_bytes(ctx->memory, size, "pdfi_object_alloc");
124
0
                    if (b->data == NULL) {
125
0
                        code = gs_note_error(gs_error_VMerror);
126
0
                        goto error_out;
127
0
                    }
128
0
                }
129
35.6k
                else {
130
35.6k
                    b->data = NULL;
131
35.6k
                }
132
35.6k
                b->length = size;
133
35.6k
            }
134
0
            break;
135
11.6M
        case PDF_ARRAY:
136
11.6M
            {
137
11.6M
                pdf_obj **values = NULL;
138
139
11.6M
                ((pdf_array *)*obj)->size = size;
140
11.6M
                if (size > 0) {
141
11.0M
                    values = (pdf_obj **)gs_alloc_bytes(ctx->memory, (size_t)size * sizeof(pdf_obj *), "pdfi_object_alloc");
142
11.0M
                    if (values == NULL) {
143
0
                        code = gs_note_error(gs_error_VMerror);
144
0
                        goto error_out;
145
0
                    }
146
11.0M
                    ((pdf_array *)*obj)->values = values;
147
11.0M
                    memset(((pdf_array *)*obj)->values, 0x00, size * sizeof(pdf_obj *));
148
11.0M
                }
149
11.6M
            }
150
11.6M
            break;
151
11.6M
        case PDF_DICT:
152
10.6M
            {
153
10.6M
                pdf_dict_entry *entries = NULL;
154
155
10.6M
                ((pdf_dict *)*obj)->size = size;
156
10.6M
                if (size > 0) {
157
10.2M
                    entries = (pdf_dict_entry *)gs_alloc_bytes(ctx->memory, (size_t)size * sizeof(pdf_dict_entry), "pdfi_object_alloc");
158
10.2M
                    if (entries == NULL) {
159
0
                        code = gs_note_error(gs_error_VMerror);
160
0
                        goto error_out;
161
0
                    }
162
10.2M
                    ((pdf_dict *)*obj)->list = entries;
163
10.2M
                    memset(((pdf_dict *)*obj)->list, 0x00, size * sizeof(pdf_dict_entry));
164
10.2M
                }
165
10.6M
            }
166
10.6M
            break;
167
        /* The following aren't PDF object types, but are objects we either want to
168
         * reference count, or store on the stack.
169
         */
170
10.6M
        case PDF_XREF_TABLE:
171
0
            break;
172
901k
        default:
173
901k
            break;
174
638M
    }
175
#if REFCNT_DEBUG
176
    (*obj)->UID = ctx->ref_UID++;
177
    outprintf(ctx->memory, "Allocated object of type %c with UID %"PRIi64"\n", (*obj)->type, (*obj)->UID);
178
#endif
179
638M
    return 0;
180
0
error_out:
181
0
    gs_free_object(ctx->memory, *obj, "pdfi_object_alloc");
182
0
    *obj = NULL;
183
0
    return code;
184
638M
}
185
186
/* Create a PDF number object from a numeric value. Attempts to create
187
 * either a REAL or INT as appropriate. As usual for the alloc functions
188
 * this returns an object with a reference count of 0.
189
 */
190
int pdfi_num_alloc(pdf_context *ctx, double d, pdf_num **num)
191
10.6k
{
192
10.6k
    uint64_t test = 0;
193
10.6k
    int code = 0;
194
195
10.6k
    test = (uint64_t)floor(d);
196
10.6k
    if (d == test) {
197
7.82k
        code = pdfi_object_alloc(ctx, PDF_INT, 0, (pdf_obj **)num);
198
7.82k
        if (code < 0)
199
0
            return code;
200
7.82k
        (*num)->value.i = test;
201
7.82k
    }
202
2.86k
    else {
203
2.86k
        code = pdfi_object_alloc(ctx, PDF_REAL, 0, (pdf_obj **)num);
204
2.86k
        if (code < 0)
205
0
            return code;
206
2.86k
        (*num)->value.d = d;
207
2.86k
    }
208
209
10.6k
    return 0;
210
10.6k
}
211
212
/***********************************************************************************/
213
/* Functions to free the various kinds of 'PDF objects'.                           */
214
/* All objects are reference counted, newly allocated objects, as noted above have */
215
/* a reference count of 0. Pushing an object onto the stack increments             */
216
/* its reference count, popping it from the stack decrements its reference count.  */
217
/* When an object's reference count is decremented to 0, pdfi_countdown calls      */
218
/* pdfi_free_object() to free it.                                                  */
219
220
static void pdfi_free_namestring(pdf_obj *o)
221
284M
{
222
    /* Currently names and strings are the same, so a single cast is OK */
223
284M
    pdf_name *n = (pdf_name *)o;
224
225
284M
    gs_free_object(OBJ_MEMORY(n), n, "pdf interpreter free name or string");
226
284M
}
227
228
static void pdfi_free_keyword(pdf_obj *o)
229
13.4M
{
230
13.4M
    pdf_keyword *k = (pdf_keyword *)o;
231
232
13.4M
    gs_free_object(OBJ_MEMORY(k), k, "pdf interpreter free keyword");
233
13.4M
}
234
235
static void pdfi_free_xref_table(pdf_obj *o)
236
77.3k
{
237
77.3k
    xref_table_t *xref = (xref_table_t *)o;
238
239
77.3k
    gs_free_object(OBJ_MEMORY(xref), xref->xref, "pdfi_free_xref_table");
240
77.3k
    gs_free_object(OBJ_MEMORY(xref), xref, "pdfi_free_xref_table");
241
77.3k
}
242
243
static void pdfi_free_stream(pdf_obj *o)
244
901k
{
245
901k
    pdf_stream *stream = (pdf_stream *)o;
246
247
901k
    pdfi_countdown(stream->stream_dict);
248
901k
    gs_free_object(OBJ_MEMORY(o), o, "pdfi_free_stream");
249
901k
}
250
251
static void pdfi_free_buffer(pdf_obj *o)
252
35.6k
{
253
35.6k
    pdf_buffer *b = (pdf_buffer *)o;
254
255
35.6k
    gs_free_object(OBJ_MEMORY(b), b->data, "pdfi_free_buffer(data)");
256
35.6k
    gs_free_object(OBJ_MEMORY(o), o, "pdfi_free_buffer");
257
35.6k
}
258
259
void pdfi_free_object(pdf_obj *o)
260
639M
{
261
639M
    if (o == NULL)
262
646k
        return;
263
639M
    if ((intptr_t)o < (intptr_t)TOKEN__LAST_KEY)
264
0
        return;
265
639M
    switch(o->type) {
266
11.7M
        case PDF_ARRAY_MARK:
267
22.1M
        case PDF_DICT_MARK:
268
22.4M
        case PDF_PROC_MARK:
269
181M
        case PDF_INT:
270
304M
        case PDF_REAL:
271
317M
        case PDF_INDIRECT:
272
317M
            gs_free_object(OBJ_MEMORY(o), o, "pdf interpreter object refcount to 0");
273
317M
            break;
274
59.9M
        case PDF_STRING:
275
284M
        case PDF_NAME:
276
284M
            pdfi_free_namestring(o);
277
284M
            break;
278
35.6k
        case PDF_BUFFER:
279
35.6k
            pdfi_free_buffer(o);
280
35.6k
            break;
281
11.6M
        case PDF_ARRAY:
282
11.6M
            pdfi_free_array(o);
283
11.6M
            break;
284
10.6M
        case PDF_DICT:
285
10.6M
            pdfi_free_dict(o);
286
10.6M
            break;
287
901k
        case PDF_STREAM:
288
901k
            pdfi_free_stream(o);
289
901k
            break;
290
13.4M
        case PDF_KEYWORD:
291
13.4M
            pdfi_free_keyword(o);
292
13.4M
            break;
293
77.3k
        case PDF_XREF_TABLE:
294
77.3k
            pdfi_free_xref_table(o);
295
77.3k
            break;
296
549k
        case PDF_FONT:
297
549k
            pdfi_free_font(o);
298
549k
            break;
299
63.5k
        case PDF_CMAP:
300
63.5k
            pdfi_free_cmap(o);
301
63.5k
            break;
302
0
        case PDF_BOOL:
303
0
        case PDF_NULL:
304
0
            dbgmprintf(OBJ_MEMORY(o), "!!! Attempting to free non-allocated object type !!!\n");
305
0
            break;
306
12
        default:
307
12
            dbgmprintf(OBJ_MEMORY(o), "!!! Attempting to free unknown object type !!!\n");
308
12
            break;
309
639M
    }
310
639M
}
311
312
313
/* Convert a pdf_dict to a pdf_stream.
314
 * do_convert -- convert the stream to use same object num as dict
315
 *               (This assumes the dict has not been cached.)
316
 * The stream will come with 1 refcnt, dict refcnt will be incremented by 1.
317
 */
318
int pdfi_obj_dict_to_stream(pdf_context *ctx, pdf_dict *dict, pdf_stream **stream, bool do_convert)
319
901k
{
320
901k
    int code = 0;
321
901k
    pdf_stream *new_stream = NULL;
322
323
901k
    if (pdfi_type_of(dict) != PDF_DICT)
324
0
        return_error(gs_error_typecheck);
325
326
901k
    code = pdfi_object_alloc(ctx, PDF_STREAM, 0, (pdf_obj **)&new_stream);
327
901k
    if (code < 0)
328
0
        goto error_exit;
329
330
901k
    new_stream->ctx = ctx;
331
901k
    pdfi_countup(new_stream);
332
333
901k
    new_stream->stream_dict = dict;
334
901k
    pdfi_countup(dict);
335
336
    /* this replaces the dict with the stream.
337
     * assumes it's not cached
338
     */
339
901k
    if (do_convert) {
340
869k
        new_stream->object_num = dict->object_num;
341
869k
        new_stream->generation_num = dict->generation_num;
342
869k
        dict->object_num = 0;
343
869k
        dict->generation_num = 0;
344
869k
    }
345
901k
    *stream = new_stream;
346
901k
    return 0;
347
348
0
 error_exit:
349
0
    pdfi_countdown(new_stream);
350
0
    return code;
351
901k
}
352
353
int pdfi_get_stream_dict(pdf_context *ctx, pdf_stream *stream, pdf_dict **dict)
354
218
{
355
218
    *dict = stream->stream_dict;
356
357
    /* Make sure the dictionary won't go away */
358
218
    pdfi_countup(*dict);
359
218
    if ((*dict)->object_num == 0) {
360
0
        (*dict)->object_num = stream->object_num;
361
0
        (*dict)->generation_num = stream->generation_num;
362
0
    }
363
364
218
    return 0;
365
218
}
366
367
/* Create a pdf_string from a c char * */
368
int pdfi_obj_charstr_to_string(pdf_context *ctx, const char *charstr, pdf_string **string)
369
401
{
370
401
    int code;
371
401
    int length = strlen(charstr);
372
401
    pdf_string *newstr = NULL;
373
374
401
    *string = NULL;
375
376
401
    code = pdfi_object_alloc(ctx, PDF_STRING, length, (pdf_obj **)&newstr);
377
401
    if (code < 0) goto exit;
378
379
401
    memcpy(newstr->data, (byte *)charstr, length);
380
381
401
    *string = newstr;
382
401
    pdfi_countup(newstr);
383
401
 exit:
384
401
    return code;
385
401
}
386
387
/* Create a pdf_name from a c char * */
388
int pdfi_obj_charstr_to_name(pdf_context *ctx, const char *charstr, pdf_name **name)
389
394k
{
390
394k
    int code;
391
394k
    int length = strlen(charstr);
392
394k
    pdf_name *newname = NULL;
393
394
394k
    *name = NULL;
395
396
394k
    code = pdfi_object_alloc(ctx, PDF_NAME, length, (pdf_obj **)&newname);
397
394k
    if (code < 0) goto exit;
398
399
394k
    memcpy(newname->data, (byte *)charstr, length);
400
401
394k
    *name = newname;
402
394k
    pdfi_countup(newname);
403
394k
 exit:
404
394k
    return code;
405
394k
}
406
407
/************ bufstream module BEGIN **************/
408
32.1k
#define INIT_BUF_SIZE 256
409
410
typedef struct {
411
    int len;  /* Length of buffer */
412
    int cur;  /* Current position */
413
    byte *data;
414
} pdfi_bufstream_t;
415
416
417
static int pdfi_bufstream_init(pdf_context *ctx, pdfi_bufstream_t *stream)
418
32.1k
{
419
32.1k
    stream->len = INIT_BUF_SIZE;
420
32.1k
    stream->cur = 0;
421
32.1k
    stream->data = gs_alloc_bytes(ctx->memory, stream->len, "pdfi_bufstream_init(data)");
422
423
32.1k
    if (!stream->data)
424
0
        return_error(gs_error_VMerror);
425
32.1k
    return 0;
426
32.1k
}
427
428
static int pdfi_bufstream_free(pdf_context *ctx, pdfi_bufstream_t *stream)
429
32.1k
{
430
32.1k
    if (stream->data)
431
99
        gs_free_object(ctx->memory, stream->data, "pdfi_bufstream_free(data)");
432
32.1k
    stream->len = 0;
433
32.1k
    stream->cur = 0;
434
32.1k
    stream->data = NULL;
435
32.1k
    return 0;
436
32.1k
}
437
438
/* Grab a copy of the stream's buffer */
439
static int pdfi_bufstream_copy(pdf_context *ctx, pdfi_bufstream_t *stream, byte **buf, int *len)
440
32.0k
{
441
32.0k
    *buf = stream->data;
442
32.0k
    *len = stream->cur;
443
32.0k
    stream->len = 0;
444
32.0k
    stream->cur = 0;
445
32.0k
    stream->data = NULL;
446
32.0k
    return 0;
447
32.0k
}
448
449
/* Increase the size of the buffer by doubling and added the known needed amount */
450
static int pdfi_bufstream_increase(pdf_context *ctx, pdfi_bufstream_t *stream, uint64_t needed)
451
1.14k
{
452
1.14k
    byte *data = NULL;
453
1.14k
    uint64_t newsize;
454
455
1.14k
    if (needed > max_int || stream->len > (max_int - needed) / 2)
456
0
        return_error(gs_error_rangecheck);
457
458
1.14k
    newsize = stream->len * 2 + needed;
459
1.14k
    data = gs_alloc_bytes(ctx->memory, newsize, "pdfi_bufstream_increase(data)");
460
1.14k
    if (!data)
461
0
        return_error(gs_error_VMerror);
462
463
1.14k
    memcpy(data, stream->data, stream->len);
464
1.14k
    gs_free_object(ctx->memory, stream->data, "pdfi_bufstream_increase(data)");
465
1.14k
    stream->data = data;
466
1.14k
    stream->len = newsize;
467
468
1.14k
    return 0;
469
1.14k
}
470
471
static int pdfi_bufstream_write(pdf_context *ctx, pdfi_bufstream_t *stream, byte *data, uint64_t len)
472
361k
{
473
361k
    int code = 0;
474
475
361k
    if (stream->cur + len > stream->len) {
476
1.14k
        code = pdfi_bufstream_increase(ctx, stream, len);
477
1.14k
        if (code < 0)
478
0
            goto exit;
479
1.14k
    }
480
361k
    memcpy(stream->data + stream->cur, data, len);
481
361k
    stream->cur += len;
482
483
361k
 exit:
484
361k
    return code;
485
361k
}
486
487
/************ bufstream module END **************/
488
489
490
/* Create a c-string to use as object label
491
 * Uses the object_num to make it unique.
492
 * (don't call this for objects with object_num=0, though I am not going to check that here)
493
 *
494
 * Bug #708127; just the object number alone is insufficient. Two consecutive input files might use the
495
 * same object number for a pdfmark, but with different content, we need to differntiate between the two.
496
 * Add a simple hash of the input filename (uses the same dumb but fast hash as pattern ID generation), this gives
497
 * the last bytes in the filename more say in the final result so is 'probably' sufficiently unique with the
498
 * object number and generation.
499
 */
500
int pdfi_obj_get_label(pdf_context *ctx, pdf_obj *obj, char **label)
501
4.42k
{
502
4.42k
    int code = 0, i;
503
4.42k
    int length;
504
4.42k
    const char *template = "{Obj%dG%dF%d}"; /* The '{' and '}' are special to pdfmark/pdfwrite driver */
505
4.42k
    char *string = NULL;
506
4.42k
    pdf_indirect_ref *ref = (pdf_indirect_ref *)obj;
507
4.42k
    uint32_t hash = 5381;
508
509
4.42k
    if (ctx->main_stream->s->file_name.data != NULL) {
510
0
        string = (char *)ctx->main_stream->s->file_name.data;
511
0
        length = ctx->main_stream->s->file_name.size;
512
513
0
        for (i=0;i < length;i++) {
514
#if ARCH_IS_BIG_ENDIAN
515
            hash = ((hash << 5) + hash) + string[length - 1 - i]; /* hash * 33 + c */
516
#else
517
0
            hash = ((hash << 5) + hash) + string[i]; /* hash * 33 + c */
518
0
#endif
519
0
        }
520
0
    }
521
522
4.42k
    *label = NULL;
523
4.42k
    length = strlen(template)+30;
524
525
4.42k
    string = (char *)gs_alloc_bytes(ctx->memory, length, "pdf_obj_get_label(label)");
526
4.42k
    if (string == NULL) {
527
0
        code = gs_note_error(gs_error_VMerror);
528
0
        goto exit;
529
0
    }
530
531
4.42k
    if (pdfi_type_of(obj) == PDF_INDIRECT)
532
4.40k
        gs_snprintf(string, length, template, ref->ref_object_num, ref->ref_generation_num, hash);
533
15
    else
534
15
        gs_snprintf(string, length, template, obj->object_num, obj->generation_num, hash);
535
536
4.42k
    *label = string;
537
4.42k
 exit:
538
4.42k
    return code;
539
4.42k
}
540
541
/*********** BEGIN obj_to_string module ************/
542
543
typedef int (*str_func)(pdf_context *ctx, pdf_obj *obj, byte **data, int *len);
544
545
/* Dispatch to get string representation of an object */
546
typedef struct {
547
    pdf_obj_type type;
548
    str_func func;
549
} obj_str_dispatch_t;
550
551
static int pdfi_obj_default_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
552
3
{
553
3
    int code = 0;
554
3
    int size = 12;
555
3
    byte *buf;
556
557
3
    buf = gs_alloc_bytes(ctx->memory, size, "pdfi_obj_default_str(data)");
558
3
    if (buf == NULL)
559
0
        return_error(gs_error_VMerror);
560
3
    memcpy(buf, "/placeholder", size);
561
3
    *data = buf;
562
3
    *len = size;
563
3
    return code;
564
3
}
565
566
static int pdfi_obj_name_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
567
119k
{
568
119k
    int code = 0, i;
569
119k
    pdf_name *name = (pdf_name *)obj;
570
119k
    int esc_size = 1;
571
119k
    byte *buf;
572
573
    /* We need to 'escape' any characters that can't be represented in a PDF name. */
574
631k
    for (i = 0;i < name->length;i++) {
575
512k
        switch(name->data[i]) {
576
0
            case 0x00:
577
0
            case 0x09:
578
0
            case 0x0a:
579
0
            case 0x0c:
580
0
            case 0x0d:
581
352
            case 0x20:
582
352
            case 0x25:
583
352
            case 0x28:
584
352
            case 0x29:
585
352
            case 0x3c:
586
352
            case 0x3e:
587
352
            case 0x5b:
588
352
            case 0x5d:
589
352
            case 0x7b:
590
352
            case 0x7d:
591
352
            case 0x2f:
592
352
                esc_size += 3;
593
352
                break;
594
512k
            default:
595
512k
                esc_size++;
596
512k
                break;
597
512k
        }
598
512k
    }
599
600
119k
    buf = gs_alloc_bytes(ctx->memory, esc_size, "pdfi_obj_name_str(data)");
601
119k
    if (buf == NULL)
602
0
        return_error(gs_error_VMerror);
603
119k
    buf[0] = '/';
604
119k
    esc_size = 1;
605
606
631k
    for (i = 0;i < name->length;i++) {
607
512k
        switch(name->data[i]) {
608
0
            case 0x00:
609
0
            case 0x09:
610
0
            case 0x0a:
611
0
            case 0x0c:
612
0
            case 0x0d:
613
352
            case 0x20:
614
352
            case 0x25:
615
352
            case 0x28:
616
352
            case 0x29:
617
352
            case 0x3c:
618
352
            case 0x3e:
619
352
            case 0x5b:
620
352
            case 0x5d:
621
352
            case 0x7b:
622
352
            case 0x7d:
623
352
            case 0x2f:
624
352
                buf[esc_size++] = '#';
625
352
                buf[esc_size++] = (name->data[i] >> 4) + 0x30;
626
352
                buf[esc_size++] = (name->data[i] & 0x0f) + 0x30;
627
352
                break;
628
512k
            default:
629
512k
                buf[esc_size++] = name->data[i];
630
512k
                break;
631
512k
        }
632
512k
    }
633
634
//    memcpy(buf+1, name->data, name->length);
635
119k
    *data = buf;
636
119k
    *len = esc_size;
637
119k
    return code;
638
119k
}
639
640
static int pdfi_obj_real_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
641
41.5k
{
642
41.5k
    int code = 0;
643
41.5k
    int size = 15;
644
41.5k
    pdf_num *number = (pdf_num *)obj;
645
41.5k
    char *buf;
646
647
41.5k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_real_str(data)");
648
41.5k
    if (buf == NULL)
649
0
        return_error(gs_error_VMerror);
650
41.5k
    snprintf(buf, size, "%.4f", number->value.d);
651
41.5k
    *data = (byte *)buf;
652
41.5k
    *len = strlen(buf);
653
41.5k
    return code;
654
41.5k
}
655
656
static int pdfi_obj_int_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
657
99.9k
{
658
99.9k
    int code = 0;
659
99.9k
    int size = 15;
660
99.9k
    pdf_num *number = (pdf_num *)obj;
661
99.9k
    char *buf;
662
663
99.9k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_int_str(data)");
664
99.9k
    if (buf == NULL)
665
0
        return_error(gs_error_VMerror);
666
99.9k
    snprintf(buf, size, "%"PRId64"", number->value.i);
667
99.9k
    *data = (byte *)buf;
668
99.9k
    *len = strlen(buf);
669
99.9k
    return code;
670
99.9k
}
671
672
static int pdfi_obj_getrefstr(pdf_context *ctx, uint64_t object_num, uint32_t generation, byte **data, int *len)
673
2.82k
{
674
2.82k
    int size = 100;
675
2.82k
    char *buf;
676
677
2.82k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_getrefstr(data)");
678
2.82k
    if (buf == NULL)
679
0
        return_error(gs_error_VMerror);
680
2.82k
    snprintf(buf, size, "%"PRId64" %d R", object_num, generation);
681
2.82k
    *data = (byte *)buf;
682
2.82k
    *len = strlen(buf);
683
2.82k
    return 0;
684
2.82k
}
685
686
static int pdfi_obj_indirect_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
687
7.40k
{
688
7.40k
    int code = 0;
689
7.40k
    pdf_indirect_ref *ref = (pdf_indirect_ref *)obj;
690
7.40k
    char *buf;
691
7.40k
    pdf_obj *object = NULL;
692
7.40k
    bool use_label = true;
693
694
7.40k
    code = pdfi_loop_detector_mark(ctx);
695
7.40k
    if (code < 0)
696
0
        return code;
697
698
7.40k
    if (ref->is_highlevelform) {
699
2.43k
        code = pdfi_obj_getrefstr(ctx, ref->highlevel_object_num, 0, data, len);
700
2.43k
        ref->is_highlevelform = false;
701
4.96k
    } else {
702
4.96k
        if (!ref->is_marking) {
703
1.94k
            code = pdfi_dereference(ctx, ref->ref_object_num, ref->ref_generation_num, &object);
704
1.94k
            if (code == gs_error_undefined) {
705
                /* Do something sensible for undefined reference (this would be a broken file) */
706
                /* TODO: Flag an error? */
707
389
                code = pdfi_obj_getrefstr(ctx, ref->ref_object_num, ref->ref_generation_num, data, len);
708
389
                goto exit;
709
389
            }
710
1.55k
            if (code < 0 && code != gs_error_circular_reference)
711
61
                goto exit;
712
1.49k
            if (code == 0) {
713
1.44k
                if (pdfi_type_of(object) == PDF_STREAM) {
714
259
                    code = pdfi_pdfmark_stream(ctx, (pdf_stream *)object);
715
259
                    if (code < 0) goto exit;
716
1.18k
                } else if (pdfi_type_of(object) == PDF_DICT) {
717
1.11k
                    code = pdfi_pdfmark_dict(ctx, (pdf_dict *)object);
718
1.11k
                    if (code < 0) goto exit;
719
1.11k
                } else {
720
67
                    code = pdfi_obj_to_string(ctx, object, data, len);
721
67
                    if (code < 0) goto exit;
722
56
                    use_label = false;
723
56
                }
724
1.44k
            }
725
1.49k
        }
726
4.46k
        if (use_label) {
727
4.40k
            code = pdfi_obj_get_label(ctx, (pdf_obj *)ref, &buf);
728
4.40k
            if (code < 0) goto exit;
729
4.40k
            *data = (byte *)buf;
730
4.40k
            *len = strlen(buf);
731
4.40k
        }
732
4.46k
    }
733
734
7.40k
 exit:
735
7.40k
    (void)pdfi_loop_detector_cleartomark(ctx);
736
7.40k
    pdfi_countdown(object);
737
7.40k
    return code;
738
7.40k
}
739
740
static int pdfi_obj_bool_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
741
3.34k
{
742
3.34k
    int code = 0;
743
3.34k
    int size = 5;
744
3.34k
    char *buf;
745
746
3.34k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_bool_str(data)");
747
3.34k
    if (buf == NULL)
748
0
        return_error(gs_error_VMerror);
749
3.34k
    if (obj == PDF_TRUE_OBJ) {
750
254
        memcpy(buf, (byte *)"true", 4);
751
254
        *len = 4;
752
3.09k
    } else {
753
3.09k
        memcpy(buf, (byte *)"false", 5);
754
3.09k
        *len = 5;
755
3.09k
    }
756
3.34k
    *data = (byte *)buf;
757
3.34k
    return code;
758
3.34k
}
759
760
static int pdfi_obj_null_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
761
314
{
762
314
    int code = 0;
763
314
    int size = 4;
764
314
    char *buf;
765
766
314
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_null_str(data)");
767
314
    if (buf == NULL)
768
0
        return_error(gs_error_VMerror);
769
314
    memcpy(buf, (byte *)"null", 4);
770
314
    *len = 4;
771
314
    *data = (byte *)buf;
772
314
    return code;
773
314
}
774
775
static int pdfi_obj_string_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
776
17.7k
{
777
17.7k
    pdf_string *string = (pdf_string *)obj;
778
17.7k
    char *buf;
779
17.7k
    int i, length = 0, j;
780
781
552k
    for (j=0;j<string->length;j++) {
782
534k
        if (string->data[j] == 0x0a || string->data[j] == 0x0d || string->data[j] == '(' || string->data[j] == ')' || string->data[j] == '\\')
783
1.06k
                length += 2;
784
533k
        else {
785
533k
            if (string->data[j] < 0x20 || string->data[j] > 0x7F || string->data[j] == '\\')
786
10.4k
                length += 4;
787
523k
            else
788
523k
                length++;
789
533k
        }
790
534k
    }
791
17.7k
    length += 2;
792
17.7k
    buf = (char *)gs_alloc_bytes(ctx->memory, length, "pdfi_obj_string_str(data)");
793
17.7k
    if (buf == NULL)
794
0
        return_error(gs_error_VMerror);
795
17.7k
    buf[0] = '(';
796
17.7k
    i = 1;
797
552k
    for (j=0;j<string->length;j++) {
798
534k
        switch(string->data[j]) {
799
191
            case 0x0a:
800
191
                buf[i++] = '\\';
801
191
                buf[i++] = 'n';
802
191
                break;
803
105
            case 0x0d:
804
105
                buf[i++] = '\\';
805
105
                buf[i++] = 'r';
806
105
                break;
807
383
            case '(':
808
767
            case ')':
809
770
            case '\\':
810
770
                buf[i++] = '\\';
811
770
                buf[i++] = string->data[j];
812
770
                break;
813
533k
            default:
814
533k
                if (string->data[j] < 0x20 || string->data[j] > 0x7F) {
815
10.4k
                    buf[i++] = '\\';
816
10.4k
                    buf[i++] = (string->data[j] >> 6) + 0x30;
817
10.4k
                    buf[i++] = ((string->data[j] & 0x3F) >> 3) + 0x30;
818
10.4k
                    buf[i++] = (string->data[j] & 0x07) + 0x30;
819
10.4k
                } else
820
523k
                buf[i++] = string->data[j];
821
533k
                break;
822
534k
        }
823
534k
    }
824
17.7k
    buf[i++] = ')';
825
826
17.7k
    *len = i;
827
17.7k
    *data = (byte *)buf;
828
17.7k
    return 0;
829
17.7k
}
830
831
static int pdfi_obj_array_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
832
18.4k
{
833
18.4k
    int code = 0;
834
18.4k
    pdf_array *array = (pdf_array *)obj;
835
18.4k
    pdf_obj *object = NULL;
836
18.4k
    byte *itembuf = NULL;
837
18.4k
    int itemsize;
838
18.4k
    pdfi_bufstream_t bufstream;
839
18.4k
    uint64_t index, arraysize;
840
841
18.4k
    code = pdfi_bufstream_init(ctx, &bufstream);
842
18.4k
    if (code < 0) goto exit;
843
844
18.4k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"[", 1);
845
18.4k
    if (code < 0) goto exit;
846
847
18.4k
    arraysize = pdfi_array_size(array);
848
147k
    for (index = 0; index < arraysize; index++) {
849
129k
        code = pdfi_array_get_no_deref(ctx, array, index, &object);
850
129k
        if (code < 0) goto exit;
851
852
129k
        code = pdfi_obj_to_string(ctx, object, &itembuf, &itemsize);
853
129k
        if (code < 0) goto exit;
854
855
128k
        code = pdfi_bufstream_write(ctx, &bufstream, itembuf, itemsize);
856
128k
        if (code < 0) goto exit;
857
858
128k
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_array_str(itembuf)");
859
128k
        itembuf = NULL;
860
128k
        itemsize = 0;
861
128k
        pdfi_countdown(object);
862
128k
        object = NULL;
863
864
        /* Put a space between elements unless last item */
865
128k
        if (index+1 != arraysize) {
866
110k
            code = pdfi_bufstream_write(ctx, &bufstream, (byte *)" ", 1);
867
110k
            if (code < 0) goto exit;
868
110k
        }
869
128k
    }
870
871
18.4k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"]", 1);
872
18.4k
    if (code < 0) goto exit;
873
874
    /* Now copy the results out into the string we can keep */
875
18.4k
    code = pdfi_bufstream_copy(ctx, &bufstream, data, len);
876
877
18.4k
 exit:
878
18.4k
    if (itembuf)
879
0
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_array_str(itembuf)");
880
18.4k
    pdfi_bufstream_free(ctx, &bufstream);
881
18.4k
    pdfi_countdown(object);
882
18.4k
    return code;
883
18.4k
}
884
885
static int pdfi_obj_stream_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
886
279
{
887
279
    int code = 0;
888
279
    byte *buf;
889
279
    pdf_stream *stream = (pdf_stream *)obj;
890
279
    int64_t bufsize = 0;
891
279
    pdf_indirect_ref *streamref = NULL;
892
893
    /* TODO: How to deal with stream dictionaries?
894
     * /AP is one example that has special handling (up in pdf_annot.c), but there are others.
895
     * See 'pushpin' annotation in annotations-galore_II.ps
896
     *
897
     * This will just literally grab the stream data.
898
     */
899
279
    if (stream->is_marking) {
900
247
        code = pdfi_stream_to_buffer(ctx, stream, &buf, &bufsize);
901
247
        if (code < 0) goto exit;
902
247
        *data = buf;
903
247
        *len = (int)bufsize;
904
247
    } else {
905
        /* Create an indirect ref for the stream */
906
32
        code = pdfi_object_alloc(ctx, PDF_INDIRECT, 0, (pdf_obj **)&streamref);
907
32
        if (code < 0) goto exit;
908
32
        pdfi_countup(streamref);
909
32
        streamref->ref_object_num = stream->object_num;
910
32
        streamref->ref_generation_num = stream->generation_num;
911
32
        code = pdfi_obj_indirect_str(ctx, (pdf_obj *)streamref, data, len);
912
32
    }
913
914
279
 exit:
915
279
    pdfi_countdown(streamref);
916
279
    return code;
917
279
}
918
919
/* This fetches without dereferencing.  If you want to see the references inline,
920
 * then you need to pre-resolve them.  See pdfi_resolve_indirect().
921
 */
922
static int pdfi_obj_dict_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
923
13.6k
{
924
13.6k
    int code = 0;
925
13.6k
    pdf_dict *dict = (pdf_dict *)obj;
926
13.6k
    pdf_name *Key = NULL;
927
13.6k
    pdf_obj *Value = NULL;
928
13.6k
    byte *itembuf = NULL;
929
13.6k
    int itemsize;
930
13.6k
    pdfi_bufstream_t bufstream;
931
13.6k
    uint64_t index, dictsize;
932
13.6k
    uint64_t itemnum = 0;
933
934
13.6k
    code = pdfi_loop_detector_mark(ctx);
935
13.6k
    if (code < 0)
936
0
        return code;
937
938
13.6k
    code = pdfi_bufstream_init(ctx, &bufstream);
939
13.6k
    if (code < 0) goto exit;
940
941
13.6k
    dictsize = pdfi_dict_entries(dict);
942
    /* Handle empty dict specially */
943
13.6k
    if (dictsize == 0) {
944
3
        code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"<< >>", 5);
945
3
        if (code < 0)
946
0
            goto exit;
947
3
        goto exit_copy;
948
3
    }
949
950
13.6k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"<<\n", 3);
951
13.6k
    if (code < 0) goto exit;
952
953
    /* Note: We specifically fetch without dereferencing, so there will be no circular
954
     * references to handle here.
955
     */
956
    /* Wrong.... */
957
958
13.6k
    if (dict->object_num !=0 ) {
959
2.57k
        if (pdfi_loop_detector_check_object(ctx, dict->object_num)) {
960
1
            code = gs_note_error(gs_error_circular_reference);
961
1
            goto exit;
962
1
        }
963
2.57k
        code = pdfi_loop_detector_add_object(ctx, dict->object_num);
964
2.57k
        if (code < 0)
965
0
            goto exit;
966
2.57k
    }
967
968
    /* Get each (key,val) pair from dict and setup param for it */
969
13.6k
    code = pdfi_dict_key_first(ctx, dict, (pdf_obj **)&Key, &index);
970
17.9k
    while (code >= 0) {
971
17.9k
        code = pdfi_obj_to_string(ctx, (pdf_obj *)Key, &itembuf, &itemsize);
972
17.9k
        if (code < 0) goto exit;
973
974
17.9k
        code = pdfi_bufstream_write(ctx, &bufstream, itembuf, itemsize);
975
17.9k
        if (code < 0) goto exit;
976
977
17.9k
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_dict_str(itembuf)");
978
17.9k
        itembuf = NULL;
979
17.9k
        itemsize = 0;
980
981
        /* Put a space between elements */
982
17.9k
        code = pdfi_bufstream_write(ctx, &bufstream, (byte *)" ", 1);
983
17.9k
        if (code < 0) goto exit;
984
985
        /* No dereference */
986
17.9k
        code = pdfi_dict_get_no_deref(ctx, dict, (const pdf_name *)Key, &Value);
987
17.9k
        if (code < 0) goto exit;
988
17.9k
        code = pdfi_obj_to_string(ctx, Value, &itembuf, &itemsize);
989
17.9k
        if (code < 0) goto exit;
990
991
17.8k
        code = pdfi_bufstream_write(ctx, &bufstream, itembuf, itemsize);
992
17.8k
        if (code < 0) goto exit;
993
994
17.8k
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_dict_str(itembuf)");
995
17.8k
        itembuf = NULL;
996
17.8k
        itemsize = 0;
997
998
17.8k
        pdfi_countdown(Value);
999
17.8k
        Value = NULL;
1000
17.8k
        pdfi_countdown(Key);
1001
17.8k
        Key = NULL;
1002
1003
17.8k
        code = pdfi_dict_key_next(ctx, dict, (pdf_obj **)&Key, &index);
1004
17.8k
        if (code == gs_error_undefined) {
1005
13.5k
            code = 0;
1006
13.5k
            break;
1007
13.5k
        }
1008
4.29k
        if (code < 0) goto exit;
1009
1010
        /* Put a space between elements */
1011
4.29k
        if (++itemnum != dictsize) {
1012
4.29k
            code = pdfi_bufstream_write(ctx, &bufstream, (byte *)" ", 1);
1013
4.29k
            if (code < 0) goto exit;
1014
4.29k
        }
1015
4.29k
    }
1016
13.5k
    if (code < 0) goto exit;
1017
1018
13.5k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"\n>>", 3);
1019
13.5k
    if (code < 0) goto exit;
1020
1021
13.5k
 exit_copy:
1022
    /* Now copy the results out into the string we can keep */
1023
13.5k
    code = pdfi_bufstream_copy(ctx, &bufstream, data, len);
1024
1025
13.6k
 exit:
1026
13.6k
    if (itembuf)
1027
0
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_dict_str(itembuf)");
1028
13.6k
    pdfi_countdown(Key);
1029
13.6k
    pdfi_countdown(Value);
1030
13.6k
    pdfi_bufstream_free(ctx, &bufstream);
1031
13.6k
    if (code < 0)
1032
61
        (void)pdfi_loop_detector_cleartomark(ctx);
1033
13.5k
    else
1034
13.5k
        code = pdfi_loop_detector_cleartomark(ctx);
1035
13.6k
    return code;
1036
13.5k
}
1037
1038
#define PARAM1(A) # A,
1039
#define PARAM2(A,B) A,
1040
static const char pdf_token_strings[][10] = {
1041
#include "pdf_tokens.h"
1042
};
1043
1044
static int pdfi_obj_fast_keyword_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
1045
0
{
1046
0
    int code = 0;
1047
0
    const char *s = pdf_token_strings[(uintptr_t)obj];
1048
0
    int size = (int)strlen(s) + 1;
1049
0
    byte *buf;
1050
1051
0
    buf = gs_alloc_bytes(ctx->memory, size, "pdfi_obj_name_str(data)");
1052
0
    if (buf == NULL)
1053
0
        return_error(gs_error_VMerror);
1054
0
    memcpy(buf, s, size);
1055
0
    *data = buf;
1056
0
    *len = size;
1057
0
    return code;
1058
0
}
1059
1060
obj_str_dispatch_t obj_str_dispatch[] = {
1061
    {PDF_NAME, pdfi_obj_name_str},
1062
    {PDF_ARRAY, pdfi_obj_array_str},
1063
    {PDF_REAL, pdfi_obj_real_str},
1064
    {PDF_INT, pdfi_obj_int_str},
1065
    {PDF_BOOL, pdfi_obj_bool_str},
1066
    {PDF_STRING, pdfi_obj_string_str},
1067
    {PDF_DICT, pdfi_obj_dict_str},
1068
    {PDF_STREAM, pdfi_obj_stream_str},
1069
    {PDF_INDIRECT, pdfi_obj_indirect_str},
1070
    {PDF_NULL, pdfi_obj_null_str},
1071
    {PDF_FAST_KEYWORD, pdfi_obj_fast_keyword_str},
1072
    {0, NULL}
1073
};
1074
1075
/* Recursive function to build a string from an object
1076
 */
1077
int pdfi_obj_to_string(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
1078
321k
{
1079
321k
    obj_str_dispatch_t *dispatch_ptr;
1080
321k
    int code = 0;
1081
321k
    pdf_obj_type type;
1082
1083
321k
    *data = NULL;
1084
321k
    *len = 0;
1085
321k
    type = pdfi_type_of(obj);
1086
970k
    for (dispatch_ptr = obj_str_dispatch; dispatch_ptr->func; dispatch_ptr ++) {
1087
970k
        if (type == dispatch_ptr->type) {
1088
321k
            code = dispatch_ptr->func(ctx, obj, data, len);
1089
321k
            goto exit;
1090
321k
        }
1091
970k
    }
1092
    /* Not implemented, use default */
1093
3
    code = pdfi_obj_default_str(ctx, obj, data, len);
1094
321k
 exit:
1095
321k
    return code;
1096
3
}
1097
1098
/*********** END obj_to_string module ************/