Coverage Report

Created: 2026-07-24 07:44

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
707M
{
39
707M
    int bytes = 0;
40
707M
    int code = 0;
41
42
707M
    switch(type) {
43
12.6M
        case PDF_ARRAY_MARK:
44
23.8M
        case PDF_DICT_MARK:
45
24.3M
        case PDF_PROC_MARK:
46
24.3M
            bytes = sizeof(pdf_obj);
47
24.3M
            break;
48
171M
        case PDF_INT:
49
301M
        case PDF_REAL:
50
301M
            bytes = sizeof(pdf_num);
51
301M
            break;
52
64.8M
        case PDF_STRING:
53
326M
        case PDF_NAME:
54
326M
            bytes = sizeof(pdf_string) + size - PDF_NAME_DECLARED_LENGTH;
55
326M
            break;
56
38.6k
        case PDF_BUFFER:
57
38.6k
            bytes = sizeof(pdf_buffer);
58
38.6k
            break;
59
12.5M
        case PDF_ARRAY:
60
12.5M
            bytes = sizeof(pdf_array);
61
12.5M
            break;
62
11.5M
        case PDF_DICT:
63
11.5M
            bytes = sizeof(pdf_dict);
64
11.5M
            break;
65
14.4M
        case PDF_INDIRECT:
66
14.4M
            bytes = sizeof(pdf_indirect_ref);
67
14.4M
            break;
68
14.9M
        case PDF_KEYWORD:
69
14.9M
            bytes = sizeof(pdf_keyword) + size - PDF_NAME_DECLARED_LENGTH;
70
14.9M
            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
982k
        case PDF_STREAM:
78
982k
            bytes = sizeof(pdf_stream);
79
982k
            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
707M
    }
86
707M
    *obj = (pdf_obj *)gs_alloc_bytes(ctx->memory, bytes, "pdfi_object_alloc");
87
707M
    if (*obj == NULL) {
88
0
        code = gs_note_error(gs_error_VMerror);
89
0
        goto error_out;
90
0
    }
91
92
707M
    memset(*obj, 0x00, bytes);
93
707M
    (*obj)->ctx = ctx;
94
707M
    (*obj)->type = type;
95
96
707M
    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
171M
        case PDF_INT:
106
301M
        case PDF_REAL:
107
316M
        case PDF_INDIRECT:
108
328M
        case PDF_ARRAY_MARK:
109
340M
        case PDF_DICT_MARK:
110
340M
        case PDF_PROC_MARK:
111
340M
            break;
112
14.9M
        case PDF_KEYWORD:
113
79.7M
        case PDF_STRING:
114
341M
        case PDF_NAME:
115
341M
            ((pdf_string *)*obj)->length = size;
116
341M
            break;
117
38.6k
        case PDF_BUFFER:
118
38.6k
            {
119
38.6k
                pdf_buffer *b = (pdf_buffer *)*obj;
120
               /* NOTE: size can be 0 if the caller wants to allocate the data area itself
121
                */
122
38.6k
                if (size > 0) {
123
0
                    b->data = gs_alloc_bytes(ctx->memory, size, "pdfi_object_alloc");
124
0
                    if (b->data == NULL) {
125
0
                        code = gs_note_error(gs_error_VMerror);
126
0
                        goto error_out;
127
0
                    }
128
0
                }
129
38.6k
                else {
130
38.6k
                    b->data = NULL;
131
38.6k
                }
132
38.6k
                b->length = size;
133
38.6k
            }
134
0
            break;
135
12.5M
        case PDF_ARRAY:
136
12.5M
            {
137
12.5M
                pdf_obj **values = NULL;
138
139
12.5M
                ((pdf_array *)*obj)->size = size;
140
12.5M
                if (size > 0) {
141
11.8M
                    values = (pdf_obj **)gs_alloc_bytes(ctx->memory, (size_t)size * sizeof(pdf_obj *), "pdfi_object_alloc");
142
11.8M
                    if (values == NULL) {
143
0
                        code = gs_note_error(gs_error_VMerror);
144
0
                        goto error_out;
145
0
                    }
146
11.8M
                    ((pdf_array *)*obj)->values = values;
147
11.8M
                    memset(((pdf_array *)*obj)->values, 0x00, size * sizeof(pdf_obj *));
148
11.8M
                }
149
12.5M
            }
150
12.5M
            break;
151
12.5M
        case PDF_DICT:
152
11.5M
            {
153
11.5M
                pdf_dict_entry *entries = NULL;
154
155
11.5M
                ((pdf_dict *)*obj)->size = size;
156
11.5M
                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.5M
            }
166
11.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
11.5M
        case PDF_XREF_TABLE:
171
0
            break;
172
982k
        default:
173
982k
            break;
174
707M
    }
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
707M
    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
707M
}
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
31.0k
{
192
31.0k
    uint64_t test = 0;
193
31.0k
    int code = 0;
194
195
31.0k
    test = (uint64_t)floor(d);
196
31.0k
    if (d == test) {
197
24.0k
        code = pdfi_object_alloc(ctx, PDF_INT, 0, (pdf_obj **)num);
198
24.0k
        if (code < 0)
199
0
            return code;
200
24.0k
        (*num)->value.i = test;
201
24.0k
    }
202
6.99k
    else {
203
6.99k
        code = pdfi_object_alloc(ctx, PDF_REAL, 0, (pdf_obj **)num);
204
6.99k
        if (code < 0)
205
0
            return code;
206
6.99k
        (*num)->value.d = d;
207
6.99k
    }
208
209
31.0k
    return 0;
210
31.0k
}
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
326M
{
222
    /* Currently names and strings are the same, so a single cast is OK */
223
326M
    pdf_name *n = (pdf_name *)o;
224
225
326M
    gs_free_object(OBJ_MEMORY(n), n, "pdf interpreter free name or string");
226
326M
}
227
228
static void pdfi_free_keyword(pdf_obj *o)
229
14.9M
{
230
14.9M
    pdf_keyword *k = (pdf_keyword *)o;
231
232
14.9M
    gs_free_object(OBJ_MEMORY(k), k, "pdf interpreter free keyword");
233
14.9M
}
234
235
static void pdfi_free_xref_table(pdf_obj *o)
236
85.0k
{
237
85.0k
    xref_table_t *xref = (xref_table_t *)o;
238
239
85.0k
    gs_free_object(OBJ_MEMORY(xref), xref->xref, "pdfi_free_xref_table");
240
85.0k
    gs_free_object(OBJ_MEMORY(xref), xref, "pdfi_free_xref_table");
241
85.0k
}
242
243
static void pdfi_free_stream(pdf_obj *o)
244
982k
{
245
982k
    pdf_stream *stream = (pdf_stream *)o;
246
247
982k
    pdfi_countdown(stream->stream_dict);
248
982k
    gs_free_object(OBJ_MEMORY(o), o, "pdfi_free_stream");
249
982k
}
250
251
static void pdfi_free_buffer(pdf_obj *o)
252
38.6k
{
253
38.6k
    pdf_buffer *b = (pdf_buffer *)o;
254
255
38.6k
    gs_free_object(OBJ_MEMORY(b), b->data, "pdfi_free_buffer(data)");
256
38.6k
    gs_free_object(OBJ_MEMORY(o), o, "pdfi_free_buffer");
257
38.6k
}
258
259
void pdfi_free_object(pdf_obj *o)
260
708M
{
261
708M
    if (o == NULL)
262
688k
        return;
263
707M
    if ((intptr_t)o < (intptr_t)TOKEN__LAST_KEY)
264
0
        return;
265
707M
    switch(o->type) {
266
12.6M
        case PDF_ARRAY_MARK:
267
23.8M
        case PDF_DICT_MARK:
268
24.3M
        case PDF_PROC_MARK:
269
196M
        case PDF_INT:
270
326M
        case PDF_REAL:
271
340M
        case PDF_INDIRECT:
272
340M
            gs_free_object(OBJ_MEMORY(o), o, "pdf interpreter object refcount to 0");
273
340M
            break;
274
64.8M
        case PDF_STRING:
275
326M
        case PDF_NAME:
276
326M
            pdfi_free_namestring(o);
277
326M
            break;
278
38.6k
        case PDF_BUFFER:
279
38.6k
            pdfi_free_buffer(o);
280
38.6k
            break;
281
12.5M
        case PDF_ARRAY:
282
12.5M
            pdfi_free_array(o);
283
12.5M
            break;
284
11.5M
        case PDF_DICT:
285
11.5M
            pdfi_free_dict(o);
286
11.5M
            break;
287
982k
        case PDF_STREAM:
288
982k
            pdfi_free_stream(o);
289
982k
            break;
290
14.9M
        case PDF_KEYWORD:
291
14.9M
            pdfi_free_keyword(o);
292
14.9M
            break;
293
85.0k
        case PDF_XREF_TABLE:
294
85.0k
            pdfi_free_xref_table(o);
295
85.0k
            break;
296
612k
        case PDF_FONT:
297
612k
            pdfi_free_font(o);
298
612k
            break;
299
69.3k
        case PDF_CMAP:
300
69.3k
            pdfi_free_cmap(o);
301
69.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
37
        default:
307
37
            dbgmprintf(OBJ_MEMORY(o), "!!! Attempting to free unknown object type !!!\n");
308
37
            break;
309
707M
    }
310
707M
}
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
982k
{
320
982k
    int code = 0;
321
982k
    pdf_stream *new_stream = NULL;
322
323
982k
    if (pdfi_type_of(dict) != PDF_DICT)
324
0
        return_error(gs_error_typecheck);
325
326
982k
    code = pdfi_object_alloc(ctx, PDF_STREAM, 0, (pdf_obj **)&new_stream);
327
982k
    if (code < 0)
328
0
        goto error_exit;
329
330
982k
    new_stream->ctx = ctx;
331
982k
    pdfi_countup(new_stream);
332
333
982k
    new_stream->stream_dict = dict;
334
982k
    pdfi_countup(dict);
335
336
    /* this replaces the dict with the stream.
337
     * assumes it's not cached
338
     */
339
982k
    if (do_convert) {
340
948k
        new_stream->object_num = dict->object_num;
341
948k
        new_stream->generation_num = dict->generation_num;
342
948k
        dict->object_num = 0;
343
948k
        dict->generation_num = 0;
344
948k
    }
345
982k
    *stream = new_stream;
346
982k
    return 0;
347
348
0
 error_exit:
349
0
    pdfi_countdown(new_stream);
350
0
    return code;
351
982k
}
352
353
int pdfi_get_stream_dict(pdf_context *ctx, pdf_stream *stream, pdf_dict **dict)
354
225
{
355
225
    *dict = stream->stream_dict;
356
357
    /* Make sure the dictionary won't go away */
358
225
    pdfi_countup(*dict);
359
225
    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
225
    return 0;
365
225
}
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
359
{
370
359
    int code;
371
359
    int length = strlen(charstr);
372
359
    pdf_string *newstr = NULL;
373
374
359
    *string = NULL;
375
376
359
    code = pdfi_object_alloc(ctx, PDF_STRING, length, (pdf_obj **)&newstr);
377
359
    if (code < 0) goto exit;
378
379
359
    memcpy(newstr->data, (byte *)charstr, length);
380
381
359
    *string = newstr;
382
359
    pdfi_countup(newstr);
383
359
 exit:
384
359
    return code;
385
359
}
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
453k
{
390
453k
    int code;
391
453k
    int length = strlen(charstr);
392
453k
    pdf_name *newname = NULL;
393
394
453k
    *name = NULL;
395
396
453k
    code = pdfi_object_alloc(ctx, PDF_NAME, length, (pdf_obj **)&newname);
397
453k
    if (code < 0) goto exit;
398
399
453k
    memcpy(newname->data, (byte *)charstr, length);
400
401
453k
    *name = newname;
402
453k
    pdfi_countup(newname);
403
453k
 exit:
404
453k
    return code;
405
453k
}
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
230
        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
5.89k
{
452
5.89k
    byte *data = NULL;
453
5.89k
    uint64_t newsize;
454
455
5.89k
    if (needed > max_int || stream->len > (max_int - needed) / 2)
456
0
        return_error(gs_error_rangecheck);
457
458
5.89k
    newsize = stream->len * 2 + needed;
459
5.89k
    data = gs_alloc_bytes(ctx->memory, newsize, "pdfi_bufstream_increase(data)");
460
5.89k
    if (!data)
461
0
        return_error(gs_error_VMerror);
462
463
5.89k
    memcpy(data, stream->data, stream->len);
464
5.89k
    gs_free_object(ctx->memory, stream->data, "pdfi_bufstream_increase(data)");
465
5.89k
    stream->data = data;
466
5.89k
    stream->len = newsize;
467
468
5.89k
    return 0;
469
5.89k
}
470
471
static int pdfi_bufstream_write(pdf_context *ctx, pdfi_bufstream_t *stream, byte *data, uint64_t len)
472
1.63M
{
473
1.63M
    int code = 0;
474
475
1.63M
    if (stream->cur + len > stream->len) {
476
5.89k
        code = pdfi_bufstream_increase(ctx, stream, len);
477
5.89k
        if (code < 0)
478
0
            goto exit;
479
5.89k
    }
480
1.63M
    memcpy(stream->data + stream->cur, data, len);
481
1.63M
    stream->cur += len;
482
483
1.63M
 exit:
484
1.63M
    return code;
485
1.63M
}
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
24.8k
{
502
24.8k
    int code = 0, i;
503
24.8k
    int length;
504
24.8k
    const char *template = "{Obj%dG%dF%d}"; /* The '{' and '}' are special to pdfmark/pdfwrite driver */
505
24.8k
    char *string = NULL;
506
24.8k
    pdf_indirect_ref *ref = (pdf_indirect_ref *)obj;
507
24.8k
    uint32_t hash = 5381;
508
509
24.8k
    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
24.8k
    *label = NULL;
523
24.8k
    length = strlen(template)+30;
524
525
24.8k
    string = (char *)gs_alloc_bytes(ctx->memory, length, "pdf_obj_get_label(label)");
526
24.8k
    if (string == NULL) {
527
0
        code = gs_note_error(gs_error_VMerror);
528
0
        goto exit;
529
0
    }
530
531
24.8k
    if (pdfi_type_of(obj) == PDF_INDIRECT)
532
24.8k
        gs_snprintf(string, length, template, ref->ref_object_num, ref->ref_generation_num, hash);
533
57
    else
534
57
        gs_snprintf(string, length, template, obj->object_num, obj->generation_num, hash);
535
536
24.8k
    *label = string;
537
24.8k
 exit:
538
24.8k
    return code;
539
24.8k
}
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
73
{
553
73
    int code = 0;
554
73
    int size = 12;
555
73
    byte *buf;
556
557
73
    buf = gs_alloc_bytes(ctx->memory, size, "pdfi_obj_default_str(data)");
558
73
    if (buf == NULL)
559
0
        return_error(gs_error_VMerror);
560
73
    memcpy(buf, "/placeholder", size);
561
73
    *data = buf;
562
73
    *len = size;
563
73
    return code;
564
73
}
565
566
static int pdfi_obj_name_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
567
539k
{
568
539k
    int code = 0, i;
569
539k
    pdf_name *name = (pdf_name *)obj;
570
539k
    int esc_size = 1, size = name->length + 1;
571
539k
    byte *buf;
572
573
    /* We need to 'escape' any characters that can't be represented in a PDF name. */
574
2.72M
    for (i = 0;i < name->length;i++) {
575
2.18M
        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
2.10k
            case 0x20:
582
2.10k
            case 0x25:
583
2.10k
            case 0x28:
584
2.10k
            case 0x29:
585
2.10k
            case 0x3c:
586
2.10k
            case 0x3e:
587
2.10k
            case 0x5b:
588
2.10k
            case 0x5d:
589
2.10k
            case 0x7b:
590
2.10k
            case 0x7d:
591
2.11k
            case 0x2f:
592
2.11k
                esc_size += 3;
593
2.11k
                break;
594
2.18M
            default:
595
2.18M
                esc_size++;
596
2.18M
                break;
597
2.18M
        }
598
2.18M
    }
599
600
539k
    buf = gs_alloc_bytes(ctx->memory, esc_size, "pdfi_obj_name_str(data)");
601
539k
    if (buf == NULL)
602
0
        return_error(gs_error_VMerror);
603
539k
    buf[0] = '/';
604
539k
    esc_size = 1;
605
606
2.72M
    for (i = 0;i < name->length;i++) {
607
2.18M
        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
2.10k
            case 0x20:
614
2.10k
            case 0x25:
615
2.10k
            case 0x28:
616
2.10k
            case 0x29:
617
2.10k
            case 0x3c:
618
2.10k
            case 0x3e:
619
2.10k
            case 0x5b:
620
2.10k
            case 0x5d:
621
2.10k
            case 0x7b:
622
2.10k
            case 0x7d:
623
2.11k
            case 0x2f:
624
2.11k
                buf[esc_size++] = '#';
625
2.11k
                buf[esc_size++] = (name->data[i] >> 4) + 0x30;
626
2.11k
                buf[esc_size++] = (name->data[i] & 0x0f) + 0x30;
627
2.11k
                break;
628
2.18M
            default:
629
2.18M
                buf[esc_size++] = name->data[i];
630
2.18M
                break;
631
2.18M
        }
632
2.18M
    }
633
634
//    memcpy(buf+1, name->data, name->length);
635
539k
    *data = buf;
636
539k
    *len = esc_size;
637
539k
    return code;
638
539k
}
639
640
static int pdfi_obj_real_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
641
192k
{
642
192k
    int code = 0;
643
192k
    int size = 15;
644
192k
    pdf_num *number = (pdf_num *)obj;
645
192k
    char *buf;
646
647
192k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_real_str(data)");
648
192k
    if (buf == NULL)
649
0
        return_error(gs_error_VMerror);
650
192k
    snprintf(buf, size, "%.4f", number->value.d);
651
192k
    *data = (byte *)buf;
652
192k
    *len = strlen(buf);
653
192k
    return code;
654
192k
}
655
656
static int pdfi_obj_int_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
657
496k
{
658
496k
    int code = 0;
659
496k
    int size = 15;
660
496k
    pdf_num *number = (pdf_num *)obj;
661
496k
    char *buf;
662
663
496k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_int_str(data)");
664
496k
    if (buf == NULL)
665
0
        return_error(gs_error_VMerror);
666
496k
    snprintf(buf, size, "%"PRId64"", number->value.i);
667
496k
    *data = (byte *)buf;
668
496k
    *len = strlen(buf);
669
496k
    return code;
670
496k
}
671
672
static int pdfi_obj_getrefstr(pdf_context *ctx, uint64_t object_num, uint32_t generation, byte **data, int *len)
673
13.6k
{
674
13.6k
    int size = 100;
675
13.6k
    char *buf;
676
677
13.6k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_getrefstr(data)");
678
13.6k
    if (buf == NULL)
679
0
        return_error(gs_error_VMerror);
680
13.6k
    snprintf(buf, size, "%"PRId64" %d R", object_num, generation);
681
13.6k
    *data = (byte *)buf;
682
13.6k
    *len = strlen(buf);
683
13.6k
    return 0;
684
13.6k
}
685
686
static int pdfi_obj_indirect_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
687
39.1k
{
688
39.1k
    int code = 0;
689
39.1k
    pdf_indirect_ref *ref = (pdf_indirect_ref *)obj;
690
39.1k
    char *buf;
691
39.1k
    pdf_obj *object = NULL;
692
39.1k
    bool use_label = true;
693
694
39.1k
    code = pdfi_loop_detector_mark(ctx);
695
39.1k
    if (code < 0)
696
0
        return code;
697
698
39.1k
    if (ref->is_highlevelform) {
699
12.6k
        code = pdfi_obj_getrefstr(ctx, ref->highlevel_object_num, 0, data, len);
700
12.6k
        ref->is_highlevelform = false;
701
26.5k
    } else {
702
26.5k
        if (!ref->is_marking) {
703
12.7k
            code = pdfi_dereference(ctx, ref->ref_object_num, ref->ref_generation_num, &object);
704
12.7k
            if (code == gs_error_undefined) {
705
                /* Do something sensible for undefined reference (this would be a broken file) */
706
                /* TODO: Flag an error? */
707
1.06k
                code = pdfi_obj_getrefstr(ctx, ref->ref_object_num, ref->ref_generation_num, data, len);
708
1.06k
                goto exit;
709
1.06k
            }
710
11.6k
            if (code < 0 && code != gs_error_circular_reference)
711
126
                goto exit;
712
11.5k
            if (code == 0) {
713
11.0k
                if (pdfi_type_of(object) == PDF_STREAM) {
714
603
                    code = pdfi_pdfmark_stream(ctx, (pdf_stream *)object);
715
603
                    if (code < 0) goto exit;
716
10.4k
                } else if (pdfi_type_of(object) == PDF_DICT) {
717
10.0k
                    code = pdfi_pdfmark_dict(ctx, (pdf_dict *)object);
718
10.0k
                    if (code < 0) goto exit;
719
10.0k
                } else {
720
441
                    code = pdfi_obj_to_string(ctx, object, data, len);
721
441
                    if (code < 0) goto exit;
722
418
                    use_label = false;
723
418
                }
724
11.0k
            }
725
11.5k
        }
726
25.2k
        if (use_label) {
727
24.8k
            code = pdfi_obj_get_label(ctx, (pdf_obj *)ref, &buf);
728
24.8k
            if (code < 0) goto exit;
729
24.8k
            *data = (byte *)buf;
730
24.8k
            *len = strlen(buf);
731
24.8k
        }
732
25.2k
    }
733
734
39.1k
 exit:
735
39.1k
    (void)pdfi_loop_detector_cleartomark(ctx);
736
39.1k
    pdfi_countdown(object);
737
39.1k
    return code;
738
39.1k
}
739
740
static int pdfi_obj_bool_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
741
20.3k
{
742
20.3k
    int code = 0;
743
20.3k
    int size = 5;
744
20.3k
    char *buf;
745
746
20.3k
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_bool_str(data)");
747
20.3k
    if (buf == NULL)
748
0
        return_error(gs_error_VMerror);
749
20.3k
    if (obj == PDF_TRUE_OBJ) {
750
692
        memcpy(buf, (byte *)"true", 4);
751
692
        *len = 4;
752
19.6k
    } else {
753
19.6k
        memcpy(buf, (byte *)"false", 5);
754
19.6k
        *len = 5;
755
19.6k
    }
756
20.3k
    *data = (byte *)buf;
757
20.3k
    return code;
758
20.3k
}
759
760
static int pdfi_obj_null_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
761
991
{
762
991
    int code = 0;
763
991
    int size = 4;
764
991
    char *buf;
765
766
991
    buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_null_str(data)");
767
991
    if (buf == NULL)
768
0
        return_error(gs_error_VMerror);
769
991
    memcpy(buf, (byte *)"null", 4);
770
991
    *len = 4;
771
991
    *data = (byte *)buf;
772
991
    return code;
773
991
}
774
775
static int pdfi_obj_string_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
776
76.1k
{
777
76.1k
    pdf_string *string = (pdf_string *)obj;
778
76.1k
    char *buf;
779
76.1k
    int i, length = 0, j;
780
781
2.84M
    for (j=0;j<string->length;j++) {
782
2.76M
        if (string->data[j] == 0x0a || string->data[j] == 0x0d || string->data[j] == '(' || string->data[j] == ')' || string->data[j] == '\\')
783
4.66k
                length += 2;
784
2.75M
        else {
785
2.75M
            if (string->data[j] < 0x20 || string->data[j] > 0x7F || string->data[j] == '\\')
786
134k
                length += 4;
787
2.62M
            else
788
2.62M
                length++;
789
2.75M
        }
790
2.76M
    }
791
76.1k
    length += 2;
792
76.1k
    buf = (char *)gs_alloc_bytes(ctx->memory, length, "pdfi_obj_string_str(data)");
793
76.1k
    if (buf == NULL)
794
0
        return_error(gs_error_VMerror);
795
76.1k
    buf[0] = '(';
796
76.1k
    i = 1;
797
2.84M
    for (j=0;j<string->length;j++) {
798
2.76M
        switch(string->data[j]) {
799
684
            case 0x0a:
800
684
                buf[i++] = '\\';
801
684
                buf[i++] = 'n';
802
684
                break;
803
671
            case 0x0d:
804
671
                buf[i++] = '\\';
805
671
                buf[i++] = 'r';
806
671
                break;
807
1.57k
            case '(':
808
3.27k
            case ')':
809
3.30k
            case '\\':
810
3.30k
                buf[i++] = '\\';
811
3.30k
                buf[i++] = string->data[j];
812
3.30k
                break;
813
2.75M
            default:
814
2.75M
                if (string->data[j] < 0x20 || string->data[j] > 0x7F) {
815
134k
                    buf[i++] = '\\';
816
134k
                    buf[i++] = (string->data[j] >> 6) + 0x30;
817
134k
                    buf[i++] = ((string->data[j] & 0x3F) >> 3) + 0x30;
818
134k
                    buf[i++] = (string->data[j] & 0x07) + 0x30;
819
134k
                } else
820
2.62M
                buf[i++] = string->data[j];
821
2.75M
                break;
822
2.76M
        }
823
2.76M
    }
824
76.1k
    buf[i++] = ')';
825
826
76.1k
    *len = i;
827
76.1k
    *data = (byte *)buf;
828
76.1k
    return 0;
829
76.1k
}
830
831
static int pdfi_obj_array_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
832
91.3k
{
833
91.3k
    int code = 0;
834
91.3k
    pdf_array *array = (pdf_array *)obj;
835
91.3k
    pdf_obj *object = NULL;
836
91.3k
    byte *itembuf = NULL;
837
91.3k
    int itemsize;
838
91.3k
    pdfi_bufstream_t bufstream;
839
91.3k
    uint64_t index, arraysize;
840
841
91.3k
    code = pdfi_bufstream_init(ctx, &bufstream);
842
91.3k
    if (code < 0) goto exit;
843
844
91.3k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"[", 1);
845
91.3k
    if (code < 0) goto exit;
846
847
91.3k
    arraysize = pdfi_array_size(array);
848
736k
    for (index = 0; index < arraysize; index++) {
849
644k
        code = pdfi_array_get_no_deref(ctx, array, index, &object);
850
644k
        if (code < 0) goto exit;
851
852
644k
        code = pdfi_obj_to_string(ctx, object, &itembuf, &itemsize);
853
644k
        if (code < 0) goto exit;
854
855
644k
        code = pdfi_bufstream_write(ctx, &bufstream, itembuf, itemsize);
856
644k
        if (code < 0) goto exit;
857
858
644k
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_array_str(itembuf)");
859
644k
        itembuf = NULL;
860
644k
        itemsize = 0;
861
644k
        pdfi_countdown(object);
862
644k
        object = NULL;
863
864
        /* Put a space between elements unless last item */
865
644k
        if (index+1 != arraysize) {
866
553k
            code = pdfi_bufstream_write(ctx, &bufstream, (byte *)" ", 1);
867
553k
            if (code < 0) goto exit;
868
553k
        }
869
644k
    }
870
871
91.2k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"]", 1);
872
91.2k
    if (code < 0) goto exit;
873
874
    /* Now copy the results out into the string we can keep */
875
91.2k
    code = pdfi_bufstream_copy(ctx, &bufstream, data, len);
876
877
91.3k
 exit:
878
91.3k
    if (itembuf)
879
0
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_array_str(itembuf)");
880
91.3k
    pdfi_bufstream_free(ctx, &bufstream);
881
91.3k
    pdfi_countdown(object);
882
91.3k
    return code;
883
91.2k
}
884
885
static int pdfi_obj_stream_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *len)
886
610
{
887
610
    int code = 0;
888
610
    byte *buf;
889
610
    pdf_stream *stream = (pdf_stream *)obj;
890
610
    int64_t bufsize = 0;
891
610
    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
610
    if (stream->is_marking) {
900
544
        code = pdfi_stream_to_buffer(ctx, stream, &buf, &bufsize);
901
544
        if (code < 0) goto exit;
902
544
        *data = buf;
903
544
        *len = (int)bufsize;
904
544
    } else {
905
        /* Create an indirect ref for the stream */
906
66
        code = pdfi_object_alloc(ctx, PDF_INDIRECT, 0, (pdf_obj **)&streamref);
907
66
        if (code < 0) goto exit;
908
66
        pdfi_countup(streamref);
909
66
        streamref->ref_object_num = stream->object_num;
910
66
        streamref->ref_generation_num = stream->generation_num;
911
66
        code = pdfi_obj_indirect_str(ctx, (pdf_obj *)streamref, data, len);
912
66
    }
913
914
610
 exit:
915
610
    pdfi_countdown(streamref);
916
610
    return code;
917
610
}
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
42.4k
{
924
42.4k
    int code = 0;
925
42.4k
    pdf_dict *dict = (pdf_dict *)obj;
926
42.4k
    pdf_name *Key = NULL;
927
42.4k
    pdf_obj *Value = NULL;
928
42.4k
    byte *itembuf = NULL;
929
42.4k
    int itemsize;
930
42.4k
    pdfi_bufstream_t bufstream;
931
42.4k
    uint64_t index, dictsize;
932
42.4k
    uint64_t itemnum = 0;
933
934
42.4k
    code = pdfi_loop_detector_mark(ctx);
935
42.4k
    if (code < 0)
936
0
        return code;
937
938
42.4k
    code = pdfi_bufstream_init(ctx, &bufstream);
939
42.4k
    if (code < 0) goto exit;
940
941
42.4k
    dictsize = pdfi_dict_entries(dict);
942
    /* Handle empty dict specially */
943
42.4k
    if (dictsize == 0) {
944
12
        code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"<< >>", 5);
945
12
        if (code < 0)
946
0
            goto exit;
947
12
        goto exit_copy;
948
12
    }
949
950
42.4k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"<<\n", 3);
951
42.4k
    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
42.4k
    if (dict->object_num !=0 ) {
959
12.7k
        if (pdfi_loop_detector_check_object(ctx, dict->object_num)) {
960
5
            code = gs_note_error(gs_error_circular_reference);
961
5
            goto exit;
962
5
        }
963
12.7k
        code = pdfi_loop_detector_add_object(ctx, dict->object_num);
964
12.7k
        if (code < 0)
965
0
            goto exit;
966
12.7k
    }
967
968
    /* Get each (key,val) pair from dict and setup param for it */
969
42.4k
    code = pdfi_dict_key_first(ctx, dict, (pdf_obj **)&Key, &index);
970
53.2k
    while (code >= 0) {
971
53.2k
        code = pdfi_obj_to_string(ctx, (pdf_obj *)Key, &itembuf, &itemsize);
972
53.2k
        if (code < 0) goto exit;
973
974
53.2k
        code = pdfi_bufstream_write(ctx, &bufstream, itembuf, itemsize);
975
53.2k
        if (code < 0) goto exit;
976
977
53.2k
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_dict_str(itembuf)");
978
53.2k
        itembuf = NULL;
979
53.2k
        itemsize = 0;
980
981
        /* Put a space between elements */
982
53.2k
        code = pdfi_bufstream_write(ctx, &bufstream, (byte *)" ", 1);
983
53.2k
        if (code < 0) goto exit;
984
985
        /* No dereference */
986
53.2k
        code = pdfi_dict_get_no_deref(ctx, dict, (const pdf_name *)Key, &Value);
987
53.2k
        if (code < 0) goto exit;
988
53.2k
        code = pdfi_obj_to_string(ctx, Value, &itembuf, &itemsize);
989
53.2k
        if (code < 0) goto exit;
990
991
53.1k
        code = pdfi_bufstream_write(ctx, &bufstream, itembuf, itemsize);
992
53.1k
        if (code < 0) goto exit;
993
994
53.1k
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_dict_str(itembuf)");
995
53.1k
        itembuf = NULL;
996
53.1k
        itemsize = 0;
997
998
53.1k
        pdfi_countdown(Value);
999
53.1k
        Value = NULL;
1000
53.1k
        pdfi_countdown(Key);
1001
53.1k
        Key = NULL;
1002
1003
53.1k
        code = pdfi_dict_key_next(ctx, dict, (pdf_obj **)&Key, &index);
1004
53.1k
        if (code == gs_error_undefined) {
1005
42.2k
            code = 0;
1006
42.2k
            break;
1007
42.2k
        }
1008
10.8k
        if (code < 0) goto exit;
1009
1010
        /* Put a space between elements */
1011
10.8k
        if (++itemnum != dictsize) {
1012
10.8k
            code = pdfi_bufstream_write(ctx, &bufstream, (byte *)" ", 1);
1013
10.8k
            if (code < 0) goto exit;
1014
10.8k
        }
1015
10.8k
    }
1016
42.2k
    if (code < 0) goto exit;
1017
1018
42.2k
    code = pdfi_bufstream_write(ctx, &bufstream, (byte *)"\n>>", 3);
1019
42.2k
    if (code < 0) goto exit;
1020
1021
42.2k
 exit_copy:
1022
    /* Now copy the results out into the string we can keep */
1023
42.2k
    code = pdfi_bufstream_copy(ctx, &bufstream, data, len);
1024
1025
42.4k
 exit:
1026
42.4k
    if (itembuf)
1027
0
        gs_free_object(ctx->memory, itembuf, "pdfi_obj_dict_str(itembuf)");
1028
42.4k
    pdfi_countdown(Key);
1029
42.4k
    pdfi_countdown(Value);
1030
42.4k
    pdfi_bufstream_free(ctx, &bufstream);
1031
42.4k
    if (code < 0)
1032
144
        (void)pdfi_loop_detector_cleartomark(ctx);
1033
42.2k
    else
1034
42.2k
        code = pdfi_loop_detector_cleartomark(ctx);
1035
42.4k
    return code;
1036
42.2k
}
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
1
{
1046
1
    int code = 0;
1047
1
    const char *s = pdf_token_strings[(uintptr_t)obj];
1048
1
    int size = (int)strlen(s) + 1;
1049
1
    byte *buf;
1050
1051
1
    buf = gs_alloc_bytes(ctx->memory, size, "pdfi_obj_name_str(data)");
1052
1
    if (buf == NULL)
1053
0
        return_error(gs_error_VMerror);
1054
1
    memcpy(buf, s, size);
1055
1
    *data = buf;
1056
1
    *len = size;
1057
1
    return code;
1058
1
}
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
1.49M
{
1079
1.49M
    obj_str_dispatch_t *dispatch_ptr;
1080
1.49M
    int code = 0;
1081
1.49M
    pdf_obj_type type;
1082
1083
1.49M
    *data = NULL;
1084
1.49M
    *len = 0;
1085
1.49M
    type = pdfi_type_of(obj);
1086
4.50M
    for (dispatch_ptr = obj_str_dispatch; dispatch_ptr->func; dispatch_ptr ++) {
1087
4.50M
        if (type == dispatch_ptr->type) {
1088
1.49M
            code = dispatch_ptr->func(ctx, obj, data, len);
1089
1.49M
            goto exit;
1090
1.49M
        }
1091
4.50M
    }
1092
    /* Not implemented, use default */
1093
73
    code = pdfi_obj_default_str(ctx, obj, data, len);
1094
1.49M
 exit:
1095
1.49M
    return code;
1096
73
}
1097
1098
/*********** END obj_to_string module ************/