Coverage Report

Created: 2025-06-10 07:27

/src/ghostpdl/pdf/pdf_xref.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2018-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
/* xref parsing */
17
18
#include "pdf_int.h"
19
#include "pdf_stack.h"
20
#include "pdf_xref.h"
21
#include "pdf_file.h"
22
#include "pdf_loop_detect.h"
23
#include "pdf_dict.h"
24
#include "pdf_array.h"
25
#include "pdf_repair.h"
26
27
static int resize_xref(pdf_context *ctx, uint64_t new_size)
28
1.83k
{
29
1.83k
    xref_entry *new_xrefs;
30
31
    /* Although we can technically handle object numbers larger than this, on some systems (32-bit Windows)
32
     * memset is limited to a (signed!) integer for the size of memory to clear. We could deal
33
     * with this by clearing the memory in blocks, but really, this is almost certainly a
34
     * corrupted file or something.
35
     */
36
1.83k
    if (new_size >= (0x7ffffff / sizeof(xref_entry)))
37
1
        return_error(gs_error_rangecheck);
38
39
1.83k
    new_xrefs = (xref_entry *)gs_alloc_bytes(ctx->memory, (new_size) * sizeof(xref_entry), "read_xref_stream allocate xref table entries");
40
1.83k
    if (new_xrefs == NULL){
41
0
        pdfi_countdown(ctx->xref_table);
42
0
        ctx->xref_table = NULL;
43
0
        return_error(gs_error_VMerror);
44
0
    }
45
1.83k
    memset(new_xrefs, 0x00, (new_size) * sizeof(xref_entry));
46
1.83k
    memcpy(new_xrefs, ctx->xref_table->xref, ctx->xref_table->xref_size * sizeof(xref_entry));
47
1.83k
    gs_free_object(ctx->memory, ctx->xref_table->xref, "reallocated xref entries");
48
1.83k
    ctx->xref_table->xref = new_xrefs;
49
1.83k
    ctx->xref_table->xref_size = new_size;
50
1.83k
    return 0;
51
1.83k
}
52
53
static int read_xref_stream_entries(pdf_context *ctx, pdf_c_stream *s, int64_t first, int64_t last, int64_t *W)
54
1.46k
{
55
1.46k
    uint i, j;
56
1.46k
    uint64_t field_width = 0;
57
1.46k
    uint32_t type = 0;
58
1.46k
    uint64_t objnum = 0, gen = 0;
59
1.46k
    byte *Buffer;
60
1.46k
    int64_t bytes = 0;
61
1.46k
    xref_entry *entry;
62
63
    /* Find max number of bytes to be read */
64
1.46k
    field_width = W[0];
65
1.46k
    if (W[1] > field_width)
66
1.46k
        field_width = W[1];
67
1.46k
    if (W[2] > field_width)
68
1
        field_width = W[2];
69
70
1.46k
    Buffer = gs_alloc_bytes(ctx->memory, field_width, "read_xref_stream_entry working buffer");
71
1.46k
    if (Buffer == NULL)
72
0
        return_error(gs_error_VMerror);
73
74
42.7k
    for (i=first;i<=last; i++){
75
        /* Defaults if W[n] = 0 */
76
41.3k
        type = 1;
77
41.3k
        objnum = gen = 0;
78
79
41.3k
        if (W[0] != 0) {
80
41.3k
            type = 0;
81
41.3k
            bytes = pdfi_read_bytes(ctx, Buffer, 1, W[0], s);
82
41.3k
            if (bytes < W[0]){
83
12
                gs_free_object(ctx->memory, Buffer, "read_xref_stream_entry, free working buffer (error)");
84
12
                return_error(gs_error_ioerror);
85
12
            }
86
82.5k
            for (j=0;j<W[0];j++)
87
41.2k
                type = (type << 8) + Buffer[j];
88
41.2k
        }
89
90
41.2k
        if (W[1] != 0) {
91
41.2k
            bytes = pdfi_read_bytes(ctx, Buffer, 1, W[1], s);
92
41.2k
            if (bytes < W[1]){
93
3
                gs_free_object(ctx->memory, Buffer, "read_xref_stream_entry free working buffer (error)");
94
3
                return_error(gs_error_ioerror);
95
3
            }
96
142k
            for (j=0;j<W[1];j++)
97
101k
                objnum = (objnum << 8) + Buffer[j];
98
41.2k
        }
99
100
41.2k
        if (W[2] != 0) {
101
39.1k
            bytes = pdfi_read_bytes(ctx, Buffer, 1, W[2], s);
102
39.1k
            if (bytes < W[2]){
103
7
                gs_free_object(ctx->memory, Buffer, "read_xref_stream_entry, free working buffer (error)");
104
7
                return_error(gs_error_ioerror);
105
7
            }
106
79.7k
            for (j=0;j<W[2];j++)
107
40.5k
                gen = (gen << 8) + Buffer[j];
108
39.1k
        }
109
110
41.2k
        entry = &ctx->xref_table->xref[i];
111
41.2k
        if (entry->object_num != 0 && !entry->free)
112
490
            continue;
113
114
40.7k
        entry->compressed = false;
115
40.7k
        entry->free = false;
116
40.7k
        entry->object_num = i;
117
40.7k
        entry->cache = NULL;
118
119
40.7k
        switch(type) {
120
2.18k
            case 0:
121
2.18k
                entry->free = true;
122
2.18k
                entry->u.uncompressed.offset = objnum;         /* For free objects we use the offset to store the object number of the next free object */
123
2.18k
                entry->u.uncompressed.generation_num = gen;    /* And the generation number is the numebr to use if this object is used again */
124
2.18k
                break;
125
12.7k
            case 1:
126
12.7k
                entry->u.uncompressed.offset = objnum;
127
12.7k
                entry->u.uncompressed.generation_num = gen;
128
12.7k
                break;
129
25.8k
            case 2:
130
25.8k
                entry->compressed = true;
131
25.8k
                entry->u.compressed.compressed_stream_num = objnum;   /* The object number of the compressed stream */
132
25.8k
                entry->u.compressed.object_index = gen;               /* And the index of the object within the stream */
133
25.8k
                break;
134
8
            default:
135
8
                gs_free_object(ctx->memory, Buffer, "read_xref_stream_entry, free working buffer");
136
8
                return_error(gs_error_rangecheck);
137
0
                break;
138
40.7k
        }
139
40.7k
    }
140
1.43k
    gs_free_object(ctx->memory, Buffer, "read_xref_stream_entry, free working buffer");
141
1.43k
    return 0;
142
1.46k
}
143
144
/* Forward definition */
145
static int read_xref(pdf_context *ctx, pdf_c_stream *s);
146
static int pdfi_check_xref_stream(pdf_context *ctx);
147
/* These two routines are recursive.... */
148
static int pdfi_read_xref_stream_dict(pdf_context *ctx, pdf_c_stream *s, int obj_num);
149
150
static int pdfi_process_xref_stream(pdf_context *ctx, pdf_stream *stream_obj, pdf_c_stream *s)
151
1.04k
{
152
1.04k
    pdf_c_stream *XRefStrm;
153
1.04k
    int code, i;
154
1.04k
    pdf_dict *sdict = NULL;
155
1.04k
    pdf_name *n;
156
1.04k
    pdf_array *a;
157
1.04k
    int64_t size;
158
1.04k
    int64_t num;
159
1.04k
    int64_t W[3] = {0, 0, 0};
160
1.04k
    int objnum;
161
1.04k
    bool known = false;
162
163
1.04k
    if (pdfi_type_of(stream_obj) != PDF_STREAM)
164
0
        return_error(gs_error_typecheck);
165
166
1.04k
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)stream_obj, &sdict);
167
1.04k
    if (code < 0)
168
0
        return code;
169
170
1.04k
    code = pdfi_dict_get_type(ctx, sdict, "Type", PDF_NAME, (pdf_obj **)&n);
171
1.04k
    if (code < 0)
172
3
        return code;
173
174
1.04k
    if (n->length != 4 || memcmp(n->data, "XRef", 4) != 0) {
175
1
        pdfi_countdown(n);
176
1
        return_error(gs_error_syntaxerror);
177
1
    }
178
1.04k
    pdfi_countdown(n);
179
180
1.04k
    code = pdfi_dict_get_int(ctx, sdict, "Size", &size);
181
1.04k
    if (code < 0)
182
1
        return code;
183
1.04k
    if (size < 1)
184
1
        return 0;
185
186
1.04k
    if (size < 0 || size > floor((double)ARCH_MAX_SIZE_T / (double)sizeof(xref_entry)))
187
0
        return_error(gs_error_rangecheck);
188
189
    /* If this is the first xref stream then allocate the xref table and store the trailer */
190
1.04k
    if (ctx->xref_table == NULL) {
191
579
        ctx->xref_table = (xref_table_t *)gs_alloc_bytes(ctx->memory, sizeof(xref_table_t), "read_xref_stream allocate xref table");
192
579
        if (ctx->xref_table == NULL) {
193
0
            return_error(gs_error_VMerror);
194
0
        }
195
579
        memset(ctx->xref_table, 0x00, sizeof(xref_table_t));
196
579
        ctx->xref_table->xref = (xref_entry *)gs_alloc_bytes(ctx->memory, size * sizeof(xref_entry), "read_xref_stream allocate xref table entries");
197
579
        if (ctx->xref_table->xref == NULL){
198
2
            gs_free_object(ctx->memory, ctx->xref_table, "failed to allocate xref table entries");
199
2
            ctx->xref_table = NULL;
200
2
            return_error(gs_error_VMerror);
201
2
        }
202
577
        memset(ctx->xref_table->xref, 0x00, size * sizeof(xref_entry));
203
577
        ctx->xref_table->ctx = ctx;
204
577
        ctx->xref_table->type = PDF_XREF_TABLE;
205
577
        ctx->xref_table->xref_size = size;
206
#if REFCNT_DEBUG
207
        ctx->xref_table->UID = ctx->ref_UID++;
208
        outprintf(ctx->memory, "Allocated xref table with UID %"PRIi64"\n", ctx->xref_table->UID);
209
#endif
210
577
        pdfi_countup(ctx->xref_table);
211
212
577
        pdfi_countdown(ctx->Trailer);
213
214
577
        ctx->Trailer = sdict;
215
577
        pdfi_countup(sdict);
216
577
    } else {
217
463
        if (size > ctx->xref_table->xref_size)
218
2
            return_error(gs_error_rangecheck);
219
220
461
        code = pdfi_merge_dicts(ctx, ctx->Trailer, sdict);
221
461
        if (code < 0 && (code = pdfi_set_error_stop(ctx, code, NULL, E_PDF_BADXREF, "pdfi_process_xref_stream", NULL)) < 0) {
222
0
            goto exit;
223
0
        }
224
461
    }
225
226
1.03k
    pdfi_seek(ctx, ctx->main_stream, pdfi_stream_offset(ctx, stream_obj), SEEK_SET);
227
228
    /* Bug #691220 has a PDF file with a compressed XRef, the stream dictionary has
229
     * a /DecodeParms entry for the stream, which has a /Colors value of 5, which makes
230
     * *no* sense whatever. If we try to apply a Predictor then we end up in a loop trying
231
     * to read 5 colour samples. Rather than meddles with more parameters to the filter
232
     * code, we'll just remove the Colors entry from the DecodeParms dictionary,
233
     * because it is nonsense. This means we'll get the (sensible) default value of 1.
234
     */
235
1.03k
    code = pdfi_dict_known(ctx, sdict, "DecodeParms", &known);
236
1.03k
    if (code < 0)
237
0
        return code;
238
239
1.03k
    if (known) {
240
943
        pdf_dict *DP;
241
943
        double f;
242
943
        pdf_obj *name;
243
244
943
        code = pdfi_dict_get_type(ctx, sdict, "DecodeParms", PDF_DICT, (pdf_obj **)&DP);
245
943
        if (code < 0)
246
0
            return code;
247
248
943
        code = pdfi_dict_knownget_number(ctx, DP, "Colors", &f);
249
943
        if (code < 0) {
250
0
            pdfi_countdown(DP);
251
0
            return code;
252
0
        }
253
943
        if (code > 0 && f != (double)1)
254
0
        {
255
0
            code = pdfi_name_alloc(ctx, (byte *)"Colors", 6, &name);
256
0
            if (code < 0) {
257
0
                pdfi_countdown(DP);
258
0
                return code;
259
0
            }
260
0
            pdfi_countup(name);
261
262
0
            code = pdfi_dict_delete_pair(ctx, DP, (pdf_name *)name);
263
0
            pdfi_countdown(name);
264
0
            if (code < 0) {
265
0
                pdfi_countdown(DP);
266
0
                return code;
267
0
            }
268
0
        }
269
943
        pdfi_countdown(DP);
270
943
    }
271
272
1.03k
    code = pdfi_filter_no_decryption(ctx, stream_obj, s, &XRefStrm, false);
273
1.03k
    if (code < 0) {
274
1
        pdfi_countdown(ctx->xref_table);
275
1
        ctx->xref_table = NULL;
276
1
        return code;
277
1
    }
278
279
1.03k
    code = pdfi_dict_get_type(ctx, sdict, "W", PDF_ARRAY, (pdf_obj **)&a);
280
1.03k
    if (code < 0) {
281
0
        pdfi_close_file(ctx, XRefStrm);
282
0
        pdfi_countdown(ctx->xref_table);
283
0
        ctx->xref_table = NULL;
284
0
        return code;
285
0
    }
286
287
1.03k
    if (pdfi_array_size(a) != 3) {
288
1
        pdfi_countdown(a);
289
1
        pdfi_close_file(ctx, XRefStrm);
290
1
        pdfi_countdown(ctx->xref_table);
291
1
        ctx->xref_table = NULL;
292
1
        return_error(gs_error_rangecheck);
293
1
    }
294
4.14k
    for (i=0;i<3;i++) {
295
3.10k
        code = pdfi_array_get_int(ctx, a, (uint64_t)i, (int64_t *)&W[i]);
296
3.10k
        if (code < 0 || W[i] < 0) {
297
2
            pdfi_countdown(a);
298
2
            pdfi_close_file(ctx, XRefStrm);
299
2
            pdfi_countdown(ctx->xref_table);
300
2
            ctx->xref_table = NULL;
301
2
            if (W[i] < 0)
302
0
                code = gs_note_error(gs_error_rangecheck);
303
2
            return code;
304
2
        }
305
3.10k
    }
306
1.03k
    pdfi_countdown(a);
307
308
    /* W[0] is either:
309
     * 0 (no type field) or a single byte with the type.
310
     * W[1] is either:
311
     * The object number of the next free object, the byte offset of this object in the file or the object5 number of the object stream where this object is stored.
312
     * W[2] is either:
313
     * The generation number to use if this object is used again, the generation number of the object or the index of this object within the object stream.
314
     *
315
     * Object and generation numbers are limited to unsigned 64-bit values, as are bytes offsets in the file, indexes of objects within the stream likewise (actually
316
     * most of these are generally 32-bit max). So we can limit the field widths to 8 bytes, enough to hold a 64-bit number.
317
     * Even if a later version of the spec makes these larger (which seems unlikely!) we still cna't cope with integers > 64-bits.
318
     */
319
1.03k
    if (W[0] > 1 || W[1] > 8 || W[2] > 8) {
320
1
        pdfi_close_file(ctx, XRefStrm);
321
1
        pdfi_countdown(ctx->xref_table);
322
1
        ctx->xref_table = NULL;
323
1
        return code;
324
1
    }
325
326
1.03k
    code = pdfi_dict_get_type(ctx, sdict, "Index", PDF_ARRAY, (pdf_obj **)&a);
327
1.03k
    if (code == gs_error_undefined) {
328
424
        code = read_xref_stream_entries(ctx, XRefStrm, 0, size - 1, W);
329
424
        if (code < 0) {
330
7
            pdfi_close_file(ctx, XRefStrm);
331
7
            pdfi_countdown(ctx->xref_table);
332
7
            ctx->xref_table = NULL;
333
7
            return code;
334
7
        }
335
609
    } else {
336
609
        int64_t start, size;
337
338
609
        if (code < 0) {
339
0
            pdfi_close_file(ctx, XRefStrm);
340
0
            pdfi_countdown(ctx->xref_table);
341
0
            ctx->xref_table = NULL;
342
0
            return code;
343
0
        }
344
345
609
        if (pdfi_array_size(a) & 1) {
346
0
            pdfi_countdown(a);
347
0
            pdfi_close_file(ctx, XRefStrm);
348
0
            pdfi_countdown(ctx->xref_table);
349
0
            ctx->xref_table = NULL;
350
0
            return_error(gs_error_rangecheck);
351
0
        }
352
353
1.63k
        for (i=0;i < pdfi_array_size(a);i+=2){
354
1.05k
            code = pdfi_array_get_int(ctx, a, (uint64_t)i, &start);
355
1.05k
            if (code < 0 || start < 0) {
356
2
                pdfi_countdown(a);
357
2
                pdfi_close_file(ctx, XRefStrm);
358
2
                pdfi_countdown(ctx->xref_table);
359
2
                ctx->xref_table = NULL;
360
2
                return code;
361
2
            }
362
363
1.04k
            code = pdfi_array_get_int(ctx, a, (uint64_t)i+1, &size);
364
1.04k
            if (code < 0) {
365
3
                pdfi_countdown(a);
366
3
                pdfi_close_file(ctx, XRefStrm);
367
3
                pdfi_countdown(ctx->xref_table);
368
3
                ctx->xref_table = NULL;
369
3
                return code;
370
3
            }
371
372
1.04k
            if (size < 1)
373
0
                continue;
374
375
1.04k
            if (start + size >= ctx->xref_table->xref_size) {
376
519
                code = resize_xref(ctx, start + size);
377
519
                if (code < 0) {
378
0
                    pdfi_countdown(a);
379
0
                    pdfi_close_file(ctx, XRefStrm);
380
0
                    pdfi_countdown(ctx->xref_table);
381
0
                    ctx->xref_table = NULL;
382
0
                    return code;
383
0
                }
384
519
            }
385
386
1.04k
            code = read_xref_stream_entries(ctx, XRefStrm, start, start + size - 1, W);
387
1.04k
            if (code < 0) {
388
23
                pdfi_countdown(a);
389
23
                pdfi_close_file(ctx, XRefStrm);
390
23
                pdfi_countdown(ctx->xref_table);
391
23
                ctx->xref_table = NULL;
392
23
                return code;
393
23
            }
394
1.04k
        }
395
609
    }
396
998
    pdfi_countdown(a);
397
398
998
    pdfi_close_file(ctx, XRefStrm);
399
400
998
    code = pdfi_dict_get_int(ctx, sdict, "Prev", &num);
401
998
    if (code == gs_error_undefined)
402
473
        return 0;
403
404
525
    if (code < 0)
405
1
        return code;
406
407
524
    if (num < 0 || num > ctx->main_stream_length)
408
36
        return_error(gs_error_rangecheck);
409
410
488
    if (pdfi_loop_detector_check_object(ctx, num) == true)
411
3
        return_error(gs_error_circular_reference);
412
485
    else {
413
485
        code = pdfi_loop_detector_add_object(ctx, num);
414
485
        if (code < 0)
415
0
            return code;
416
485
    }
417
418
485
    if(ctx->args.pdfdebug)
419
0
        outprintf(ctx->memory, "%% Reading /Prev xref\n");
420
421
485
    pdfi_seek(ctx, s, num, SEEK_SET);
422
423
485
    code = pdfi_read_bare_int(ctx, ctx->main_stream, &objnum);
424
485
    if (code == 1) {
425
458
        if (pdfi_check_xref_stream(ctx))
426
456
            return pdfi_read_xref_stream_dict(ctx, s, objnum);
427
458
    }
428
429
29
    code = pdfi_read_bare_keyword(ctx, ctx->main_stream);
430
29
    if (code < 0)
431
0
        return code;
432
29
    if (code == TOKEN_XREF) {
433
6
        if ((code = pdfi_set_error_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, E_PDF_PREV_NOT_XREF_STREAM, "pdfi_process_xref_stream", NULL)) < 0) {
434
0
            goto exit;
435
0
        }
436
        /* Read old-style xref table */
437
6
        return(read_xref(ctx, ctx->main_stream));
438
6
    }
439
23
exit:
440
23
    return_error(gs_error_syntaxerror);
441
29
}
442
443
static int pdfi_check_xref_stream(pdf_context *ctx)
444
1.36k
{
445
1.36k
    gs_offset_t offset;
446
1.36k
    int gen_num, code = 0;
447
448
1.36k
    offset = pdfi_unread_tell(ctx);
449
450
1.36k
    code = pdfi_read_bare_int(ctx, ctx->main_stream, &gen_num);
451
1.36k
    if (code <= 0) {
452
115
        code = 0;
453
115
        goto exit;
454
115
    }
455
456
    /* Try to read 'obj' */
457
1.25k
    code = pdfi_read_bare_keyword(ctx, ctx->main_stream);
458
1.25k
    if (code <= 0) {
459
0
        code = 0;
460
0
        goto exit;
461
0
    }
462
463
    /* Third element must be obj, or it's not a valid xref */
464
1.25k
    if (code != TOKEN_OBJ)
465
159
        code = 0;
466
1.09k
    else
467
1.09k
        code = 1;
468
469
1.36k
exit:
470
1.36k
    pdfi_seek(ctx, ctx->main_stream, offset, SEEK_SET);
471
1.36k
    return code;
472
1.25k
}
473
474
static int pdfi_read_xref_stream_dict(pdf_context *ctx, pdf_c_stream *s, int obj_num)
475
1.11k
{
476
1.11k
    int code;
477
1.11k
    int gen_num;
478
479
1.11k
    if (ctx->args.pdfdebug)
480
0
        outprintf(ctx->memory, "\n%% Reading PDF 1.5+ xref stream\n");
481
482
    /* We have the obj_num. Lets try for obj_num gen obj as a XRef stream */
483
1.11k
    code = pdfi_read_bare_int(ctx, ctx->main_stream, &gen_num);
484
1.11k
    if (code <= 0) {
485
0
        if ((code = pdfi_set_error_stop(ctx, code, NULL, E_PDF_BADXREFSTREAM, "pdfi_read_xref_stream_dict", "")) < 0) {
486
0
            return code;
487
0
        }
488
0
        return(pdfi_repair_file(ctx));
489
0
    }
490
491
    /* Try to read 'obj' */
492
1.11k
    code = pdfi_read_bare_keyword(ctx, ctx->main_stream);
493
1.11k
    if (code < 0)
494
0
        return code;
495
1.11k
    if (code == 0)
496
0
        return_error(gs_error_syntaxerror);
497
498
    /* Third element must be obj, or it's not a valid xref */
499
1.11k
    if (code != TOKEN_OBJ) {
500
0
        if ((code = pdfi_set_error_stop(ctx, gs_note_error(gs_error_rangecheck), NULL, E_PDF_BAD_XREFSTMOFFSET, "pdfi_read_xref_stream_dict", "")) < 0) {
501
0
            return code;
502
0
        }
503
0
        return(pdfi_repair_file(ctx));
504
0
    }
505
506
44.9k
    do {
507
44.9k
        code = pdfi_read_token(ctx, ctx->main_stream, obj_num, gen_num);
508
44.9k
        if (code <= 0) {
509
53
            if ((code = pdfi_set_error_stop(ctx, code, NULL, E_PDF_BADXREFSTREAM, "pdfi_read_xref_stream_dict", NULL)) < 0) {
510
0
                return code;
511
0
            }
512
53
            return pdfi_repair_file(ctx);
513
53
        }
514
515
44.8k
        if (pdfi_count_stack(ctx) >= 2 && pdfi_type_of(ctx->stack_top[-1]) == PDF_FAST_KEYWORD) {
516
1.25k
            uintptr_t keyword = (uintptr_t)ctx->stack_top[-1];
517
1.25k
            if (keyword == TOKEN_STREAM) {
518
1.05k
                pdf_dict *dict;
519
1.05k
                pdf_stream *sdict = NULL;
520
1.05k
                int64_t Length;
521
522
                /* Remove the 'stream' token from the stack, should leave a dictionary object on the stack */
523
1.05k
                pdfi_pop(ctx, 1);
524
1.05k
                if (pdfi_type_of(ctx->stack_top[-1]) != PDF_DICT) {
525
2
                    if ((code = pdfi_set_error_stop(ctx, code, NULL, E_PDF_BADXREFSTREAM, "pdfi_read_xref_stream_dict", NULL)) < 0) {
526
0
                        return code;
527
0
                    }
528
2
                    return pdfi_repair_file(ctx);
529
2
                }
530
1.04k
                dict = (pdf_dict *)ctx->stack_top[-1];
531
532
                /* Convert the dict into a stream (sdict comes back with at least one ref) */
533
1.04k
                code = pdfi_obj_dict_to_stream(ctx, dict, &sdict, true);
534
                /* Pop off the dict */
535
1.04k
                pdfi_pop(ctx, 1);
536
1.04k
                if (code < 0) {
537
0
                    if ((code = pdfi_set_error_stop(ctx, code, NULL, E_PDF_BADXREFSTREAM, "pdfi_read_xref_stream_dict", NULL)) < 0) {
538
0
                        return code;
539
0
                    }
540
                    /* TODO: should I return code instead of trying to repair?
541
                     * Normally the above routine should not fail so something is
542
                     * probably seriously fubar.
543
                     */
544
0
                    return pdfi_repair_file(ctx);
545
0
                }
546
1.04k
                dict = NULL;
547
548
                /* Init the stuff for the stream */
549
1.04k
                sdict->stream_offset = pdfi_unread_tell(ctx);
550
1.04k
                sdict->object_num = obj_num;
551
1.04k
                sdict->generation_num = gen_num;
552
553
1.04k
                code = pdfi_dict_get_int(ctx, sdict->stream_dict, "Length", &Length);
554
1.04k
                if (code < 0) {
555
                    /* TODO: Not positive this will actually have a length -- just use 0 */
556
6
                    (void)pdfi_set_error_var(ctx, 0, NULL, E_PDF_BADSTREAM, "pdfi_read_xref_stream_dict", "Xref Stream object %u missing mandatory keyword /Length\n", obj_num);
557
6
                    code = 0;
558
6
                    Length = 0;
559
6
                }
560
1.04k
                sdict->Length = Length;
561
1.04k
                sdict->length_valid = true;
562
563
1.04k
                code = pdfi_process_xref_stream(ctx, sdict, ctx->main_stream);
564
1.04k
                pdfi_countdown(sdict);
565
1.04k
                if (code < 0) {
566
134
                    pdfi_set_error(ctx, gs_note_error(gs_error_syntaxerror), NULL, E_PDF_PREV_NOT_XREF_STREAM, "pdfi_read_xref_stream_dict", NULL);
567
134
                    return code;
568
134
                }
569
914
                break;
570
1.04k
            } else if (keyword == TOKEN_ENDOBJ) {
571
                /* Something went wrong, this is not a stream dictionary */
572
11
                if ((code = pdfi_set_error_var(ctx, 0, NULL, E_PDF_BADSTREAM, "pdfi_read_xref_stream_dict", "Xref Stream object %u missing mandatory keyword /Length\n", obj_num)) < 0) {
573
0
                    return code;
574
0
                }
575
11
                return(pdfi_repair_file(ctx));
576
11
            }
577
1.25k
        }
578
44.8k
    } while(1);
579
914
    return 0;
580
1.11k
}
581
582
static int skip_to_digit(pdf_context *ctx, pdf_c_stream *s, unsigned int limit)
583
245
{
584
245
    int c, read = 0;
585
586
892
    do {
587
892
        c = pdfi_read_byte(ctx, s);
588
892
        if (c < 0)
589
0
            return_error(gs_error_ioerror);
590
892
        if (c >= '0' && c <= '9') {
591
224
            pdfi_unread_byte(ctx, s, (byte)c);
592
224
            return read;
593
224
        }
594
668
        read++;
595
668
    } while (read < limit);
596
597
21
    return read;
598
245
}
599
600
static int read_digits(pdf_context *ctx, pdf_c_stream *s, byte *Buffer, int limit)
601
245
{
602
245
    int c, read = 0;
603
604
    /* Since the "limit" is a value calculated by the caller,
605
       it's easier to check it in one place (here) than before
606
       every call.
607
     */
608
245
    if (limit <= 0)
609
22
        return_error(gs_error_syntaxerror);
610
611
    /* We assume that Buffer always has limit+1 bytes available, so we can
612
     * safely terminate it. */
613
614
1.41k
    do {
615
1.41k
        c = pdfi_read_byte(ctx, s);
616
1.41k
        if (c < 0)
617
0
            return_error(gs_error_ioerror);
618
1.41k
        if (c < '0' || c > '9') {
619
85
            pdfi_unread_byte(ctx, s, c);
620
85
            break;
621
85
        }
622
1.32k
        *Buffer++ = (byte)c;
623
1.32k
        read++;
624
1.32k
    } while (read < limit);
625
223
    *Buffer = 0;
626
627
223
    return read;
628
223
}
629
630
631
static int read_xref_entry_slow(pdf_context *ctx, pdf_c_stream *s, gs_offset_t *offset, uint32_t *generation_num, unsigned char *free)
632
126
{
633
126
    byte Buffer[20];
634
126
    int c, code, read = 0;
635
636
    /* First off, find a number. If we don't find one, and read 20 bytes, throw an error */
637
126
    code = skip_to_digit(ctx, s, 20);
638
126
    if (code < 0)
639
0
        return code;
640
126
    read += code;
641
642
    /* Now read a number */
643
126
    code = read_digits(ctx, s, (byte *)&Buffer,  (read > 10 ? 20 - read : 10));
644
126
    if (code < 0)
645
7
        return code;
646
119
    read += code;
647
648
119
    *offset = atol((const char *)Buffer);
649
650
    /* find next number */
651
119
    code = skip_to_digit(ctx, s, 20 - read);
652
119
    if (code < 0)
653
0
        return code;
654
119
    read += code;
655
656
    /* and read it */
657
119
    code = read_digits(ctx, s, (byte *)&Buffer, (read > 15 ? 20 - read : 5));
658
119
    if (code < 0)
659
15
        return code;
660
104
    read += code;
661
662
104
    *generation_num = atol((const char *)Buffer);
663
664
178
    do {
665
178
        c = pdfi_read_byte(ctx, s);
666
178
        if (c < 0)
667
0
            return_error(gs_error_ioerror);
668
178
        read ++;
669
178
        if (c == 0x09 || c == 0x20)
670
75
            continue;
671
103
        if (c == 'n' || c == 'f') {
672
60
            *free = (unsigned char)c;
673
60
            break;
674
60
        } else {
675
43
            return_error(gs_error_syntaxerror);
676
43
        }
677
103
    } while (read < 20);
678
61
    if (read >= 20)
679
3
        return_error(gs_error_syntaxerror);
680
681
114
    do {
682
114
        c = pdfi_read_byte(ctx, s);
683
114
        if (c < 0)
684
0
            return_error(gs_error_syntaxerror);
685
114
        read++;
686
114
        if (c == 0x20 || c == 0x09 || c == 0x0d || c == 0x0a)
687
54
            continue;
688
114
    } while (read < 20);
689
58
    return 0;
690
58
}
691
692
static int write_offset(byte *B, gs_offset_t o, unsigned int g, unsigned char free)
693
58
{
694
58
    byte b[20], *ptr = B;
695
58
    int index = 0;
696
697
58
    gs_snprintf((char *)b, sizeof(b), "%"PRIdOFFSET"", o);
698
58
    if (strlen((const char *)b) > 10)
699
0
        return_error(gs_error_rangecheck);
700
463
    for(index=0;index < 10 - strlen((const char *)b); index++) {
701
405
        *ptr++ = 0x30;
702
405
    }
703
58
    memcpy(ptr, b, strlen((const char *)b));
704
58
    ptr += strlen((const char *)b);
705
58
    *ptr++ = 0x20;
706
707
58
    gs_snprintf((char *)b, sizeof(b), "%d", g);
708
58
    if (strlen((const char *)b) > 5)
709
0
        return_error(gs_error_rangecheck);
710
268
    for(index=0;index < 5 - strlen((const char *)b);index++) {
711
210
        *ptr++ = 0x30;
712
210
    }
713
58
    memcpy(ptr, b, strlen((const char *)b));
714
58
    ptr += strlen((const char *)b);
715
58
    *ptr++ = 0x20;
716
58
    *ptr++ = free;
717
58
    *ptr++ = 0x20;
718
58
    *ptr++ = 0x0d;
719
58
    return 0;
720
58
}
721
722
static int read_xref_section(pdf_context *ctx, pdf_c_stream *s, uint64_t *section_start, uint64_t *section_size)
723
3.13k
{
724
3.13k
    int code = 0, i, j;
725
3.13k
    int start = 0;
726
3.13k
    int size = 0;
727
3.13k
    int64_t bytes = 0;
728
3.13k
    char Buffer[21];
729
730
3.13k
    *section_start = *section_size = 0;
731
732
3.13k
    if (ctx->args.pdfdebug)
733
0
        outprintf(ctx->memory, "\n%% Reading xref section\n");
734
735
3.13k
    code = pdfi_read_bare_int(ctx, ctx->main_stream, &start);
736
3.13k
    if (code < 0) {
737
        /* Not an int, might be a keyword */
738
722
        code = pdfi_read_bare_keyword(ctx, ctx->main_stream);
739
722
        if (code < 0)
740
0
            return code;
741
742
722
        if (code != TOKEN_TRAILER) {
743
            /* element is not an integer, and not a keyword - not a valid xref */
744
13
            return_error(gs_error_typecheck);
745
13
        }
746
709
        return 1;
747
722
    }
748
749
2.41k
    if (start < 0)
750
4
        return_error(gs_error_rangecheck);
751
752
2.40k
    *section_start = start;
753
754
2.40k
    code = pdfi_read_bare_int(ctx, ctx->main_stream, &size);
755
2.40k
    if (code < 0)
756
1
        return code;
757
2.40k
    if (code == 0)
758
2
        return_error(gs_error_syntaxerror);
759
760
    /* Zero sized xref sections are valid; see the file attached to
761
     * bug 704947 for an example. */
762
2.40k
    if (size < 0)
763
2
        return_error(gs_error_rangecheck);
764
765
2.40k
    *section_size = size;
766
767
2.40k
    if (ctx->args.pdfdebug)
768
0
        outprintf(ctx->memory, "\n%% Section starts at %d and has %d entries\n", (unsigned int) start, (unsigned int)size);
769
770
2.40k
    if (size > 0) {
771
2.36k
        if (ctx->xref_table == NULL) {
772
697
            ctx->xref_table = (xref_table_t *)gs_alloc_bytes(ctx->memory, sizeof(xref_table_t), "read_xref_stream allocate xref table");
773
697
            if (ctx->xref_table == NULL)
774
0
                return_error(gs_error_VMerror);
775
697
            memset(ctx->xref_table, 0x00, sizeof(xref_table_t));
776
777
697
            ctx->xref_table->xref = (xref_entry *)gs_alloc_bytes(ctx->memory, (start + size) * sizeof(xref_entry), "read_xref_stream allocate xref table entries");
778
697
            if (ctx->xref_table->xref == NULL){
779
1
                gs_free_object(ctx->memory, ctx->xref_table, "free xref table on error allocating entries");
780
1
                ctx->xref_table = NULL;
781
1
                return_error(gs_error_VMerror);
782
1
            }
783
#if REFCNT_DEBUG
784
            ctx->xref_table->UID = ctx->ref_UID++;
785
            outprintf(ctx->memory, "Allocated xref table with UID %"PRIi64"\n", ctx->xref_table->UID);
786
#endif
787
788
696
            memset(ctx->xref_table->xref, 0x00, (start + size) * sizeof(xref_entry));
789
696
            ctx->xref_table->ctx = ctx;
790
696
            ctx->xref_table->type = PDF_XREF_TABLE;
791
696
            ctx->xref_table->xref_size = start + size;
792
696
            pdfi_countup(ctx->xref_table);
793
1.66k
        } else {
794
1.66k
            if (start + size > ctx->xref_table->xref_size) {
795
1.31k
                code = resize_xref(ctx, start + size);
796
1.31k
                if (code < 0)
797
1
                    return code;
798
1.31k
            }
799
1.66k
        }
800
2.36k
    }
801
802
2.40k
    pdfi_skip_white(ctx, s);
803
41.1k
    for (i=0;i< size;i++){
804
38.8k
        xref_entry *entry = &ctx->xref_table->xref[i + start];
805
38.8k
        unsigned char free;
806
38.8k
        gs_offset_t off;
807
38.8k
        unsigned int gen;
808
809
38.8k
        bytes = pdfi_read_bytes(ctx, (byte *)Buffer, 1, 20, s);
810
38.8k
        if (bytes < 20)
811
0
            return_error(gs_error_ioerror);
812
38.8k
        j = 19;
813
38.8k
        if ((Buffer[19] != 0x0a && Buffer[19] != 0x0d) || (Buffer[18] != 0x0d && Buffer[18] != 0x0a && Buffer[18] != 0x20))
814
1.68k
            pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_XREF_ENTRY_SIZE, "read_xref_section", NULL);
815
40.6k
        while (Buffer[j] != 0x0D && Buffer[j] != 0x0A) {
816
1.85k
            pdfi_unread_byte(ctx, s, (byte)Buffer[j]);
817
1.85k
            if (--j < 0) {
818
71
                pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_XREF_ENTRY_NO_EOL, "read_xref_section", NULL);
819
71
                outprintf(ctx->memory, "Invalid xref entry, line terminator missing.\n");
820
71
                code = read_xref_entry_slow(ctx, s, &off, &gen, &free);
821
71
                if (code < 0)
822
39
                    return code;
823
32
                code = write_offset((byte *)Buffer, off, gen, free);
824
32
                if (code < 0)
825
0
                    return code;
826
32
                j = 19;
827
32
                break;
828
32
            }
829
1.85k
        }
830
38.8k
        Buffer[j] = 0x00;
831
38.8k
        if (entry->object_num != 0)
832
1.36k
            continue;
833
834
37.4k
        if (sscanf(Buffer, "%"PRIdOFFSET" %d %c", &entry->u.uncompressed.offset, &entry->u.uncompressed.generation_num, &free) != 3) {
835
55
            pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_XREF_ENTRY_FORMAT, "read_xref_section", NULL);
836
55
            outprintf(ctx->memory, "Invalid xref entry, incorrect format.\n");
837
55
            pdfi_unread(ctx, s, (byte *)Buffer, 20);
838
55
            code = read_xref_entry_slow(ctx, s, &off, &gen, &free);
839
55
            if (code < 0)
840
29
                return code;
841
26
            code = write_offset((byte *)Buffer, off, gen, free);
842
26
            if (code < 0)
843
0
                return code;
844
26
        }
845
846
37.4k
        entry->compressed = false;
847
37.4k
        entry->object_num = i + start;
848
37.4k
        if (free == 'f')
849
14.2k
            entry->free = true;
850
37.4k
        if(free == 'n')
851
23.1k
            entry->free = false;
852
37.4k
        if (entry->object_num == 0) {
853
542
            if (!entry->free) {
854
5
                pdfi_set_warning(ctx, 0, NULL, W_PDF_XREF_OBJECT0_NOT_FREE, "read_xref_section", NULL);
855
5
            }
856
542
        }
857
37.4k
    }
858
859
2.33k
    return 0;
860
2.40k
}
861
862
static int read_xref(pdf_context *ctx, pdf_c_stream *s)
863
802
{
864
802
    int code = 0;
865
802
    pdf_dict *d = NULL;
866
802
    uint64_t max_obj = 0;
867
802
    int64_t num, XRefStm = 0;
868
802
    int obj_num;
869
802
    bool known = false;
870
871
802
    if (ctx->repaired)
872
1
        return 0;
873
874
3.13k
    do {
875
3.13k
        uint64_t section_start, section_size;
876
877
3.13k
        code = read_xref_section(ctx, s, &section_start, &section_size);
878
3.13k
        if (code < 0)
879
92
            return code;
880
881
3.04k
        if (section_size > 0 && section_start + section_size - 1 > max_obj)
882
2.16k
            max_obj = section_start + section_size - 1;
883
884
        /* code == 1 => read_xref_section ended with a trailer. */
885
3.04k
    } while (code != 1);
886
887
709
    code = pdfi_read_dict(ctx, ctx->main_stream, 0, 0);
888
709
    if (code < 0)
889
17
        return code;
890
891
692
    d = (pdf_dict *)ctx->stack_top[-1];
892
692
    if (pdfi_type_of(d) != PDF_DICT) {
893
0
        pdfi_pop(ctx, 1);
894
0
        return_error(gs_error_typecheck);
895
0
    }
896
692
    pdfi_countup(d);
897
692
    pdfi_pop(ctx, 1);
898
899
    /* We don't want to pollute the Trailer dictionary with any XRefStm key/value pairs
900
     * which will happen when we do pdfi_merge_dicts(). So we get any XRefStm here and
901
     * if there was one, remove it from the dictionary before we merge with the
902
     * primary trailer.
903
     */
904
692
    code = pdfi_dict_get_int(ctx, d, "XRefStm", &XRefStm);
905
692
    if (code < 0 && code != gs_error_undefined)
906
0
        goto error;
907
908
692
    if (code == 0) {
909
35
        code = pdfi_dict_delete(ctx, d, "XRefStm");
910
35
        if (code < 0)
911
0
            goto error;
912
35
    }
913
914
692
    if (ctx->Trailer == NULL) {
915
602
        ctx->Trailer = d;
916
602
        pdfi_countup(d);
917
602
    } else {
918
90
        code = pdfi_merge_dicts(ctx, ctx->Trailer, d);
919
90
        if (code < 0) {
920
0
            if ((code = pdfi_set_error_stop(ctx, code, NULL, E_PDF_BADXREF, "read_xref", "")) < 0) {
921
0
                return code;
922
0
            }
923
0
        }
924
90
    }
925
926
    /* Check if the highest subsection + size exceeds the /Size in the
927
     * trailer dictionary and set a warning flag if it does
928
     */
929
692
    code = pdfi_dict_get_int(ctx, d, "Size", &num);
930
692
    if (code < 0)
931
1
        goto error;
932
933
691
    if (max_obj >= num)
934
58
        pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_XREF_SIZE, "read_xref", NULL);
935
936
    /* Check if this is a modified file and has any
937
     * previous xref entries.
938
     */
939
691
    code = pdfi_dict_known(ctx, d, "Prev", &known);
940
691
    if (known) {
941
235
        code = pdfi_dict_get_int(ctx, d, "Prev", &num);
942
235
        if (code < 0)
943
2
            goto error;
944
945
233
        if (num < 0 || num > ctx->main_stream_length) {
946
73
            code = gs_note_error(gs_error_rangecheck);
947
73
            goto error;
948
73
        }
949
950
160
        if (pdfi_loop_detector_check_object(ctx, num) == true) {
951
0
            code = gs_note_error(gs_error_circular_reference);
952
0
            goto error;
953
0
        }
954
160
        else {
955
160
            code = pdfi_loop_detector_add_object(ctx, num);
956
160
            if (code < 0)
957
0
                goto error;
958
160
        }
959
960
160
        code = pdfi_seek(ctx, s, num, SEEK_SET);
961
160
        if (code < 0)
962
0
            goto error;
963
964
160
        if (!ctx->repaired) {
965
160
            code = pdfi_read_token(ctx, ctx->main_stream, 0, 0);
966
160
            if (code < 0)
967
4
                goto error;
968
969
156
            if (code == 0) {
970
0
                code = gs_note_error(gs_error_syntaxerror);
971
0
                goto error;
972
0
            }
973
156
        } else {
974
0
            code = 0;
975
0
            goto error;
976
0
        }
977
978
156
        if ((intptr_t)(ctx->stack_top[-1]) == (intptr_t)TOKEN_XREF) {
979
            /* Read old-style xref table */
980
90
            pdfi_pop(ctx, 1);
981
90
            code = read_xref(ctx, ctx->main_stream);
982
90
            if (code < 0)
983
13
                goto error;
984
90
        } else {
985
66
            pdfi_pop(ctx, 1);
986
66
            code = gs_note_error(gs_error_typecheck);
987
66
            goto error;
988
66
        }
989
156
    }
990
991
    /* Now check if this is a hybrid file. */
992
533
    if (XRefStm != 0) {
993
21
        ctx->is_hybrid = true;
994
995
21
        if (ctx->args.pdfdebug)
996
0
            outprintf(ctx->memory, "%% File is a hybrid, containing xref table and xref stream. Reading the stream.\n");
997
998
999
21
        if (pdfi_loop_detector_check_object(ctx, XRefStm) == true) {
1000
0
            code = gs_note_error(gs_error_circular_reference);
1001
0
            goto error;
1002
0
        }
1003
21
        else {
1004
21
            code = pdfi_loop_detector_add_object(ctx, XRefStm);
1005
21
            if (code < 0)
1006
0
                goto error;
1007
21
        }
1008
1009
21
        code = pdfi_loop_detector_mark(ctx);
1010
21
        if (code < 0)
1011
0
            goto error;
1012
1013
        /* Because of the way the code works when we read a file which is a pure
1014
         * xref stream file, we need to read the first integer of 'x y obj'
1015
         * because the xref stream decoding code expects that to be on the stack.
1016
         */
1017
21
        pdfi_seek(ctx, s, XRefStm, SEEK_SET);
1018
1019
21
        code = pdfi_read_bare_int(ctx, ctx->main_stream, &obj_num);
1020
21
        if (code < 0) {
1021
0
            pdfi_set_error(ctx, 0, NULL, E_PDF_BADXREFSTREAM, "read_xref", "");
1022
0
            pdfi_loop_detector_cleartomark(ctx);
1023
0
            goto error;
1024
0
        }
1025
1026
21
        code = pdfi_read_xref_stream_dict(ctx, ctx->main_stream, obj_num);
1027
        /* We could just fall through to the exit here, but choose not to in order to avoid possible mistakes in future */
1028
21
        if (code < 0) {
1029
4
            pdfi_loop_detector_cleartomark(ctx);
1030
4
            goto error;
1031
4
        }
1032
1033
17
        pdfi_loop_detector_cleartomark(ctx);
1034
17
    } else
1035
512
        code = 0;
1036
1037
692
error:
1038
692
    pdfi_countdown(d);
1039
692
    return code;
1040
533
}
1041
1042
int pdfi_read_xref(pdf_context *ctx)
1043
5.53k
{
1044
5.53k
    int code = 0;
1045
5.53k
    int obj_num;
1046
1047
5.53k
    code = pdfi_loop_detector_mark(ctx);
1048
5.53k
    if (code < 0)
1049
0
        return code;
1050
1051
5.53k
    if (ctx->startxref == 0)
1052
2.23k
        goto repair;
1053
1054
3.30k
    code = pdfi_loop_detector_add_object(ctx, ctx->startxref);
1055
3.30k
    if (code < 0)
1056
0
        goto exit;
1057
1058
3.30k
    if (ctx->args.pdfdebug)
1059
0
        outprintf(ctx->memory, "%% Trying to read 'xref' token for xref table, or 'int int obj' for an xref stream\n");
1060
1061
3.30k
    if (ctx->startxref > ctx->main_stream_length - 5) {
1062
840
        if ((code = pdfi_set_error_stop(ctx, gs_note_error(gs_error_rangecheck), NULL, E_PDF_BADSTARTXREF, "pdfi_read_xref", (char *)"startxref offset is beyond end of file")) < 0)
1063
0
            goto exit;
1064
1065
840
        goto repair;
1066
840
    }
1067
2.46k
    if (ctx->startxref < 0) {
1068
39
        if ((code = pdfi_set_error_stop(ctx, gs_note_error(gs_error_rangecheck), NULL, E_PDF_BADSTARTXREF, "pdfi_read_xref", (char *)"startxref offset is before start of file")) < 0)
1069
0
            goto exit;
1070
1071
39
        goto repair;
1072
39
    }
1073
1074
    /* Read the xref(s) */
1075
2.42k
    pdfi_seek(ctx, ctx->main_stream, ctx->startxref, SEEK_SET);
1076
1077
    /* If it starts with an int, it's an xref stream dict */
1078
2.42k
    code = pdfi_read_bare_int(ctx, ctx->main_stream, &obj_num);
1079
2.42k
    if (code == 1) {
1080
909
        if (pdfi_check_xref_stream(ctx)) {
1081
637
            code = pdfi_read_xref_stream_dict(ctx, ctx->main_stream, obj_num);
1082
637
            if (code < 0)
1083
118
                goto repair;
1084
637
        } else
1085
272
            goto repair;
1086
1.51k
    } else {
1087
        /* If not, it had better start 'xref', and be an old-style xref table */
1088
1.51k
        code = pdfi_read_bare_keyword(ctx, ctx->main_stream);
1089
1.51k
        if (code != TOKEN_XREF) {
1090
809
            if ((code = pdfi_set_error_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, E_PDF_BADSTARTXREF, "pdfi_read_xref", (char *)"Failed to read any token at the startxref location")) < 0)
1091
0
                goto exit;
1092
1093
809
            goto repair;
1094
809
        }
1095
1096
706
        code = read_xref(ctx, ctx->main_stream);
1097
706
        if (code < 0)
1098
255
            goto repair;
1099
706
    }
1100
1101
970
    if(ctx->args.pdfdebug && ctx->xref_table) {
1102
0
        int i, j;
1103
0
        xref_entry *entry;
1104
0
        char Buffer[32];
1105
1106
0
        outprintf(ctx->memory, "\n%% Dumping xref table\n");
1107
0
        for (i=0;i < ctx->xref_table->xref_size;i++) {
1108
0
            entry = &ctx->xref_table->xref[i];
1109
0
            if(entry->compressed) {
1110
0
                outprintf(ctx->memory, "*");
1111
0
                gs_snprintf(Buffer, sizeof(Buffer), "%"PRId64"", entry->object_num);
1112
0
                j = 10 - strlen(Buffer);
1113
0
                while(j--) {
1114
0
                    outprintf(ctx->memory, " ");
1115
0
                }
1116
0
                outprintf(ctx->memory, "%s ", Buffer);
1117
1118
0
                gs_snprintf(Buffer, sizeof(Buffer), "%ld", entry->u.compressed.compressed_stream_num);
1119
0
                j = 10 - strlen(Buffer);
1120
0
                while(j--) {
1121
0
                    outprintf(ctx->memory, " ");
1122
0
                }
1123
0
                outprintf(ctx->memory, "%s ", Buffer);
1124
1125
0
                gs_snprintf(Buffer, sizeof(Buffer), "%ld", entry->u.compressed.object_index);
1126
0
                j = 10 - strlen(Buffer);
1127
0
                while(j--) {
1128
0
                    outprintf(ctx->memory, " ");
1129
0
                }
1130
0
                outprintf(ctx->memory, "%s ", Buffer);
1131
0
            }
1132
0
            else {
1133
0
                outprintf(ctx->memory, " ");
1134
1135
0
                gs_snprintf(Buffer, sizeof(Buffer), "%ld", entry->object_num);
1136
0
                j = 10 - strlen(Buffer);
1137
0
                while(j--) {
1138
0
                    outprintf(ctx->memory, " ");
1139
0
                }
1140
0
                outprintf(ctx->memory, "%s ", Buffer);
1141
1142
0
                gs_snprintf(Buffer, sizeof(Buffer), "%"PRIdOFFSET"", entry->u.uncompressed.offset);
1143
0
                j = 10 - strlen(Buffer);
1144
0
                while(j--) {
1145
0
                    outprintf(ctx->memory, " ");
1146
0
                }
1147
0
                outprintf(ctx->memory, "%s ", Buffer);
1148
1149
0
                gs_snprintf(Buffer, sizeof(Buffer), "%ld", entry->u.uncompressed.generation_num);
1150
0
                j = 10 - strlen(Buffer);
1151
0
                while(j--) {
1152
0
                    outprintf(ctx->memory, " ");
1153
0
                }
1154
0
                outprintf(ctx->memory, "%s ", Buffer);
1155
0
            }
1156
0
            if (entry->free)
1157
0
                outprintf(ctx->memory, "f\n");
1158
0
            else
1159
0
                outprintf(ctx->memory, "n\n");
1160
0
        }
1161
0
    }
1162
970
    if (ctx->args.pdfdebug)
1163
0
        outprintf(ctx->memory, "\n");
1164
1165
970
 exit:
1166
970
    (void)pdfi_loop_detector_cleartomark(ctx);
1167
1168
970
    if (code < 0)
1169
0
        return code;
1170
1171
970
    return 0;
1172
1173
4.56k
repair:
1174
4.56k
    (void)pdfi_loop_detector_cleartomark(ctx);
1175
4.56k
    if (!ctx->repaired && !ctx->args.pdfstoponerror)
1176
4.55k
        return(pdfi_repair_file(ctx));
1177
10
    return 0;
1178
4.56k
}