Coverage Report

Created: 2025-06-10 07:27

/src/ghostpdl/pdf/pdf_repair.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2020-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
/* Routines to attempt repair of PDF files in the event of an error */
17
18
#include "pdf_int.h"
19
#include "pdf_stack.h"
20
#include "strmio.h"
21
#include "stream.h"
22
#include "pdf_deref.h"
23
#include "pdf_dict.h"
24
#include "pdf_file.h"
25
#include "pdf_misc.h"
26
#include "pdf_repair.h"
27
28
static int pdfi_repair_add_object(pdf_context *ctx, int64_t obj, int64_t gen, gs_offset_t offset)
29
203k
{
30
    /* Although we can handle object numbers larger than this, on some systems (32-bit Windows)
31
     * memset is limited to a (signed!) integer for the size of memory to clear. We could deal
32
     * with this by clearing the memory in blocks, but really, this is almost certainly a
33
     * corrupted file or something.
34
     */
35
203k
    if (obj >= 0x7ffffff / sizeof(xref_entry) || obj < 1 || gen < 0 || offset < 0)
36
938
        return_error(gs_error_rangecheck);
37
38
202k
    if (ctx->xref_table == NULL) {
39
3.87k
        ctx->xref_table = (xref_table_t *)gs_alloc_bytes(ctx->memory, sizeof(xref_table_t), "repair xref table");
40
3.87k
        if (ctx->xref_table == NULL) {
41
0
            return_error(gs_error_VMerror);
42
0
        }
43
3.87k
        memset(ctx->xref_table, 0x00, sizeof(xref_table_t));
44
3.87k
        ctx->xref_table->xref = (xref_entry *)gs_alloc_bytes(ctx->memory, (obj + 1) * sizeof(xref_entry), "repair xref table");
45
3.87k
        if (ctx->xref_table->xref == NULL){
46
0
            gs_free_object(ctx->memory, ctx->xref_table, "failed to allocate xref table entries for repair");
47
0
            ctx->xref_table = NULL;
48
0
            return_error(gs_error_VMerror);
49
0
        }
50
3.87k
        memset(ctx->xref_table->xref, 0x00, (obj + 1) * sizeof(xref_entry));
51
3.87k
        ctx->xref_table->ctx = ctx;
52
3.87k
        ctx->xref_table->type = PDF_XREF_TABLE;
53
3.87k
        ctx->xref_table->xref_size = obj + 1;
54
#if REFCNT_DEBUG
55
        ctx->xref_table->UID = ctx->ref_UID++;
56
        outprintf(ctx->memory, "Allocated xref table with UID %"PRIi64"\n", ctx->xref_table->UID);
57
#endif
58
3.87k
        pdfi_countup(ctx->xref_table);
59
198k
    } else {
60
198k
        if (ctx->xref_table->xref_size < (obj + 1)) {
61
115k
            xref_entry *new_xrefs;
62
63
115k
            new_xrefs = (xref_entry *)gs_alloc_bytes(ctx->memory, (obj + 1) * sizeof(xref_entry), "read_xref_stream allocate xref table entries");
64
115k
            if (new_xrefs == NULL){
65
0
                pdfi_countdown(ctx->xref_table);
66
0
                ctx->xref_table = NULL;
67
0
                return_error(gs_error_VMerror);
68
0
            }
69
115k
            memset(new_xrefs, 0x00, (obj + 1) * sizeof(xref_entry));
70
115k
            memcpy(new_xrefs, ctx->xref_table->xref, ctx->xref_table->xref_size * sizeof(xref_entry));
71
115k
            gs_free_object(ctx->memory, ctx->xref_table->xref, "reallocated xref entries");
72
115k
            ctx->xref_table->xref = new_xrefs;
73
115k
            ctx->xref_table->xref_size = obj + 1;
74
115k
        }
75
198k
    }
76
202k
    ctx->xref_table->xref[obj].compressed = false;
77
202k
    ctx->xref_table->xref[obj].free = false;
78
202k
    ctx->xref_table->xref[obj].object_num = obj;
79
202k
    ctx->xref_table->xref[obj].u.uncompressed.generation_num = gen;
80
202k
    ctx->xref_table->xref[obj].u.uncompressed.offset = offset;
81
202k
    return 0;
82
202k
}
83
84
int pdfi_repair_file(pdf_context *ctx)
85
40.5k
{
86
40.5k
    int code = 0;
87
40.5k
    gs_offset_t offset, saved_offset;
88
40.5k
    int64_t object_num = 0, generation_num = 0;
89
40.5k
    int i;
90
40.5k
    gs_offset_t outer_saved_offset[3];
91
92
40.5k
    if (ctx->repaired) {
93
35.7k
        pdfi_set_error(ctx, 0, NULL, E_PDF_UNREPAIRABLE, "pdfi_repair_file", (char *)"%% Trying to repair file for second time -- unrepairable");
94
35.7k
        return_error(gs_error_undefined);
95
35.7k
    }
96
97
4.79k
    saved_offset = pdfi_unread_tell(ctx);
98
99
4.79k
    ctx->repaired = true;
100
4.79k
    if ((code = pdfi_set_error_stop(ctx, gs_note_error(gs_error_ioerror), NULL, E_PDF_REPAIRED, "pdfi_repair_file", NULL)) < 0)
101
0
        return code;
102
103
4.79k
    ctx->repairing = true;
104
105
4.79k
    pdfi_clearstack(ctx);
106
107
4.79k
    if(ctx->args.pdfdebug)
108
0
        outprintf(ctx->memory, "%% Error encountered in opening PDF file, attempting repair\n");
109
110
    /* First try to locate a %PDF header. If we can't find one, abort this, the file is too broken
111
     * and may not even be a PDF file.
112
     */
113
4.79k
    pdfi_seek(ctx, ctx->main_stream, 0, SEEK_SET);
114
4.79k
    {
115
4.79k
        static const char test[] = "%PDF";
116
4.79k
        int index = 0;
117
118
19.1k
        do {
119
19.1k
            int c = pdfi_read_byte(ctx, ctx->main_stream);
120
19.1k
            if (c < 0)
121
0
                goto exit;
122
123
19.1k
            if (c == test[index])
124
19.1k
                index++;
125
0
            else
126
0
                index = 0;
127
19.1k
        } while (index < 4);
128
4.79k
        if (index != 4) {
129
0
            code = gs_note_error(gs_error_undefined);
130
0
            goto exit;
131
0
        }
132
4.79k
        pdfi_unread(ctx, ctx->main_stream, (byte *)test, 4);
133
4.79k
        pdfi_skip_comment(ctx, ctx->main_stream);
134
4.79k
    }
135
4.79k
    if (ctx->main_stream->eof == true) {
136
70
        code = gs_note_error(gs_error_ioerror);
137
70
        goto exit;
138
70
    }
139
140
    /* First pass, identify all the objects of the form x y obj */
141
142
199k
    do {
143
199k
        code = pdfi_skip_white(ctx, ctx->main_stream);
144
199k
        if (code < 0) {
145
0
            if (code != gs_error_VMerror && code != gs_error_ioerror) {
146
0
                pdfi_clearstack(ctx);
147
0
                continue;
148
0
            } else
149
0
                goto exit;
150
0
        }
151
199k
        offset = pdfi_unread_tell(ctx);
152
199k
        outer_saved_offset[0] = outer_saved_offset[1] = outer_saved_offset[2] = 0;
153
1.83M
        do {
154
1.83M
            outer_saved_offset[0] = outer_saved_offset[1];
155
1.83M
            outer_saved_offset[1] = outer_saved_offset[2];
156
1.83M
            outer_saved_offset[2] = pdfi_unread_tell(ctx);
157
158
1.83M
            object_num = 0;
159
160
1.83M
            code = pdfi_read_token(ctx, ctx->main_stream, 0, 0);
161
1.83M
            if (code < 0) {
162
63.0k
                if (code != gs_error_VMerror && code != gs_error_ioerror) {
163
63.0k
                    pdfi_clearstack(ctx);
164
63.0k
                    continue;
165
63.0k
                } else
166
5
                    goto exit;
167
63.0k
            }
168
1.76M
            if (pdfi_count_stack(ctx) > 0) {
169
1.69M
                if (pdfi_type_of(ctx->stack_top[-1]) == PDF_FAST_KEYWORD) {
170
441k
                    pdf_obj *k = ctx->stack_top[-1];
171
441k
                    pdf_num *n;
172
173
441k
                    if (k == PDF_TOKEN_AS_OBJ(TOKEN_OBJ)) {
174
197k
                        gs_offset_t saved_offset[3];
175
176
197k
                        offset = outer_saved_offset[0];
177
178
197k
                        saved_offset[0] = saved_offset[1] = saved_offset[2] = 0;
179
180
197k
                        if (pdfi_count_stack(ctx) < 3 || pdfi_type_of(ctx->stack_top[-3]) != PDF_INT || pdfi_type_of(ctx->stack_top[-2]) != PDF_INT) {
181
1.02k
                            pdfi_clearstack(ctx);
182
1.02k
                            continue;
183
1.02k
                        }
184
196k
                        n = (pdf_num *)ctx->stack_top[-3];
185
196k
                        object_num = n->value.i;
186
196k
                        n = (pdf_num *)ctx->stack_top[-2];
187
196k
                        generation_num = n->value.i;
188
196k
                        pdfi_clearstack(ctx);
189
190
5.97M
                        do {
191
                            /* move all the saved offsets up by one */
192
5.97M
                            saved_offset[0] = saved_offset[1];
193
5.97M
                            saved_offset[1] = saved_offset[2];
194
5.97M
                            saved_offset[2] = pdfi_unread_tell(ctx);
195
196
5.97M
                            code = pdfi_read_token(ctx, ctx->main_stream, 0, 0);
197
5.97M
                            if (code < 0) {
198
28.6k
                                if (code != gs_error_VMerror && code != gs_error_ioerror)
199
28.6k
                                    continue;
200
5
                                goto exit;
201
28.6k
                            }
202
5.94M
                            if (code == 0 && ctx->main_stream->eof)
203
938
                                break;
204
205
5.94M
                            if (pdfi_type_of(ctx->stack_top[-1]) == PDF_FAST_KEYWORD) {
206
213k
                                pdf_obj *k = ctx->stack_top[-1];
207
208
213k
                                if (k == PDF_TOKEN_AS_OBJ(TOKEN_OBJ)) {
209
                                    /* Found obj while looking for endobj, store the existing 'obj'
210
                                     * and start afresh.
211
                                     */
212
4.49k
                                    code = pdfi_repair_add_object(ctx, object_num, generation_num, offset);
213
4.49k
                                    if (pdfi_count_stack(ctx) < 3 || pdfi_type_of(ctx->stack_top[-3]) != PDF_INT || pdfi_type_of(ctx->stack_top[-2]) != PDF_INT) {
214
462
                                        pdfi_clearstack(ctx);
215
462
                                        break;
216
462
                                    }
217
4.03k
                                    n = (pdf_num *)ctx->stack_top[-3];
218
4.03k
                                    object_num = n->value.i;
219
4.03k
                                    n = (pdf_num *)ctx->stack_top[-2];
220
4.03k
                                    generation_num = n->value.i;
221
4.03k
                                    pdfi_clearstack(ctx);
222
4.03k
                                    offset = saved_offset[0];
223
4.03k
                                    continue;
224
4.49k
                                }
225
226
208k
                                if (k == PDF_TOKEN_AS_OBJ(TOKEN_ENDOBJ)) {
227
136k
                                    code = pdfi_repair_add_object(ctx, object_num, generation_num, offset);
228
136k
                                    if (code < 0)
229
16
                                        goto exit;
230
136k
                                    pdfi_clearstack(ctx);
231
136k
                                    break;
232
136k
                                } else {
233
72.5k
                                    if (k == PDF_TOKEN_AS_OBJ(TOKEN_STREAM)) {
234
58.8k
                                        static const char test[] = "endstream";
235
58.8k
                                        int index = 0;
236
237
222M
                                        do {
238
222M
                                            int c = pdfi_read_byte(ctx, ctx->main_stream);
239
222M
                                            if (c == EOFC)
240
978
                                                break;
241
222M
                                            if (c < 0)
242
0
                                                goto exit;
243
222M
                                            if (c == test[index])
244
1.64M
                                                index++;
245
220M
                                            else if (c == test[0]) /* Pesky 'e' appears twice */
246
12.1k
                                                index = 1;
247
220M
                                            else
248
220M
                                                index = 0;
249
222M
                                        } while (index < 9);
250
58.9k
                                        do {
251
58.9k
                                            code = pdfi_read_bare_keyword(ctx, ctx->main_stream);
252
58.9k
                                            if (code == gs_error_VMerror || code == gs_error_ioerror)
253
0
                                                goto exit;
254
58.9k
                                            if (code < 0) {
255
                                                /* Something went wrong and we couldn't read a token, consume one byte and retry */
256
0
                                                (void)pdfi_read_byte(ctx, ctx->main_stream);
257
58.9k
                                            } else {
258
58.9k
                                                if (code == TOKEN_ENDOBJ || code == TOKEN_INVALID_KEY) {
259
58.8k
                                                    code = pdfi_repair_add_object(ctx, object_num, generation_num, offset);
260
58.8k
                                                    if (code == gs_error_VMerror || code == gs_error_ioerror)
261
0
                                                        goto exit;
262
58.8k
                                                    break;
263
58.8k
                                                }
264
58.9k
                                            }
265
58.9k
                                        } while(ctx->main_stream->eof == false);
266
58.8k
                                        pdfi_clearstack(ctx);
267
58.8k
                                        break;
268
58.8k
                                    } else {
269
13.6k
                                        pdfi_clearstack(ctx);
270
13.6k
                                    }
271
72.5k
                                }
272
208k
                            }
273
5.94M
                        } while(1);
274
196k
                        break;
275
243k
                    } else {
276
243k
                        if (k == PDF_TOKEN_AS_OBJ(TOKEN_ENDOBJ)) {
277
3.29k
                            pdfi_clearstack(ctx);
278
3.29k
                        } else
279
240k
                            if (k == PDF_TOKEN_AS_OBJ(TOKEN_STARTXREF)) {
280
1.08k
                                code = pdfi_read_token(ctx, ctx->main_stream, 0, 0);
281
1.08k
                                if (code < 0 && code != gs_error_VMerror && code != gs_error_ioerror)
282
1
                                    continue;
283
1.08k
                                if (code < 0)
284
0
                                    goto exit;
285
1.08k
                                pdfi_clearstack(ctx);
286
239k
                            } else {
287
239k
                                if (k == PDF_TOKEN_AS_OBJ(TOKEN_TRAILER)) {
288
4.42k
                                    code = pdfi_read_bare_object(ctx, ctx->main_stream, 0, 0, 0);
289
4.42k
                                    if (code == 0 && pdfi_count_stack(ctx) > 0 && pdfi_type_of(ctx->stack_top[-1]) == PDF_DICT) {
290
2.51k
                                        if (ctx->Trailer) {
291
697
                                            pdf_dict *d = (pdf_dict *)ctx->stack_top[-1];
292
697
                                            bool known = false;
293
294
697
                                            code = pdfi_dict_known(ctx, d, "Root", &known);
295
697
                                            if (code == 0 && known) {
296
504
                                                pdfi_countdown(ctx->Trailer);
297
504
                                                ctx->Trailer = (pdf_dict *)ctx->stack_top[-1];
298
504
                                                pdfi_countup(ctx->Trailer);
299
504
                                            }
300
1.82k
                                        } else {
301
1.82k
                                            ctx->Trailer = (pdf_dict *)ctx->stack_top[-1];
302
1.82k
                                            pdfi_countup(ctx->Trailer);
303
1.82k
                                        }
304
2.51k
                                    }
305
4.42k
                                }
306
239k
                                pdfi_clearstack(ctx);
307
239k
                            }
308
243k
                    }
309
243k
                    code = pdfi_skip_white(ctx, ctx->main_stream);
310
243k
                    if (code < 0) {
311
0
                        if (code != gs_error_VMerror && code != gs_error_ioerror) {
312
0
                            pdfi_clearstack(ctx);
313
0
                            continue;
314
0
                        } else
315
0
                            goto exit;
316
0
                    }
317
243k
                }
318
1.49M
                if (pdfi_count_stack(ctx) > 0 && pdfi_type_of(ctx->stack_top[-1]) != PDF_INT)
319
342k
                    pdfi_clearstack(ctx);
320
1.49M
            }
321
1.76M
        } while (ctx->main_stream->eof == false);
322
199k
    } while(ctx->main_stream->eof == false);
323
324
4.70k
    pdfi_seek(ctx, ctx->main_stream, 0, SEEK_SET);
325
4.70k
    ctx->main_stream->eof = false;
326
327
    /* Second pass, examine every object we have located to see if its an ObjStm */
328
4.70k
    if (ctx->xref_table == NULL || ctx->xref_table->xref_size < 1) {
329
349
        code = gs_note_error(gs_error_syntaxerror);
330
349
        goto exit;
331
349
    }
332
333
10.2M
    for (i=1;i < ctx->xref_table->xref_size;i++) {
334
10.2M
        if (ctx->xref_table->xref[i].object_num != 0) {
335
            /* At this stage, all the objects we've found must be uncompressed */
336
241k
            if (ctx->xref_table->xref[i].u.uncompressed.offset > ctx->main_stream_length) {
337
                /* This can only happen if we had read an xref table before we tried to repair
338
                 * the file, and the table has entries we didn't find in the file. So
339
                 * mark the entry as free, and offset of 0, and just carry on.
340
                 */
341
308
                ctx->xref_table->xref[i].free = 1;
342
308
                ctx->xref_table->xref[i].u.uncompressed.offset = 0;
343
308
                continue;
344
308
            }
345
346
241k
            pdfi_seek(ctx, ctx->main_stream, ctx->xref_table->xref[i].u.uncompressed.offset, SEEK_SET);
347
8.04M
            do {
348
8.04M
                code = pdfi_read_token(ctx, ctx->main_stream, 0, 0);
349
8.04M
                if (ctx->main_stream->eof == true || (code < 0 && code != gs_error_ioerror && code != gs_error_VMerror)) {
350
                    /* object offset is beyond EOF or object is broken (possibly due to multiple xref
351
                     * errors) ignore the error and carry on, if the object gets used then we will
352
                     * error out at that point.
353
                     */
354
12.2k
                    code = 0;
355
12.2k
                    break;
356
12.2k
                }
357
8.03M
                if (code < 0)
358
0
                    goto exit;
359
8.03M
                if (pdfi_type_of(ctx->stack_top[-1]) == PDF_FAST_KEYWORD) {
360
830k
                    pdf_obj *k = ctx->stack_top[-1];
361
362
830k
                    if (k == PDF_TOKEN_AS_OBJ(TOKEN_OBJ)) {
363
225k
                        continue;
364
225k
                    }
365
605k
                    if (k == PDF_TOKEN_AS_OBJ(TOKEN_ENDOBJ)) {
366
171k
                        if (pdfi_count_stack(ctx) > 1) {
367
169k
                            if (pdfi_type_of(ctx->stack_top[-2]) == PDF_DICT) {
368
122k
                                pdf_dict *d = (pdf_dict *)ctx->stack_top[-2];
369
122k
                                pdf_obj *o = NULL;
370
371
122k
                                code = pdfi_dict_knownget_type(ctx, d, "Type", PDF_NAME, &o);
372
122k
                                if (code < 0) {
373
13
                                    pdfi_clearstack(ctx);
374
13
                                    continue;
375
13
                                }
376
122k
                                if (code > 0) {
377
70.8k
                                    pdf_name *n = (pdf_name *)o;
378
379
70.8k
                                    if (pdfi_name_is(n, "Catalog")) {
380
4.92k
                                        pdfi_countdown(ctx->Root); /* In case it was already set */
381
4.92k
                                        ctx->Root = (pdf_dict *)ctx->stack_top[-2];
382
4.92k
                                        pdfi_countup(ctx->Root);
383
4.92k
                                    }
384
70.8k
                                }
385
122k
                                pdfi_countdown(o);
386
122k
                            }
387
169k
                        }
388
171k
                        pdfi_clearstack(ctx);
389
171k
                        break;
390
171k
                    }
391
433k
                    if (k == PDF_TOKEN_AS_OBJ(TOKEN_STREAM)) {
392
57.4k
                        pdf_dict *d;
393
57.4k
                        pdf_name *n = NULL;
394
395
57.4k
                        if (pdfi_count_stack(ctx) <= 1) {
396
98
                            pdfi_clearstack(ctx);
397
98
                            break;;
398
0
                        }
399
57.3k
                        d = (pdf_dict *)ctx->stack_top[-2];
400
57.3k
                        if (pdfi_type_of(d) != PDF_DICT) {
401
1.67k
                            pdfi_clearstack(ctx);
402
1.67k
                            break;;
403
0
                        }
404
55.6k
                        code = pdfi_dict_knownget_type(ctx, d, "Type", PDF_NAME, (pdf_obj **)&n);
405
55.6k
                        if (code < 0) {
406
2
                            if ((code = pdfi_set_error_stop(ctx, code, NULL, E_PDF_UNREPAIRABLE, "pdfi_repair_file", NULL)) < 0) {
407
0
                                pdfi_clearstack(ctx);
408
0
                                goto exit;
409
0
                            }
410
2
                        }
411
55.6k
                        if (code > 0) {
412
24.3k
                            if (pdfi_name_is(n, "ObjStm")) {
413
1.90k
                                int64_t N;
414
1.90k
                                int obj_num, offset;
415
1.90k
                                int j;
416
1.90k
                                pdf_c_stream *compressed_stream;
417
1.90k
                                pdf_stream *stream;
418
419
1.90k
                                offset = pdfi_unread_tell(ctx);
420
1.90k
                                pdfi_seek(ctx, ctx->main_stream, offset, SEEK_SET);
421
422
1.90k
                                code = pdfi_obj_dict_to_stream(ctx, d, &stream, true);
423
1.90k
                                if (code == 0)
424
1.90k
                                    code = pdfi_filter(ctx, stream, ctx->main_stream, &compressed_stream, false);
425
426
1.90k
                                pdfi_countdown(stream);
427
428
1.90k
                                if (code == 0) {
429
1.89k
                                    code = pdfi_dict_get_int(ctx, d, "N", &N);
430
1.89k
                                    if (code == 0) {
431
68.1k
                                        for (j=0;j < N; j++) {
432
66.5k
                                            code = pdfi_read_bare_int(ctx, compressed_stream, &obj_num);
433
66.5k
                                            if (code <= 0)
434
250
                                                break;
435
66.2k
                                            else {
436
66.2k
                                                code = pdfi_read_bare_int(ctx, compressed_stream, &offset);
437
66.2k
                                                if (code > 0) {
438
66.2k
                                                    if (obj_num < 1) {
439
6
                                                        pdfi_close_file(ctx, compressed_stream);
440
6
                                                        pdfi_countdown(n);
441
6
                                                        pdfi_clearstack(ctx);
442
6
                                                        code = gs_note_error(gs_error_rangecheck);
443
6
                                                        goto exit;
444
6
                                                    }
445
66.2k
                                                    if (obj_num >= ctx->xref_table->xref_size)
446
3.36k
                                                        code = pdfi_repair_add_object(ctx, obj_num, 0, 0);
447
448
66.2k
                                                    if (code >= 0) {
449
66.1k
                                                        ctx->xref_table->xref[obj_num].compressed = true;
450
66.1k
                                                        ctx->xref_table->xref[obj_num].free = false;
451
66.1k
                                                        ctx->xref_table->xref[obj_num].object_num = obj_num;
452
66.1k
                                                        ctx->xref_table->xref[obj_num].u.compressed.compressed_stream_num = i;
453
66.1k
                                                        ctx->xref_table->xref[obj_num].u.compressed.object_index = j;
454
66.1k
                                                    }
455
66.2k
                                                }
456
66.2k
                                            }
457
66.5k
                                        }
458
1.88k
                                    }
459
1.88k
                                    pdfi_close_file(ctx, compressed_stream);
460
1.88k
                                }
461
1.90k
                                if (code < 0) {
462
146
                                    if ((code = pdfi_set_error_stop(ctx, code, NULL, E_PDF_UNREPAIRABLE, "pdfi_repair_file", NULL)) < 0) {
463
0
                                        pdfi_countdown(n);
464
0
                                        pdfi_clearstack(ctx);
465
0
                                        goto exit;
466
0
                                    }
467
146
                                }
468
1.90k
                            }
469
24.3k
                        }
470
55.6k
                        pdfi_countdown(n);
471
55.6k
                        pdfi_clearstack(ctx);
472
55.6k
                        break;
473
55.6k
                    }
474
433k
                }
475
8.03M
            } while (1);
476
241k
        }
477
10.2M
    }
478
479
4.79k
exit:
480
4.79k
    if (code > 0)
481
1.51k
        code = 0;
482
4.79k
    pdfi_seek(ctx, ctx->main_stream, saved_offset, SEEK_SET);
483
4.79k
    ctx->main_stream->eof = false;
484
4.79k
    ctx->repairing = false;
485
4.79k
    return code;
486
4.35k
}