Coverage Report

Created: 2026-02-14 07:09

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-2025 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
735M
{
39
735M
    int bytes = 0;
40
735M
    int code = 0;
41
42
735M
    switch(type) {
43
13.4M
        case PDF_ARRAY_MARK:
44
25.5M
        case PDF_DICT_MARK:
45
26.1M
        case PDF_PROC_MARK:
46
26.1M
            bytes = sizeof(pdf_obj);
47
26.1M
            break;
48
184M
        case PDF_INT:
49
309M
        case PDF_REAL:
50
309M
            bytes = sizeof(pdf_num);
51
309M
            break;
52
68.3M
        case PDF_STRING:
53
340M
        case PDF_NAME:
54
340M
            bytes = sizeof(pdf_string) + size - PDF_NAME_DECLARED_LENGTH;
55
340M
            break;
56
42.3k
        case PDF_BUFFER:
57
42.3k
            bytes = sizeof(pdf_buffer);
58
42.3k
            break;
59
13.3M
        case PDF_ARRAY:
60
13.3M
            bytes = sizeof(pdf_array);
61
13.3M
            break;
62
12.3M
        case PDF_DICT:
63
12.3M
            bytes = sizeof(pdf_dict);
64
12.3M
            break;
65
16.0M
        case PDF_INDIRECT:
66
16.0M
            bytes = sizeof(pdf_indirect_ref);
67
16.0M
            break;
68
16.3M
        case PDF_KEYWORD:
69
16.3M
            bytes = sizeof(pdf_keyword) + size - PDF_NAME_DECLARED_LENGTH;
70
16.3M
            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
1.08M
        case PDF_STREAM:
78
1.08M
            bytes = sizeof(pdf_stream);
79
1.08M
            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
735M
    }
86
735M
    *obj = (pdf_obj *)gs_alloc_bytes(ctx->memory, bytes, "pdfi_object_alloc");
87
735M
    if (*obj == NULL) {
88
0
        code = gs_note_error(gs_error_VMerror);
89
0
        goto error_out;
90
0
    }
91
92
735M
    memset(*obj, 0x00, bytes);
93
735M
    (*obj)->ctx = ctx;
94
735M
    (*obj)->type = type;
95
96
735M
    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
184M
        case PDF_INT:
106
309M
        case PDF_REAL:
107
325M
        case PDF_INDIRECT:
108
338M
        case PDF_ARRAY_MARK:
109
350M
        case PDF_DICT_MARK:
110
351M
        case PDF_PROC_MARK:
111
351M
            break;
112
16.3M
        case PDF_KEYWORD:
113
84.7M
        case PDF_STRING:
114
356M
        case PDF_NAME:
115
356M
            ((pdf_string *)*obj)->length = size;
116
356M
            break;
117
42.3k
        case PDF_BUFFER:
118
42.3k
            {
119
42.3k
                pdf_buffer *b = (pdf_buffer *)*obj;
120
               /* NOTE: size can be 0 if the caller wants to allocate the data area itself
121
                */
122
42.3k
                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
42.3k
                else {
130
42.3k
                    b->data = NULL;
131
42.3k
                }
132
42.3k
                b->length = size;
133
42.3k
            }
134
0
            break;
135
13.3M
        case PDF_ARRAY:
136
13.3M
            {
137
13.3M
                pdf_obj **values = NULL;
138
139
13.3M
                ((pdf_array *)*obj)->size = size;
140
13.3M
                if (size > 0) {
141
12.4M
                    values = (pdf_obj **)gs_alloc_bytes(ctx->memory, (size_t)size * sizeof(pdf_obj *), "pdfi_object_alloc");
142
12.4M
                    if (values == NULL) {
143
0
                        code = gs_note_error(gs_error_VMerror);
144
0
                        goto error_out;
145
0
                    }
146
12.4M
                    ((pdf_array *)*obj)->values = values;
147
12.4M
                    memset(((pdf_array *)*obj)->values, 0x00, size * sizeof(pdf_obj *));
148
12.4M
                }
149
13.3M
            }
150
13.3M
            break;
151
13.3M
        case PDF_DICT:
152
12.3M
            {
153
12.3M
                pdf_dict_entry *entries = NULL;
154
155
12.3M
                ((pdf_dict *)*obj)->size = size;
156
12.3M
                if (size > 0) {
157
11.8M
                    entries = (pdf_dict_entry *)gs_alloc_bytes(ctx->memory, (size_t)size * sizeof(pdf_dict_entry), "pdfi_object_alloc");
158
11.8M
                    if (entries == NULL) {
159
0
                        code = gs_note_error(gs_error_VMerror);
160
0
                        goto error_out;
161
0
                    }
162
11.8M
                    ((pdf_dict *)*obj)->list = entries;
163
11.8M
                    memset(((pdf_dict *)*obj)->list, 0x00, size * sizeof(pdf_dict_entry));
164
11.8M
                }
165
12.3M
            }
166
12.3M
            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
12.3M
        case PDF_XREF_TABLE:
171
0
            break;
172
1.08M
        default:
173
1.08M
            break;
174
735M
    }
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
735M
    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
735M
}
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
29.7k
{
192
29.7k
    uint64_t test = 0;
193
29.7k
    int code = 0;
194
195
29.7k
    test = (uint64_t)floor(d);
196
29.7k
    if (d == test) {
197
23.5k
        code = pdfi_object_alloc(ctx, PDF_INT, 0, (pdf_obj **)num);
198
23.5k
        if (code < 0)
199
0
            return code;
200
23.5k
        (*num)->value.i = test;
201
23.5k
    }
202
6.23k
    else {
203
6.23k
        code = pdfi_object_alloc(ctx, PDF_REAL, 0, (pdf_obj **)num);
204
6.23k
        if (code < 0)
205
0
            return code;
206
6.23k
        (*num)->value.d = d;
207
6.23k
    }
208
209
29.7k
    return 0;
210
29.7k
}
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
340M
{
222
    /* Currently names and strings are the same, so a single cast is OK */
223
340M
    pdf_name *n = (pdf_name *)o;
224
225
340M
    gs_free_object(OBJ_MEMORY(n), n, "pdf interpreter free name or string");
226
340M
}
227
228
static void pdfi_free_keyword(pdf_obj *o)
229
16.3M
{
230
16.3M
    pdf_keyword *k = (pdf_keyword *)o;
231
232
16.3M
    gs_free_object(OBJ_MEMORY(k), k, "pdf interpreter free keyword");
233
16.3M
}
234
235
static void pdfi_free_xref_table(pdf_obj *o)
236
96.0k
{
237
96.0k
    xref_table_t *xref = (xref_table_t *)o;
238
239
96.0k
    gs_free_object(OBJ_MEMORY(xref), xref->xref, "pdfi_free_xref_table");
240
96.0k
    gs_free_object(OBJ_MEMORY(xref), xref, "pdfi_free_xref_table");
241
96.0k
}
242
243
static void pdfi_free_stream(pdf_obj *o)
244
1.08M
{
245
1.08M
    pdf_stream *stream = (pdf_stream *)o;
246
247
1.08M
    pdfi_countdown(stream->stream_dict);
248
1.08M
    gs_free_object(OBJ_MEMORY(o), o, "pdfi_free_stream");
249
1.08M
}
250
251
static void pdfi_free_buffer(pdf_obj *o)
252
42.3k
{
253
42.3k
    pdf_buffer *b = (pdf_buffer *)o;
254
255
42.3k
    gs_free_object(OBJ_MEMORY(b), b->data, "pdfi_free_buffer(data)");
256
42.3k
    gs_free_object(OBJ_MEMORY(o), o, "pdfi_free_buffer");
257
42.3k
}
258
259
void pdfi_free_object(pdf_obj *o)
260
736M
{
261
736M
    if (o == NULL)
262
673k
        return;
263
736M
    if ((intptr_t)o < (intptr_t)TOKEN__LAST_KEY)
264
0
        return;
265
736M
    switch(o->type) {
266
13.4M
        case PDF_ARRAY_MARK:
267
25.5M
        case PDF_DICT_MARK:
268
26.1M
        case PDF_PROC_MARK:
269
210M
        case PDF_INT:
270
335M
        case PDF_REAL:
271
351M
        case PDF_INDIRECT:
272
351M
            gs_free_object(OBJ_MEMORY(o), o, "pdf interpreter object refcount to 0");
273
351M
            break;
274
68.3M
        case PDF_STRING:
275
340M
        case PDF_NAME:
276
340M
            pdfi_free_namestring(o);
277
340M
            break;
278
42.3k
        case PDF_BUFFER:
279
42.3k
            pdfi_free_buffer(o);
280
42.3k
            break;
281
13.3M
        case PDF_ARRAY:
282
13.3M
            pdfi_free_array(o);
283
13.3M
            break;
284
12.2M
        case PDF_DICT:
285
12.2M
            pdfi_free_dict(o);
286
12.2M
            break;
287
1.08M
        case PDF_STREAM:
288
1.08M
            pdfi_free_stream(o);
289
1.08M
            break;
290
16.3M
        case PDF_KEYWORD:
291
16.3M
            pdfi_free_keyword(o);
292
16.3M
            break;
293
96.0k
        case PDF_XREF_TABLE:
294
96.0k
            pdfi_free_xref_table(o);
295
96.0k
            break;
296
617k
        case PDF_FONT:
297
617k
            pdfi_free_font(o);
298
617k
            break;
299
76.5k
        case PDF_CMAP:
300
76.5k
            pdfi_free_cmap(o);
301
76.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
38
        default:
307
38
            dbgmprintf(OBJ_MEMORY(o), "!!! Attempting to free unknown object type !!!\n");
308
38
            break;
309
736M
    }
310
736M
}
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
1.08M
{
320
1.08M
    int code = 0;
321
1.08M
    pdf_stream *new_stream = NULL;
322
323
1.08M
    if (pdfi_type_of(dict) != PDF_DICT)
324
0
        return_error(gs_error_typecheck);
325
326
1.08M
    code = pdfi_object_alloc(ctx, PDF_STREAM, 0, (pdf_obj **)&new_stream);
327
1.08M
    if (code < 0)
328
0
        goto error_exit;
329
330
1.08M
    new_stream->ctx = ctx;
331
1.08M
    pdfi_countup(new_stream);
332
333
1.08M
    new_stream->stream_dict = dict;
334
1.08M
    pdfi_countup(dict);
335
336
    /* this replaces the dict with the stream.
337
     * assumes it's not cached
338
     */
339
1.08M
    if (do_convert) {
340
1.03M
        new_stream->object_num = dict->object_num;
341
1.03M
        new_stream->generation_num = dict->generation_num;
342
1.03M
        dict->object_num = 0;
343
1.03M
        dict->generation_num = 0;
344
1.03M
    }
345
1.08M
    *stream = new_stream;
346
1.08M
    return 0;
347
348
0
 error_exit:
349
0
    pdfi_countdown(new_stream);
350
0
    return code;
351
1.08M
}
352
353
int pdfi_get_stream_dict(pdf_context *ctx, pdf_stream *stream, pdf_dict **dict)
354
234
{
355
234
    *dict = stream->stream_dict;
356
357
    /* Make sure the dictionary won't go away */
358
234
    pdfi_countup(*dict);
359
234
    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
234
    return 0;
365
234
}
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
541
{
370
541
    int code;
371
541
    int length = strlen(charstr);
372
541
    pdf_string *newstr = NULL;
373
374
541
    *string = NULL;
375
376
541
    code = pdfi_object_alloc(ctx, PDF_STRING, length, (pdf_obj **)&newstr);
377
541
    if (code < 0) goto exit;
378
379
541
    memcpy(newstr->data, (byte *)charstr, length);
380
381
541
    *string = newstr;
382
541
    pdfi_countup(newstr);
383
541
 exit:
384
541
    return code;
385
541
}
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
439k
{
390
439k
    int code;
391
439k
    int length = strlen(charstr);
392
439k
    pdf_name *newname = NULL;
393
394
439k
    *name = NULL;
395
396
439k
    code = pdfi_object_alloc(ctx, PDF_NAME, length, (pdf_obj **)&newname);
397
439k
    if (code < 0) goto exit;
398
399
439k
    memcpy(newname->data, (byte *)charstr, length);
400
401
439k
    *name = newname;
402
439k
    pdfi_countup(newname);
403
439k
 exit:
404
439k
    return code;
405
439k
}
406
407
/************ bufstream module BEGIN **************/
408
133k
#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
133k
{
419
133k
    stream->len = INIT_BUF_SIZE;
420
133k
    stream->cur = 0;
421
133k
    stream->data = gs_alloc_bytes(ctx->memory, stream->len, "pdfi_bufstream_init(data)");
422
423
133k
    if (!stream->data)
424
0
        return_error(gs_error_VMerror);
425
133k
    return 0;
426
133k
}
427
428
static int pdfi_bufstream_free(pdf_context *ctx, pdfi_bufstream_t *stream)
429
133k
{
430
133k
    if (stream->data)
431
215
        gs_free_object(ctx->memory, stream->data, "pdfi_bufstream_free(data)");
432
133k
    stream->len = 0;
433
133k
    stream->cur = 0;
434
133k
    stream->data = NULL;
435
133k
    return 0;
436
133k
}
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
133k
{
441
133k
    *buf = stream->data;
442
133k
    *len = stream->cur;
443
133k
    stream->len = 0;
444
133k
    stream->cur = 0;
445
133k
    stream->data = NULL;
446
133k
    return 0;
447
133k
}
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
6.18k
{
452
6.18k
    byte *data = NULL;
453
6.18k
    uint64_t newsize;
454
455
6.18k
    newsize = stream->len * 2 + needed;
456
6.18k
    data = gs_alloc_bytes(ctx->memory, newsize, "pdfi_bufstream_increase(data)");
457
6.18k
    if (!data)
458
0
        return_error(gs_error_VMerror);
459
460
6.18k
    memcpy(data, stream->data, stream->len);
461
6.18k
    gs_free_object(ctx->memory, stream->data, "pdfi_bufstream_increase(data)");
462
6.18k
    stream->data = data;
463
6.18k
    stream->len = newsize;
464
465
6.18k
    return 0;
466
6.18k
}
467
468
static int pdfi_bufstream_write(pdf_context *ctx, pdfi_bufstream_t *stream, byte *data, uint64_t len)
469
1.67M
{
470
1.67M
    int code = 0;
471
472
1.67M
    if (stream->cur + len > stream->len) {
473
6.18k
        code = pdfi_bufstream_increase(ctx, stream, len);
474
6.18k
        if (code < 0)
475
0
            goto exit;
476
6.18k
    }
477
1.67M
    memcpy(stream->data + stream->cur, data, len);
478
1.67M
    stream->cur += len;
479
480
1.67M
 exit:
481
1.67M
    return code;
482
1.67M
}
483
484
/************ bufstream module END **************/
485
486
487
/* Create a c-string to use as object label
488
 * Uses the object_num to make it unique.
489
 * (don't call this for objects with object_num=0, though I am not going to check that here)
490
 *
491
 * Bug #708127; just the object number alone is insufficient. Two consecutive input files might use the
492
 * same object number for a pdfmark, but with different content, we need to differntiate between the two.
493
 * Add a simple hash of the input filename (uses the same dumb but fast hash as pattern ID generation), this gives
494
 * the last bytes in the filename more say in the final result so is 'probably' sufficiently unique with the
495
 * object number and generation.
496
 */
497
int pdfi_obj_get_label(pdf_context *ctx, pdf_obj *obj, char **label)
498
16.6k
{
499
16.6k
    int code = 0, i;
500
16.6k
    int length;
501
16.6k
    const char *template = "{Obj%dG%dF%d}"; /* The '{' and '}' are special to pdfmark/pdfwrite driver */
502
16.6k
    char *string = NULL;
503
16.6k
    pdf_indirect_ref *ref = (pdf_indirect_ref *)obj;
504
16.6k
    uint32_t hash = 5381;
505
506
16.6k
    if (ctx->main_stream->s->file_name.data != NULL) {
507
0
        string = (char *)ctx->main_stream->s->file_name.data;
508
0
        length = ctx->main_stream->s->file_name.size;
509
510
0
        for (i=0;i < length;i++) {
511
#if ARCH_IS_BIG_ENDIAN
512
            hash = ((hash << 5) + hash) + string[length - 1 - i]; /* hash * 33 + c */
513
#else
514
0
            hash = ((hash << 5) + hash) + string[i]; /* hash * 33 + c */
515
0
#endif
516
0
        }
517
0
    }
518
519
16.6k
    *label = NULL;
520
16.6k
    length = strlen(template)+30;
521
522
16.6k
    string = (char *)gs_alloc_bytes(ctx->memory, length, "pdf_obj_get_label(label)");
523
16.6k
    if (string == NULL) {
524
0
        code = gs_note_error(gs_error_VMerror);
525
0
        goto exit;
526
0
    }
527
528
16.6k
    if (pdfi_type_of(obj) == PDF_INDIRECT)
529
16.6k
        gs_snprintf(string, length, template, ref->ref_object_num, ref->ref_generation_num, hash);
530
40
    else
531
40
        gs_snprintf(string, length, template, obj->object_num, obj->generation_num, hash);
532
533
16.6k
    *label = string;
534
16.6k
 exit:
535
16.6k
    return code;
536
16.6k
}
537
538
/*********** BEGIN obj_to_string module ************/
539
540
typedef int (*str_func)(pdf_context *ctx, pdf_obj *obj, byte **data, int *len);
541
542
/* Dispatch to get string representation of an object */
543
typedef struct {
544
    pdf_obj_type type;
545
    str_func func;
546
} obj_str_dispatch_t;
547
548
static int pdfi_obj_default_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
549
69
{
550
69
    int code = 0;
551
69
    int size = 12;
552
69
    byte *buf;
553
554
69
    buf = gs_alloc_bytes(ctx->memory, size, "pdfi_obj_default_str(data)");
555
69
    if (buf == NULL)
556
0
        return_error(gs_error_VMerror);
557
69
    memcpy(buf, "/placeholder", size);
558
69
    *data = buf;
559
69
    *len = size;
560
69
    return code;
561
69
}
562
563
static int pdfi_obj_name_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
564
543k
{
565
543k
    int code = 0;
566
543k
    pdf_name *name = (pdf_name *)obj;
567
543k
    int size = name->length + 1;
568
543k
    byte *buf;
569
570
543k
    buf = gs_alloc_bytes(ctx->memory, size, "pdfi_obj_name_str(data)");
571
543k
    if (buf == NULL)
572
0
        return_error(gs_error_VMerror);
573
543k
    buf[0] = '/';
574
543k
    memcpy(buf+1, name->data, name->length);
575
543k
    *data = buf;
576
543k
    *len = size;
577
543k
    return code;
578
543k
}
579
580
static int pdfi_obj_real_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
581
189k
{
582
189k
    int code = 0;
583
189k
    int size = 15;
584
189k
    pdf_num *number = (pdf_num *)obj;
585
189k
    char *buf;
586
587
189k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_real_str(data)");
588
189k
    if (buf == NULL)
589
0
        return_error(gs_error_VMerror);
590
189k
    snprintf(buf, size, "%.4f", number->value.d);
591
189k
    *data = (byte *)buf;
592
189k
    *len = strlen(buf);
593
189k
    return code;
594
189k
}
595
596
static int pdfi_obj_int_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
597
528k
{
598
528k
    int code = 0;
599
528k
    int size = 15;
600
528k
    pdf_num *number = (pdf_num *)obj;
601
528k
    char *buf;
602
603
528k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_int_str(data)");
604
528k
    if (buf == NULL)
605
0
        return_error(gs_error_VMerror);
606
528k
    snprintf(buf, size, "%"PRId64"", number->value.i);
607
528k
    *data = (byte *)buf;
608
528k
    *len = strlen(buf);
609
528k
    return code;
610
528k
}
611
612
static int pdfi_obj_getrefstr(pdf_context *ctx, uint64_t object_num, uint32_t generation, byte **data, int *len)
613
14.6k
{
614
14.6k
    int size = 100;
615
14.6k
    char *buf;
616
617
14.6k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_getrefstr(data)");
618
14.6k
    if (buf == NULL)
619
0
        return_error(gs_error_VMerror);
620
14.6k
    snprintf(buf, size, "%"PRId64" %d R", object_num, generation);
621
14.6k
    *data = (byte *)buf;
622
14.6k
    *len = strlen(buf);
623
14.6k
    return 0;
624
14.6k
}
625
626
static int pdfi_obj_indirect_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
627
31.8k
{
628
31.8k
    int code = 0;
629
31.8k
    pdf_indirect_ref *ref = (pdf_indirect_ref *)obj;
630
31.8k
    char *buf;
631
31.8k
    pdf_obj *object = NULL;
632
31.8k
    bool use_label = true;
633
634
31.8k
    code = pdfi_loop_detector_mark(ctx);
635
31.8k
    if (code < 0)
636
0
        return code;
637
638
31.8k
    if (ref->is_highlevelform) {
639
13.5k
        code = pdfi_obj_getrefstr(ctx, ref->highlevel_object_num, 0, data, len);
640
13.5k
        ref->is_highlevelform = false;
641
18.2k
    } else {
642
18.2k
        if (!ref->is_marking) {
643
8.43k
            code = pdfi_dereference(ctx, ref->ref_object_num, ref->ref_generation_num, &object);
644
8.43k
            if (code == gs_error_undefined) {
645
                /* Do something sensible for undefined reference (this would be a broken file) */
646
                /* TODO: Flag an error? */
647
1.04k
                code = pdfi_obj_getrefstr(ctx, ref->ref_object_num, ref->ref_generation_num, data, len);
648
1.04k
                goto exit;
649
1.04k
            }
650
7.39k
            if (code < 0 && code != gs_error_circular_reference)
651
126
                goto exit;
652
7.26k
            if (code == 0) {
653
6.82k
                if (pdfi_type_of(object) == PDF_STREAM) {
654
511
                    code = pdfi_pdfmark_stream(ctx, (pdf_stream *)object);
655
511
                    if (code < 0) goto exit;
656
6.31k
                } else if (pdfi_type_of(object) == PDF_DICT) {
657
5.93k
                    code = pdfi_pdfmark_dict(ctx, (pdf_dict *)object);
658
5.93k
                    if (code < 0) goto exit;
659
5.93k
                } else {
660
380
                    code = pdfi_obj_to_string(ctx, object, data, len);
661
380
                    if (code < 0) goto exit;
662
359
                    use_label = false;
663
359
                }
664
6.82k
            }
665
7.26k
        }
666
16.9k
        if (use_label) {
667
16.6k
            code = pdfi_obj_get_label(ctx, (pdf_obj *)ref, &buf);
668
16.6k
            if (code < 0) goto exit;
669
16.6k
            *data = (byte *)buf;
670
16.6k
            *len = strlen(buf);
671
16.6k
        }
672
16.9k
    }
673
674
31.8k
 exit:
675
31.8k
    (void)pdfi_loop_detector_cleartomark(ctx);
676
31.8k
    pdfi_countdown(object);
677
31.8k
    return code;
678
31.8k
}
679
680
static int pdfi_obj_bool_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
681
21.8k
{
682
21.8k
    int code = 0;
683
21.8k
    int size = 5;
684
21.8k
    char *buf;
685
686
21.8k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_bool_str(data)");
687
21.8k
    if (buf == NULL)
688
0
        return_error(gs_error_VMerror);
689
21.8k
    if (obj == PDF_TRUE_OBJ) {
690
736
        memcpy(buf, (byte *)"true", 4);
691
736
        *len = 4;
692
21.1k
    } else {
693
21.1k
        memcpy(buf, (byte *)"false", 5);
694
21.1k
        *len = 5;
695
21.1k
    }
696
21.8k
    *data = (byte *)buf;
697
21.8k
    return code;
698
21.8k
}
699
700
static int pdfi_obj_null_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
701
824
{
702
824
    int code = 0;
703
824
    int size = 4;
704
824
    char *buf;
705
706
824
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_null_str(data)");
707
824
    if (buf == NULL)
708
0
        return_error(gs_error_VMerror);
709
824
    memcpy(buf, (byte *)"null", 4);
710
824
    *len = 4;
711
824
    *data = (byte *)buf;
712
824
    return code;
713
824
}
714
715
static int pdfi_obj_string_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
716
78.0k
{
717
78.0k
    pdf_string *string = (pdf_string *)obj;
718
78.0k
    char *buf;
719
78.0k
    int i, length = 0, j;
720
721
2.83M
    for (j=0;j<string->length;j++) {
722
2.75M
        if (string->data[j] == 0x0a || string->data[j] == 0x0d || string->data[j] == '(' || string->data[j] == ')' || string->data[j] == '\\')
723
4.32k
                length += 2;
724
2.74M
        else {
725
2.74M
            if (string->data[j] < 0x20 || string->data[j] > 0x7F || string->data[j] == '\\')
726
120k
                length += 4;
727
2.62M
            else
728
2.62M
                length++;
729
2.74M
        }
730
2.75M
    }
731
78.0k
    length += 2;
732
78.0k
    buf = (char *)gs_alloc_bytes(ctx->memory, length, "pdfi_obj_string_str(data)");
733
78.0k
    if (buf == NULL)
734
0
        return_error(gs_error_VMerror);
735
78.0k
    buf[0] = '(';
736
78.0k
    i = 1;
737
2.83M
    for (j=0;j<string->length;j++) {
738
2.75M
        switch(string->data[j]) {
739
637
            case 0x0a:
740
637
                buf[i++] = '\\';
741
637
                buf[i++] = 'n';
742
637
                break;
743
714
            case 0x0d:
744
714
                buf[i++] = '\\';
745
714
                buf[i++] = 'r';
746
714
                break;
747
1.41k
            case '(':
748
2.94k
            case ')':
749
2.97k
            case '\\':
750
2.97k
                buf[i++] = '\\';
751
2.97k
                buf[i++] = string->data[j];
752
2.97k
                break;
753
2.74M
            default:
754
2.74M
                if (string->data[j] < 0x20 || string->data[j] > 0x7F) {
755
120k
                    buf[i++] = '\\';
756
120k
                    buf[i++] = (string->data[j] >> 6) + 0x30;
757
120k
                    buf[i++] = ((string->data[j] & 0x3F) >> 3) + 0x30;
758
120k
                    buf[i++] = (string->data[j] & 0x07) + 0x30;
759
120k
                } else
760
2.62M
                buf[i++] = string->data[j];
761
2.74M
                break;
762
2.75M
        }
763
2.75M
    }
764
78.0k
    buf[i++] = ')';
765
766
78.0k
    *len = i;
767
78.0k
    *data = (byte *)buf;
768
78.0k
    return 0;
769
78.0k
}
770
771
static int pdfi_obj_array_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
772
94.4k
{
773
94.4k
    int code = 0;
774
94.4k
    pdf_array *array = (pdf_array *)obj;
775
94.4k
    pdf_obj *object = NULL;
776
94.4k
    byte *itembuf = NULL;
777
94.4k
    int itemsize;
778
94.4k
    pdfi_bufstream_t bufstream;
779
94.4k
    uint64_t index, arraysize;
780
781
94.4k
    code = pdfi_bufstream_init(ctx, &bufstream);
782
94.4k
    if (code < 0) goto exit;
783
784
94.4k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"[", 1);
785
94.4k
    if (code < 0) goto exit;
786
787
94.4k
    arraysize = pdfi_array_size(array);
788
765k
    for (index = 0; index < arraysize; index++) {
789
671k
        code = pdfi_array_get_no_deref(ctx, array, index, &object);
790
671k
        if (code < 0) goto exit;
791
792
671k
        code = pdfi_obj_to_string(ctx, object, &itembuf, &itemsize);
793
671k
        if (code < 0) goto exit;
794
795
671k
        code = pdfi_bufstream_write(ctx, &bufstream, itembuf, itemsize);
796
671k
        if (code < 0) goto exit;
797
798
671k
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_array_str(itembuf)");
799
671k
        itembuf = NULL;
800
671k
        itemsize = 0;
801
671k
        pdfi_countdown(object);
802
671k
        object = NULL;
803
804
        /* Put a space between elements unless last item */
805
671k
        if (index+1 != arraysize) {
806
577k
            code = pdfi_bufstream_write(ctx, &bufstream, (byte *)" ", 1);
807
577k
            if (code < 0) goto exit;
808
577k
        }
809
671k
    }
810
811
94.3k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"]", 1);
812
94.3k
    if (code < 0) goto exit;
813
814
    /* Now copy the results out into the string we can keep */
815
94.3k
    code = pdfi_bufstream_copy(ctx, &bufstream, data, len);
816
817
94.4k
 exit:
818
94.4k
    if (itembuf)
819
0
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_array_str(itembuf)");
820
94.4k
    pdfi_bufstream_free(ctx, &bufstream);
821
94.4k
    pdfi_countdown(object);
822
94.4k
    return code;
823
94.3k
}
824
825
static int pdfi_obj_stream_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
826
524
{
827
524
    int code = 0;
828
524
    byte *buf;
829
524
    pdf_stream *stream = (pdf_stream *)obj;
830
524
    int64_t bufsize = 0;
831
524
    pdf_indirect_ref *streamref = NULL;
832
833
    /* TODO: How to deal with stream dictionaries?
834
     * /AP is one example that has special handling (up in pdf_annot.c), but there are others.
835
     * See 'pushpin' annotation in annotations-galore_II.ps
836
     *
837
     * This will just literally grab the stream data.
838
     */
839
524
    if (stream->is_marking) {
840
462
        code = pdfi_stream_to_buffer(ctx, stream, &buf, &bufsize);
841
462
        if (code < 0) goto exit;
842
462
        *data = buf;
843
462
        *len = (int)bufsize;
844
462
    } else {
845
        /* Create an indirect ref for the stream */
846
62
        code = pdfi_object_alloc(ctx, PDF_INDIRECT, 0, (pdf_obj **)&streamref);
847
62
        if (code < 0) goto exit;
848
62
        pdfi_countup(streamref);
849
62
        streamref->ref_object_num = stream->object_num;
850
62
        streamref->ref_generation_num = stream->generation_num;
851
62
        code = pdfi_obj_indirect_str(ctx, (pdf_obj *)streamref, data, len);
852
62
    }
853
854
524
 exit:
855
524
    pdfi_countdown(streamref);
856
524
    return code;
857
524
}
858
859
/* This fetches without dereferencing.  If you want to see the references inline,
860
 * then you need to pre-resolve them.  See pdfi_resolve_indirect().
861
 */
862
static int pdfi_obj_dict_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
863
39.5k
{
864
39.5k
    int code = 0;
865
39.5k
    pdf_dict *dict = (pdf_dict *)obj;
866
39.5k
    pdf_name *Key = NULL;
867
39.5k
    pdf_obj *Value = NULL;
868
39.5k
    byte *itembuf = NULL;
869
39.5k
    int itemsize;
870
39.5k
    pdfi_bufstream_t bufstream;
871
39.5k
    uint64_t index, dictsize;
872
39.5k
    uint64_t itemnum = 0;
873
874
39.5k
    code = pdfi_loop_detector_mark(ctx);
875
39.5k
    if (code < 0)
876
0
        return code;
877
878
39.5k
    code = pdfi_bufstream_init(ctx, &bufstream);
879
39.5k
    if (code < 0) goto exit;
880
881
39.5k
    dictsize = pdfi_dict_entries(dict);
882
    /* Handle empty dict specially */
883
39.5k
    if (dictsize == 0) {
884
5
        code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"<< >>", 5);
885
5
        if (code < 0)
886
0
            goto exit;
887
5
        goto exit_copy;
888
5
    }
889
890
39.4k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"<<\n", 3);
891
39.4k
    if (code < 0) goto exit;
892
893
    /* Note: We specifically fetch without dereferencing, so there will be no circular
894
     * references to handle here.
895
     */
896
    /* Wrong.... */
897
898
39.4k
    if (dict->object_num !=0 ) {
899
13.8k
        if (pdfi_loop_detector_check_object(ctx, dict->object_num)) {
900
4
            code = gs_note_error(gs_error_circular_reference);
901
4
            goto exit;
902
4
        }
903
13.8k
        code = pdfi_loop_detector_add_object(ctx, dict->object_num);
904
13.8k
        if (code < 0)
905
0
            goto exit;
906
13.8k
    }
907
908
    /* Get each (key,val) pair from dict and setup param for it */
909
39.4k
    code = pdfi_dict_key_first(ctx, dict, (pdf_obj **)&Key, &index);
910
48.5k
    while (code >= 0) {
911
48.5k
        code = pdfi_obj_to_string(ctx, (pdf_obj *)Key, &itembuf, &itemsize);
912
48.5k
        if (code < 0) goto exit;
913
914
48.5k
        code = pdfi_bufstream_write(ctx, &bufstream, itembuf, itemsize);
915
48.5k
        if (code < 0) goto exit;
916
917
48.5k
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_dict_str(itembuf)");
918
48.5k
        itembuf = NULL;
919
48.5k
        itemsize = 0;
920
921
        /* Put a space between elements */
922
48.5k
        code = pdfi_bufstream_write(ctx, &bufstream, (byte *)" ", 1);
923
48.5k
        if (code < 0) goto exit;
924
925
        /* No dereference */
926
48.5k
        code = pdfi_dict_get_no_deref(ctx, dict, (const pdf_name *)Key, &Value);
927
48.5k
        if (code < 0) goto exit;
928
48.5k
        code = pdfi_obj_to_string(ctx, Value, &itembuf, &itemsize);
929
48.5k
        if (code < 0) goto exit;
930
931
48.3k
        code = pdfi_bufstream_write(ctx, &bufstream, itembuf, itemsize);
932
48.3k
        if (code < 0) goto exit;
933
934
48.3k
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_dict_str(itembuf)");
935
48.3k
        itembuf = NULL;
936
48.3k
        itemsize = 0;
937
938
48.3k
        pdfi_countdown(Value);
939
48.3k
        Value = NULL;
940
48.3k
        pdfi_countdown(Key);
941
48.3k
        Key = NULL;
942
943
48.3k
        code = pdfi_dict_key_next(ctx, dict, (pdf_obj **)&Key, &index);
944
48.3k
        if (code == gs_error_undefined) {
945
39.3k
            code = 0;
946
39.3k
            break;
947
39.3k
        }
948
9.01k
        if (code < 0) goto exit;
949
950
        /* Put a space between elements */
951
9.01k
        if (++itemnum != dictsize) {
952
9.01k
            code = pdfi_bufstream_write(ctx, &bufstream, (byte *)" ", 1);
953
9.01k
            if (code < 0) goto exit;
954
9.01k
        }
955
9.01k
    }
956
39.3k
    if (code < 0) goto exit;
957
958
39.3k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"\n>>", 3);
959
39.3k
    if (code < 0) goto exit;
960
961
39.3k
 exit_copy:
962
    /* Now copy the results out into the string we can keep */
963
39.3k
    code = pdfi_bufstream_copy(ctx, &bufstream, data, len);
964
965
39.5k
 exit:
966
39.5k
    if (itembuf)
967
0
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_dict_str(itembuf)");
968
39.5k
    pdfi_countdown(Key);
969
39.5k
    pdfi_countdown(Value);
970
39.5k
    pdfi_bufstream_free(ctx, &bufstream);
971
39.5k
    if (code < 0)
972
133
        (void)pdfi_loop_detector_cleartomark(ctx);
973
39.3k
    else
974
39.3k
        code = pdfi_loop_detector_cleartomark(ctx);
975
39.5k
    return code;
976
39.3k
}
977
978
#define PARAM1(A) # A,
979
#define PARAM2(A,B) A,
980
static const char pdf_token_strings[][10] = {
981
#include "pdf_tokens.h"
982
};
983
984
static int pdfi_obj_fast_keyword_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
985
0
{
986
0
    int code = 0;
987
0
    const char *s = pdf_token_strings[(uintptr_t)obj];
988
0
    int size = (int)strlen(s) + 1;
989
0
    byte *buf;
990
991
0
    buf = gs_alloc_bytes(ctx->memory, size, "pdfi_obj_name_str(data)");
992
0
    if (buf == NULL)
993
0
        return_error(gs_error_VMerror);
994
0
    memcpy(buf, s, size);
995
0
    *data = buf;
996
0
    *len = size;
997
0
    return code;
998
0
}
999
1000
obj_str_dispatch_t obj_str_dispatch[] = {
1001
    {PDF_NAME, pdfi_obj_name_str},
1002
    {PDF_ARRAY, pdfi_obj_array_str},
1003
    {PDF_REAL, pdfi_obj_real_str},
1004
    {PDF_INT, pdfi_obj_int_str},
1005
    {PDF_BOOL, pdfi_obj_bool_str},
1006
    {PDF_STRING, pdfi_obj_string_str},
1007
    {PDF_DICT, pdfi_obj_dict_str},
1008
    {PDF_STREAM, pdfi_obj_stream_str},
1009
    {PDF_INDIRECT, pdfi_obj_indirect_str},
1010
    {PDF_NULL, pdfi_obj_null_str},
1011
    {PDF_FAST_KEYWORD, pdfi_obj_fast_keyword_str},
1012
    {0, NULL}
1013
};
1014
1015
/* Recursive function to build a string from an object
1016
 */
1017
int pdfi_obj_to_string(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
1018
1.52M
{
1019
1.52M
    obj_str_dispatch_t *dispatch_ptr;
1020
1.52M
    int code = 0;
1021
1.52M
    pdf_obj_type type;
1022
1023
1.52M
    *data = NULL;
1024
1.52M
    *len = 0;
1025
1.52M
    type = pdfi_type_of(obj);
1026
4.56M
    for (dispatch_ptr = obj_str_dispatch; dispatch_ptr->func; dispatch_ptr ++) {
1027
4.56M
        if (type == dispatch_ptr->type) {
1028
1.52M
            code = dispatch_ptr->func(ctx, obj, data, len);
1029
1.52M
            goto exit;
1030
1.52M
        }
1031
4.56M
    }
1032
    /* Not implemented, use default */
1033
69
    code = pdfi_obj_default_str(ctx, obj, data, len);
1034
1.52M
 exit:
1035
1.52M
    return code;
1036
69
}
1037
1038
/*********** END obj_to_string module ************/