Coverage Report

Created: 2025-11-16 07:40

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