Coverage Report

Created: 2026-04-09 07:06

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