Coverage Report

Created: 2026-04-09 07:06

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