Coverage Report

Created: 2026-10-28 08:05

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
692M
{
39
692M
    int bytes = 0;
40
692M
    int code = 0;
41
42
692M
    switch(type) {
43
12.8M
        case PDF_ARRAY_MARK:
44
24.2M
        case PDF_DICT_MARK:
45
24.5M
        case PDF_PROC_MARK:
46
24.5M
            bytes = sizeof(pdf_obj);
47
24.5M
            break;
48
175M
        case PDF_INT:
49
310M
        case PDF_REAL:
50
310M
            bytes = sizeof(pdf_num);
51
310M
            break;
52
63.5M
        case PDF_STRING:
53
301M
        case PDF_NAME:
54
301M
            bytes = sizeof(pdf_string) + size - PDF_NAME_DECLARED_LENGTH;
55
301M
            break;
56
38.0k
        case PDF_BUFFER:
57
38.0k
            bytes = sizeof(pdf_buffer);
58
38.0k
            break;
59
12.7M
        case PDF_ARRAY:
60
12.7M
            bytes = sizeof(pdf_array);
61
12.7M
            break;
62
11.6M
        case PDF_DICT:
63
11.6M
            bytes = sizeof(pdf_dict);
64
11.6M
            break;
65
15.2M
        case PDF_INDIRECT:
66
15.2M
            bytes = sizeof(pdf_indirect_ref);
67
15.2M
            break;
68
15.2M
        case PDF_KEYWORD:
69
15.2M
            bytes = sizeof(pdf_keyword) + size - PDF_NAME_DECLARED_LENGTH;
70
15.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
959k
        case PDF_STREAM:
78
959k
            bytes = sizeof(pdf_stream);
79
959k
            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
692M
    }
86
692M
    *obj = (pdf_obj *)gs_alloc_bytes(ctx->memory, bytes, "pdfi_object_alloc");
87
692M
    if (*obj == NULL) {
88
0
        code = gs_note_error(gs_error_VMerror);
89
0
        goto error_out;
90
0
    }
91
92
692M
    memset(*obj, 0x00, bytes);
93
692M
    (*obj)->ctx = ctx;
94
692M
    (*obj)->type = type;
95
96
692M
    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
175M
        case PDF_INT:
106
310M
        case PDF_REAL:
107
325M
        case PDF_INDIRECT:
108
338M
        case PDF_ARRAY_MARK:
109
350M
        case PDF_DICT_MARK:
110
350M
        case PDF_PROC_MARK:
111
350M
            break;
112
15.2M
        case PDF_KEYWORD:
113
78.8M
        case PDF_STRING:
114
316M
        case PDF_NAME:
115
316M
            ((pdf_string *)*obj)->length = size;
116
316M
            break;
117
38.0k
        case PDF_BUFFER:
118
38.0k
            {
119
38.0k
                pdf_buffer *b = (pdf_buffer *)*obj;
120
               /* NOTE: size can be 0 if the caller wants to allocate the data area itself
121
                */
122
38.0k
                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
38.0k
                else {
130
38.0k
                    b->data = NULL;
131
38.0k
                }
132
38.0k
                b->length = size;
133
38.0k
            }
134
0
            break;
135
12.7M
        case PDF_ARRAY:
136
12.7M
            {
137
12.7M
                pdf_obj **values = NULL;
138
139
12.7M
                ((pdf_array *)*obj)->size = size;
140
12.7M
                if (size > 0) {
141
11.9M
                    values = (pdf_obj **)gs_alloc_bytes(ctx->memory, (size_t)size * sizeof(pdf_obj *), "pdfi_object_alloc");
142
11.9M
                    if (values == NULL) {
143
0
                        code = gs_note_error(gs_error_VMerror);
144
0
                        goto error_out;
145
0
                    }
146
11.9M
                    ((pdf_array *)*obj)->values = values;
147
11.9M
                    memset(((pdf_array *)*obj)->values, 0x00, size * sizeof(pdf_obj *));
148
11.9M
                }
149
12.7M
            }
150
12.7M
            break;
151
12.7M
        case PDF_DICT:
152
11.6M
            {
153
11.6M
                pdf_dict_entry *entries = NULL;
154
155
11.6M
                ((pdf_dict *)*obj)->size = size;
156
11.6M
                if (size > 0) {
157
11.1M
                    entries = (pdf_dict_entry *)gs_alloc_bytes(ctx->memory, (size_t)size * sizeof(pdf_dict_entry), "pdfi_object_alloc");
158
11.1M
                    if (entries == NULL) {
159
0
                        code = gs_note_error(gs_error_VMerror);
160
0
                        goto error_out;
161
0
                    }
162
11.1M
                    ((pdf_dict *)*obj)->list = entries;
163
11.1M
                    memset(((pdf_dict *)*obj)->list, 0x00, size * sizeof(pdf_dict_entry));
164
11.1M
                }
165
11.6M
            }
166
11.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
11.6M
        case PDF_XREF_TABLE:
171
0
            break;
172
959k
        default:
173
959k
            break;
174
692M
    }
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
692M
    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
692M
}
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.3k
{
192
10.3k
    uint64_t test = 0;
193
10.3k
    int code = 0;
194
195
10.3k
    test = (uint64_t)floor(d);
196
10.3k
    if (d == test) {
197
7.53k
        code = pdfi_object_alloc(ctx, PDF_INT, 0, (pdf_obj **)num);
198
7.53k
        if (code < 0)
199
0
            return code;
200
7.53k
        (*num)->value.i = test;
201
7.53k
    }
202
2.84k
    else {
203
2.84k
        code = pdfi_object_alloc(ctx, PDF_REAL, 0, (pdf_obj **)num);
204
2.84k
        if (code < 0)
205
0
            return code;
206
2.84k
        (*num)->value.d = d;
207
2.84k
    }
208
209
10.3k
    return 0;
210
10.3k
}
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
301M
{
222
    /* Currently names and strings are the same, so a single cast is OK */
223
301M
    pdf_name *n = (pdf_name *)o;
224
225
301M
    gs_free_object(OBJ_MEMORY(n), n, "pdf interpreter free name or string");
226
301M
}
227
228
static void pdfi_free_keyword(pdf_obj *o)
229
15.2M
{
230
15.2M
    pdf_keyword *k = (pdf_keyword *)o;
231
232
15.2M
    gs_free_object(OBJ_MEMORY(k), k, "pdf interpreter free keyword");
233
15.2M
}
234
235
static void pdfi_free_xref_table(pdf_obj *o)
236
82.6k
{
237
82.6k
    xref_table_t *xref = (xref_table_t *)o;
238
239
82.6k
    gs_free_object(OBJ_MEMORY(xref), xref->xref, "pdfi_free_xref_table");
240
82.6k
    gs_free_object(OBJ_MEMORY(xref), xref, "pdfi_free_xref_table");
241
82.6k
}
242
243
static void pdfi_free_stream(pdf_obj *o)
244
959k
{
245
959k
    pdf_stream *stream = (pdf_stream *)o;
246
247
959k
    pdfi_countdown(stream->stream_dict);
248
959k
    gs_free_object(OBJ_MEMORY(o), o, "pdfi_free_stream");
249
959k
}
250
251
static void pdfi_free_buffer(pdf_obj *o)
252
38.0k
{
253
38.0k
    pdf_buffer *b = (pdf_buffer *)o;
254
255
38.0k
    gs_free_object(OBJ_MEMORY(b), b->data, "pdfi_free_buffer(data)");
256
38.0k
    gs_free_object(OBJ_MEMORY(o), o, "pdfi_free_buffer");
257
38.0k
}
258
259
void pdfi_free_object(pdf_obj *o)
260
693M
{
261
693M
    if (o == NULL)
262
697k
        return;
263
693M
    if ((intptr_t)o < (intptr_t)TOKEN__LAST_KEY)
264
0
        return;
265
693M
    switch(o->type) {
266
12.8M
        case PDF_ARRAY_MARK:
267
24.2M
        case PDF_DICT_MARK:
268
24.5M
        case PDF_PROC_MARK:
269
200M
        case PDF_INT:
270
335M
        case PDF_REAL:
271
350M
        case PDF_INDIRECT:
272
350M
            gs_free_object(OBJ_MEMORY(o), o, "pdf interpreter object refcount to 0");
273
350M
            break;
274
63.5M
        case PDF_STRING:
275
301M
        case PDF_NAME:
276
301M
            pdfi_free_namestring(o);
277
301M
            break;
278
38.0k
        case PDF_BUFFER:
279
38.0k
            pdfi_free_buffer(o);
280
38.0k
            break;
281
12.7M
        case PDF_ARRAY:
282
12.7M
            pdfi_free_array(o);
283
12.7M
            break;
284
11.5M
        case PDF_DICT:
285
11.5M
            pdfi_free_dict(o);
286
11.5M
            break;
287
959k
        case PDF_STREAM:
288
959k
            pdfi_free_stream(o);
289
959k
            break;
290
15.2M
        case PDF_KEYWORD:
291
15.2M
            pdfi_free_keyword(o);
292
15.2M
            break;
293
82.6k
        case PDF_XREF_TABLE:
294
82.6k
            pdfi_free_xref_table(o);
295
82.6k
            break;
296
594k
        case PDF_FONT:
297
594k
            pdfi_free_font(o);
298
594k
            break;
299
67.3k
        case PDF_CMAP:
300
67.3k
            pdfi_free_cmap(o);
301
67.3k
            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
693M
    }
310
693M
}
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
959k
{
320
959k
    int code = 0;
321
959k
    pdf_stream *new_stream = NULL;
322
323
959k
    if (pdfi_type_of(dict) != PDF_DICT)
324
0
        return_error(gs_error_typecheck);
325
326
959k
    code = pdfi_object_alloc(ctx, PDF_STREAM, 0, (pdf_obj **)&new_stream);
327
959k
    if (code < 0)
328
0
        goto error_exit;
329
330
959k
    new_stream->ctx = ctx;
331
959k
    pdfi_countup(new_stream);
332
333
959k
    new_stream->stream_dict = dict;
334
959k
    pdfi_countup(dict);
335
336
    /* this replaces the dict with the stream.
337
     * assumes it's not cached
338
     */
339
959k
    if (do_convert) {
340
925k
        new_stream->object_num = dict->object_num;
341
925k
        new_stream->generation_num = dict->generation_num;
342
925k
        dict->object_num = 0;
343
925k
        dict->generation_num = 0;
344
925k
    }
345
959k
    *stream = new_stream;
346
959k
    return 0;
347
348
0
 error_exit:
349
0
    pdfi_countdown(new_stream);
350
0
    return code;
351
959k
}
352
353
int pdfi_get_stream_dict(pdf_context *ctx, pdf_stream *stream, pdf_dict **dict)
354
243
{
355
243
    *dict = stream->stream_dict;
356
357
    /* Make sure the dictionary won't go away */
358
243
    pdfi_countup(*dict);
359
243
    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
243
    return 0;
365
243
}
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
370
{
370
370
    int code;
371
370
    int length = strlen(charstr);
372
370
    pdf_string *newstr = NULL;
373
374
370
    *string = NULL;
375
376
370
    code = pdfi_object_alloc(ctx, PDF_STRING, length, (pdf_obj **)&newstr);
377
370
    if (code < 0) goto exit;
378
379
370
    memcpy(newstr->data, (byte *)charstr, length);
380
381
370
    *string = newstr;
382
370
    pdfi_countup(newstr);
383
370
 exit:
384
370
    return code;
385
370
}
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
428k
{
390
428k
    int code;
391
428k
    int length = strlen(charstr);
392
428k
    pdf_name *newname = NULL;
393
394
428k
    *name = NULL;
395
396
428k
    code = pdfi_object_alloc(ctx, PDF_NAME, length, (pdf_obj **)&newname);
397
428k
    if (code < 0) goto exit;
398
399
428k
    memcpy(newname->data, (byte *)charstr, length);
400
401
428k
    *name = newname;
402
428k
    pdfi_countup(newname);
403
428k
 exit:
404
428k
    return code;
405
428k
}
406
407
/************ bufstream module BEGIN **************/
408
29.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
29.1k
{
419
29.1k
    stream->len = INIT_BUF_SIZE;
420
29.1k
    stream->cur = 0;
421
29.1k
    stream->data = gs_alloc_bytes(ctx->memory, stream->len, "pdfi_bufstream_init(data)");
422
423
29.1k
    if (!stream->data)
424
0
        return_error(gs_error_VMerror);
425
29.1k
    return 0;
426
29.1k
}
427
428
static int pdfi_bufstream_free(pdf_context *ctx, pdfi_bufstream_t *stream)
429
29.1k
{
430
29.1k
    if (stream->data)
431
99
        gs_free_object(ctx->memory, stream->data, "pdfi_bufstream_free(data)");
432
29.1k
    stream->len = 0;
433
29.1k
    stream->cur = 0;
434
29.1k
    stream->data = NULL;
435
29.1k
    return 0;
436
29.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
29.0k
{
441
29.0k
    *buf = stream->data;
442
29.0k
    *len = stream->cur;
443
29.0k
    stream->len = 0;
444
29.0k
    stream->cur = 0;
445
29.0k
    stream->data = NULL;
446
29.0k
    return 0;
447
29.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.03k
{
452
1.03k
    byte *data = NULL;
453
1.03k
    uint64_t newsize;
454
455
1.03k
    if (needed > max_int || stream->len > (max_int - needed) / 2)
456
0
        return_error(gs_error_rangecheck);
457
458
1.03k
    newsize = stream->len * 2 + needed;
459
1.03k
    data = gs_alloc_bytes(ctx->memory, newsize, "pdfi_bufstream_increase(data)");
460
1.03k
    if (!data)
461
0
        return_error(gs_error_VMerror);
462
463
1.03k
    memcpy(data, stream->data, stream->len);
464
1.03k
    gs_free_object(ctx->memory, stream->data, "pdfi_bufstream_increase(data)");
465
1.03k
    stream->data = data;
466
1.03k
    stream->len = newsize;
467
468
1.03k
    return 0;
469
1.03k
}
470
471
static int pdfi_bufstream_write(pdf_context *ctx, pdfi_bufstream_t *stream, byte *data, uint64_t len)
472
326k
{
473
326k
    int code = 0;
474
475
326k
    if (stream->cur + len > stream->len) {
476
1.03k
        code = pdfi_bufstream_increase(ctx, stream, len);
477
1.03k
        if (code < 0)
478
0
            goto exit;
479
1.03k
    }
480
326k
    memcpy(stream->data + stream->cur, data, len);
481
326k
    stream->cur += len;
482
483
326k
 exit:
484
326k
    return code;
485
326k
}
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.19k
{
502
4.19k
    int code = 0, i;
503
4.19k
    int length;
504
4.19k
    const char *template = "{Obj%dG%dF%d}"; /* The '{' and '}' are special to pdfmark/pdfwrite driver */
505
4.19k
    char *string = NULL;
506
4.19k
    pdf_indirect_ref *ref = (pdf_indirect_ref *)obj;
507
4.19k
    uint32_t hash = 5381;
508
509
4.19k
    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.19k
    *label = NULL;
523
4.19k
    length = strlen(template)+30;
524
525
4.19k
    string = (char *)gs_alloc_bytes(ctx->memory, length, "pdf_obj_get_label(label)");
526
4.19k
    if (string == NULL) {
527
0
        code = gs_note_error(gs_error_VMerror);
528
0
        goto exit;
529
0
    }
530
531
4.19k
    if (pdfi_type_of(obj) == PDF_INDIRECT)
532
4.18k
        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.19k
    *label = string;
537
4.19k
 exit:
538
4.19k
    return code;
539
4.19k
}
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
2
{
553
2
    int code = 0;
554
2
    int size = 12;
555
2
    byte *buf;
556
557
2
    buf = gs_alloc_bytes(ctx->memory, size, "pdfi_obj_default_str(data)");
558
2
    if (buf == NULL)
559
0
        return_error(gs_error_VMerror);
560
2
    memcpy(buf, "/placeholder", size);
561
2
    *data = buf;
562
2
    *len = size;
563
2
    return code;
564
2
}
565
566
static int pdfi_obj_name_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
567
107k
{
568
107k
    int code = 0, i;
569
107k
    pdf_name *name = (pdf_name *)obj;
570
107k
    int esc_size = 1;
571
107k
    byte *buf;
572
573
    /* We need to 'escape' any characters that can't be represented in a PDF name. */
574
571k
    for (i = 0;i < name->length;i++) {
575
464k
        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
464k
            default:
595
464k
                esc_size++;
596
464k
                break;
597
464k
        }
598
464k
    }
599
600
107k
    buf = gs_alloc_bytes(ctx->memory, esc_size, "pdfi_obj_name_str(data)");
601
107k
    if (buf == NULL)
602
0
        return_error(gs_error_VMerror);
603
107k
    buf[0] = '/';
604
107k
    esc_size = 1;
605
606
571k
    for (i = 0;i < name->length;i++) {
607
464k
        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
                {
625
352
                    char byte;
626
627
352
                    buf[esc_size++] = '#';
628
352
                    byte = name->data[i] >> 4;
629
352
                    if (byte > 9)
630
0
                        buf[esc_size++] = byte + 0x37;
631
352
                    else
632
352
                        buf[esc_size++] = byte + 0x30;
633
352
                    byte = name->data[i] & 0x0f;
634
352
                    if (byte > 9)
635
0
                        buf[esc_size++] = byte + 0x37;
636
352
                    else
637
352
                        buf[esc_size++] = byte + 0x30;
638
352
                }
639
352
                break;
640
464k
            default:
641
464k
                buf[esc_size++] = name->data[i];
642
464k
                break;
643
464k
        }
644
464k
    }
645
646
//    memcpy(buf+1, name->data, name->length);
647
107k
    *data = buf;
648
107k
    *len = esc_size;
649
107k
    return code;
650
107k
}
651
652
static int pdfi_obj_real_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
653
38.3k
{
654
38.3k
    int code = 0;
655
38.3k
    int size = 15;
656
38.3k
    pdf_num *number = (pdf_num *)obj;
657
38.3k
    char *buf;
658
659
38.3k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_real_str(data)");
660
38.3k
    if (buf == NULL)
661
0
        return_error(gs_error_VMerror);
662
38.3k
    snprintf(buf, size, "%.4f", number->value.d);
663
38.3k
    *data = (byte *)buf;
664
38.3k
    *len = strlen(buf);
665
38.3k
    return code;
666
38.3k
}
667
668
static int pdfi_obj_int_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
669
89.4k
{
670
89.4k
    int code = 0;
671
89.4k
    int size = 15;
672
89.4k
    pdf_num *number = (pdf_num *)obj;
673
89.4k
    char *buf;
674
675
89.4k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_int_str(data)");
676
89.4k
    if (buf == NULL)
677
0
        return_error(gs_error_VMerror);
678
89.4k
    snprintf(buf, size, "%"PRId64"", number->value.i);
679
89.4k
    *data = (byte *)buf;
680
89.4k
    *len = strlen(buf);
681
89.4k
    return code;
682
89.4k
}
683
684
static int pdfi_obj_getrefstr(pdf_context *ctx, uint64_t object_num, uint32_t generation, byte **data, int *len)
685
2.60k
{
686
2.60k
    int size = 100;
687
2.60k
    char *buf;
688
689
2.60k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_getrefstr(data)");
690
2.60k
    if (buf == NULL)
691
0
        return_error(gs_error_VMerror);
692
2.60k
    snprintf(buf, size, "%"PRId64" %d R", object_num, generation);
693
2.60k
    *data = (byte *)buf;
694
2.60k
    *len = strlen(buf);
695
2.60k
    return 0;
696
2.60k
}
697
698
static int pdfi_obj_indirect_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
699
6.95k
{
700
6.95k
    int code = 0;
701
6.95k
    pdf_indirect_ref *ref = (pdf_indirect_ref *)obj;
702
6.95k
    char *buf;
703
6.95k
    pdf_obj *object = NULL;
704
6.95k
    bool use_label = true;
705
706
6.95k
    code = pdfi_loop_detector_mark(ctx);
707
6.95k
    if (code < 0)
708
0
        return code;
709
710
6.95k
    if (ref->is_highlevelform) {
711
2.21k
        code = pdfi_obj_getrefstr(ctx, ref->highlevel_object_num, 0, data, len);
712
2.21k
        ref->is_highlevelform = false;
713
4.73k
    } else {
714
4.73k
        if (!ref->is_marking) {
715
1.91k
            code = pdfi_dereference(ctx, ref->ref_object_num, ref->ref_generation_num, &object);
716
1.91k
            if (code == gs_error_undefined) {
717
                /* Do something sensible for undefined reference (this would be a broken file) */
718
                /* TODO: Flag an error? */
719
389
                code = pdfi_obj_getrefstr(ctx, ref->ref_object_num, ref->ref_generation_num, data, len);
720
389
                goto exit;
721
389
            }
722
1.52k
            if (code < 0 && code != gs_error_circular_reference)
723
58
                goto exit;
724
1.46k
            if (code == 0) {
725
1.41k
                if (pdfi_type_of(object) == PDF_STREAM) {
726
232
                    code = pdfi_pdfmark_stream(ctx, (pdf_stream *)object);
727
232
                    if (code < 0) goto exit;
728
1.18k
                } else if (pdfi_type_of(object) == PDF_DICT) {
729
1.11k
                    code = pdfi_pdfmark_dict(ctx, (pdf_dict *)object);
730
1.11k
                    if (code < 0) goto exit;
731
1.11k
                } else {
732
67
                    code = pdfi_obj_to_string(ctx, object, data, len);
733
67
                    if (code < 0) goto exit;
734
56
                    use_label = false;
735
56
                }
736
1.41k
            }
737
1.46k
        }
738
4.23k
        if (use_label) {
739
4.18k
            code = pdfi_obj_get_label(ctx, (pdf_obj *)ref, &buf);
740
4.18k
            if (code < 0) goto exit;
741
4.18k
            *data = (byte *)buf;
742
4.18k
            *len = strlen(buf);
743
4.18k
        }
744
4.23k
    }
745
746
6.95k
 exit:
747
6.95k
    (void)pdfi_loop_detector_cleartomark(ctx);
748
6.95k
    pdfi_countdown(object);
749
6.95k
    return code;
750
6.95k
}
751
752
static int pdfi_obj_bool_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
753
2.95k
{
754
2.95k
    int code = 0;
755
2.95k
    int size = 5;
756
2.95k
    char *buf;
757
758
2.95k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_bool_str(data)");
759
2.95k
    if (buf == NULL)
760
0
        return_error(gs_error_VMerror);
761
2.95k
    if (obj == PDF_TRUE_OBJ) {
762
238
        memcpy(buf, (byte *)"true", 4);
763
238
        *len = 4;
764
2.72k
    } else {
765
2.72k
        memcpy(buf, (byte *)"false", 5);
766
2.72k
        *len = 5;
767
2.72k
    }
768
2.95k
    *data = (byte *)buf;
769
2.95k
    return code;
770
2.95k
}
771
772
static int pdfi_obj_null_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
773
302
{
774
302
    int code = 0;
775
302
    int size = 4;
776
302
    char *buf;
777
778
302
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_null_str(data)");
779
302
    if (buf == NULL)
780
0
        return_error(gs_error_VMerror);
781
302
    memcpy(buf, (byte *)"null", 4);
782
302
    *len = 4;
783
302
    *data = (byte *)buf;
784
302
    return code;
785
302
}
786
787
static int pdfi_obj_string_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
788
15.4k
{
789
15.4k
    pdf_string *string = (pdf_string *)obj;
790
15.4k
    char *buf;
791
15.4k
    int i, length = 0, j;
792
793
496k
    for (j=0;j<string->length;j++) {
794
481k
        if (string->data[j] == 0x0a || string->data[j] == 0x0d || string->data[j] == '(' || string->data[j] == ')' || string->data[j] == '\\')
795
969
                length += 2;
796
480k
        else {
797
480k
            if (string->data[j] < 0x20 || string->data[j] > 0x7F || string->data[j] == '\\')
798
9.87k
                length += 4;
799
470k
            else
800
470k
                length++;
801
480k
        }
802
481k
    }
803
15.4k
    length += 2;
804
15.4k
    buf = (char *)gs_alloc_bytes(ctx->memory, length, "pdfi_obj_string_str(data)");
805
15.4k
    if (buf == NULL)
806
0
        return_error(gs_error_VMerror);
807
15.4k
    buf[0] = '(';
808
15.4k
    i = 1;
809
496k
    for (j=0;j<string->length;j++) {
810
481k
        switch(string->data[j]) {
811
186
            case 0x0a:
812
186
                buf[i++] = '\\';
813
186
                buf[i++] = 'n';
814
186
                break;
815
93
            case 0x0d:
816
93
                buf[i++] = '\\';
817
93
                buf[i++] = 'r';
818
93
                break;
819
343
            case '(':
820
687
            case ')':
821
690
            case '\\':
822
690
                buf[i++] = '\\';
823
690
                buf[i++] = string->data[j];
824
690
                break;
825
480k
            default:
826
480k
                if (string->data[j] < 0x20 || string->data[j] > 0x7F) {
827
9.87k
                    buf[i++] = '\\';
828
9.87k
                    buf[i++] = (string->data[j] >> 6) + 0x30;
829
9.87k
                    buf[i++] = ((string->data[j] & 0x3F) >> 3) + 0x30;
830
9.87k
                    buf[i++] = (string->data[j] & 0x07) + 0x30;
831
9.87k
                } else
832
470k
                buf[i++] = string->data[j];
833
480k
                break;
834
481k
        }
835
481k
    }
836
15.4k
    buf[i++] = ')';
837
838
15.4k
    *len = i;
839
15.4k
    *data = (byte *)buf;
840
15.4k
    return 0;
841
15.4k
}
842
843
static int pdfi_obj_array_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
844
16.6k
{
845
16.6k
    int code = 0;
846
16.6k
    pdf_array *array = (pdf_array *)obj;
847
16.6k
    pdf_obj *object = NULL;
848
16.6k
    byte *itembuf = NULL;
849
16.6k
    int itemsize;
850
16.6k
    pdfi_bufstream_t bufstream;
851
16.6k
    uint64_t index, arraysize;
852
853
16.6k
    code = pdfi_bufstream_init(ctx, &bufstream);
854
16.6k
    if (code < 0) goto exit;
855
856
16.6k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"[", 1);
857
16.6k
    if (code < 0) goto exit;
858
859
16.6k
    arraysize = pdfi_array_size(array);
860
133k
    for (index = 0; index < arraysize; index++) {
861
116k
        code = pdfi_array_get_no_deref(ctx, array, index, &object);
862
116k
        if (code < 0) goto exit;
863
864
116k
        code = pdfi_obj_to_string(ctx, object, &itembuf, &itemsize);
865
116k
        if (code < 0) goto exit;
866
867
116k
        code = pdfi_bufstream_write(ctx, &bufstream, itembuf, itemsize);
868
116k
        if (code < 0) goto exit;
869
870
116k
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_array_str(itembuf)");
871
116k
        itembuf = NULL;
872
116k
        itemsize = 0;
873
116k
        pdfi_countdown(object);
874
116k
        object = NULL;
875
876
        /* Put a space between elements unless last item */
877
116k
        if (index+1 != arraysize) {
878
99.9k
            code = pdfi_bufstream_write(ctx, &bufstream, (byte *)" ", 1);
879
99.9k
            if (code < 0) goto exit;
880
99.9k
        }
881
116k
    }
882
883
16.5k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"]", 1);
884
16.5k
    if (code < 0) goto exit;
885
886
    /* Now copy the results out into the string we can keep */
887
16.5k
    code = pdfi_bufstream_copy(ctx, &bufstream, data, len);
888
889
16.6k
 exit:
890
16.6k
    if (itembuf)
891
0
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_array_str(itembuf)");
892
16.6k
    pdfi_bufstream_free(ctx, &bufstream);
893
16.6k
    pdfi_countdown(object);
894
16.6k
    return code;
895
16.5k
}
896
897
static int pdfi_obj_stream_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
898
252
{
899
252
    int code = 0;
900
252
    byte *buf;
901
252
    pdf_stream *stream = (pdf_stream *)obj;
902
252
    int64_t bufsize = 0;
903
252
    pdf_indirect_ref *streamref = NULL;
904
905
    /* TODO: How to deal with stream dictionaries?
906
     * /AP is one example that has special handling (up in pdf_annot.c), but there are others.
907
     * See 'pushpin' annotation in annotations-galore_II.ps
908
     *
909
     * This will just literally grab the stream data.
910
     */
911
252
    if (stream->is_marking) {
912
220
        code = pdfi_stream_to_buffer(ctx, stream, &buf, &bufsize);
913
220
        if (code < 0) goto exit;
914
220
        *data = buf;
915
220
        *len = (int)bufsize;
916
220
    } else {
917
        /* Create an indirect ref for the stream */
918
32
        code = pdfi_object_alloc(ctx, PDF_INDIRECT, 0, (pdf_obj **)&streamref);
919
32
        if (code < 0) goto exit;
920
32
        pdfi_countup(streamref);
921
32
        streamref->ref_object_num = stream->object_num;
922
32
        streamref->ref_generation_num = stream->generation_num;
923
32
        code = pdfi_obj_indirect_str(ctx, (pdf_obj *)streamref, data, len);
924
32
    }
925
926
252
 exit:
927
252
    pdfi_countdown(streamref);
928
252
    return code;
929
252
}
930
931
/* This fetches without dereferencing.  If you want to see the references inline,
932
 * then you need to pre-resolve them.  See pdfi_resolve_indirect().
933
 */
934
static int pdfi_obj_dict_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
935
12.5k
{
936
12.5k
    int code = 0;
937
12.5k
    pdf_dict *dict = (pdf_dict *)obj;
938
12.5k
    pdf_name *Key = NULL;
939
12.5k
    pdf_obj *Value = NULL;
940
12.5k
    byte *itembuf = NULL;
941
12.5k
    int itemsize;
942
12.5k
    pdfi_bufstream_t bufstream;
943
12.5k
    uint64_t index, dictsize;
944
12.5k
    uint64_t itemnum = 0;
945
946
12.5k
    code = pdfi_loop_detector_mark(ctx);
947
12.5k
    if (code < 0)
948
0
        return code;
949
950
12.5k
    code = pdfi_bufstream_init(ctx, &bufstream);
951
12.5k
    if (code < 0) goto exit;
952
953
12.5k
    dictsize = pdfi_dict_entries(dict);
954
    /* Handle empty dict specially */
955
12.5k
    if (dictsize == 0) {
956
3
        code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"<< >>", 5);
957
3
        if (code < 0)
958
0
            goto exit;
959
3
        goto exit_copy;
960
3
    }
961
962
12.5k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"<<\n", 3);
963
12.5k
    if (code < 0) goto exit;
964
965
    /* Note: We specifically fetch without dereferencing, so there will be no circular
966
     * references to handle here.
967
     */
968
    /* Wrong.... */
969
970
12.5k
    if (dict->object_num !=0 ) {
971
2.35k
        if (pdfi_loop_detector_check_object(ctx, dict->object_num)) {
972
1
            code = gs_note_error(gs_error_circular_reference);
973
1
            goto exit;
974
1
        }
975
2.35k
        code = pdfi_loop_detector_add_object(ctx, dict->object_num);
976
2.35k
        if (code < 0)
977
0
            goto exit;
978
2.35k
    }
979
980
    /* Get each (key,val) pair from dict and setup param for it */
981
12.5k
    code = pdfi_dict_key_first(ctx, dict, (pdf_obj **)&Key, &index);
982
16.1k
    while (code >= 0) {
983
16.1k
        code = pdfi_obj_to_string(ctx, (pdf_obj *)Key, &itembuf, &itemsize);
984
16.1k
        if (code < 0) goto exit;
985
986
16.1k
        code = pdfi_bufstream_write(ctx, &bufstream, itembuf, itemsize);
987
16.1k
        if (code < 0) goto exit;
988
989
16.1k
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_dict_str(itembuf)");
990
16.1k
        itembuf = NULL;
991
16.1k
        itemsize = 0;
992
993
        /* Put a space between elements */
994
16.1k
        code = pdfi_bufstream_write(ctx, &bufstream, (byte *)" ", 1);
995
16.1k
        if (code < 0) goto exit;
996
997
        /* No dereference */
998
16.1k
        code = pdfi_dict_get_no_deref(ctx, dict, (const pdf_name *)Key, &Value);
999
16.1k
        if (code < 0) goto exit;
1000
16.1k
        code = pdfi_obj_to_string(ctx, Value, &itembuf, &itemsize);
1001
16.1k
        if (code < 0) goto exit;
1002
1003
16.1k
        code = pdfi_bufstream_write(ctx, &bufstream, itembuf, itemsize);
1004
16.1k
        if (code < 0) goto exit;
1005
1006
16.1k
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_dict_str(itembuf)");
1007
16.1k
        itembuf = NULL;
1008
16.1k
        itemsize = 0;
1009
1010
16.1k
        pdfi_countdown(Value);
1011
16.1k
        Value = NULL;
1012
16.1k
        pdfi_countdown(Key);
1013
16.1k
        Key = NULL;
1014
1015
16.1k
        code = pdfi_dict_key_next(ctx, dict, (pdf_obj **)&Key, &index);
1016
16.1k
        if (code == gs_error_undefined) {
1017
12.4k
            code = 0;
1018
12.4k
            break;
1019
12.4k
        }
1020
3.67k
        if (code < 0) goto exit;
1021
1022
        /* Put a space between elements */
1023
3.67k
        if (++itemnum != dictsize) {
1024
3.67k
            code = pdfi_bufstream_write(ctx, &bufstream, (byte *)" ", 1);
1025
3.67k
            if (code < 0) goto exit;
1026
3.67k
        }
1027
3.67k
    }
1028
12.4k
    if (code < 0) goto exit;
1029
1030
12.4k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"\n>>", 3);
1031
12.4k
    if (code < 0) goto exit;
1032
1033
12.4k
 exit_copy:
1034
    /* Now copy the results out into the string we can keep */
1035
12.4k
    code = pdfi_bufstream_copy(ctx, &bufstream, data, len);
1036
1037
12.5k
 exit:
1038
12.5k
    if (itembuf)
1039
0
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_dict_str(itembuf)");
1040
12.5k
    pdfi_countdown(Key);
1041
12.5k
    pdfi_countdown(Value);
1042
12.5k
    pdfi_bufstream_free(ctx, &bufstream);
1043
12.5k
    if (code < 0)
1044
61
        (void)pdfi_loop_detector_cleartomark(ctx);
1045
12.4k
    else
1046
12.4k
        code = pdfi_loop_detector_cleartomark(ctx);
1047
12.5k
    return code;
1048
12.4k
}
1049
1050
#define PARAM1(A) # A,
1051
#define PARAM2(A,B) A,
1052
static const char pdf_token_strings[][10] = {
1053
#include "pdf_tokens.h"
1054
};
1055
1056
static int pdfi_obj_fast_keyword_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
1057
0
{
1058
0
    int code = 0;
1059
0
    const char *s = pdf_token_strings[(uintptr_t)obj];
1060
0
    int size = (int)strlen(s) + 1;
1061
0
    byte *buf;
1062
1063
0
    buf = gs_alloc_bytes(ctx->memory, size, "pdfi_obj_name_str(data)");
1064
0
    if (buf == NULL)
1065
0
        return_error(gs_error_VMerror);
1066
0
    memcpy(buf, s, size);
1067
0
    *data = buf;
1068
0
    *len = size;
1069
0
    return code;
1070
0
}
1071
1072
obj_str_dispatch_t obj_str_dispatch[] = {
1073
    {PDF_NAME, pdfi_obj_name_str},
1074
    {PDF_ARRAY, pdfi_obj_array_str},
1075
    {PDF_REAL, pdfi_obj_real_str},
1076
    {PDF_INT, pdfi_obj_int_str},
1077
    {PDF_BOOL, pdfi_obj_bool_str},
1078
    {PDF_STRING, pdfi_obj_string_str},
1079
    {PDF_DICT, pdfi_obj_dict_str},
1080
    {PDF_STREAM, pdfi_obj_stream_str},
1081
    {PDF_INDIRECT, pdfi_obj_indirect_str},
1082
    {PDF_NULL, pdfi_obj_null_str},
1083
    {PDF_FAST_KEYWORD, pdfi_obj_fast_keyword_str},
1084
    {0, NULL}
1085
};
1086
1087
/* Recursive function to build a string from an object
1088
 */
1089
int pdfi_obj_to_string(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
1090
289k
{
1091
289k
    obj_str_dispatch_t *dispatch_ptr;
1092
289k
    int code = 0;
1093
289k
    pdf_obj_type type;
1094
1095
289k
    *data = NULL;
1096
289k
    *len = 0;
1097
289k
    type = pdfi_type_of(obj);
1098
875k
    for (dispatch_ptr = obj_str_dispatch; dispatch_ptr->func; dispatch_ptr ++) {
1099
875k
        if (type == dispatch_ptr->type) {
1100
289k
            code = dispatch_ptr->func(ctx, obj, data, len);
1101
289k
            goto exit;
1102
289k
        }
1103
875k
    }
1104
    /* Not implemented, use default */
1105
2
    code = pdfi_obj_default_str(ctx, obj, data, len);
1106
289k
 exit:
1107
289k
    return code;
1108
2
}
1109
1110
/*********** END obj_to_string module ************/