Coverage Report

Created: 2026-09-14 07:34

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
634M
{
39
634M
    int bytes = 0;
40
634M
    int code = 0;
41
42
634M
    switch(type) {
43
11.6M
        case PDF_ARRAY_MARK:
44
21.9M
        case PDF_DICT_MARK:
45
22.2M
        case PDF_PROC_MARK:
46
22.2M
            bytes = sizeof(pdf_obj);
47
22.2M
            break;
48
157M
        case PDF_INT:
49
278M
        case PDF_REAL:
50
278M
            bytes = sizeof(pdf_num);
51
278M
            break;
52
59.2M
        case PDF_STRING:
53
284M
        case PDF_NAME:
54
284M
            bytes = sizeof(pdf_string) + size - PDF_NAME_DECLARED_LENGTH;
55
284M
            break;
56
35.5k
        case PDF_BUFFER:
57
35.5k
            bytes = sizeof(pdf_buffer);
58
35.5k
            break;
59
11.5M
        case PDF_ARRAY:
60
11.5M
            bytes = sizeof(pdf_array);
61
11.5M
            break;
62
10.5M
        case PDF_DICT:
63
10.5M
            bytes = sizeof(pdf_dict);
64
10.5M
            break;
65
13.3M
        case PDF_INDIRECT:
66
13.3M
            bytes = sizeof(pdf_indirect_ref);
67
13.3M
            break;
68
13.2M
        case PDF_KEYWORD:
69
13.2M
            bytes = sizeof(pdf_keyword) + size - PDF_NAME_DECLARED_LENGTH;
70
13.2M
            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
889k
        case PDF_STREAM:
78
889k
            bytes = sizeof(pdf_stream);
79
889k
            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
634M
    }
86
634M
    *obj = (pdf_obj *)gs_alloc_bytes(ctx->memory, bytes, "pdfi_object_alloc");
87
634M
    if (*obj == NULL) {
88
0
        code = gs_note_error(gs_error_VMerror);
89
0
        goto error_out;
90
0
    }
91
92
634M
    memset(*obj, 0x00, bytes);
93
634M
    (*obj)->ctx = ctx;
94
634M
    (*obj)->type = type;
95
96
634M
    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
157M
        case PDF_INT:
106
278M
        case PDF_REAL:
107
291M
        case PDF_INDIRECT:
108
303M
        case PDF_ARRAY_MARK:
109
313M
        case PDF_DICT_MARK:
110
313M
        case PDF_PROC_MARK:
111
313M
            break;
112
13.2M
        case PDF_KEYWORD:
113
72.5M
        case PDF_STRING:
114
297M
        case PDF_NAME:
115
297M
            ((pdf_string *)*obj)->length = size;
116
297M
            break;
117
35.5k
        case PDF_BUFFER:
118
35.5k
            {
119
35.5k
                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.5k
                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.5k
                else {
130
35.5k
                    b->data = NULL;
131
35.5k
                }
132
35.5k
                b->length = size;
133
35.5k
            }
134
0
            break;
135
11.5M
        case PDF_ARRAY:
136
11.5M
            {
137
11.5M
                pdf_obj **values = NULL;
138
139
11.5M
                ((pdf_array *)*obj)->size = size;
140
11.5M
                if (size > 0) {
141
10.8M
                    values = (pdf_obj **)gs_alloc_bytes(ctx->memory, (size_t)size * sizeof(pdf_obj *), "pdfi_object_alloc");
142
10.8M
                    if (values == NULL) {
143
0
                        code = gs_note_error(gs_error_VMerror);
144
0
                        goto error_out;
145
0
                    }
146
10.8M
                    ((pdf_array *)*obj)->values = values;
147
10.8M
                    memset(((pdf_array *)*obj)->values, 0x00, size * sizeof(pdf_obj *));
148
10.8M
                }
149
11.5M
            }
150
11.5M
            break;
151
11.5M
        case PDF_DICT:
152
10.5M
            {
153
10.5M
                pdf_dict_entry *entries = NULL;
154
155
10.5M
                ((pdf_dict *)*obj)->size = size;
156
10.5M
                if (size > 0) {
157
10.0M
                    entries = (pdf_dict_entry *)gs_alloc_bytes(ctx->memory, (size_t)size * sizeof(pdf_dict_entry), "pdfi_object_alloc");
158
10.0M
                    if (entries == NULL) {
159
0
                        code = gs_note_error(gs_error_VMerror);
160
0
                        goto error_out;
161
0
                    }
162
10.0M
                    ((pdf_dict *)*obj)->list = entries;
163
10.0M
                    memset(((pdf_dict *)*obj)->list, 0x00, size * sizeof(pdf_dict_entry));
164
10.0M
                }
165
10.5M
            }
166
10.5M
            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.5M
        case PDF_XREF_TABLE:
171
0
            break;
172
889k
        default:
173
889k
            break;
174
634M
    }
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
634M
    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
634M
}
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.2k
{
192
10.2k
    uint64_t test = 0;
193
10.2k
    int code = 0;
194
195
10.2k
    test = (uint64_t)floor(d);
196
10.2k
    if (d == test) {
197
7.45k
        code = pdfi_object_alloc(ctx, PDF_INT, 0, (pdf_obj **)num);
198
7.45k
        if (code < 0)
199
0
            return code;
200
7.45k
        (*num)->value.i = test;
201
7.45k
    }
202
2.80k
    else {
203
2.80k
        code = pdfi_object_alloc(ctx, PDF_REAL, 0, (pdf_obj **)num);
204
2.80k
        if (code < 0)
205
0
            return code;
206
2.80k
        (*num)->value.d = d;
207
2.80k
    }
208
209
10.2k
    return 0;
210
10.2k
}
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.2M
{
230
13.2M
    pdf_keyword *k = (pdf_keyword *)o;
231
232
13.2M
    gs_free_object(OBJ_MEMORY(k), k, "pdf interpreter free keyword");
233
13.2M
}
234
235
static void pdfi_free_xref_table(pdf_obj *o)
236
76.9k
{
237
76.9k
    xref_table_t *xref = (xref_table_t *)o;
238
239
76.9k
    gs_free_object(OBJ_MEMORY(xref), xref->xref, "pdfi_free_xref_table");
240
76.9k
    gs_free_object(OBJ_MEMORY(xref), xref, "pdfi_free_xref_table");
241
76.9k
}
242
243
static void pdfi_free_stream(pdf_obj *o)
244
888k
{
245
888k
    pdf_stream *stream = (pdf_stream *)o;
246
247
888k
    pdfi_countdown(stream->stream_dict);
248
888k
    gs_free_object(OBJ_MEMORY(o), o, "pdfi_free_stream");
249
888k
}
250
251
static void pdfi_free_buffer(pdf_obj *o)
252
35.5k
{
253
35.5k
    pdf_buffer *b = (pdf_buffer *)o;
254
255
35.5k
    gs_free_object(OBJ_MEMORY(b), b->data, "pdfi_free_buffer(data)");
256
35.5k
    gs_free_object(OBJ_MEMORY(o), o, "pdfi_free_buffer");
257
35.5k
}
258
259
void pdfi_free_object(pdf_obj *o)
260
636M
{
261
636M
    if (o == NULL)
262
640k
        return;
263
635M
    if ((intptr_t)o < (intptr_t)TOKEN__LAST_KEY)
264
0
        return;
265
635M
    switch(o->type) {
266
11.6M
        case PDF_ARRAY_MARK:
267
21.9M
        case PDF_DICT_MARK:
268
22.2M
        case PDF_PROC_MARK:
269
180M
        case PDF_INT:
270
300M
        case PDF_REAL:
271
313M
        case PDF_INDIRECT:
272
313M
            gs_free_object(OBJ_MEMORY(o), o, "pdf interpreter object refcount to 0");
273
313M
            break;
274
59.2M
        case PDF_STRING:
275
284M
        case PDF_NAME:
276
284M
            pdfi_free_namestring(o);
277
284M
            break;
278
35.5k
        case PDF_BUFFER:
279
35.5k
            pdfi_free_buffer(o);
280
35.5k
            break;
281
11.5M
        case PDF_ARRAY:
282
11.5M
            pdfi_free_array(o);
283
11.5M
            break;
284
10.5M
        case PDF_DICT:
285
10.5M
            pdfi_free_dict(o);
286
10.5M
            break;
287
888k
        case PDF_STREAM:
288
888k
            pdfi_free_stream(o);
289
888k
            break;
290
13.2M
        case PDF_KEYWORD:
291
13.2M
            pdfi_free_keyword(o);
292
13.2M
            break;
293
76.9k
        case PDF_XREF_TABLE:
294
76.9k
            pdfi_free_xref_table(o);
295
76.9k
            break;
296
561k
        case PDF_FONT:
297
561k
            pdfi_free_font(o);
298
561k
            break;
299
63.4k
        case PDF_CMAP:
300
63.4k
            pdfi_free_cmap(o);
301
63.4k
            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
635M
    }
310
635M
}
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
889k
{
320
889k
    int code = 0;
321
889k
    pdf_stream *new_stream = NULL;
322
323
889k
    if (pdfi_type_of(dict) != PDF_DICT)
324
0
        return_error(gs_error_typecheck);
325
326
889k
    code = pdfi_object_alloc(ctx, PDF_STREAM, 0, (pdf_obj **)&new_stream);
327
889k
    if (code < 0)
328
0
        goto error_exit;
329
330
889k
    new_stream->ctx = ctx;
331
889k
    pdfi_countup(new_stream);
332
333
889k
    new_stream->stream_dict = dict;
334
889k
    pdfi_countup(dict);
335
336
    /* this replaces the dict with the stream.
337
     * assumes it's not cached
338
     */
339
889k
    if (do_convert) {
340
857k
        new_stream->object_num = dict->object_num;
341
857k
        new_stream->generation_num = dict->generation_num;
342
857k
        dict->object_num = 0;
343
857k
        dict->generation_num = 0;
344
857k
    }
345
889k
    *stream = new_stream;
346
889k
    return 0;
347
348
0
 error_exit:
349
0
    pdfi_countdown(new_stream);
350
0
    return code;
351
889k
}
352
353
int pdfi_get_stream_dict(pdf_context *ctx, pdf_stream *stream, pdf_dict **dict)
354
213
{
355
213
    *dict = stream->stream_dict;
356
357
    /* Make sure the dictionary won't go away */
358
213
    pdfi_countup(*dict);
359
213
    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
213
    return 0;
365
213
}
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
358
{
370
358
    int code;
371
358
    int length = strlen(charstr);
372
358
    pdf_string *newstr = NULL;
373
374
358
    *string = NULL;
375
376
358
    code = pdfi_object_alloc(ctx, PDF_STRING, length, (pdf_obj **)&newstr);
377
358
    if (code < 0) goto exit;
378
379
358
    memcpy(newstr->data, (byte *)charstr, length);
380
381
358
    *string = newstr;
382
358
    pdfi_countup(newstr);
383
358
 exit:
384
358
    return code;
385
358
}
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
407k
{
390
407k
    int code;
391
407k
    int length = strlen(charstr);
392
407k
    pdf_name *newname = NULL;
393
394
407k
    *name = NULL;
395
396
407k
    code = pdfi_object_alloc(ctx, PDF_NAME, length, (pdf_obj **)&newname);
397
407k
    if (code < 0) goto exit;
398
399
407k
    memcpy(newname->data, (byte *)charstr, length);
400
401
407k
    *name = newname;
402
407k
    pdfi_countup(newname);
403
407k
 exit:
404
407k
    return code;
405
407k
}
406
407
/************ bufstream module BEGIN **************/
408
29.2k
#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
29.2k
{
419
29.2k
    stream->len = INIT_BUF_SIZE;
420
29.2k
    stream->cur = 0;
421
29.2k
    stream->data = gs_alloc_bytes(ctx->memory, stream->len, "pdfi_bufstream_init(data)");
422
423
29.2k
    if (!stream->data)
424
0
        return_error(gs_error_VMerror);
425
29.2k
    return 0;
426
29.2k
}
427
428
static int pdfi_bufstream_free(pdf_context *ctx, pdfi_bufstream_t *stream)
429
29.2k
{
430
29.2k
    if (stream->data)
431
99
        gs_free_object(ctx->memory, stream->data, "pdfi_bufstream_free(data)");
432
29.2k
    stream->len = 0;
433
29.2k
    stream->cur = 0;
434
29.2k
    stream->data = NULL;
435
29.2k
    return 0;
436
29.2k
}
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
29.1k
{
441
29.1k
    *buf = stream->data;
442
29.1k
    *len = stream->cur;
443
29.1k
    stream->len = 0;
444
29.1k
    stream->cur = 0;
445
29.1k
    stream->data = NULL;
446
29.1k
    return 0;
447
29.1k
}
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.06k
{
452
1.06k
    byte *data = NULL;
453
1.06k
    uint64_t newsize;
454
455
1.06k
    if (needed > max_int || stream->len > (max_int - needed) / 2)
456
0
        return_error(gs_error_rangecheck);
457
458
1.06k
    newsize = stream->len * 2 + needed;
459
1.06k
    data = gs_alloc_bytes(ctx->memory, newsize, "pdfi_bufstream_increase(data)");
460
1.06k
    if (!data)
461
0
        return_error(gs_error_VMerror);
462
463
1.06k
    memcpy(data, stream->data, stream->len);
464
1.06k
    gs_free_object(ctx->memory, stream->data, "pdfi_bufstream_increase(data)");
465
1.06k
    stream->data = data;
466
1.06k
    stream->len = newsize;
467
468
1.06k
    return 0;
469
1.06k
}
470
471
static int pdfi_bufstream_write(pdf_context *ctx, pdfi_bufstream_t *stream, byte *data, uint64_t len)
472
330k
{
473
330k
    int code = 0;
474
475
330k
    if (stream->cur + len > stream->len) {
476
1.06k
        code = pdfi_bufstream_increase(ctx, stream, len);
477
1.06k
        if (code < 0)
478
0
            goto exit;
479
1.06k
    }
480
330k
    memcpy(stream->data + stream->cur, data, len);
481
330k
    stream->cur += len;
482
483
330k
 exit:
484
330k
    return code;
485
330k
}
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.10k
{
502
4.10k
    int code = 0, i;
503
4.10k
    int length;
504
4.10k
    const char *template = "{Obj%dG%dF%d}"; /* The '{' and '}' are special to pdfmark/pdfwrite driver */
505
4.10k
    char *string = NULL;
506
4.10k
    pdf_indirect_ref *ref = (pdf_indirect_ref *)obj;
507
4.10k
    uint32_t hash = 5381;
508
509
4.10k
    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.10k
    *label = NULL;
523
4.10k
    length = strlen(template)+30;
524
525
4.10k
    string = (char *)gs_alloc_bytes(ctx->memory, length, "pdf_obj_get_label(label)");
526
4.10k
    if (string == NULL) {
527
0
        code = gs_note_error(gs_error_VMerror);
528
0
        goto exit;
529
0
    }
530
531
4.10k
    if (pdfi_type_of(obj) == PDF_INDIRECT)
532
4.09k
        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.10k
    *label = string;
537
4.10k
 exit:
538
4.10k
    return code;
539
4.10k
}
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
108k
{
568
108k
    int code = 0, i;
569
108k
    pdf_name *name = (pdf_name *)obj;
570
108k
    int esc_size = 1;
571
108k
    byte *buf;
572
573
    /* We need to 'escape' any characters that can't be represented in a PDF name. */
574
576k
    for (i = 0;i < name->length;i++) {
575
468k
        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
468k
            default:
595
468k
                esc_size++;
596
468k
                break;
597
468k
        }
598
468k
    }
599
600
108k
    buf = gs_alloc_bytes(ctx->memory, esc_size, "pdfi_obj_name_str(data)");
601
108k
    if (buf == NULL)
602
0
        return_error(gs_error_VMerror);
603
108k
    buf[0] = '/';
604
108k
    esc_size = 1;
605
606
576k
    for (i = 0;i < name->length;i++) {
607
468k
        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
468k
            default:
629
468k
                buf[esc_size++] = name->data[i];
630
468k
                break;
631
468k
        }
632
468k
    }
633
634
//    memcpy(buf+1, name->data, name->length);
635
108k
    *data = buf;
636
108k
    *len = esc_size;
637
108k
    return code;
638
108k
}
639
640
static int pdfi_obj_real_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
641
39.3k
{
642
39.3k
    int code = 0;
643
39.3k
    int size = 15;
644
39.3k
    pdf_num *number = (pdf_num *)obj;
645
39.3k
    char *buf;
646
647
39.3k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_real_str(data)");
648
39.3k
    if (buf == NULL)
649
0
        return_error(gs_error_VMerror);
650
39.3k
    snprintf(buf, size, "%.4f", number->value.d);
651
39.3k
    *data = (byte *)buf;
652
39.3k
    *len = strlen(buf);
653
39.3k
    return code;
654
39.3k
}
655
656
static int pdfi_obj_int_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
657
91.6k
{
658
91.6k
    int code = 0;
659
91.6k
    int size = 15;
660
91.6k
    pdf_num *number = (pdf_num *)obj;
661
91.6k
    char *buf;
662
663
91.6k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_int_str(data)");
664
91.6k
    if (buf == NULL)
665
0
        return_error(gs_error_VMerror);
666
91.6k
    snprintf(buf, size, "%"PRId64"", number->value.i);
667
91.6k
    *data = (byte *)buf;
668
91.6k
    *len = strlen(buf);
669
91.6k
    return code;
670
91.6k
}
671
672
static int pdfi_obj_getrefstr(pdf_context *ctx, uint64_t object_num, uint32_t generation, byte **data, int *len)
673
2.66k
{
674
2.66k
    int size = 100;
675
2.66k
    char *buf;
676
677
2.66k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_getrefstr(data)");
678
2.66k
    if (buf == NULL)
679
0
        return_error(gs_error_VMerror);
680
2.66k
    snprintf(buf, size, "%"PRId64" %d R", object_num, generation);
681
2.66k
    *data = (byte *)buf;
682
2.66k
    *len = strlen(buf);
683
2.66k
    return 0;
684
2.66k
}
685
686
static int pdfi_obj_indirect_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
687
6.92k
{
688
6.92k
    int code = 0;
689
6.92k
    pdf_indirect_ref *ref = (pdf_indirect_ref *)obj;
690
6.92k
    char *buf;
691
6.92k
    pdf_obj *object = NULL;
692
6.92k
    bool use_label = true;
693
694
6.92k
    code = pdfi_loop_detector_mark(ctx);
695
6.92k
    if (code < 0)
696
0
        return code;
697
698
6.92k
    if (ref->is_highlevelform) {
699
2.27k
        code = pdfi_obj_getrefstr(ctx, ref->highlevel_object_num, 0, data, len);
700
2.27k
        ref->is_highlevelform = false;
701
4.64k
    } else {
702
4.64k
        if (!ref->is_marking) {
703
1.90k
            code = pdfi_dereference(ctx, ref->ref_object_num, ref->ref_generation_num, &object);
704
1.90k
            if (code == gs_error_undefined) {
705
                /* Do something sensible for undefined reference (this would be a broken file) */
706
                /* TODO: Flag an error? */
707
387
                code = pdfi_obj_getrefstr(ctx, ref->ref_object_num, ref->ref_generation_num, data, len);
708
387
                goto exit;
709
387
            }
710
1.51k
            if (code < 0 && code != gs_error_circular_reference)
711
56
                goto exit;
712
1.45k
            if (code == 0) {
713
1.40k
                if (pdfi_type_of(object) == PDF_STREAM) {
714
222
                    code = pdfi_pdfmark_stream(ctx, (pdf_stream *)object);
715
222
                    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.40k
            }
725
1.45k
        }
726
4.14k
        if (use_label) {
727
4.09k
            code = pdfi_obj_get_label(ctx, (pdf_obj *)ref, &buf);
728
4.09k
            if (code < 0) goto exit;
729
4.09k
            *data = (byte *)buf;
730
4.09k
            *len = strlen(buf);
731
4.09k
        }
732
4.14k
    }
733
734
6.92k
 exit:
735
6.92k
    (void)pdfi_loop_detector_cleartomark(ctx);
736
6.92k
    pdfi_countdown(object);
737
6.92k
    return code;
738
6.92k
}
739
740
static int pdfi_obj_bool_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
741
3.06k
{
742
3.06k
    int code = 0;
743
3.06k
    int size = 5;
744
3.06k
    char *buf;
745
746
3.06k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_bool_str(data)");
747
3.06k
    if (buf == NULL)
748
0
        return_error(gs_error_VMerror);
749
3.06k
    if (obj == PDF_TRUE_OBJ) {
750
242
        memcpy(buf, (byte *)"true", 4);
751
242
        *len = 4;
752
2.82k
    } else {
753
2.82k
        memcpy(buf, (byte *)"false", 5);
754
2.82k
        *len = 5;
755
2.82k
    }
756
3.06k
    *data = (byte *)buf;
757
3.06k
    return code;
758
3.06k
}
759
760
static int pdfi_obj_null_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
761
303
{
762
303
    int code = 0;
763
303
    int size = 4;
764
303
    char *buf;
765
766
303
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_null_str(data)");
767
303
    if (buf == NULL)
768
0
        return_error(gs_error_VMerror);
769
303
    memcpy(buf, (byte *)"null", 4);
770
303
    *len = 4;
771
303
    *data = (byte *)buf;
772
303
    return code;
773
303
}
774
775
static int pdfi_obj_string_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
776
15.4k
{
777
15.4k
    pdf_string *string = (pdf_string *)obj;
778
15.4k
    char *buf;
779
15.4k
    int i, length = 0, j;
780
781
511k
    for (j=0;j<string->length;j++) {
782
496k
        if (string->data[j] == 0x0a || string->data[j] == 0x0d || string->data[j] == '(' || string->data[j] == ')' || string->data[j] == '\\')
783
976
                length += 2;
784
495k
        else {
785
495k
            if (string->data[j] < 0x20 || string->data[j] > 0x7F || string->data[j] == '\\')
786
9.55k
                length += 4;
787
485k
            else
788
485k
                length++;
789
495k
        }
790
496k
    }
791
15.4k
    length += 2;
792
15.4k
    buf = (char *)gs_alloc_bytes(ctx->memory, length, "pdfi_obj_string_str(data)");
793
15.4k
    if (buf == NULL)
794
0
        return_error(gs_error_VMerror);
795
15.4k
    buf[0] = '(';
796
15.4k
    i = 1;
797
511k
    for (j=0;j<string->length;j++) {
798
496k
        switch(string->data[j]) {
799
181
            case 0x0a:
800
181
                buf[i++] = '\\';
801
181
                buf[i++] = 'n';
802
181
                break;
803
97
            case 0x0d:
804
97
                buf[i++] = '\\';
805
97
                buf[i++] = 'r';
806
97
                break;
807
347
            case '(':
808
695
            case ')':
809
698
            case '\\':
810
698
                buf[i++] = '\\';
811
698
                buf[i++] = string->data[j];
812
698
                break;
813
495k
            default:
814
495k
                if (string->data[j] < 0x20 || string->data[j] > 0x7F) {
815
9.55k
                    buf[i++] = '\\';
816
9.55k
                    buf[i++] = (string->data[j] >> 6) + 0x30;
817
9.55k
                    buf[i++] = ((string->data[j] & 0x3F) >> 3) + 0x30;
818
9.55k
                    buf[i++] = (string->data[j] & 0x07) + 0x30;
819
9.55k
                } else
820
485k
                buf[i++] = string->data[j];
821
495k
                break;
822
496k
        }
823
496k
    }
824
15.4k
    buf[i++] = ')';
825
826
15.4k
    *len = i;
827
15.4k
    *data = (byte *)buf;
828
15.4k
    return 0;
829
15.4k
}
830
831
static int pdfi_obj_array_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
832
17.2k
{
833
17.2k
    int code = 0;
834
17.2k
    pdf_array *array = (pdf_array *)obj;
835
17.2k
    pdf_obj *object = NULL;
836
17.2k
    byte *itembuf = NULL;
837
17.2k
    int itemsize;
838
17.2k
    pdfi_bufstream_t bufstream;
839
17.2k
    uint64_t index, arraysize;
840
841
17.2k
    code = pdfi_bufstream_init(ctx, &bufstream);
842
17.2k
    if (code < 0) goto exit;
843
844
17.2k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"[", 1);
845
17.2k
    if (code < 0) goto exit;
846
847
17.2k
    arraysize = pdfi_array_size(array);
848
137k
    for (index = 0; index < arraysize; index++) {
849
120k
        code = pdfi_array_get_no_deref(ctx, array, index, &object);
850
120k
        if (code < 0) goto exit;
851
852
120k
        code = pdfi_obj_to_string(ctx, object, &itembuf, &itemsize);
853
120k
        if (code < 0) goto exit;
854
855
120k
        code = pdfi_bufstream_write(ctx, &bufstream, itembuf, itemsize);
856
120k
        if (code < 0) goto exit;
857
858
120k
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_array_str(itembuf)");
859
120k
        itembuf = NULL;
860
120k
        itemsize = 0;
861
120k
        pdfi_countdown(object);
862
120k
        object = NULL;
863
864
        /* Put a space between elements unless last item */
865
120k
        if (index+1 != arraysize) {
866
102k
            code = pdfi_bufstream_write(ctx, &bufstream, (byte *)" ", 1);
867
102k
            if (code < 0) goto exit;
868
102k
        }
869
120k
    }
870
871
17.1k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"]", 1);
872
17.1k
    if (code < 0) goto exit;
873
874
    /* Now copy the results out into the string we can keep */
875
17.1k
    code = pdfi_bufstream_copy(ctx, &bufstream, data, len);
876
877
17.2k
 exit:
878
17.2k
    if (itembuf)
879
0
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_array_str(itembuf)");
880
17.2k
    pdfi_bufstream_free(ctx, &bufstream);
881
17.2k
    pdfi_countdown(object);
882
17.2k
    return code;
883
17.1k
}
884
885
static int pdfi_obj_stream_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
886
242
{
887
242
    int code = 0;
888
242
    byte *buf;
889
242
    pdf_stream *stream = (pdf_stream *)obj;
890
242
    int64_t bufsize = 0;
891
242
    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
242
    if (stream->is_marking) {
900
210
        code = pdfi_stream_to_buffer(ctx, stream, &buf, &bufsize);
901
210
        if (code < 0) goto exit;
902
210
        *data = buf;
903
210
        *len = (int)bufsize;
904
210
    } 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
242
 exit:
915
242
    pdfi_countdown(streamref);
916
242
    return code;
917
242
}
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
12.0k
{
924
12.0k
    int code = 0;
925
12.0k
    pdf_dict *dict = (pdf_dict *)obj;
926
12.0k
    pdf_name *Key = NULL;
927
12.0k
    pdf_obj *Value = NULL;
928
12.0k
    byte *itembuf = NULL;
929
12.0k
    int itemsize;
930
12.0k
    pdfi_bufstream_t bufstream;
931
12.0k
    uint64_t index, dictsize;
932
12.0k
    uint64_t itemnum = 0;
933
934
12.0k
    code = pdfi_loop_detector_mark(ctx);
935
12.0k
    if (code < 0)
936
0
        return code;
937
938
12.0k
    code = pdfi_bufstream_init(ctx, &bufstream);
939
12.0k
    if (code < 0) goto exit;
940
941
12.0k
    dictsize = pdfi_dict_entries(dict);
942
    /* Handle empty dict specially */
943
12.0k
    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
12.0k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"<<\n", 3);
951
12.0k
    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
12.0k
    if (dict->object_num !=0 ) {
959
2.41k
        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.41k
        code = pdfi_loop_detector_add_object(ctx, dict->object_num);
964
2.41k
        if (code < 0)
965
0
            goto exit;
966
2.41k
    }
967
968
    /* Get each (key,val) pair from dict and setup param for it */
969
12.0k
    code = pdfi_dict_key_first(ctx, dict, (pdf_obj **)&Key, &index);
970
15.3k
    while (code >= 0) {
971
15.3k
        code = pdfi_obj_to_string(ctx, (pdf_obj *)Key, &itembuf, &itemsize);
972
15.3k
        if (code < 0) goto exit;
973
974
15.3k
        code = pdfi_bufstream_write(ctx, &bufstream, itembuf, itemsize);
975
15.3k
        if (code < 0) goto exit;
976
977
15.3k
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_dict_str(itembuf)");
978
15.3k
        itembuf = NULL;
979
15.3k
        itemsize = 0;
980
981
        /* Put a space between elements */
982
15.3k
        code = pdfi_bufstream_write(ctx, &bufstream, (byte *)" ", 1);
983
15.3k
        if (code < 0) goto exit;
984
985
        /* No dereference */
986
15.3k
        code = pdfi_dict_get_no_deref(ctx, dict, (const pdf_name *)Key, &Value);
987
15.3k
        if (code < 0) goto exit;
988
15.3k
        code = pdfi_obj_to_string(ctx, Value, &itembuf, &itemsize);
989
15.3k
        if (code < 0) goto exit;
990
991
15.2k
        code = pdfi_bufstream_write(ctx, &bufstream, itembuf, itemsize);
992
15.2k
        if (code < 0) goto exit;
993
994
15.2k
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_dict_str(itembuf)");
995
15.2k
        itembuf = NULL;
996
15.2k
        itemsize = 0;
997
998
15.2k
        pdfi_countdown(Value);
999
15.2k
        Value = NULL;
1000
15.2k
        pdfi_countdown(Key);
1001
15.2k
        Key = NULL;
1002
1003
15.2k
        code = pdfi_dict_key_next(ctx, dict, (pdf_obj **)&Key, &index);
1004
15.2k
        if (code == gs_error_undefined) {
1005
11.9k
            code = 0;
1006
11.9k
            break;
1007
11.9k
        }
1008
3.26k
        if (code < 0) goto exit;
1009
1010
        /* Put a space between elements */
1011
3.26k
        if (++itemnum != dictsize) {
1012
3.26k
            code = pdfi_bufstream_write(ctx, &bufstream, (byte *)" ", 1);
1013
3.26k
            if (code < 0) goto exit;
1014
3.26k
        }
1015
3.26k
    }
1016
11.9k
    if (code < 0) goto exit;
1017
1018
11.9k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"\n>>", 3);
1019
11.9k
    if (code < 0) goto exit;
1020
1021
11.9k
 exit_copy:
1022
    /* Now copy the results out into the string we can keep */
1023
11.9k
    code = pdfi_bufstream_copy(ctx, &bufstream, data, len);
1024
1025
12.0k
 exit:
1026
12.0k
    if (itembuf)
1027
0
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_dict_str(itembuf)");
1028
12.0k
    pdfi_countdown(Key);
1029
12.0k
    pdfi_countdown(Value);
1030
12.0k
    pdfi_bufstream_free(ctx, &bufstream);
1031
12.0k
    if (code < 0)
1032
61
        (void)pdfi_loop_detector_cleartomark(ctx);
1033
11.9k
    else
1034
11.9k
        code = pdfi_loop_detector_cleartomark(ctx);
1035
12.0k
    return code;
1036
11.9k
}
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
294k
{
1079
294k
    obj_str_dispatch_t *dispatch_ptr;
1080
294k
    int code = 0;
1081
294k
    pdf_obj_type type;
1082
1083
294k
    *data = NULL;
1084
294k
    *len = 0;
1085
294k
    type = pdfi_type_of(obj);
1086
886k
    for (dispatch_ptr = obj_str_dispatch; dispatch_ptr->func; dispatch_ptr ++) {
1087
886k
        if (type == dispatch_ptr->type) {
1088
294k
            code = dispatch_ptr->func(ctx, obj, data, len);
1089
294k
            goto exit;
1090
294k
        }
1091
886k
    }
1092
    /* Not implemented, use default */
1093
3
    code = pdfi_obj_default_str(ctx, obj, data, len);
1094
294k
 exit:
1095
294k
    return code;
1096
3
}
1097
1098
/*********** END obj_to_string module ************/