Coverage Report

Created: 2026-02-14 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/pdf/pdf_xref.c
Line
Count
Source
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
21.9k
{
29
21.9k
    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
21.9k
    if (new_size >= (0x7ffffff / sizeof(xref_entry)))
37
21
        return_error(gs_error_rangecheck);
38
39
21.8k
    new_xrefs = (xref_entry *)gs_alloc_bytes(ctx->memory, (size_t)(new_size) * sizeof(xref_entry), "read_xref_stream allocate xref table entries");
40
21.8k
    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
21.8k
    memset(new_xrefs, 0x00, (new_size) * sizeof(xref_entry));
46
21.8k
    memcpy(new_xrefs, ctx->xref_table->xref, ctx->xref_table->xref_size * sizeof(xref_entry));
47
21.8k
    gs_free_object(ctx->memory, ctx->xref_table->xref, "reallocated xref entries");
48
21.8k
    ctx->xref_table->xref = new_xrefs;
49
21.8k
    ctx->xref_table->xref_size = new_size;
50
21.8k
    return 0;
51
21.8k
}
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
16.5k
{
55
16.5k
    uint i, j;
56
16.5k
    uint64_t field_width = 0;
57
16.5k
    uint32_t type = 0;
58
16.5k
    uint64_t objnum = 0, gen = 0;
59
16.5k
    byte *Buffer;
60
16.5k
    int64_t bytes = 0;
61
16.5k
    xref_entry *entry;
62
63
    /* Find max number of bytes to be read */
64
16.5k
    field_width = W[0];
65
16.5k
    if (W[1] > field_width)
66
16.4k
        field_width = W[1];
67
16.5k
    if (W[2] > field_width)
68
19
        field_width = W[2];
69
70
16.5k
    Buffer = gs_alloc_bytes(ctx->memory, field_width, "read_xref_stream_entry working buffer");
71
16.5k
    if (Buffer == NULL)
72
0
        return_error(gs_error_VMerror);
73
74
661k
    for (i=first;i<=last; i++){
75
        /* Defaults if W[n] = 0 */
76
645k
        type = 1;
77
645k
        objnum = gen = 0;
78
79
645k
        if (W[0] != 0) {
80
643k
            type = 0;
81
643k
            bytes = pdfi_read_bytes(ctx, Buffer, 1, W[0], s);
82
643k
            if (bytes < W[0]){
83
138
                gs_free_object(ctx->memory, Buffer, "read_xref_stream_entry, free working buffer (error)");
84
138
                return_error(gs_error_ioerror);
85
138
            }
86
1.28M
            for (j=0;j<W[0];j++)
87
643k
                type = (type << 8) + Buffer[j];
88
643k
        }
89
90
645k
        if (W[1] != 0) {
91
645k
            bytes = pdfi_read_bytes(ctx, Buffer, 1, W[1], s);
92
645k
            if (bytes < W[1]){
93
41
                gs_free_object(ctx->memory, Buffer, "read_xref_stream_entry free working buffer (error)");
94
41
                return_error(gs_error_ioerror);
95
41
            }
96
2.20M
            for (j=0;j<W[1];j++)
97
1.55M
                objnum = (objnum << 8) + Buffer[j];
98
645k
        }
99
100
645k
        if (W[2] != 0) {
101
628k
            bytes = pdfi_read_bytes(ctx, Buffer, 1, W[2], s);
102
628k
            if (bytes < W[2]){
103
41
                gs_free_object(ctx->memory, Buffer, "read_xref_stream_entry, free working buffer (error)");
104
41
                return_error(gs_error_ioerror);
105
41
            }
106
1.27M
            for (j=0;j<W[2];j++)
107
644k
                gen = (gen << 8) + Buffer[j];
108
628k
        }
109
110
645k
        entry = &ctx->xref_table->xref[i];
111
645k
        if (entry->object_num != 0 && !entry->free)
112
4.04k
            continue;
113
114
641k
        entry->compressed = false;
115
641k
        entry->free = false;
116
641k
        entry->object_num = i;
117
641k
        entry->cache = NULL;
118
119
641k
        switch(type) {
120
18.9k
            case 0:
121
18.9k
                entry->free = true;
122
18.9k
                entry->u.uncompressed.offset = objnum;         /* For free objects we use the offset to store the object number of the next free object */
123
18.9k
                entry->u.uncompressed.generation_num = gen;    /* And the generation number is the numebr to use if this object is used again */
124
18.9k
                break;
125
214k
            case 1:
126
214k
                entry->u.uncompressed.offset = objnum;
127
214k
                entry->u.uncompressed.generation_num = gen;
128
214k
                break;
129
407k
            case 2:
130
407k
                entry->compressed = true;
131
407k
                entry->u.compressed.compressed_stream_num = objnum;   /* The object number of the compressed stream */
132
407k
                entry->u.compressed.object_index = gen;               /* And the index of the object within the stream */
133
407k
                break;
134
169
            default:
135
169
                gs_free_object(ctx->memory, Buffer, "read_xref_stream_entry, free working buffer");
136
169
                return_error(gs_error_rangecheck);
137
0
                break;
138
641k
        }
139
641k
    }
140
16.1k
    gs_free_object(ctx->memory, Buffer, "read_xref_stream_entry, free working buffer");
141
16.1k
    return 0;
142
16.5k
}
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
13.1k
{
152
13.1k
    pdf_c_stream *XRefStrm;
153
13.1k
    int code, i;
154
13.1k
    pdf_dict *sdict = NULL;
155
13.1k
    pdf_name *n;
156
13.1k
    pdf_array *a;
157
13.1k
    int64_t size;
158
13.1k
    int64_t num;
159
13.1k
    int64_t W[3] = {0, 0, 0};
160
13.1k
    int objnum;
161
13.1k
    bool known = false;
162
163
13.1k
    if (pdfi_type_of(stream_obj) != PDF_STREAM)
164
0
        return_error(gs_error_typecheck);
165
166
13.1k
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)stream_obj, &sdict);
167
13.1k
    if (code < 0)
168
0
        return code;
169
170
13.1k
    code = pdfi_dict_get_type(ctx, sdict, "Type", PDF_NAME, (pdf_obj **)&n);
171
13.1k
    if (code < 0)
172
60
        return code;
173
174
13.1k
    if (n->length != 4 || memcmp(n->data, "XRef", 4) != 0) {
175
30
        pdfi_countdown(n);
176
30
        return_error(gs_error_syntaxerror);
177
30
    }
178
13.0k
    pdfi_countdown(n);
179
180
13.0k
    code = pdfi_dict_get_int(ctx, sdict, "Size", &size);
181
13.0k
    if (code < 0)
182
14
        return code;
183
13.0k
    if (size < 1)
184
13
        return 0;
185
186
13.0k
    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
13.0k
    if (ctx->xref_table == NULL) {
191
8.38k
        ctx->xref_table = (xref_table_t *)gs_alloc_bytes(ctx->memory, sizeof(xref_table_t), "read_xref_stream allocate xref table");
192
8.38k
        if (ctx->xref_table == NULL) {
193
0
            return_error(gs_error_VMerror);
194
0
        }
195
8.38k
        memset(ctx->xref_table, 0x00, sizeof(xref_table_t));
196
8.38k
        ctx->xref_table->xref = (xref_entry *)gs_alloc_bytes(ctx->memory, (size_t)size * sizeof(xref_entry), "read_xref_stream allocate xref table entries");
197
8.38k
        if (ctx->xref_table->xref == NULL){
198
5
            gs_free_object(ctx->memory, ctx->xref_table, "failed to allocate xref table entries");
199
5
            ctx->xref_table = NULL;
200
5
            return_error(gs_error_VMerror);
201
5
        }
202
8.37k
        memset(ctx->xref_table->xref, 0x00, size * sizeof(xref_entry));
203
8.37k
        ctx->xref_table->ctx = ctx;
204
8.37k
        ctx->xref_table->type = PDF_XREF_TABLE;
205
8.37k
        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
8.37k
        pdfi_countup(ctx->xref_table);
211
212
8.37k
        pdfi_countdown(ctx->Trailer);
213
214
8.37k
        ctx->Trailer = sdict;
215
8.37k
        pdfi_countup(sdict);
216
8.37k
    } else {
217
4.67k
        if (size > ctx->xref_table->xref_size)
218
4
            return_error(gs_error_rangecheck);
219
220
4.66k
        code = pdfi_merge_dicts(ctx, ctx->Trailer, sdict);
221
4.66k
        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
4.66k
    }
225
226
13.0k
    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
13.0k
    code = pdfi_dict_known(ctx, sdict, "DecodeParms", &known);
236
13.0k
    if (code < 0)
237
0
        return code;
238
239
13.0k
    if (known) {
240
11.9k
        pdf_dict *DP;
241
11.9k
        double f;
242
11.9k
        pdf_obj *name;
243
244
11.9k
        code = pdfi_dict_get_type(ctx, sdict, "DecodeParms", PDF_DICT, (pdf_obj **)&DP);
245
11.9k
        if (code < 0)
246
2
            return code;
247
248
11.9k
        code = pdfi_dict_knownget_number(ctx, DP, "Colors", &f);
249
11.9k
        if (code < 0) {
250
0
            pdfi_countdown(DP);
251
0
            return code;
252
0
        }
253
11.9k
        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
11.9k
        pdfi_countdown(DP);
270
11.9k
    }
271
272
13.0k
    code = pdfi_filter_no_decryption(ctx, stream_obj, s, &XRefStrm, false);
273
13.0k
    if (code < 0) {
274
56
        pdfi_countdown(ctx->xref_table);
275
56
        ctx->xref_table = NULL;
276
56
        return code;
277
56
    }
278
279
12.9k
    code = pdfi_dict_get_type(ctx, sdict, "W", PDF_ARRAY, (pdf_obj **)&a);
280
12.9k
    if (code < 0) {
281
12
        pdfi_close_file(ctx, XRefStrm);
282
12
        pdfi_countdown(ctx->xref_table);
283
12
        ctx->xref_table = NULL;
284
12
        return code;
285
12
    }
286
287
12.9k
    if (pdfi_array_size(a) != 3) {
288
11
        pdfi_countdown(a);
289
11
        pdfi_close_file(ctx, XRefStrm);
290
11
        pdfi_countdown(ctx->xref_table);
291
11
        ctx->xref_table = NULL;
292
11
        return_error(gs_error_rangecheck);
293
11
    }
294
51.7k
    for (i=0;i<3;i++) {
295
38.8k
        code = pdfi_array_get_int(ctx, a, (uint64_t)i, (int64_t *)&W[i]);
296
38.8k
        if (code < 0 || W[i] < 0) {
297
48
            pdfi_countdown(a);
298
48
            pdfi_close_file(ctx, XRefStrm);
299
48
            pdfi_countdown(ctx->xref_table);
300
48
            ctx->xref_table = NULL;
301
48
            if (W[i] < 0)
302
15
                code = gs_note_error(gs_error_rangecheck);
303
48
            return code;
304
48
        }
305
38.8k
    }
306
12.9k
    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
12.9k
    if (W[0] > 1 || W[1] > 8 || W[2] > 8) {
320
38
        pdfi_close_file(ctx, XRefStrm);
321
38
        pdfi_countdown(ctx->xref_table);
322
38
        ctx->xref_table = NULL;
323
38
        return code;
324
38
    }
325
326
12.8k
    code = pdfi_dict_get_type(ctx, sdict, "Index", PDF_ARRAY, (pdf_obj **)&a);
327
12.8k
    if (code == gs_error_undefined) {
328
4.52k
        code = read_xref_stream_entries(ctx, XRefStrm, 0, size - 1, W);
329
4.52k
        if (code < 0) {
330
127
            pdfi_close_file(ctx, XRefStrm);
331
127
            pdfi_countdown(ctx->xref_table);
332
127
            ctx->xref_table = NULL;
333
127
            return code;
334
127
        }
335
8.35k
    } else {
336
8.35k
        int64_t start, size;
337
338
8.35k
        if (code < 0) {
339
3
            pdfi_close_file(ctx, XRefStrm);
340
3
            pdfi_countdown(ctx->xref_table);
341
3
            ctx->xref_table = NULL;
342
3
            return code;
343
3
        }
344
345
8.34k
        if (pdfi_array_size(a) & 1) {
346
13
            pdfi_countdown(a);
347
13
            pdfi_close_file(ctx, XRefStrm);
348
13
            pdfi_countdown(ctx->xref_table);
349
13
            ctx->xref_table = NULL;
350
13
            return_error(gs_error_rangecheck);
351
13
        }
352
353
20.0k
        for (i=0;i < pdfi_array_size(a);i+=2){
354
12.0k
            code = pdfi_array_get_int(ctx, a, (uint64_t)i, &start);
355
12.0k
            if (code < 0 || start < 0) {
356
21
                pdfi_countdown(a);
357
21
                pdfi_close_file(ctx, XRefStrm);
358
21
                pdfi_countdown(ctx->xref_table);
359
21
                ctx->xref_table = NULL;
360
21
                return code;
361
21
            }
362
363
12.0k
            code = pdfi_array_get_int(ctx, a, (uint64_t)i+1, &size);
364
12.0k
            if (code < 0) {
365
15
                pdfi_countdown(a);
366
15
                pdfi_close_file(ctx, XRefStrm);
367
15
                pdfi_countdown(ctx->xref_table);
368
15
                ctx->xref_table = NULL;
369
15
                return code;
370
15
            }
371
372
12.0k
            if (size < 1)
373
12
                continue;
374
375
12.0k
            if (start + size >= ctx->xref_table->xref_size) {
376
7.57k
                code = resize_xref(ctx, start + size);
377
7.57k
                if (code < 0) {
378
7
                    pdfi_countdown(a);
379
7
                    pdfi_close_file(ctx, XRefStrm);
380
7
                    pdfi_countdown(ctx->xref_table);
381
7
                    ctx->xref_table = NULL;
382
7
                    return code;
383
7
                }
384
7.57k
            }
385
386
12.0k
            code = read_xref_stream_entries(ctx, XRefStrm, start, start + size - 1, W);
387
12.0k
            if (code < 0) {
388
262
                pdfi_countdown(a);
389
262
                pdfi_close_file(ctx, XRefStrm);
390
262
                pdfi_countdown(ctx->xref_table);
391
262
                ctx->xref_table = NULL;
392
262
                return code;
393
262
            }
394
12.0k
        }
395
8.33k
    }
396
12.4k
    pdfi_countdown(a);
397
398
12.4k
    pdfi_close_file(ctx, XRefStrm);
399
400
12.4k
    code = pdfi_dict_get_int(ctx, sdict, "Prev", &num);
401
12.4k
    if (code == gs_error_undefined)
402
5.04k
        return 0;
403
404
7.38k
    if (code < 0)
405
16
        return code;
406
407
7.36k
    if (num < 0 || num > ctx->main_stream_length)
408
2.26k
        return_error(gs_error_rangecheck);
409
410
5.10k
    if (pdfi_loop_detector_check_object(ctx, num) == true)
411
13
        return_error(gs_error_circular_reference);
412
5.09k
    else {
413
5.09k
        code = pdfi_loop_detector_add_object(ctx, num);
414
5.09k
        if (code < 0)
415
0
            return code;
416
5.09k
    }
417
418
5.09k
    if(ctx->args.pdfdebug)
419
0
        outprintf(ctx->memory, "%% Reading /Prev xref\n");
420
421
5.09k
    pdfi_seek(ctx, s, num, SEEK_SET);
422
423
5.09k
    code = pdfi_read_bare_int(ctx, ctx->main_stream, &objnum);
424
5.09k
    if (code == 1) {
425
4.71k
        if (pdfi_check_xref_stream(ctx))
426
4.66k
            return pdfi_read_xref_stream_dict(ctx, s, objnum);
427
4.71k
    }
428
429
422
    code = pdfi_read_bare_keyword(ctx, ctx->main_stream);
430
422
    if (code < 0)
431
0
        return code;
432
422
    if (code == TOKEN_XREF) {
433
38
        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
38
        return(read_xref(ctx, ctx->main_stream));
438
38
    }
439
384
exit:
440
384
    return_error(gs_error_syntaxerror);
441
422
}
442
443
static int pdfi_check_xref_stream(pdf_context *ctx)
444
17.0k
{
445
17.0k
    gs_offset_t offset;
446
17.0k
    int gen_num, code = 0;
447
448
17.0k
    offset = pdfi_unread_tell(ctx);
449
450
17.0k
    code = pdfi_read_bare_int(ctx, ctx->main_stream, &gen_num);
451
17.0k
    if (code <= 0) {
452
1.31k
        code = 0;
453
1.31k
        goto exit;
454
1.31k
    }
455
456
    /* Try to read 'obj' */
457
15.7k
    code = pdfi_read_bare_keyword(ctx, ctx->main_stream);
458
15.7k
    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
15.7k
    if (code != TOKEN_OBJ)
465
1.96k
        code = 0;
466
13.7k
    else
467
13.7k
        code = 1;
468
469
17.0k
exit:
470
17.0k
    pdfi_seek(ctx, ctx->main_stream, offset, SEEK_SET);
471
17.0k
    return code;
472
15.7k
}
473
474
static int pdfi_read_xref_stream_dict(pdf_context *ctx, pdf_c_stream *s, int obj_num)
475
13.9k
{
476
13.9k
    int code;
477
13.9k
    int gen_num;
478
479
13.9k
    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
13.9k
    code = pdfi_read_bare_int(ctx, ctx->main_stream, &gen_num);
484
13.9k
    if (code <= 0) {
485
1
        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
1
        return(pdfi_repair_file(ctx));
489
1
    }
490
491
    /* Try to read 'obj' */
492
13.9k
    code = pdfi_read_bare_keyword(ctx, ctx->main_stream);
493
13.9k
    if (code < 0)
494
0
        return code;
495
13.9k
    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
13.9k
    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
571k
    do {
507
571k
        code = pdfi_read_token(ctx, ctx->main_stream, obj_num, gen_num);
508
571k
        if (code <= 0) {
509
559
            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
559
            return pdfi_repair_file(ctx);
513
559
        }
514
515
570k
        if (pdfi_count_stack(ctx) >= 2 && pdfi_type_of(ctx->stack_top[-1]) == PDF_FAST_KEYWORD) {
516
15.6k
            uintptr_t keyword = (uintptr_t)ctx->stack_top[-1];
517
15.6k
            if (keyword == TOKEN_STREAM) {
518
13.1k
                pdf_dict *dict;
519
13.1k
                pdf_stream *sdict = NULL;
520
13.1k
                int64_t Length;
521
522
                /* Remove the 'stream' token from the stack, should leave a dictionary object on the stack */
523
13.1k
                pdfi_pop(ctx, 1);
524
13.1k
                if (pdfi_type_of(ctx->stack_top[-1]) != PDF_DICT) {
525
25
                    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
25
                    return pdfi_repair_file(ctx);
529
25
                }
530
13.1k
                dict = (pdf_dict *)ctx->stack_top[-1];
531
532
                /* Convert the dict into a stream (sdict comes back with at least one ref) */
533
13.1k
                code = pdfi_obj_dict_to_stream(ctx, dict, &sdict, true);
534
                /* Pop off the dict */
535
13.1k
                pdfi_pop(ctx, 1);
536
13.1k
                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
13.1k
                dict = NULL;
547
548
                /* Init the stuff for the stream */
549
13.1k
                sdict->stream_offset = pdfi_unread_tell(ctx);
550
13.1k
                sdict->object_num = obj_num;
551
13.1k
                sdict->generation_num = gen_num;
552
553
13.1k
                code = pdfi_dict_get_int(ctx, sdict->stream_dict, "Length", &Length);
554
13.1k
                if (code < 0) {
555
                    /* TODO: Not positive this will actually have a length -- just use 0 */
556
61
                    (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
61
                    code = 0;
558
61
                    Length = 0;
559
61
                }
560
13.1k
                sdict->Length = Length;
561
13.1k
                sdict->length_valid = true;
562
563
13.1k
                code = pdfi_process_xref_stream(ctx, sdict, ctx->main_stream);
564
13.1k
                pdfi_countdown(sdict);
565
13.1k
                if (code < 0) {
566
3.58k
                    pdfi_set_error(ctx, gs_note_error(gs_error_syntaxerror), NULL, E_PDF_PREV_NOT_XREF_STREAM, "pdfi_read_xref_stream_dict", NULL);
567
3.58k
                    return code;
568
3.58k
                }
569
9.58k
                break;
570
13.1k
            } else if (keyword == TOKEN_ENDOBJ) {
571
                /* Something went wrong, this is not a stream dictionary */
572
167
                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
167
                return(pdfi_repair_file(ctx));
576
167
            }
577
15.6k
        }
578
570k
    } while(1);
579
9.58k
    return 0;
580
13.9k
}
581
582
static int skip_to_digit(pdf_context *ctx, pdf_c_stream *s, unsigned int limit)
583
3.54k
{
584
3.54k
    int c, read = 0;
585
586
13.2k
    do {
587
13.2k
        c = pdfi_read_byte(ctx, s);
588
13.2k
        if (c < 0)
589
0
            return_error(gs_error_ioerror);
590
13.2k
        if (c >= '0' && c <= '9') {
591
3.19k
            pdfi_unread_byte(ctx, s, (byte)c);
592
3.19k
            return read;
593
3.19k
        }
594
10.1k
        read++;
595
10.1k
    } while (read < limit);
596
597
350
    return read;
598
3.54k
}
599
600
static int read_digits(pdf_context *ctx, pdf_c_stream *s, byte *Buffer, int limit)
601
3.54k
{
602
3.54k
    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
3.54k
    if (limit <= 0)
609
357
        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
19.0k
    do {
615
19.0k
        c = pdfi_read_byte(ctx, s);
616
19.0k
        if (c < 0)
617
0
            return_error(gs_error_ioerror);
618
19.0k
        if (c < '0' || c > '9') {
619
1.42k
            pdfi_unread_byte(ctx, s, c);
620
1.42k
            break;
621
1.42k
        }
622
17.5k
        *Buffer++ = (byte)c;
623
17.5k
        read++;
624
17.5k
    } while (read < limit);
625
3.18k
    *Buffer = 0;
626
627
3.18k
    return read;
628
3.18k
}
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
1.80k
{
633
1.80k
    byte Buffer[20];
634
1.80k
    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
1.80k
    code = skip_to_digit(ctx, s, 20);
638
1.80k
    if (code < 0)
639
0
        return code;
640
1.80k
    read += code;
641
642
    /* Now read a number */
643
1.80k
    code = read_digits(ctx, s, (byte *)&Buffer,  (read > 10 ? 20 - read : 10));
644
1.80k
    if (code < 0)
645
57
        return code;
646
1.74k
    read += code;
647
648
1.74k
    *offset = atol((const char *)Buffer);
649
650
    /* find next number */
651
1.74k
    code = skip_to_digit(ctx, s, 20 - read);
652
1.74k
    if (code < 0)
653
0
        return code;
654
1.74k
    read += code;
655
656
    /* and read it */
657
1.74k
    code = read_digits(ctx, s, (byte *)&Buffer, (read > 15 ? 20 - read : 5));
658
1.74k
    if (code < 0)
659
300
        return code;
660
1.44k
    read += code;
661
662
1.44k
    *generation_num = atol((const char *)Buffer);
663
664
2.50k
    do {
665
2.50k
        c = pdfi_read_byte(ctx, s);
666
2.50k
        if (c < 0)
667
0
            return_error(gs_error_ioerror);
668
2.50k
        read ++;
669
2.50k
        if (c == 0x09 || c == 0x20)
670
1.09k
            continue;
671
1.41k
        if (c == 'n' || c == 'f') {
672
822
            *free = (unsigned char)c;
673
822
            break;
674
822
        } else {
675
589
            return_error(gs_error_syntaxerror);
676
589
        }
677
1.41k
    } while (read < 20);
678
854
    if (read >= 20)
679
40
        return_error(gs_error_syntaxerror);
680
681
2.09k
    do {
682
2.09k
        c = pdfi_read_byte(ctx, s);
683
2.09k
        if (c < 0)
684
0
            return_error(gs_error_syntaxerror);
685
2.09k
        read++;
686
2.09k
        if (c == 0x20 || c == 0x09 || c == 0x0d || c == 0x0a)
687
998
            continue;
688
2.09k
    } while (read < 20);
689
814
    return 0;
690
814
}
691
692
static int write_offset(byte *B, gs_offset_t o, unsigned int g, unsigned char free)
693
814
{
694
814
    byte b[20], *ptr = B;
695
814
    int index = 0;
696
697
814
    gs_snprintf((char *)b, sizeof(b), "%"PRIdOFFSET"", o);
698
814
    if (strlen((const char *)b) > 10)
699
0
        return_error(gs_error_rangecheck);
700
6.66k
    for(index=0;index < 10 - strlen((const char *)b); index++) {
701
5.84k
        *ptr++ = 0x30;
702
5.84k
    }
703
814
    memcpy(ptr, b, strlen((const char *)b));
704
814
    ptr += strlen((const char *)b);
705
814
    *ptr++ = 0x20;
706
707
814
    gs_snprintf((char *)b, sizeof(b), "%d", g);
708
814
    if (strlen((const char *)b) > 5)
709
0
        return_error(gs_error_rangecheck);
710
3.70k
    for(index=0;index < 5 - strlen((const char *)b);index++) {
711
2.89k
        *ptr++ = 0x30;
712
2.89k
    }
713
814
    memcpy(ptr, b, strlen((const char *)b));
714
814
    ptr += strlen((const char *)b);
715
814
    *ptr++ = 0x20;
716
814
    *ptr++ = free;
717
814
    *ptr++ = 0x20;
718
814
    *ptr++ = 0x0d;
719
814
    return 0;
720
814
}
721
722
static int read_xref_section(pdf_context *ctx, pdf_c_stream *s, uint64_t *section_start, uint64_t *section_size)
723
41.5k
{
724
41.5k
    int code = 0, i, j;
725
41.5k
    int start = 0;
726
41.5k
    int size = 0;
727
41.5k
    int64_t bytes = 0;
728
41.5k
    char Buffer[21];
729
730
41.5k
    *section_start = *section_size = 0;
731
732
41.5k
    if (ctx->args.pdfdebug)
733
0
        outprintf(ctx->memory, "\n%% Reading xref section\n");
734
735
41.5k
    code = pdfi_read_bare_int(ctx, ctx->main_stream, &start);
736
41.5k
    if (code < 0) {
737
        /* Not an int, might be a keyword */
738
11.1k
        code = pdfi_read_bare_keyword(ctx, ctx->main_stream);
739
11.1k
        if (code < 0)
740
0
            return code;
741
742
11.1k
        if (code != TOKEN_TRAILER) {
743
            /* element is not an integer, and not a keyword - not a valid xref */
744
159
            return_error(gs_error_typecheck);
745
159
        }
746
11.0k
        return 1;
747
11.1k
    }
748
749
30.3k
    if (start < 0)
750
26
        return_error(gs_error_rangecheck);
751
752
30.3k
    *section_start = start;
753
754
30.3k
    code = pdfi_read_bare_int(ctx, ctx->main_stream, &size);
755
30.3k
    if (code < 0)
756
22
        return code;
757
30.3k
    if (code == 0)
758
53
        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
30.2k
    if (size < 0)
763
10
        return_error(gs_error_rangecheck);
764
765
30.2k
    *section_size = size;
766
767
30.2k
    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
30.2k
    if (size > 0) {
771
29.7k
        if (ctx->xref_table == NULL) {
772
10.8k
            ctx->xref_table = (xref_table_t *)gs_alloc_bytes(ctx->memory, sizeof(xref_table_t), "read_xref_stream allocate xref table");
773
10.8k
            if (ctx->xref_table == NULL)
774
0
                return_error(gs_error_VMerror);
775
10.8k
            memset(ctx->xref_table, 0x00, sizeof(xref_table_t));
776
777
10.8k
            ctx->xref_table->xref = (xref_entry *)gs_alloc_bytes(ctx->memory, ((size_t)start + (size_t)size) * (size_t)sizeof(xref_entry), "read_xref_stream allocate xref table entries");
778
10.8k
            if (ctx->xref_table->xref == NULL){
779
33
                gs_free_object(ctx->memory, ctx->xref_table, "free xref table on error allocating entries");
780
33
                ctx->xref_table = NULL;
781
33
                return_error(gs_error_VMerror);
782
33
            }
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
10.7k
            memset(ctx->xref_table->xref, 0x00, (start + size) * sizeof(xref_entry));
789
10.7k
            ctx->xref_table->ctx = ctx;
790
10.7k
            ctx->xref_table->type = PDF_XREF_TABLE;
791
10.7k
            ctx->xref_table->xref_size = start + size;
792
10.7k
            pdfi_countup(ctx->xref_table);
793
18.9k
        } else {
794
18.9k
            if (start + size > ctx->xref_table->xref_size) {
795
14.3k
                code = resize_xref(ctx, start + size);
796
14.3k
                if (code < 0)
797
14
                    return code;
798
14.3k
            }
799
18.9k
        }
800
29.7k
    }
801
802
30.2k
    pdfi_skip_white(ctx, s);
803
374k
    for (i=0;i< size;i++){
804
345k
        xref_entry *entry = &ctx->xref_table->xref[i + start];
805
345k
        unsigned char free;
806
345k
        gs_offset_t off;
807
345k
        unsigned int gen;
808
809
345k
        bytes = pdfi_read_bytes(ctx, (byte *)Buffer, 1, 20, s);
810
345k
        if (bytes < 20)
811
8
            return_error(gs_error_ioerror);
812
345k
        j = 19;
813
345k
        if ((Buffer[19] != 0x0a && Buffer[19] != 0x0d) || (Buffer[18] != 0x0d && Buffer[18] != 0x0a && Buffer[18] != 0x20))
814
13.5k
            pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_XREF_ENTRY_SIZE, "read_xref_section", NULL);
815
370k
        while (Buffer[j] != 0x0D && Buffer[j] != 0x0A) {
816
25.7k
            pdfi_unread_byte(ctx, s, (byte)Buffer[j]);
817
25.7k
            if (--j < 0) {
818
821
                pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_XREF_ENTRY_NO_EOL, "read_xref_section", NULL);
819
821
                outprintf(ctx->memory, "Invalid xref entry, line terminator missing.\n");
820
821
                code = read_xref_entry_slow(ctx, s, &off, &gen, &free);
821
821
                if (code < 0)
822
414
                    return code;
823
407
                code = write_offset((byte *)Buffer, off, gen, free);
824
407
                if (code < 0)
825
0
                    return code;
826
407
                j = 19;
827
407
                break;
828
407
            }
829
25.7k
        }
830
345k
        Buffer[j] = 0x00;
831
345k
        if (entry->object_num != 0)
832
6.15k
            continue;
833
834
338k
        if (sscanf(Buffer, "%"PRIdOFFSET" %d %c", &entry->u.uncompressed.offset, &entry->u.uncompressed.generation_num, &free) != 3) {
835
979
            pdfi_set_warning(ctx, 0, NULL, W_PDF_BAD_XREF_ENTRY_FORMAT, "read_xref_section", NULL);
836
979
            outprintf(ctx->memory, "Invalid xref entry, incorrect format.\n");
837
979
            pdfi_unread(ctx, s, (byte *)Buffer, 20);
838
979
            code = read_xref_entry_slow(ctx, s, &off, &gen, &free);
839
979
            if (code < 0)
840
572
                return code;
841
407
            code = write_offset((byte *)Buffer, off, gen, free);
842
407
            if (code < 0)
843
0
                return code;
844
407
        }
845
846
338k
        entry->compressed = false;
847
338k
        entry->object_num = i + start;
848
338k
        if (free == 'f')
849
84.9k
            entry->free = true;
850
338k
        if(free == 'n')
851
253k
            entry->free = false;
852
338k
        if (entry->object_num == 0) {
853
7.24k
            if (!entry->free) {
854
91
                pdfi_set_warning(ctx, 0, NULL, W_PDF_XREF_OBJECT0_NOT_FREE, "read_xref_section", NULL);
855
91
            }
856
7.24k
        }
857
338k
    }
858
859
29.2k
    return 0;
860
30.2k
}
861
862
static int read_xref(pdf_context *ctx, pdf_c_stream *s)
863
12.3k
{
864
12.3k
    int code = 0;
865
12.3k
    pdf_dict *d = NULL;
866
12.3k
    uint64_t max_obj = 0;
867
12.3k
    int64_t num, XRefStm = 0;
868
12.3k
    int obj_num;
869
12.3k
    bool known = false;
870
871
12.3k
    if (ctx->repaired)
872
7
        return 0;
873
874
41.5k
    do {
875
41.5k
        uint64_t section_start, section_size;
876
877
41.5k
        code = read_xref_section(ctx, s, &section_start, &section_size);
878
41.5k
        if (code < 0)
879
1.31k
            return code;
880
881
40.2k
        if (section_size > 0 && section_start + section_size - 1 > max_obj)
882
25.8k
            max_obj = section_start + section_size - 1;
883
884
        /* code == 1 => read_xref_section ended with a trailer. */
885
40.2k
    } while (code != 1);
886
887
11.0k
    code = pdfi_read_dict(ctx, ctx->main_stream, 0, 0);
888
11.0k
    if (code < 0)
889
211
        return code;
890
891
10.7k
    d = (pdf_dict *)ctx->stack_top[-1];
892
10.7k
    if (pdfi_type_of(d) != PDF_DICT) {
893
18
        pdfi_pop(ctx, 1);
894
18
        return_error(gs_error_typecheck);
895
18
    }
896
10.7k
    pdfi_countup(d);
897
10.7k
    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
10.7k
    code = pdfi_dict_get_int(ctx, d, "XRefStm", &XRefStm);
905
10.7k
    if (code < 0 && code != gs_error_undefined)
906
2
        goto error;
907
908
10.7k
    if (code == 0) {
909
316
        code = pdfi_dict_delete(ctx, d, "XRefStm");
910
316
        if (code < 0)
911
0
            goto error;
912
316
    }
913
914
10.7k
    if (ctx->Trailer == NULL) {
915
9.49k
        ctx->Trailer = d;
916
9.49k
        pdfi_countup(d);
917
9.49k
    } else {
918
1.27k
        code = pdfi_merge_dicts(ctx, ctx->Trailer, d);
919
1.27k
        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
1.27k
    }
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
10.7k
    code = pdfi_dict_get_int(ctx, d, "Size", &num);
930
10.7k
    if (code < 0)
931
18
        goto error;
932
933
10.7k
    if (max_obj >= num)
934
636
        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
10.7k
    code = pdfi_dict_known(ctx, d, "Prev", &known);
940
10.7k
    if (known) {
941
4.79k
        code = pdfi_dict_get_int(ctx, d, "Prev", &num);
942
4.79k
        if (code < 0)
943
19
            goto error;
944
945
4.77k
        if (num < 0 || num > ctx->main_stream_length) {
946
1.69k
            code = gs_note_error(gs_error_rangecheck);
947
1.69k
            goto error;
948
1.69k
        }
949
950
3.07k
        if (pdfi_loop_detector_check_object(ctx, num) == true) {
951
9
            code = gs_note_error(gs_error_circular_reference);
952
9
            goto error;
953
9
        }
954
3.06k
        else {
955
3.06k
            code = pdfi_loop_detector_add_object(ctx, num);
956
3.06k
            if (code < 0)
957
0
                goto error;
958
3.06k
        }
959
960
3.06k
        code = pdfi_seek(ctx, s, num, SEEK_SET);
961
3.06k
        if (code < 0)
962
0
            goto error;
963
964
3.06k
        if (!ctx->repaired) {
965
3.06k
            code = pdfi_read_token(ctx, ctx->main_stream, 0, 0);
966
3.06k
            if (code < 0)
967
133
                goto error;
968
969
2.93k
            if (code == 0) {
970
4
                code = gs_note_error(gs_error_syntaxerror);
971
4
                goto error;
972
4
            }
973
2.93k
        } else {
974
0
            code = 0;
975
0
            goto error;
976
0
        }
977
978
2.93k
        if ((intptr_t)(ctx->stack_top[-1]) == (intptr_t)TOKEN_XREF) {
979
            /* Read old-style xref table */
980
1.35k
            pdfi_pop(ctx, 1);
981
1.35k
            code = read_xref(ctx, ctx->main_stream);
982
1.35k
            if (code < 0)
983
235
                goto error;
984
1.57k
        } else {
985
1.57k
            pdfi_pop(ctx, 1);
986
1.57k
            code = gs_note_error(gs_error_typecheck);
987
1.57k
            goto error;
988
1.57k
        }
989
2.93k
    }
990
991
    /* Now check if this is a hybrid file. */
992
7.08k
    if (XRefStm != 0) {
993
188
        ctx->is_hybrid = true;
994
995
188
        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
188
        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
188
        else {
1004
188
            code = pdfi_loop_detector_add_object(ctx, XRefStm);
1005
188
            if (code < 0)
1006
0
                goto error;
1007
188
        }
1008
1009
188
        code = pdfi_loop_detector_mark(ctx);
1010
188
        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
188
        pdfi_seek(ctx, s, XRefStm, SEEK_SET);
1018
1019
188
        code = pdfi_read_bare_int(ctx, ctx->main_stream, &obj_num);
1020
188
        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
188
        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
188
        if (code < 0) {
1029
15
            pdfi_loop_detector_cleartomark(ctx);
1030
15
            goto error;
1031
15
        }
1032
1033
173
        pdfi_loop_detector_cleartomark(ctx);
1034
173
    } else
1035
6.89k
        code = 0;
1036
1037
10.7k
error:
1038
10.7k
    pdfi_countdown(d);
1039
10.7k
    return code;
1040
7.08k
}
1041
1042
int pdfi_read_xref(pdf_context *ctx)
1043
105k
{
1044
105k
    int code = 0;
1045
105k
    int obj_num;
1046
1047
105k
    code = pdfi_loop_detector_mark(ctx);
1048
105k
    if (code < 0)
1049
0
        return code;
1050
1051
105k
    if (ctx->startxref == 0)
1052
59.4k
        goto repair;
1053
1054
45.8k
    code = pdfi_loop_detector_add_object(ctx, ctx->startxref);
1055
45.8k
    if (code < 0)
1056
0
        goto exit;
1057
1058
45.8k
    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
45.8k
    if (ctx->startxref > ctx->main_stream_length - 5) {
1062
11.8k
        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
11.8k
        goto repair;
1066
11.8k
    }
1067
34.0k
    if (ctx->startxref < 0) {
1068
549
        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
549
        goto repair;
1072
549
    }
1073
1074
    /* Read the xref(s) */
1075
33.4k
    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
33.4k
    code = pdfi_read_bare_int(ctx, ctx->main_stream, &obj_num);
1079
33.4k
    if (code == 1) {
1080
12.2k
        if (pdfi_check_xref_stream(ctx)) {
1081
9.06k
            code = pdfi_read_xref_stream_dict(ctx, ctx->main_stream, obj_num);
1082
9.06k
            if (code < 0)
1083
3.42k
                goto repair;
1084
9.06k
        } else
1085
3.23k
            goto repair;
1086
21.1k
    } else {
1087
        /* If not, it had better start 'xref', and be an old-style xref table */
1088
21.1k
        code = pdfi_read_bare_keyword(ctx, ctx->main_stream);
1089
21.1k
        if (code != TOKEN_XREF) {
1090
10.2k
            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
10.2k
            goto repair;
1094
10.2k
        }
1095
1096
10.9k
        code = read_xref(ctx, ctx->main_stream);
1097
10.9k
        if (code < 0)
1098
4.98k
            goto repair;
1099
10.9k
    }
1100
1101
11.5k
    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
11.5k
    if (ctx->args.pdfdebug)
1163
0
        outprintf(ctx->memory, "\n");
1164
1165
11.5k
 exit:
1166
11.5k
    (void)pdfi_loop_detector_cleartomark(ctx);
1167
1168
11.5k
    if (code < 0)
1169
0
        return code;
1170
1171
11.5k
    return 0;
1172
1173
93.6k
repair:
1174
93.6k
    (void)pdfi_loop_detector_cleartomark(ctx);
1175
93.6k
    if (!ctx->repaired && !ctx->args.pdfstoponerror)
1176
93.6k
        return(pdfi_repair_file(ctx));
1177
76
    return 0;
1178
93.6k
}