Coverage Report

Created: 2026-04-01 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/pdf/pdf_file.c
Line
Count
Source
1
/* Copyright (C) 2018-2026 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
#include "ghostpdf.h"
17
#include "pdf_types.h"
18
#include "pdf_stack.h"
19
#include "pdf_dict.h"
20
#include "pdf_file.h"
21
#include "pdf_int.h"
22
#include "pdf_array.h"
23
#include "pdf_misc.h"
24
#include "pdf_sec.h"
25
#include "pdf_loop_detect.h"
26
#include "stream.h"
27
#include "strimpl.h"
28
#include "strmio.h"
29
#include "gpmisc.h"
30
#include "simscale.h"   /* SIMScaleDecode */
31
#include "szlibx.h"     /* Flate */
32
#include "spngpx.h"     /* PNG Predictor */
33
#include "spdiffx.h"    /* Horizontal differencing predictor */
34
#include "slzwx.h"      /* LZW ZLib */
35
#include "sbrotlix.h"   /* Brotli */
36
#include "sstring.h"    /* ASCIIHexDecode */
37
#include "sa85d.h"      /* ASCII85Decode */
38
#include "scfx.h"       /* CCITTFaxDecode */
39
#include "srlx.h"       /* RunLengthDecode */
40
#include "jpeglib_.h"
41
#include "sdct.h"       /* DCTDecode */
42
#include "sjpeg.h"
43
#include "sfilter.h"    /* SubFileDecode and PFBDecode */
44
#include "sarc4.h"      /* Arc4Decode */
45
#include "saes.h"       /* AESDecode */
46
#include "ssha2.h"      /* SHA256Encode */
47
#include "gxdevsop.h"       /* For special ops */
48
49
#ifdef USE_LDF_JB2
50
#include "sjbig2_luratech.h"
51
#else
52
#include "sjbig2.h"
53
#endif
54
#if defined(USE_LWF_JP2)
55
#  include "sjpx_luratech.h"
56
#elif defined(USE_OPENJPEG_JP2)
57
#  include "sjpx_openjpeg.h"
58
#else
59
#  include "sjpx.h"
60
#endif
61
62
extern const uint file_default_buffer_size;
63
64
static void pdfi_close_filter_chain(pdf_context *ctx, stream *s, stream *target);
65
66
/* Utility routine to create a pdf_c_stream object */
67
static int pdfi_alloc_stream(pdf_context *ctx, stream *source, stream *original, pdf_c_stream **new_stream)
68
5.96M
{
69
5.96M
    *new_stream = NULL;
70
5.96M
    *new_stream = (pdf_c_stream *)gs_alloc_bytes(ctx->memory, sizeof(pdf_c_stream), "pdfi_alloc_stream");
71
5.96M
    if (*new_stream == NULL)
72
0
        return_error(gs_error_VMerror);
73
5.96M
    memset(*new_stream, 0x00, sizeof(pdf_c_stream));
74
5.96M
    (*new_stream)->eof = false;
75
5.96M
    ((pdf_c_stream *)(*new_stream))->s = source;
76
5.96M
    ((pdf_c_stream *)(*new_stream))->original = original;
77
5.96M
    return 0;
78
5.96M
}
79
80
/***********************************************************************************/
81
/* Decompression filters.                                                          */
82
83
static int
84
pdfi_filter_report_error(stream_state * st, const char *str)
85
4.38k
{
86
4.38k
    if_debug1m('s', st->memory, "[s]stream error: %s\n", str);
87
4.38k
    strncpy(st->error_string, str, STREAM_MAX_ERROR_STRING);
88
    /* Ensure null termination. */
89
4.38k
    st->error_string[STREAM_MAX_ERROR_STRING] = 0;
90
4.38k
    return 0;
91
4.38k
}
92
93
/* Open a file stream for a filter. */
94
static int
95
pdfi_filter_open(uint buffer_size,
96
            const stream_procs * procs, const stream_template * templat,
97
            const stream_state * st, gs_memory_t *mem, stream **new_stream)
98
5.38M
{
99
5.38M
    stream *s;
100
5.38M
    uint ssize = gs_struct_type_size(templat->stype);
101
5.38M
    stream_state *sst = NULL;
102
5.38M
    int code;
103
104
5.38M
    if (templat->stype != &st_stream_state) {
105
5.38M
        sst = s_alloc_state(mem, templat->stype, "pdfi_filter_open(stream_state)");
106
5.38M
        if (sst == NULL)
107
0
            return_error(gs_error_VMerror);
108
5.38M
        if (templat->set_defaults != NULL) {
109
5.33M
            (*templat->set_defaults)(sst);
110
5.33M
        }
111
5.38M
    }
112
5.38M
    if (buffer_size < 128)
113
38.6k
        buffer_size = file_default_buffer_size;
114
115
5.38M
    code = file_open_stream((char *)0, 0, "r", buffer_size, &s,
116
5.38M
                                (gx_io_device *)0, (iodev_proc_fopen_t)0, mem);
117
5.38M
    if (code < 0) {
118
0
        gs_free_object(mem, sst, "pdfi_filter_open(stream_state)");
119
0
        return code;
120
0
    }
121
5.38M
    s_std_init(s, s->cbuf, s->bsize, procs, s_mode_read);
122
5.38M
    s->procs.process = templat->process;
123
5.38M
    s->save_close = s->procs.close;
124
5.38M
    s->procs.close = file_close_file;
125
5.38M
    s->close_at_eod = 0;
126
5.38M
    if (sst == NULL) {
127
        /* This stream doesn't have any state of its own. */
128
        /* Hack: use the stream itself as the state. */
129
0
        sst = (stream_state *) s;
130
5.38M
    } else if (st != NULL)         /* might not have client parameters */
131
5.38M
        memcpy(sst, st, ssize);
132
5.38M
    s->state = sst;
133
5.38M
    s_init_state(sst, templat, mem);
134
5.38M
    sst->report_error = pdfi_filter_report_error;
135
136
5.38M
    if (templat->init != NULL) {
137
5.37M
        code = (*templat->init)(sst);
138
5.37M
        if (code < 0) {
139
1
            gs_free_object(mem, sst, "filter_open(stream_state)");
140
1
            gs_free_object(mem, s->cbuf, "filter_open(buffer)");
141
1
            gs_free_object(mem, s, "filter_open(stream)");
142
1
            return code;
143
1
        }
144
5.37M
    }
145
5.38M
    *new_stream = s;
146
5.38M
    return 0;
147
5.38M
}
148
149
static int pdfi_Predictor_filter(pdf_context *ctx, pdf_dict *d, stream *source, stream **new_stream)
150
41.5k
{
151
41.5k
    int code;
152
41.5k
    int64_t Predictor, Colors, BPC, Columns;
153
41.5k
    uint min_size;
154
41.5k
    stream_PNGP_state pps;
155
41.5k
    stream_PDiff_state ppds;
156
    /* NOTE: 'max_min_left=1' is a horribly named definition from stream.h */
157
158
41.5k
    code = pdfi_dict_get_int_def(ctx, d, "Predictor", &Predictor, 1);
159
41.5k
    if (code < 0)
160
5
        return code;
161
162
    /* Predictor values 0,1 are identity (use the existing stream).
163
     * The other values need to be cascaded.
164
     */
165
41.5k
    switch(Predictor) {
166
4
        case 0:
167
4
            Predictor = 1;
168
4
            break;
169
2.45k
        case 1:
170
2.45k
            break;
171
15
        case 2:
172
15
        case 10:
173
24
        case 11:
174
11.2k
        case 12:
175
11.2k
        case 13:
176
11.2k
        case 14:
177
38.9k
        case 15:
178
            /* grab values common to both kinds of predictors */
179
38.9k
            min_size = s_zlibD_template.min_out_size + max_min_left;
180
38.9k
            code = pdfi_dict_get_int_def(ctx, d, "Colors", &Colors, 1);
181
38.9k
            if (code < 0)
182
3
                return code;
183
38.9k
            if (Colors < 1 || Colors > s_PNG_max_Colors)
184
620
                return_error(gs_error_rangecheck);
185
186
38.2k
            code = pdfi_dict_get_int_def(ctx, d, "BitsPerComponent", &BPC, 8);
187
38.2k
            if (code < 0)
188
0
                return code;
189
            /* tests for 1-16, powers of 2 */
190
38.2k
            if (BPC < 1 || BPC > 16 || (BPC & (BPC - 1)) != 0)
191
263
                return_error(gs_error_rangecheck);
192
193
38.0k
            code = pdfi_dict_get_int_def(ctx, d, "Columns", &Columns, 1);
194
38.0k
            if (code < 0)
195
99
                return code;
196
37.9k
            if (Columns < 1)
197
14
                return_error(gs_error_rangecheck);
198
37.9k
            break;
199
37.9k
        default:
200
224
            return_error(gs_error_rangecheck);
201
41.5k
    }
202
203
40.3k
    switch(Predictor) {
204
2.45k
        case 1:
205
2.45k
            *new_stream = source;
206
2.45k
            break;
207
15
        case 2:
208
            /* zpd_setup, componentwise horizontal differencing */
209
15
            ppds.Colors = (int)Colors;
210
15
            ppds.BitsPerComponent = (int)BPC;
211
15
            ppds.Columns = (int)Columns;
212
15
            code = pdfi_filter_open(min_size, &s_filter_read_procs,
213
15
                             (const stream_template *)&s_PDiffD_template,
214
15
                             (const stream_state *)&ppds, ctx->memory->non_gc_memory, new_stream);
215
15
            if (code < 0)
216
0
                return code;
217
218
15
            (*new_stream)->strm = source;
219
15
            break;
220
37.9k
        default:
221
            /* zpp_setup, PNG predictor */
222
37.9k
            pps.Colors = (int)Colors;
223
37.9k
            pps.BitsPerComponent = (int)BPC;
224
37.9k
            pps.Columns = (uint)Columns;
225
37.9k
            pps.Predictor = Predictor;
226
37.9k
            code = pdfi_filter_open(min_size, &s_filter_read_procs,
227
37.9k
                             (const stream_template *)&s_PNGPD_template,
228
37.9k
                             (const stream_state *)&pps, ctx->memory->non_gc_memory, new_stream);
229
37.9k
            if (code < 0)
230
0
                return code;
231
232
37.9k
            (*new_stream)->strm = source;
233
37.9k
            break;
234
40.3k
    }
235
40.3k
    return 0;
236
40.3k
}
237
238
int pdfi_apply_Arc4_filter(pdf_context *ctx, pdf_string *Key, pdf_c_stream *source, pdf_c_stream **new_stream)
239
17.6k
{
240
17.6k
    int code = 0;
241
17.6k
    stream_arcfour_state state;
242
17.6k
    stream *new_s;
243
17.6k
    int min_size = 2048;
244
245
17.6k
    s_arcfour_set_key(&state, (const unsigned char *)Key->data, Key->length); /* lgtm [cpp/weak-cryptographic-algorithm] */
246
247
17.6k
    code = pdfi_filter_open(min_size, &s_filter_read_procs, (const stream_template *)&s_arcfour_template, (const stream_state *)&state, ctx->memory->non_gc_memory, &new_s);
248
17.6k
    if (code < 0)
249
0
        return code;
250
251
17.6k
    code = pdfi_alloc_stream(ctx, new_s, source->s, new_stream);
252
17.6k
    if (code >= 0)
253
17.6k
        new_s->strm = source->s;
254
17.6k
    return code;
255
17.6k
}
256
257
int pdfi_apply_AES_filter(pdf_context *ctx, pdf_string *Key, bool use_padding, pdf_c_stream *source, pdf_c_stream **new_stream)
258
38.3k
{
259
38.3k
    stream_aes_state state;
260
38.3k
    uint min_size = 2048;
261
38.3k
    int code = 0;
262
38.3k
    stream *new_s;
263
264
38.3k
    s_aes_set_key(&state, Key->data, Key->length);
265
38.3k
    s_aes_set_padding(&state, use_padding);
266
267
38.3k
    code = pdfi_filter_open(min_size, &s_filter_read_procs, (const stream_template *)&s_aes_template, (const stream_state *)&state, ctx->memory->non_gc_memory, &new_s);
268
269
38.3k
    if (code < 0)
270
0
        return code;
271
272
38.3k
    code = pdfi_alloc_stream(ctx, new_s, source->s, new_stream);
273
38.3k
    if (code >= 0)
274
38.3k
        new_s->strm = source->s;
275
38.3k
    return code;
276
38.3k
}
277
278
#ifdef UNUSED_FILTER
279
int pdfi_apply_SHA256_filter(pdf_context *ctx, pdf_c_stream *source, pdf_c_stream **new_stream)
280
{
281
    stream_SHA256E_state state;
282
    uint min_size = 2048;
283
    int code = 0;
284
    stream *new_s;
285
286
    pSHA256_Init(&state.sha256);
287
    code = pdfi_filter_open(min_size, &s_filter_read_procs, (const stream_template *)&s_SHA256E_template, (const stream_state *)&state, ctx->memory->non_gc_memory, &new_s);
288
289
    if (code < 0)
290
        return code;
291
292
    code = pdfi_alloc_stream(ctx, new_s, source->s, new_stream);
293
    if (code >= 0)
294
        new_s->strm = source->s;
295
    return code;
296
}
297
#endif
298
299
int pdfi_apply_imscale_filter(pdf_context *ctx, pdf_string *Key, int width, int height, pdf_c_stream *source, pdf_c_stream **new_stream)
300
0
{
301
0
    int code = 0;
302
0
    stream_imscale_state state;
303
0
    stream *new_s;
304
305
0
    state.params.spp_decode = 1;
306
0
    state.params.spp_interp = 1;
307
0
    state.params.BitsPerComponentIn = 1;
308
0
    state.params.MaxValueIn = 1;
309
0
    state.params.WidthIn = width;
310
0
    state.params.HeightIn = height;
311
0
    state.params.BitsPerComponentOut = 1;
312
0
    state.params.MaxValueOut = 1;
313
0
    state.params.WidthOut = width << 2;
314
0
    state.params.HeightOut = height << 2;
315
316
0
    code = pdfi_filter_open(2048, &s_filter_read_procs, (const stream_template *)&s_imscale_template, (const stream_state *)&state, ctx->memory->non_gc_memory, &new_s);
317
318
0
    if (code < 0)
319
0
        return code;
320
321
0
    code = pdfi_alloc_stream(ctx, new_s, source->s, new_stream);
322
0
    if (code >= 0)
323
0
        new_s->strm = source->s;
324
0
    return code;
325
0
}
326
327
static int pdfi_Flate_filter(pdf_context *ctx, pdf_dict *d, stream *source, stream **new_stream)
328
2.19M
{
329
2.19M
    stream_zlib_state zls;
330
2.19M
    uint min_size = 2048;
331
2.19M
    int code;
332
2.19M
    stream *Flate_source = NULL;
333
334
2.19M
    memset(&zls, 0, sizeof(zls));
335
336
    /* s_zlibD_template defined in base/szlibd.c */
337
2.19M
    (*s_zlibD_template.set_defaults)((stream_state *)&zls);
338
339
2.19M
    code = pdfi_filter_open(min_size, &s_filter_read_procs, (const stream_template *)&s_zlibD_template, (const stream_state *)&zls, ctx->memory->non_gc_memory, new_stream);
340
2.19M
    if (code < 0)
341
0
        return code;
342
343
2.19M
    (*new_stream)->strm = source;
344
2.19M
    source = *new_stream;
345
346
2.19M
    if (d && pdfi_type_of(d) == PDF_DICT) {
347
41.5k
        Flate_source = (*new_stream)->strm;
348
41.5k
        code = pdfi_Predictor_filter(ctx, d, source, new_stream);
349
41.5k
        if (code < 0)
350
1.22k
            pdfi_close_filter_chain(ctx, source, Flate_source);
351
41.5k
    }
352
2.19M
    return code;
353
2.19M
}
354
355
static int pdfi_Brotli_filter(pdf_context *ctx, pdf_dict *d, stream *source, stream **new_stream)
356
0
{
357
0
    stream_brotlid_state zls;
358
0
    uint min_size = 2048;
359
0
    int code;
360
0
    stream *Brotli_source = NULL;
361
362
0
    memset(&zls, 0, sizeof(zls));
363
364
0
    code = pdfi_filter_open(min_size, &s_filter_read_procs, (const stream_template *)&s_brotliD_template, (const stream_state *)&zls, ctx->memory->non_gc_memory, new_stream);
365
0
    if (code < 0)
366
0
        return code;
367
368
0
    (*new_stream)->strm = source;
369
0
    source = *new_stream;
370
371
0
    if (d && pdfi_type_of(d) == PDF_DICT) {
372
0
        Brotli_source = (*new_stream)->strm;
373
0
        code = pdfi_Predictor_filter(ctx, d, source, new_stream);
374
0
        if (code < 0)
375
0
            pdfi_close_filter_chain(ctx, source, Brotli_source);
376
0
    }
377
0
    return code;
378
0
}
379
380
static int
381
pdfi_JBIG2Decode_filter(pdf_context *ctx, pdf_dict *dict, pdf_dict *decode,
382
                        stream *source, stream **new_stream)
383
703
{
384
703
    stream_jbig2decode_state state;
385
703
    uint min_size = s_jbig2decode_template.min_out_size;
386
703
    int code;
387
703
    pdf_stream *Globals = NULL;
388
703
    byte *buf = NULL;
389
703
    int64_t buflen = 0;
390
703
    void *globalctx;
391
392
703
    s_jbig2decode_set_global_data((stream_state*)&state, NULL, NULL);
393
394
703
    if (decode) {
395
0
        code = pdfi_dict_knownget_type(ctx, decode, "JBIG2Globals", PDF_STREAM,
396
0
                                       (pdf_obj **)&Globals);
397
0
        if (code < 0) {
398
0
            goto cleanupExit;
399
0
        }
400
401
        /* read in the globals from stream */
402
0
        if (code > 0) {
403
0
            code = pdfi_stream_to_buffer(ctx, Globals, &buf, &buflen);
404
0
            if (code == 0) {
405
0
                code = s_jbig2decode_make_global_data(ctx->memory->non_gc_memory,
406
0
                                                      buf, buflen, &globalctx);
407
0
                if (code < 0)
408
0
                    goto cleanupExit;
409
410
0
                s_jbig2decode_set_global_data((stream_state*)&state, NULL, globalctx);
411
0
            }
412
0
        }
413
0
    }
414
415
703
    code = pdfi_filter_open(min_size, &s_filter_read_procs,
416
703
                            (const stream_template *)&s_jbig2decode_template,
417
703
                            (const stream_state *)&state, ctx->memory->non_gc_memory, new_stream);
418
703
    if (code < 0)
419
0
        goto cleanupExit;
420
421
703
    (*new_stream)->strm = source;
422
703
    code = 0;
423
424
703
 cleanupExit:
425
703
    gs_free_object(ctx->memory, buf, "pdfi_JBIG2Decode_filter (Globals buf)");
426
703
    pdfi_countdown(Globals);
427
703
    return code;
428
703
}
429
430
static int pdfi_LZW_filter(pdf_context *ctx, pdf_dict *d, stream *source, stream **new_stream)
431
198
{
432
198
    stream_LZW_state lzs;
433
198
    uint min_size = 2048;
434
198
    int code;
435
198
    int64_t i;
436
437
    /* s_zlibD_template defined in base/szlibd.c */
438
198
    s_LZW_set_defaults_inline(&lzs);
439
440
198
    if (d && pdfi_type_of(d) == PDF_DICT) {
441
0
        code = pdfi_dict_get_int(ctx, d, "EarlyChange", &i);
442
0
        if (code < 0 && code != gs_error_undefined)
443
0
            return code;
444
0
        if (code == 0) {
445
0
            if (i == 0)
446
0
                lzs.EarlyChange = false;
447
0
            else
448
0
                lzs.EarlyChange = true;
449
0
        }
450
0
    }
451
452
198
    code = pdfi_filter_open(min_size, &s_filter_read_procs, (const stream_template *)&s_LZWD_template, (const stream_state *)&lzs, ctx->memory->non_gc_memory, new_stream);
453
198
    if (code < 0)
454
0
        return code;
455
198
    (*new_stream)->strm = source;
456
198
    source = *new_stream;
457
458
198
    if (d && pdfi_type_of(d) == PDF_DICT)
459
0
        pdfi_Predictor_filter(ctx, d, source, new_stream);
460
198
    return 0;
461
198
}
462
463
static int PS_JPXD_PassThrough(void *d, byte *Buffer, int Size)
464
145k
{
465
145k
    gx_device *dev = (gx_device *)d;
466
145k
    int code = 0;
467
468
145k
    if (Buffer == NULL) {
469
5.31k
        if (Size == 0)
470
2.75k
            code = dev_proc(dev, dev_spec_op)(dev, gxdso_JPX_passthrough_end, NULL, 0);
471
2.55k
        else
472
2.55k
            code = dev_proc(dev, dev_spec_op)(dev, gxdso_JPX_passthrough_begin, NULL, 0);
473
140k
    } else {
474
140k
        code = dev_proc(dev, dev_spec_op)(dev, gxdso_JPX_passthrough_data, Buffer, Size);
475
140k
    }
476
145k
    return code;
477
145k
}
478
479
/*
480
 * dict -- the dict that contained the decoder (i.e. the image dict)
481
 * decode -- the decoder dict
482
 */
483
static int
484
pdfi_JPX_filter(pdf_context *ctx, pdf_dict *dict, pdf_dict *decode,
485
                stream *source, stream **new_stream)
486
11.7k
{
487
11.7k
    stream_jpxd_state state;
488
11.7k
    uint min_size = s_jpxd_template.min_out_size;
489
11.7k
    int code;
490
11.7k
    pdf_obj *csobj = NULL;
491
11.7k
    pdf_name *csname = NULL;
492
11.7k
    bool alpha;
493
11.7k
    gx_device *dev = gs_currentdevice(ctx->pgs);
494
495
11.7k
    state.memory = ctx->memory->non_gc_memory;
496
11.7k
    if (s_jpxd_template.set_defaults)
497
11.7k
      (*s_jpxd_template.set_defaults)((stream_state *)&state);
498
499
    /* Pull some extra params out of the image dict */
500
11.7k
    if (dict) {
501
        /* This Alpha is a thing that gs code uses to tell that we
502
         * are doing an SMask.  It's a bit of a hack, but
503
         * I guess we can do the same.
504
         */
505
11.7k
        code = pdfi_dict_get_bool(ctx, dict, "Alpha", &alpha);
506
11.7k
        if (code == 0)
507
0
            state.alpha = alpha;
508
11.7k
    }
509
11.7k
    if (dict && pdfi_dict_get(ctx, dict, "ColorSpace", &csobj) == 0) {
510
        /* parse the value */
511
5.36k
        switch (pdfi_type_of(csobj)) {
512
20
        case PDF_ARRAY:
513
            /* assume it's the first array element */
514
20
            code = pdfi_array_get(ctx, (pdf_array *)csobj, (uint64_t)0, (pdf_obj **)&csname);
515
20
            if (code < 0) {
516
0
                pdfi_countdown(csobj);
517
0
                return code;
518
0
            }
519
20
            break;
520
5.34k
        case PDF_NAME:
521
            /* use the name directly */
522
5.34k
            csname = (pdf_name *)csobj;
523
5.34k
            csobj = NULL; /* To keep ref counting straight */
524
5.34k
            break;
525
0
        default:
526
0
            code = pdfi_set_error_stop(ctx, gs_note_error(gs_error_undefined), NULL, E_PDF_BAD_JPX_CS, "pdfi_JPX_filter", "");
527
0
            break;
528
5.36k
        }
529
5.36k
        if (csname != NULL && pdfi_type_of(csname) == PDF_NAME) {
530
            /* request raw index values if the colorspace is /Indexed */
531
5.36k
            if (pdfi_name_is(csname, "Indexed"))
532
20
                state.colorspace = gs_jpx_cs_indexed;
533
            /* tell the filter what output we want for other spaces */
534
5.34k
            else if (pdfi_name_is(csname, "DeviceGray"))
535
1.47k
                state.colorspace = gs_jpx_cs_gray;
536
3.87k
            else if (pdfi_name_is(csname, "DeviceRGB"))
537
3.87k
                state.colorspace = gs_jpx_cs_rgb;
538
0
            else if (pdfi_name_is(csname, "DeviceCMYK"))
539
0
                state.colorspace = gs_jpx_cs_cmyk;
540
0
            else if (pdfi_name_is(csname, "ICCBased")) {
541
                /* TODO: I don't think this even happens without PS wrapper code? */
542
#if 0
543
                /* The second array element should be the profile's
544
                   stream dict */
545
                ref *csdict = csobj->value.refs + 1;
546
                ref *nref;
547
                ref altname;
548
                if (r_is_array(csobj) && (r_size(csobj) > 1) &&
549
                    r_has_type(csdict, t_dictionary)) {
550
                    check_dict_read(*csdict);
551
                    /* try to look up the alternate space */
552
                    if (dict_find_string(csdict, "Alternate", &nref) > 0) {
553
                        name_string_ref(imemory, csname, &altname);
554
                        if (pdfi_name_is(&altname, "DeviceGray"))
555
                            state.colorspace = gs_jpx_cs_gray;
556
                        else if (pdfi_name_is(&altname, "DeviceRGB"))
557
                            state.colorspace = gs_jpx_cs_rgb;
558
                        else if (pdfi_name_is(&altname, "DeviceCMYK"))
559
                            state.colorspace = gs_jpx_cs_cmyk;
560
                    }
561
                    /* else guess based on the number of components */
562
                    if (state.colorspace == gs_jpx_cs_unset &&
563
                        dict_find_string(csdict, "N", &nref) > 0) {
564
                        if_debug1m('w', imemory, "[w] JPX image has an external %"PRIpsint
565
                                   " channel colorspace\n", nref->value.intval);
566
                        switch (nref->value.intval) {
567
                        case 1: state.colorspace = gs_jpx_cs_gray;
568
                            break;
569
                        case 3: state.colorspace = gs_jpx_cs_rgb;
570
                            break;
571
                        case 4: state.colorspace = gs_jpx_cs_cmyk;
572
                            break;
573
                        }
574
                    }
575
                }
576
#endif
577
0
            }
578
5.36k
        }
579
5.36k
    }
580
581
11.7k
    if (csobj)
582
20
        pdfi_countdown(csobj);
583
11.7k
    if (csname)
584
5.36k
        pdfi_countdown(csname);
585
586
587
11.7k
    if (dev_proc(dev, dev_spec_op)(dev, gxdso_JPX_passthrough_query, NULL, 0) > 0) {
588
2.75k
        state.StartedPassThrough = 0;
589
2.75k
        state.PassThrough = 1;
590
2.75k
        state.PassThroughfn = (PS_JPXD_PassThrough);
591
2.75k
        state.device = (void *)dev;
592
2.75k
    }
593
9.02k
    else {
594
9.02k
        state.PassThrough = 0;
595
9.02k
        state.device = (void *)NULL;
596
9.02k
    }
597
598
11.7k
    code = pdfi_filter_open(min_size, &s_filter_read_procs, (const stream_template *)&s_jpxd_template,
599
11.7k
                            (const stream_state *)&state, ctx->memory->non_gc_memory, new_stream);
600
11.7k
    if (code < 0)
601
0
        return code;
602
11.7k
    (*new_stream)->strm = source;
603
11.7k
    source = *new_stream;
604
605
11.7k
    return 0;
606
11.7k
}
607
608
private_st_jpeg_decompress_data();
609
610
static int PDF_DCTD_PassThrough(void *d, byte *Buffer, int Size)
611
285k
{
612
285k
    gx_device *dev = (gx_device *)d;
613
285k
    int code = 0;
614
615
285k
    if (Buffer == NULL) {
616
5.36k
        if (Size == 0)
617
2.59k
            code = dev_proc(dev, dev_spec_op)(dev, gxdso_JPEG_passthrough_end, NULL, 0);
618
2.76k
        else
619
2.76k
            code = dev_proc(dev, dev_spec_op)(dev, gxdso_JPEG_passthrough_begin, NULL, 0);
620
280k
    } else {
621
280k
        code = dev_proc(dev, dev_spec_op)(dev, gxdso_JPEG_passthrough_data, Buffer, Size);
622
280k
    }
623
285k
    return code;
624
285k
}
625
626
static int pdfi_DCT_filter(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *decode,
627
                           stream *source, stream **new_stream)
628
12.3k
{
629
12.3k
    stream_DCT_state dcts;
630
12.3k
    uint min_size = s_DCTD_template.min_out_size;
631
12.3k
    int code;
632
12.3k
    int64_t i;
633
12.3k
    jpeg_decompress_data *jddp;
634
12.3k
    gx_device *dev = gs_currentdevice_inline(ctx->pgs);
635
12.3k
    double Height = 0;
636
637
12.3k
    dcts.memory = ctx->memory;
638
    /* First allocate space for IJG parameters. */
639
12.3k
    jddp = gs_alloc_struct_immovable(ctx->memory, jpeg_decompress_data,
640
12.3k
      &st_jpeg_decompress_data, "pdfi_DCT");
641
12.3k
    if (jddp == 0)
642
0
        return_error(gs_error_VMerror);
643
12.3k
    if (s_DCTD_template.set_defaults)
644
12.3k
        (*s_DCTD_template.set_defaults) ((stream_state *) & dcts);
645
646
12.3k
    dcts.data.decompress = jddp;
647
12.3k
    jddp->memory = dcts.jpeg_memory = ctx->memory;  /* set now for allocation */
648
12.3k
    jddp->scanline_buffer = NULL;                 /* set this early for safe error exit */
649
12.3k
    dcts.report_error = pdfi_filter_report_error;     /* in case create fails */
650
12.3k
    if ((code = gs_jpeg_create_decompress(&dcts)) < 0) {
651
0
        gs_jpeg_destroy(&dcts);
652
0
        gs_free_object(ctx->memory, jddp, "zDCTD fail");
653
0
        return code;
654
0
    }
655
656
12.3k
    if (decode && pdfi_type_of(decode) == PDF_DICT) {
657
        /* TODO: Why is this here?  'i' never gets used? */
658
450
        code = pdfi_dict_get_int(ctx, decode, "ColorTransform", &i);
659
450
        if (code < 0 && code != gs_error_undefined)
660
0
            return code;
661
450
    }
662
663
12.3k
    if (dev_proc(dev, dev_spec_op)(dev, gxdso_JPEG_passthrough_query, NULL, 0) > 0) {
664
2.78k
        jddp->StartedPassThrough = 0;
665
2.78k
        jddp->PassThrough = 1;
666
2.78k
        jddp->PassThroughfn = (PDF_DCTD_PassThrough);
667
2.78k
        jddp->device = (void *)dev;
668
2.78k
    }
669
9.52k
    else {
670
9.52k
        jddp->PassThrough = 0;
671
9.52k
        jddp->device = (void *)NULL;
672
9.52k
    }
673
674
    /* Hack for Bug695112.pdf to grab a height in case it is missing from the JPEG data */
675
12.3k
    code = pdfi_dict_knownget_number(ctx, stream_dict, "Height", &Height);
676
12.3k
    if (code < 0)
677
0
        return code;
678
12.3k
    jddp->Height = (int)floor(Height);
679
680
12.3k
    jddp->templat = s_DCTD_template;
681
682
12.3k
    code = pdfi_filter_open(min_size, &s_filter_read_procs, (const stream_template *)&jddp->templat, (const stream_state *)&dcts, ctx->memory->non_gc_memory, new_stream);
683
12.3k
    if (code < 0)
684
0
        return code;
685
12.3k
    (*new_stream)->strm = source;
686
12.3k
    source = *new_stream;
687
688
12.3k
    return 0;
689
12.3k
}
690
691
static int pdfi_ASCII85_filter(pdf_context *ctx, pdf_dict *d, stream *source, stream **new_stream)
692
575
{
693
575
    stream_A85D_state ss;
694
575
    uint min_size = 2048;
695
575
    int code;
696
697
575
    ss.pdf_rules = true;
698
699
575
    code = pdfi_filter_open(min_size, &s_filter_read_procs, (const stream_template *)&s_A85D_template, (const stream_state *)&ss, ctx->memory->non_gc_memory, new_stream);
700
575
    if (code < 0)
701
0
        return code;
702
703
575
    (*new_stream)->strm = source;
704
575
    return 0;
705
575
}
706
707
static int pdfi_CCITTFax_filter(pdf_context *ctx, pdf_dict *d, stream *source, stream **new_stream)
708
6.89k
{
709
6.89k
    stream_CFD_state ss;
710
6.89k
    uint min_size = 2048;
711
6.89k
    bool bval;
712
6.89k
    int code;
713
6.89k
    int64_t i;
714
715
6.89k
    s_CF_set_defaults_inline(&ss);
716
717
6.89k
    if (d && pdfi_type_of(d) == PDF_DICT) {
718
6.85k
        code = pdfi_dict_get_int(ctx, d, "K", &i);
719
6.85k
        if (code < 0 && code != gs_error_undefined)
720
4
            return code;
721
6.84k
        if (code == 0)
722
6.78k
            ss.K = i;
723
724
6.84k
        code = pdfi_dict_get_bool(ctx, d, "EndOfLine", &bval);
725
6.84k
        if (code < 0 && code != gs_error_undefined)
726
0
            return code;
727
6.84k
        if (code == 0)
728
0
            ss.EndOfLine = bval ? 1 : 0;
729
730
6.84k
        code = pdfi_dict_get_bool(ctx, d, "EncodedByteAlign", &bval);
731
6.84k
        if (code < 0 && code != gs_error_undefined)
732
0
            return code;
733
6.84k
        if (code == 0)
734
0
            ss.EncodedByteAlign = bval ? 1 : 0;
735
736
6.84k
        code = pdfi_dict_get_bool(ctx, d, "EndOfBlock", &bval);
737
6.84k
        if (code < 0 && code != gs_error_undefined)
738
0
            return code;
739
6.84k
        if (code == 0)
740
687
            ss.EndOfBlock = bval ? 1 : 0;
741
742
6.84k
        code = pdfi_dict_get_bool(ctx, d, "BlackIs1", &bval);
743
6.84k
        if (code < 0 && code != gs_error_undefined)
744
0
            return code;
745
6.84k
        if (code == 0)
746
119
            ss.BlackIs1 = bval ? 1 : 0;
747
748
6.84k
        code = pdfi_dict_get_int(ctx, d, "Columns", &i);
749
6.84k
        if (code < 0 && code != gs_error_undefined)
750
8
            return code;
751
6.83k
        if (code == 0)
752
6.80k
            ss.Columns = i;
753
754
6.83k
        code = pdfi_dict_get_int(ctx, d, "Rows", &i);
755
6.83k
        if (code < 0 && code != gs_error_undefined)
756
0
            return code;
757
6.83k
        if (code == 0)
758
1.61k
            ss.Rows = i;
759
760
6.83k
        code = pdfi_dict_get_int(ctx, d, "DamagedRowsBeforeError", &i);
761
6.83k
        if (code < 0 && code != gs_error_undefined)
762
0
            return code;
763
6.83k
        if (code == 0)
764
0
            ss.DamagedRowsBeforeError = i;
765
766
6.83k
    }
767
768
6.88k
    code = pdfi_filter_open(min_size, &s_filter_read_procs,
769
6.88k
                            (const stream_template *)&s_CFD_template,
770
6.88k
                            (const stream_state *)&ss,
771
6.88k
                            ctx->memory->non_gc_memory, new_stream);
772
6.88k
    if (code < 0)
773
1
        return code;
774
775
6.88k
    (*new_stream)->strm = source;
776
6.88k
    return 0;
777
6.88k
}
778
779
static int pdfi_RunLength_filter(pdf_context *ctx, pdf_dict *d, stream *source, stream **new_stream)
780
218
{
781
218
    stream_RLD_state ss;
782
218
    uint min_size = 2048;
783
218
    int code;
784
785
218
    if (s_RLD_template.set_defaults)
786
218
        (*s_RLD_template.set_defaults) ((stream_state *) & ss);
787
788
218
    code = pdfi_filter_open(min_size, &s_filter_read_procs, (const stream_template *)&s_RLD_template, (const stream_state *)&ss, ctx->memory->non_gc_memory, new_stream);
789
218
    if (code < 0)
790
0
        return code;
791
792
218
    (*new_stream)->strm = source;
793
218
    return 0;
794
218
}
795
796
static int pdfi_simple_filter(pdf_context *ctx, const stream_template *tmplate, stream *source, stream **new_stream)
797
1.62k
{
798
1.62k
    uint min_size = 2048;
799
1.62k
    int code;
800
801
1.62k
    code = pdfi_filter_open(min_size, &s_filter_read_procs, tmplate, NULL, ctx->memory->non_gc_memory, new_stream);
802
1.62k
    if (code < 0)
803
0
        return code;
804
805
1.62k
    (*new_stream)->strm = source;
806
1.62k
    return 0;
807
1.62k
}
808
809
static int pdfi_apply_filter(pdf_context *ctx, pdf_dict *dict, pdf_name *n, pdf_dict *decode,
810
                             stream *source, stream **new_stream, bool inline_image)
811
2.23M
{
812
2.23M
    int code;
813
814
2.23M
    code = pdfi_loop_detector_mark(ctx);
815
2.23M
    if (code < 0)
816
0
        return code;
817
818
2.23M
    if (dict->object_num != 0) {
819
2.17M
        code = pdfi_loop_detector_add_object(ctx, dict->object_num);
820
2.17M
        if (code < 0)
821
0
            goto cleanupExit;
822
2.17M
    } else {
823
63.8k
        if (dict->indirect_num != 0) {
824
11.8k
            code = pdfi_loop_detector_add_object(ctx, dict->indirect_num);
825
11.8k
            if (code < 0)
826
0
                goto cleanupExit;
827
11.8k
        }
828
63.8k
    }
829
830
2.23M
    if (ctx->args.pdfdebug)
831
0
    {
832
0
        char *str;
833
0
        str = (char *)gs_alloc_bytes(ctx->memory, (size_t)n->length + 1, "temp string for debug");
834
0
        if (str == NULL)
835
0
            return_error(gs_error_VMerror);
836
0
        memcpy(str, (const char *)n->data, n->length);
837
0
        str[n->length] = '\0';
838
0
        outprintf(ctx->memory, "FILTER NAME:%s\n", str);
839
0
        gs_free_object(ctx->memory, str, "temp string for debug");
840
0
    }
841
842
2.23M
    if (pdfi_name_is(n, "RunLengthDecode")) {
843
217
        code = pdfi_RunLength_filter(ctx, decode, source, new_stream);
844
217
        goto cleanupExit;
845
217
    }
846
2.23M
    if (pdfi_name_is(n, "CCITTFaxDecode")) {
847
2.50k
        code = pdfi_CCITTFax_filter(ctx, decode, source, new_stream);
848
2.50k
        goto cleanupExit;
849
2.50k
    }
850
2.23M
    if (pdfi_name_is(n, "ASCIIHexDecode")) {
851
832
        code = pdfi_simple_filter(ctx, &s_AXD_template, source, new_stream);
852
832
        goto cleanupExit;
853
832
    }
854
2.23M
    if (pdfi_name_is(n, "ASCII85Decode")) {
855
410
        code = pdfi_ASCII85_filter(ctx, decode, source, new_stream);
856
410
        goto cleanupExit;
857
410
    }
858
2.23M
    if (pdfi_name_is(n, "FlateDecode")) {
859
2.19M
        code = pdfi_Flate_filter(ctx, decode, source, new_stream);
860
2.19M
        goto cleanupExit;
861
2.19M
    }
862
34.7k
    if (pdfi_name_is(n, "JBIG2Decode")) {
863
703
        code = pdfi_JBIG2Decode_filter(ctx, dict, decode, source, new_stream);
864
703
        goto cleanupExit;
865
703
    }
866
34.0k
    if (pdfi_name_is(n, "LZWDecode")) {
867
198
        code = pdfi_LZW_filter(ctx, decode, source, new_stream);
868
198
        goto cleanupExit;
869
198
    }
870
33.8k
    if (pdfi_name_is(n, "DCTDecode")) {
871
12.2k
        code = pdfi_DCT_filter(ctx, dict, decode, source, new_stream);
872
12.2k
        goto cleanupExit;
873
12.2k
    }
874
21.6k
    if (pdfi_name_is(n, "JPXDecode")) {
875
11.7k
        code = pdfi_JPX_filter(ctx, dict, decode, source, new_stream);
876
11.7k
        goto cleanupExit;
877
11.7k
    }
878
9.89k
    if (pdfi_name_is(n, "BrotliDecode")) {
879
0
        code = pdfi_Brotli_filter(ctx, decode, source, new_stream);
880
0
        goto cleanupExit;
881
0
    }
882
883
9.89k
    if (pdfi_name_is(n, "AHx")) {
884
794
        if (!inline_image) {
885
89
            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_BAD_INLINEFILTER, "pdfi_apply_filter", NULL)) < 0)
886
0
                goto cleanupExit;
887
89
        }
888
794
        code = pdfi_simple_filter(ctx, &s_AXD_template, source, new_stream);
889
794
        goto cleanupExit;
890
794
    }
891
9.10k
    if (pdfi_name_is(n, "A85")) {
892
165
        if (!inline_image) {
893
165
            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_BAD_INLINEFILTER, "pdfi_apply_filter", NULL)) < 0)
894
0
                goto cleanupExit;
895
165
        }
896
165
        code = pdfi_ASCII85_filter(ctx, decode, source, new_stream);
897
165
        goto cleanupExit;
898
165
    }
899
8.93k
    if (pdfi_name_is(n, "LZW")) {
900
0
        if (!inline_image) {
901
0
            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_BAD_INLINEFILTER, "pdfi_apply_filter", NULL)) < 0)
902
0
                goto cleanupExit;
903
0
        }
904
0
        code = pdfi_LZW_filter(ctx, decode, source, new_stream);
905
0
        goto cleanupExit;
906
0
    }
907
8.93k
    if (pdfi_name_is(n, "CCF")) {
908
4.39k
        if (!inline_image) {
909
1
            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_BAD_INLINEFILTER, "pdfi_apply_filter", NULL)) < 0)
910
0
                goto cleanupExit;
911
1
        }
912
4.39k
        code = pdfi_CCITTFax_filter(ctx, decode, source, new_stream);
913
4.39k
        goto cleanupExit;
914
4.39k
    }
915
4.54k
    if (pdfi_name_is(n, "DCT")) {
916
109
        if (!inline_image) {
917
0
            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_BAD_INLINEFILTER, "pdfi_apply_filter", NULL)) < 0)
918
0
                goto cleanupExit;
919
0
        }
920
109
        code = pdfi_DCT_filter(ctx, dict, decode, source, new_stream);
921
109
        goto cleanupExit;
922
109
    }
923
4.43k
    if (pdfi_name_is(n, "Fl")) {
924
242
        if (!inline_image) {
925
36
            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_BAD_INLINEFILTER, "pdfi_apply_filter", NULL)) < 0)
926
0
                goto cleanupExit;
927
36
        }
928
242
        code = pdfi_Flate_filter(ctx, decode, source, new_stream);
929
242
        goto cleanupExit;
930
242
    }
931
4.19k
    if (pdfi_name_is(n, "RL")) {
932
1
        if (!inline_image) {
933
1
            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_BAD_INLINEFILTER, "pdfi_apply_filter", NULL)) < 0)
934
0
                goto cleanupExit;
935
1
        }
936
1
        code = pdfi_RunLength_filter(ctx, decode, source, new_stream);
937
1
        goto cleanupExit;
938
1
    }
939
4.19k
    if (pdfi_name_is(n, "Br")) {
940
0
        if (!inline_image) {
941
0
            if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_BAD_INLINEFILTER, "pdfi_apply_filter", NULL)) < 0)
942
0
                goto cleanupExit;
943
0
        }
944
0
        code = pdfi_Brotli_filter(ctx, decode, source, new_stream);
945
0
        goto cleanupExit;
946
0
    }
947
948
4.19k
    pdfi_set_error(ctx, 0, NULL, E_PDF_UNKNOWNFILTER, "pdfi_apply_filter", NULL);
949
4.19k
    code = gs_error_undefined;
950
951
2.23M
cleanupExit:
952
2.23M
    pdfi_loop_detector_cleartomark(ctx);
953
2.23M
    return code;
954
4.19k
}
955
956
/* This function simply rplaces all 'abbreviated' filter names with standard names. Its purely for the benefit
957
 * of the code below checking arrays of filters to detect 'filter bombs', repeated use of identical filters.
958
 * This is wasteful, but we need to prevent it.
959
 */
960
static int pdfi_normalize_filter_array(pdf_context *ctx, pdf_array *filter_array)
961
35.4k
{
962
35.4k
    int i = 0, code = 0;
963
35.4k
    pdf_name *old, *new;
964
965
36.4k
    for (i = 0; i < (int)pdfi_array_size(filter_array) - 1;i++) {
966
952
        code = pdfi_array_get_type(ctx, filter_array, i, PDF_NAME, (pdf_obj **)&old);
967
952
        if (code < 0)
968
1
            goto exit;
969
951
        if (old->length > 3) {
970
847
            pdfi_countdown(old);
971
847
            continue;
972
847
        }
973
104
        if (old->length == 2) {
974
6
            if (memcmp(old->data, "Fl", 2) == 0) {
975
6
                code = pdfi_name_alloc(ctx, (byte *)"FlateDecode", 11, (pdf_obj **)&new);
976
6
                if (code < 0)
977
0
                    goto exit;
978
6
                code = pdfi_array_put(ctx, filter_array, i, (pdf_obj *)new);
979
6
                if (code < 0)
980
0
                    goto exit;
981
6
                pdfi_countdown(old);
982
6
            } else {
983
0
                if (memcmp(old->data, "RL", 2) == 0) {
984
0
                    code = pdfi_name_alloc(ctx, (byte *)"RunLengthDecode", 15, (pdf_obj **)&new);
985
0
                    if (code < 0)
986
0
                        goto exit;
987
0
                    code = pdfi_array_put(ctx, filter_array, i, (pdf_obj *)&new);
988
0
                    if (code < 0)
989
0
                        goto exit;
990
0
                    pdfi_countdown(old);
991
0
                } else {
992
0
                    if (memcmp(old->data, "Br", 2) == 0) {
993
0
                        code = pdfi_name_alloc(ctx, (byte *)"BrotliDecode", 12, (pdf_obj **)&new);
994
0
                        if (code < 0)
995
0
                            goto exit;
996
0
                        code = pdfi_array_put(ctx, filter_array, i, (pdf_obj *)new);
997
0
                        if (code < 0)
998
0
                            goto exit;
999
0
                        pdfi_countdown(old);
1000
0
                    } else {
1001
0
                        code = gs_note_error(gs_error_syntaxerror);
1002
0
                        goto exit;
1003
0
                    }
1004
0
                }
1005
0
            }
1006
98
        } else {
1007
98
            if (old->length == 3) {
1008
97
                if (memcmp(old->data, "CCF", 2) == 0) {
1009
0
                    code = pdfi_name_alloc(ctx, (byte *)"CCITTFaxDecode", 14, (pdf_obj **)&new);
1010
0
                    if (code < 0)
1011
0
                        goto exit;
1012
0
                    code = pdfi_array_put(ctx, filter_array, i, (pdf_obj *)new);
1013
0
                    if (code < 0)
1014
0
                        goto exit;
1015
0
                    pdfi_countdown(old);
1016
97
                } else {
1017
97
                    if (memcmp(old->data, "AHx", 2) == 0) {
1018
97
                        code = pdfi_name_alloc(ctx, (byte *)"ASCIIHexDecode", 14, (pdf_obj **)&new);
1019
97
                        if (code < 0)
1020
0
                            goto exit;
1021
97
                        code = pdfi_array_put(ctx, filter_array, i, (pdf_obj *)new);
1022
97
                        if (code < 0)
1023
0
                            goto exit;
1024
97
                        pdfi_countdown(old);
1025
97
                    } else {
1026
0
                        if (memcmp(old->data, "A85", 2) == 0) {
1027
0
                            code = pdfi_name_alloc(ctx, (byte *)"ASCII85Decode", 13, (pdf_obj **)&new);
1028
0
                            if (code < 0)
1029
0
                                goto exit;
1030
0
                            code = pdfi_array_put(ctx, filter_array, i, (pdf_obj *)new);
1031
0
                            if (code < 0)
1032
0
                                goto exit;
1033
0
                            pdfi_countdown(old);
1034
0
                        } else {
1035
0
                            if (memcmp(old->data, "LZW", 2) == 0) {
1036
0
                                code = pdfi_name_alloc(ctx, (byte *)"LZWDecode", 9, (pdf_obj **)&new);
1037
0
                                if (code < 0)
1038
0
                                    goto exit;
1039
0
                                code = pdfi_array_put(ctx, filter_array, i, (pdf_obj *)new);
1040
0
                                if (code < 0)
1041
0
                                    goto exit;
1042
0
                                pdfi_countdown(old);
1043
0
                            } else {
1044
0
                                if (memcmp(old->data, "DCT", 2) == 0) {
1045
0
                                    code = pdfi_name_alloc(ctx, (byte *)"DCTDecode", 9, (pdf_obj **)&new);
1046
0
                                    if (code < 0)
1047
0
                                        goto exit;
1048
0
                                    code = pdfi_array_put(ctx, filter_array, i, (pdf_obj *)new);
1049
0
                                    if (code < 0)
1050
0
                                        goto exit;
1051
0
                                    pdfi_countdown(old);
1052
0
                                } else {
1053
0
                                    code = gs_note_error(gs_error_syntaxerror);
1054
0
                                    goto exit;
1055
0
                                }
1056
0
                            }
1057
0
                        }
1058
0
                    }
1059
97
                }
1060
97
            } else {
1061
1
                code = gs_note_error(gs_error_syntaxerror);
1062
1
                goto exit;
1063
1
            }
1064
98
        }
1065
104
    }
1066
1067
35.4k
exit:
1068
35.4k
    return code;
1069
35.4k
}
1070
1071
int pdfi_filter_no_decryption(pdf_context *ctx, pdf_stream *stream_obj,
1072
                              pdf_c_stream *source, pdf_c_stream **new_stream, bool inline_image)
1073
2.65M
{
1074
2.65M
    pdf_obj *o = NULL, *o1 = NULL;
1075
2.65M
    pdf_obj *decode = NULL;
1076
2.65M
    pdf_obj *Filter = NULL;
1077
2.65M
    pdf_dict *stream_dict = NULL;
1078
2.65M
    pdf_array *DecodeParams = NULL;
1079
2.65M
    int code;
1080
2.65M
    int64_t i, j, duplicates;
1081
2.65M
    stream *s = source->s, *new_s = NULL;
1082
1083
2.65M
    *new_stream = NULL;
1084
1085
2.65M
    if (ctx->args.pdfdebug) {
1086
0
        gs_offset_t stream_offset = pdfi_stream_offset(ctx, stream_obj);
1087
0
        outprintf(ctx->memory, "Filter: offset %ld(0x%lx)\n", stream_offset, stream_offset);
1088
0
    }
1089
1090
2.65M
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)stream_obj, &stream_dict);
1091
2.65M
    if (code < 0)
1092
0
        goto exit;
1093
1094
    /* ISO 32000-2:2020 (PDF 2.0) - abbreviated names take precendence. */
1095
2.65M
    if (inline_image) {
1096
272k
        code = pdfi_dict_knownget(ctx, stream_dict, "F", &Filter);
1097
272k
        if (code == 0)
1098
266k
            code = pdfi_dict_knownget(ctx, stream_dict, "Filter", &Filter);
1099
272k
    } else
1100
2.37M
        code = pdfi_dict_knownget(ctx, stream_dict, "Filter", &Filter);
1101
1102
2.65M
    if (code < 0)
1103
0
        goto exit;
1104
2.65M
    if (code == 0) {
1105
        /* No filter, just open the stream */
1106
417k
        code = pdfi_alloc_stream(ctx, s, source->s, new_stream);
1107
417k
        goto exit;
1108
417k
    }
1109
1110
2.23M
    switch (pdfi_type_of(Filter)) {
1111
14
    default:
1112
14
        code = gs_note_error(gs_error_typecheck);
1113
14
        goto exit;
1114
2.19M
    case PDF_NAME:
1115
        /* ISO 32000-2:2020 (PDF 2.0) - abbreviated names take precendence. */
1116
2.19M
        if (inline_image) {
1117
4.51k
            code = pdfi_dict_knownget(ctx, stream_dict, "DP", &decode);
1118
4.51k
            if (code == 0)
1119
116
                code = pdfi_dict_knownget(ctx, stream_dict, "DecodeParms", &decode);
1120
2.19M
        } else {
1121
2.19M
            code = pdfi_dict_knownget(ctx, stream_dict, "DecodeParms", &decode);
1122
2.19M
            if (code == 0)
1123
2.15M
                code = pdfi_dict_knownget(ctx, stream_dict, "DP", &decode);
1124
2.19M
        }
1125
2.19M
        if (code < 0)
1126
14
            goto exit;
1127
1128
2.19M
        code = pdfi_apply_filter(ctx, stream_dict, (pdf_name *)Filter,
1129
2.19M
                                 (pdf_dict *)decode, s, &new_s, inline_image);
1130
2.19M
        if (code < 0)
1131
5.34k
            goto exit;
1132
1133
2.19M
        code = pdfi_alloc_stream(ctx, new_s, source->s, new_stream);
1134
2.19M
        break;
1135
35.4k
    case PDF_ARRAY:
1136
35.4k
    {
1137
35.4k
        pdf_array *filter_array = (pdf_array *)Filter;
1138
1139
        /* ISO 32000-2:2020 (PDF 2.0) - abbreviated names take precendence. */
1140
35.4k
        if (inline_image) {
1141
1.04k
            code = pdfi_dict_knownget(ctx, stream_dict, "DP", (pdf_obj **)&DecodeParams);
1142
1.04k
            if (code == 0)
1143
926
                code = pdfi_dict_knownget(ctx, stream_dict, "DecodeParms", (pdf_obj **)&DecodeParams);
1144
34.4k
        } else {
1145
34.4k
            code = pdfi_dict_knownget(ctx, stream_dict, "DecodeParms", (pdf_obj **)&DecodeParams);
1146
34.4k
            if (code == 0)
1147
29.8k
                code = pdfi_dict_knownget(ctx, stream_dict, "DP", &decode);
1148
34.4k
        }
1149
35.4k
        if (code < 0)
1150
0
            goto exit;
1151
1152
35.4k
        if (DecodeParams != NULL) {
1153
4.65k
            if (pdfi_array_size(DecodeParams) == 0 || pdfi_array_size(DecodeParams) != pdfi_array_size(filter_array)) {
1154
82
                pdfi_countdown(DecodeParams);
1155
82
                DecodeParams = NULL;
1156
82
                if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_rangecheck), NULL, W_PDF_STREAM_BAD_DECODEPARMS, "pdfi_filter_no_decryption", NULL)) < 0)
1157
0
                    goto exit;
1158
4.57k
            } else {
1159
4.57k
                if (pdfi_array_size(DecodeParams) != pdfi_array_size(filter_array)) {
1160
0
                    code = gs_note_error(gs_error_typecheck);
1161
0
                    goto exit;
1162
0
                }
1163
4.57k
            }
1164
4.65k
        }
1165
1166
        /* Turn any abbreviated filter names into standard naems for the loop below. */
1167
35.4k
        code = pdfi_normalize_filter_array(ctx, filter_array);
1168
35.4k
        if (code < 0)
1169
2
            goto exit;
1170
1171
        /* Check the Filter array to see if we have any duplicates (to prevent filter bombs)
1172
         * For now we will allow one duplicate (in case people do stupid things like ASCIIEncode
1173
         * and Flate and ASCIIEncode again or something).
1174
         */
1175
36.4k
        for (i = 0; i < (int)pdfi_array_size(filter_array) - 1;i++) {
1176
950
            code = pdfi_array_get_type(ctx, filter_array, i, PDF_NAME, &o);
1177
950
            if (code < 0)
1178
0
                goto exit;
1179
950
            duplicates = 0;
1180
1181
1.93k
            for (j = i + 1; j < pdfi_array_size(filter_array);j++) {
1182
984
                code = pdfi_array_get_type(ctx, filter_array, j, PDF_NAME, &o1);
1183
984
                if (code < 0) {
1184
0
                    goto exit;
1185
0
                }
1186
984
                if (((pdf_name *)o)->length == ((pdf_name *)o1)->length) {
1187
28
                    if (memcmp(((pdf_name *)o)->data, ((pdf_name *)o1)->data, ((pdf_name *)o)->length) == 0)
1188
14
                        duplicates++;
1189
28
                }
1190
984
                pdfi_countdown(o1);
1191
984
                o1 = NULL;
1192
984
            }
1193
950
            pdfi_countdown(o);
1194
950
            o = NULL;
1195
950
            if (duplicates > 1) {
1196
0
                pdfi_set_error(ctx, 0, NULL, E_PDF_BADSTREAM, "pdfi_filter_nodecryption", (char *)"**** ERROR Detected possible filter bomb (duplicate Filters).  Aborting processing");
1197
0
                code = gs_note_error(gs_error_syntaxerror);
1198
0
                goto exit;
1199
0
            }
1200
950
        }
1201
1202
71.6k
        for (i = 0; i < pdfi_array_size(filter_array);i++) {
1203
36.3k
            code = pdfi_array_get_type(ctx, filter_array, i, PDF_NAME, &o);
1204
36.3k
            if (code < 0)
1205
0
                goto error;
1206
36.3k
            if (DecodeParams != NULL) {
1207
4.81k
                code = pdfi_array_get(ctx, DecodeParams, i, &decode);
1208
4.81k
                if (code < 0) {
1209
12
                    goto error;
1210
12
                }
1211
4.81k
            }
1212
36.3k
            if (decode && decode != PDF_NULL_OBJ && pdfi_type_of(decode) != PDF_DICT) {
1213
0
                pdfi_countdown(decode);
1214
0
                decode = NULL;
1215
0
                if ((code = pdfi_set_warning_stop(ctx, gs_note_error(gs_error_typecheck), NULL, W_PDF_STREAM_BAD_DECODEPARMS, "pdfi_filter_no_decryption", NULL)) < 0)
1216
0
                    goto error;
1217
0
            }
1218
36.3k
            if (decode && decode == PDF_NULL_OBJ) {
1219
342
                pdfi_countdown(decode);
1220
342
                decode = NULL;
1221
342
            }
1222
1223
36.3k
            code = pdfi_apply_filter(ctx, stream_dict, (pdf_name *)o,
1224
36.3k
                                     (pdf_dict *)decode, s, &new_s, inline_image);
1225
36.3k
            pdfi_countdown(decode);
1226
36.3k
            decode = NULL;
1227
36.3k
            pdfi_countdown(o);
1228
36.3k
            o = NULL;
1229
36.3k
            if (code < 0)
1230
92
                goto error;
1231
1232
36.2k
            s = new_s;
1233
36.2k
        }
1234
35.3k
        code = pdfi_alloc_stream(ctx, s, source->s, new_stream);
1235
35.3k
    }
1236
2.23M
    }
1237
1238
2.65M
 exit:
1239
2.65M
    pdfi_countdown(o);
1240
2.65M
    pdfi_countdown(o1);
1241
2.65M
    pdfi_countdown(DecodeParams);
1242
2.65M
    pdfi_countdown(decode);
1243
2.65M
    pdfi_countdown(Filter);
1244
2.65M
    return code;
1245
1246
104
 error:
1247
104
    if (s)
1248
104
        pdfi_close_filter_chain(ctx, s, source->s);
1249
104
    *new_stream = NULL;
1250
104
    pdfi_countdown(o);
1251
104
    pdfi_countdown(o1);
1252
104
    pdfi_countdown(DecodeParams);
1253
104
    pdfi_countdown(decode);
1254
104
    pdfi_countdown(Filter);
1255
104
    return code;
1256
2.23M
}
1257
1258
int pdfi_filter(pdf_context *ctx, pdf_stream *stream_obj, pdf_c_stream *source,
1259
                pdf_c_stream **new_stream, bool inline_image)
1260
2.63M
{
1261
2.63M
    int code;
1262
2.63M
    pdf_c_stream *crypt_stream = NULL, *SubFile_stream = NULL;
1263
2.63M
    pdf_string *StreamKey = NULL;
1264
2.63M
    pdf_dict *stream_dict = NULL;
1265
2.63M
    pdf_obj *FileSpec = NULL;
1266
2.63M
    pdf_stream *NewStream = NULL;
1267
2.63M
    bool known = false, substituted = false;
1268
1269
2.63M
    *new_stream = NULL;
1270
1271
2.63M
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)stream_obj, &stream_dict);
1272
2.63M
    if (code < 0)
1273
0
        goto error;
1274
1275
    /* Horrifyingly, any stream dictionary can contain a file specification, which means that
1276
     * instead of using the stream from the PDF file we must use an external file.
1277
     * So much for portability!
1278
     * Note: We must not do this for inline images as an inline image dictionary can
1279
     * contain the abbreviation /F for the Filter, and an inline image is never a
1280
     * separate stream, it is (obviously) contained in the current stream.
1281
     */
1282
2.63M
    if (!inline_image) {
1283
2.36M
        code = pdfi_dict_known(ctx, stream_dict, "F", &known);
1284
2.36M
        if (code >= 0 && known) {
1285
9
            pdf_obj *FS = NULL, *o = NULL;
1286
9
            pdf_dict *dict = NULL;
1287
9
            stream *gstream = NULL;
1288
9
            char CFileName[gp_file_name_sizeof];
1289
1290
9
            code = pdfi_dict_get(ctx, stream_dict, "F", &FileSpec);
1291
9
            if (code < 0)
1292
0
                goto error;
1293
9
            if (pdfi_type_of(FileSpec) == PDF_DICT) {
1294
                /* We don't really support FileSpec dictionaries, partly because we
1295
                 * don't really know which platform to use. If there is a /F string
1296
                 * then we will use that, just as if we had been given a string in
1297
                 * the first place.
1298
                 */
1299
0
                code = pdfi_dict_knownget(ctx, (pdf_dict *)FileSpec, "F", &FS);
1300
0
                if (code < 0) {
1301
0
                    goto error;
1302
0
                }
1303
0
                pdfi_countdown(FileSpec);
1304
0
                FileSpec = FS;
1305
0
                FS = NULL;
1306
0
            }
1307
9
            if (pdfi_type_of(FileSpec) != PDF_STRING) {
1308
9
                code = gs_note_error(gs_error_typecheck);
1309
9
                goto error;
1310
9
            }
1311
1312
0
            if (((pdf_string *)FileSpec)->length + 1 > gp_file_name_sizeof) {
1313
0
                code = gs_note_error(gs_error_ioerror);
1314
0
                goto error;
1315
0
            }
1316
0
            memcpy(CFileName, ((pdf_string *)FileSpec)->data, ((pdf_string *)FileSpec)->length);
1317
0
            CFileName[((pdf_string *)FileSpec)->length] = 0x00;
1318
1319
            /* We should now have a string with the filename (or URL). We need
1320
             * to open the file and create a stream, if that succeeds.
1321
             */
1322
0
            gstream = sfopen((const char *)CFileName, "r", ctx->memory);
1323
0
            if (gstream == NULL) {
1324
0
                emprintf1(ctx->memory, "Failed to open file %s\n", CFileName);
1325
0
                code = gs_note_error(gs_error_ioerror);
1326
0
                goto error;
1327
0
            }
1328
1329
0
            source = (pdf_c_stream *)gs_alloc_bytes(ctx->memory, sizeof(pdf_c_stream), "external stream");
1330
0
            if (source == NULL) {
1331
0
                sfclose(gstream);
1332
0
                code = gs_note_error(gs_error_VMerror);
1333
0
                goto error;
1334
0
            }
1335
0
            memset(source, 0x00, sizeof(pdf_c_stream));
1336
0
            source->s = gstream;
1337
1338
0
            code = pdfi_object_alloc(ctx, PDF_STREAM, 0, (pdf_obj **)&NewStream);
1339
0
            if (code < 0) {
1340
0
                sfclose(gstream);
1341
0
                gs_free_object(ctx->memory, source, "pdfi_filter");
1342
0
                goto error;
1343
0
            }
1344
0
            pdfi_countup(NewStream);
1345
0
            code = pdfi_dict_alloc(ctx, 32, &dict);
1346
0
            if (code < 0){
1347
0
                sfclose(gstream);
1348
0
                gs_free_object(ctx->memory, source, "pdfi_filter");
1349
0
                pdfi_countdown(NewStream);
1350
0
                goto error;
1351
0
            }
1352
0
            pdfi_countup(dict);
1353
0
            NewStream->stream_dict = dict;
1354
0
            code = pdfi_dict_get(ctx, stream_dict, "FFilter", &o);
1355
0
            if (code >= 0) {
1356
0
                code = pdfi_dict_put(ctx, NewStream->stream_dict, "Filter", o);
1357
0
                if (code < 0) {
1358
0
                    sfclose(gstream);
1359
0
                    gs_free_object(ctx->memory, source, "pdfi_filter");
1360
0
                    pdfi_countdown(NewStream);
1361
0
                    goto error;
1362
0
                }
1363
0
            }
1364
0
            code = pdfi_dict_get(ctx, stream_dict, "FPredictor", &o);
1365
0
            if (code >= 0) {
1366
0
                code = pdfi_dict_put(ctx, NewStream->stream_dict, "Predictor", o);
1367
0
                if (code < 0) {
1368
0
                    sfclose(gstream);
1369
0
                    gs_free_object(ctx->memory, source, "pdfi_filter");
1370
0
                    pdfi_countdown(NewStream);
1371
0
                    goto error;
1372
0
                }
1373
0
            }
1374
0
            NewStream->stream_offset = 0;
1375
0
            NewStream->Length = 0;
1376
0
            NewStream->length_valid = 0;
1377
0
            NewStream->stream_written = 0;
1378
0
            NewStream->is_marking = 0;
1379
0
            NewStream->parent_obj = NULL;
1380
0
            stream_obj = NewStream;
1381
0
            stream_dict = NewStream->stream_dict;
1382
0
            substituted = true;
1383
0
        }
1384
2.36M
    }
1385
1386
    /* If the file isn't encrypted, don't apply encryption. If this is an inline
1387
     * image then its in a content stream and will already be decrypted, so don't
1388
     * apply decryption again.
1389
     */
1390
2.63M
    if (ctx->encryption.is_encrypted && !inline_image) {
1391
29.0k
        int64_t Length;
1392
1393
29.0k
        if (ctx->encryption.StmF == CRYPT_IDENTITY)
1394
0
            return pdfi_filter_no_decryption(ctx, stream_obj, source, new_stream, inline_image);
1395
1396
29.0k
        code = pdfi_dict_get_type(ctx, stream_dict, "StreamKey", PDF_STRING, (pdf_obj **)&StreamKey);
1397
29.0k
        if (code == gs_error_undefined) {
1398
8.45k
            code = pdfi_compute_objkey(ctx, (pdf_obj *)stream_dict, &StreamKey);
1399
8.45k
            if (code < 0)
1400
0
                return code;
1401
8.45k
            code = pdfi_dict_put(ctx, stream_dict, "StreamKey", (pdf_obj *)StreamKey);
1402
8.45k
            if (code < 0)
1403
0
                goto error;
1404
8.45k
        }
1405
29.0k
        if (code < 0)
1406
0
            return code;
1407
1408
        /* If we are applying a decryption filter we must also apply a SubFileDecode filter.
1409
         * This is because the underlying stream may not have a compression filter, if it doesn't
1410
         * then we have no way of detecting the end of the data. Normally we would get an 'endstream'
1411
         * token but if we have applied a decryption filter then we'll 'decrypt' that token
1412
         * and that will corrupt it. So make sure we can't read past the end of the stream
1413
         * by applying a SubFileDecode.
1414
         * NB applying a SubFileDecode filter with an EODString seems to limit the amount of data
1415
         * that the decode filter is prepared to return at any time to the size of the EODString.
1416
         * This doesn't play well with other filters (eg the AESDecode filter) which require a
1417
         * larger minimum to be returned (16 bytes for AESDecode). So I'm using the filter
1418
         * Length here, even though I'd prefer not to.....
1419
         */
1420
29.0k
        Length = pdfi_stream_length(ctx, stream_obj);
1421
1422
29.0k
        if (Length <= 0) {
1423
            /* Don't treat as an encrypted stream if Length is 0 */
1424
246
            pdfi_countdown(StreamKey);
1425
246
            return pdfi_filter_no_decryption(ctx, stream_obj, source, new_stream, inline_image);
1426
246
        }
1427
1428
28.7k
        code = pdfi_apply_SubFileDecode_filter(ctx, Length, NULL, source, &SubFile_stream, false);
1429
28.7k
        if (code < 0)
1430
0
            goto error;
1431
1432
28.7k
        SubFile_stream->original = source->s;
1433
1434
28.7k
        switch(ctx->encryption.StmF) {
1435
0
            case CRYPT_IDENTITY:
1436
                /* Can't happen, handled above */
1437
0
                break;
1438
            /* There are only two possible filters, RC4 or AES, we take care
1439
             * of the number of bits in the key by using ctx->Length.
1440
             */
1441
2.59k
            case CRYPT_V1:
1442
2.71k
            case CRYPT_V2:
1443
2.71k
                code = pdfi_apply_Arc4_filter(ctx, StreamKey, SubFile_stream, &crypt_stream);
1444
2.71k
                break;
1445
25.0k
            case CRYPT_AESV2:
1446
26.0k
            case CRYPT_AESV3:
1447
26.0k
                code = pdfi_apply_AES_filter(ctx, StreamKey, 1, SubFile_stream, &crypt_stream);
1448
26.0k
                break;
1449
0
            default:
1450
0
                code = gs_error_rangecheck;
1451
28.7k
        }
1452
28.7k
        if (code < 0) {
1453
0
            pdfi_close_file(ctx, SubFile_stream);
1454
0
            goto error;
1455
0
        }
1456
1457
28.7k
        crypt_stream->original = SubFile_stream->original;
1458
28.7k
        gs_free_object(ctx->memory, SubFile_stream, "pdfi_filter");
1459
1460
28.7k
        code = pdfi_filter_no_decryption(ctx, stream_obj, crypt_stream, new_stream, false);
1461
28.7k
        if (code < 0) {
1462
791
            pdfi_close_file(ctx, crypt_stream);
1463
791
            goto error;
1464
791
        }
1465
1466
28.0k
        (*new_stream)->original = source->s;
1467
28.0k
        gs_free_object(ctx->memory, crypt_stream, "pdfi_filter");
1468
2.61M
    } else {
1469
2.61M
        code = pdfi_filter_no_decryption(ctx, stream_obj, source, new_stream, inline_image);
1470
2.61M
    }
1471
2.63M
    if (substituted) {
1472
0
        gs_free_object(ctx->memory, source, "pdfi_filter");
1473
0
        (*new_stream)->original = 0;
1474
0
    }
1475
1476
2.63M
error:
1477
2.63M
    pdfi_countdown(NewStream);
1478
2.63M
    pdfi_countdown(StreamKey);
1479
2.63M
    pdfi_countdown(FileSpec);
1480
2.63M
    return code;
1481
2.63M
}
1482
1483
/* This is just a convenience routine. We could use pdfi_filter() above, but because PDF
1484
 * doesn't support the SubFileDecode filter that would mean callers having to manufacture
1485
 * a dictionary in order to use it. That's excessively convoluted, so just supply a simple
1486
 * means to instantiate a SubFileDecode filter.
1487
 *
1488
 * NB! The EODString can't be tracked by the stream code. The caller is responsible for
1489
 * managing the lifetime of this object. It must remain valid until the filter is closed.
1490
 */
1491
int pdfi_apply_SubFileDecode_filter(pdf_context *ctx, int EODCount, const char *EODString, pdf_c_stream *source, pdf_c_stream **new_stream, bool inline_image)
1492
3.06M
{
1493
3.06M
    int code;
1494
3.06M
    stream_SFD_state state;
1495
3.06M
    stream *new_s = NULL;
1496
3.06M
    int min_size = 2048;
1497
1498
3.06M
    *new_stream = NULL;
1499
1500
3.06M
    memset(&state, 0, sizeof(state));
1501
1502
3.06M
    if (s_SFD_template.set_defaults)
1503
3.06M
        s_SFD_template.set_defaults((stream_state *)&state);
1504
1505
3.06M
    if (EODString != NULL) {
1506
371k
        state.eod.data = (const byte *)EODString;
1507
371k
        state.eod.size = strlen(EODString);
1508
371k
    }
1509
1510
3.06M
    if (EODCount > 0)
1511
2.69M
        state.count = EODCount - source->unread_size;
1512
371k
    else
1513
371k
        state.count = EODCount;
1514
1515
3.06M
    code = pdfi_filter_open(min_size, &s_filter_read_procs, (const stream_template *)&s_SFD_template, (const stream_state *)&state, ctx->memory->non_gc_memory, &new_s);
1516
3.06M
    if (code < 0)
1517
0
        return code;
1518
1519
3.06M
    code = pdfi_alloc_stream(ctx, new_s, source->s, new_stream);
1520
3.06M
    if (code < 0) {
1521
0
        gs_free_object(ctx->memory->non_gc_memory, new_s->state, "pdfi_apply_SubFileDecode_filter");
1522
0
        gs_free_object(ctx->memory->non_gc_memory, new_s->cbuf, "pdfi_apply_SubFileDecode_filter");
1523
0
        gs_free_object(ctx->memory->non_gc_memory, new_s, "pdfi_apply_SubFileDecode_filter");
1524
0
        return code;
1525
0
    }
1526
3.06M
    new_s->strm = source->s;
1527
3.06M
    if (source->unread_size != 0) {
1528
0
        (*new_stream)->unread_size = source->unread_size;
1529
0
        memcpy((*new_stream)->unget_buffer, source->unget_buffer, source->unread_size);
1530
0
        source->unread_size = 0;
1531
0
    }
1532
3.06M
    return code;
1533
3.06M
}
1534
1535
/* We would really like to use a ReusableStreamDecode filter here, but that filter is defined
1536
 * purely in the PostScript interpreter. So instead we make a temporary stream from a
1537
 * memory buffer. Its icky (we can end up with the same data in memory multiple times)
1538
 * but it works, and is used elsewhere in Ghostscript.
1539
 * If retain_ownership is true then the calling function is responsible for buffer pointer lifetime.
1540
 * Otherwise the buffer will be freed when the stream is closed.
1541
 */
1542
int pdfi_open_memory_stream_from_stream(pdf_context *ctx, unsigned int size, byte **Buffer, pdf_c_stream *source, pdf_c_stream **new_pdf_stream, bool retain_ownership)
1543
0
{
1544
0
    stream *new_stream;
1545
0
    int code;
1546
1547
0
    new_stream = file_alloc_stream(ctx->memory, "open memory stream(stream)");
1548
0
    if (new_stream == NULL)
1549
0
        return_error(gs_error_VMerror);
1550
1551
0
    *Buffer = gs_alloc_bytes(ctx->memory, size, "open memory stream (buffer)");
1552
0
    if (*Buffer == NULL) {
1553
0
        gs_free_object(ctx->memory, new_stream, "open memory stream(stream)");
1554
0
        return_error(gs_error_VMerror);
1555
0
    }
1556
0
    code = pdfi_read_bytes(ctx, *Buffer, 1, size, source);
1557
0
    if (code < 0) {
1558
0
        gs_free_object(ctx->memory, *Buffer, "open memory stream(buffer)");
1559
0
        gs_free_object(ctx->memory, new_stream, "open memory stream(stream)");
1560
0
        return code;
1561
0
    }
1562
1563
0
    if (retain_ownership)
1564
0
        sread_string_reusable(new_stream, *Buffer, size);
1565
0
    else
1566
0
        sread_transient_string_reusable(new_stream, ctx->memory, *Buffer, size);
1567
1568
0
    code = pdfi_alloc_stream(ctx, new_stream, source->s, new_pdf_stream);
1569
0
    if (code < 0) {
1570
0
        sclose(new_stream);
1571
0
        gs_free_object(ctx->memory, *Buffer, "open memory stream(buffer)");
1572
0
        gs_free_object(ctx->memory, new_stream, "open memory stream(stream)");
1573
0
    }
1574
1575
0
    return code;
1576
0
}
1577
1578
/*
1579
 * Like pdfi_open_memory_stream_from_stream (and makes use of it) this is a way to read from a stream into
1580
 * memory, and return a stream which reads from that memory. The difference is that this function takes
1581
 * any filters into account, decompressing them. We could layer a decompression stream onto the memory
1582
 * stream returned by open_memory_stream_from_stream above instead.
1583
 *
1584
 * This function returns < 0 for an error, and the length of the uncompressed data on success.
1585
 */
1586
int pdfi_open_memory_stream_from_filtered_stream(pdf_context *ctx, pdf_stream *stream_obj,
1587
                                                 byte **Buffer, pdf_c_stream **new_pdf_stream, bool retain_ownership)
1588
49.4k
{
1589
49.4k
    int code;
1590
49.4k
    int64_t bufferlen = 0;
1591
1592
49.4k
    code = pdfi_stream_to_buffer(ctx, stream_obj, Buffer, &bufferlen);
1593
49.4k
    if (code < 0) {
1594
433
        *Buffer = NULL;
1595
433
        *new_pdf_stream = NULL;
1596
433
        return code;
1597
433
    }
1598
49.0k
    code = pdfi_open_memory_stream_from_memory(ctx, (unsigned int)bufferlen, *Buffer, new_pdf_stream, retain_ownership);
1599
49.0k
    if (code < 0) {
1600
0
        gs_free_object(ctx->memory, *Buffer, "pdfi_open_memory_stream_from_filtered_stream");
1601
0
        *Buffer = NULL;
1602
0
        *new_pdf_stream = NULL;
1603
0
        return code;
1604
0
    }
1605
49.0k
    return (int)bufferlen;
1606
49.0k
}
1607
1608
int pdfi_open_memory_stream_from_memory(pdf_context *ctx, unsigned int size, byte *Buffer, pdf_c_stream **new_pdf_stream, bool retain_ownership)
1609
196k
{
1610
196k
    int code;
1611
196k
    stream *new_stream;
1612
1613
196k
    new_stream = file_alloc_stream(ctx->memory, "open memory stream from memory(stream)");
1614
196k
    if (new_stream == NULL)
1615
0
        return_error(gs_error_VMerror);
1616
196k
    new_stream->close_at_eod = false;
1617
196k
    if (retain_ownership)
1618
171k
        sread_string(new_stream, Buffer, size);
1619
24.4k
    else
1620
24.4k
        sread_transient_string(new_stream, ctx->memory, Buffer, size);
1621
1622
196k
    code = pdfi_alloc_stream(ctx, new_stream, NULL, new_pdf_stream);
1623
196k
    if (code < 0) {
1624
0
        sclose(new_stream);
1625
0
        gs_free_object(ctx->memory, new_stream, "open memory stream from memory(stream)");
1626
0
    }
1627
1628
196k
    return code;
1629
196k
}
1630
1631
int pdfi_close_memory_stream(pdf_context *ctx, byte *Buffer, pdf_c_stream *source)
1632
87.5k
{
1633
87.5k
    gs_free_object(ctx->memory, Buffer, "open memory stream(buffer)");
1634
87.5k
    if (source != NULL) {
1635
87.5k
        if (source->s != NULL) {
1636
87.5k
            sclose(source->s);
1637
87.5k
            gs_free_object(ctx->memory, source->s, "open memory stream(stream)");
1638
87.5k
        }
1639
87.5k
        gs_free_object(ctx->memory, source, "open memory stream(pdf_stream)");
1640
87.5k
    }
1641
87.5k
    return 0;
1642
87.5k
}
1643
1644
/***********************************************************************************/
1645
/* Basic 'file' operations. Because of the need to 'unread' bytes we need our own  */
1646
1647
static void pdfi_close_filter_chain(pdf_context *ctx, stream *s, stream *target)
1648
5.79M
{
1649
5.79M
    stream *next_s = s;
1650
1651
11.2M
    while(next_s && next_s != target){
1652
5.47M
        stream *curr_s = next_s;
1653
5.47M
        next_s = next_s->strm;
1654
5.47M
        if (curr_s != ctx->main_stream->s)
1655
5.47M
            sfclose(curr_s);
1656
5.47M
    }
1657
5.79M
}
1658
1659
void pdfi_close_file(pdf_context *ctx, pdf_c_stream *s)
1660
5.79M
{
1661
5.79M
    pdfi_close_filter_chain(ctx, s->s, s->original);
1662
1663
5.79M
    gs_free_object(ctx->memory, s, "closing pdf_file");
1664
5.79M
}
1665
1666
int pdfi_seek(pdf_context *ctx, pdf_c_stream *s, gs_offset_t offset, uint32_t origin)
1667
14.0M
{
1668
14.0M
    int code = 0;
1669
1670
14.0M
    if (origin == SEEK_CUR && s->unread_size != 0)
1671
1.18k
        offset -= s->unread_size;
1672
1673
14.0M
    s->unread_size = 0;;
1674
1675
14.0M
    code = sfseek(s->s, offset, origin);
1676
14.0M
    if (s->eof && code >= 0)
1677
141k
        s->eof = 0;
1678
1679
14.0M
    return code;
1680
14.0M
}
1681
1682
/* We use 'stell' sometimes to save the position of the underlying file
1683
 * when reading a compressed stream, so that we can return to the same
1684
 * point in the underlying file after performing some other operation. This
1685
 * allows us (for instance) to load a font while interpreting a content stream.
1686
 * However, if we've 'unread' any bytes we need to take that into account.
1687
 * NOTE! this is only going to be valid when performed on the main stream
1688
 * the original PDF file, not any compressed stream!
1689
 */
1690
gs_offset_t pdfi_unread_tell(pdf_context *ctx)
1691
157M
{
1692
157M
    gs_offset_t off = stell(ctx->main_stream->s);
1693
1694
157M
    return (off - ctx->main_stream->unread_size);
1695
157M
}
1696
1697
gs_offset_t pdfi_tell(pdf_c_stream *s)
1698
1.09M
{
1699
1.09M
    return stell(s->s);
1700
1.09M
}
1701
1702
int pdfi_unread_byte(pdf_context *ctx, pdf_c_stream *s, char c)
1703
1.72G
{
1704
1.72G
    if (s->unread_size == UNREAD_BUFFER_SIZE)
1705
0
        return_error(gs_error_ioerror);
1706
1707
1.72G
    s->unget_buffer[s->unread_size++] = c;
1708
1709
1.72G
    return 0;
1710
1.72G
}
1711
1712
int pdfi_unread(pdf_context *ctx, pdf_c_stream *s, byte *Buffer, uint32_t size)
1713
184k
{
1714
184k
    if (size + s->unread_size > UNREAD_BUFFER_SIZE)
1715
13
        return_error(gs_error_ioerror);
1716
1717
184k
    Buffer += size;
1718
752k
    while (size) {
1719
568k
        s->unget_buffer[s->unread_size++] = *--Buffer;
1720
568k
        size--;
1721
568k
    }
1722
1723
184k
    return 0;
1724
184k
}
1725
1726
int pdfi_read_byte(pdf_context *ctx, pdf_c_stream *s)
1727
14.3G
{
1728
14.3G
    int32_t code;
1729
1730
14.3G
    if (s->eof && s->unread_size == 0)
1731
399k
        return EOFC;
1732
1733
14.3G
    if (s->unread_size)
1734
1.71G
        return (byte)s->unget_buffer[--s->unread_size];
1735
1736
    /* TODO the Ghostscript code uses sbufptr(s) to avoid a memcpy
1737
     * at some point we should modify this code to do so as well.
1738
     */
1739
12.6G
    code = spgetc(s->s);
1740
12.6G
    if (code == EOFC) {
1741
625k
        s->eof = true;
1742
625k
        return EOFC;
1743
12.6G
    } else if (code == gs_error_ioerror) {
1744
383
        pdfi_set_error(ctx, code, "sgets", E_PDF_BADSTREAM, "pdfi_read_bytes", NULL);
1745
383
        s->eof = true;
1746
383
        return EOFC;
1747
12.6G
    } else if(code == ERRC) {
1748
98.6k
        return ERRC;
1749
98.6k
    }
1750
12.6G
    return (int)code;
1751
12.6G
}
1752
1753
1754
int pdfi_read_bytes(pdf_context *ctx, byte *Buffer, uint32_t size, uint32_t count, pdf_c_stream *s)
1755
3.38M
{
1756
3.38M
    uint32_t i = 0, total = size * count;
1757
3.38M
    uint32_t bytes = 0;
1758
3.38M
    int32_t code;
1759
1760
3.38M
    if (s->eof && s->unread_size == 0)
1761
12
        return 0;
1762
1763
3.38M
    if (s->unread_size) {
1764
39.1k
        i = s->unread_size;
1765
39.1k
        if (i >= total)
1766
0
            i = total;
1767
39.1k
        bytes = i;
1768
81.9k
        while (bytes) {
1769
42.7k
            *Buffer++ = s->unget_buffer[--s->unread_size];
1770
42.7k
            bytes--;
1771
42.7k
        }
1772
39.1k
        total -= i;
1773
39.1k
        if (total == 0 || s->eof)
1774
0
            return i;
1775
39.1k
    }
1776
1777
    /* TODO the Ghostscript code uses sbufptr(s) to avoid a memcpy
1778
     * at some point we should modify this code to do so as well.
1779
     */
1780
3.38M
    code = sgets(s->s, Buffer, total, &bytes);
1781
3.38M
    if (code == EOFC) {
1782
932
        s->eof = true;
1783
3.38M
    } else if (code == gs_error_ioerror) {
1784
0
        pdfi_set_error(ctx, code, "sgets", E_PDF_BADSTREAM, "pdfi_read_bytes", NULL);
1785
0
        s->eof = true;
1786
3.38M
    } else if(code == ERRC) {
1787
206
        bytes = ERRC;
1788
3.38M
    } else {
1789
3.38M
        bytes = bytes + i;
1790
3.38M
    }
1791
1792
3.38M
    return bytes;
1793
3.38M
}
1794
1795
/* Read bytes from stream object into buffer.
1796
 * Handles both plain streams and filtered streams.
1797
 * Buffer gets allocated here, and must be freed by caller.
1798
 * Preserves the location of the current stream file position.
1799
 */
1800
int
1801
pdfi_stream_to_buffer(pdf_context *ctx, pdf_stream *stream_obj, byte **buf, int64_t *bufferlen)
1802
150k
{
1803
150k
    byte *Buffer = NULL;
1804
150k
    int code = 0;
1805
150k
    uint read = 0;
1806
150k
    size_t buflen = 0;
1807
150k
    int64_t ToRead = *bufferlen;
1808
150k
    gs_offset_t savedoffset;
1809
150k
    pdf_c_stream *stream = NULL, *SubFileStream = NULL;
1810
150k
    bool filtered;
1811
150k
    pdf_dict *stream_dict = NULL;
1812
1813
150k
    savedoffset = pdfi_tell(ctx->main_stream);
1814
1815
150k
    pdfi_seek(ctx, ctx->main_stream, pdfi_stream_offset(ctx, stream_obj), SEEK_SET);
1816
1817
150k
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)stream_obj, &stream_dict);
1818
150k
    if (code < 0)
1819
0
        goto exit;
1820
1821
    /* See if this is a filtered stream */
1822
150k
    code = pdfi_dict_known(ctx, stream_dict, "Filter", &filtered);
1823
150k
    if (code < 0)
1824
0
        goto exit;
1825
1826
150k
    if (!filtered) {
1827
19.3k
        code = pdfi_dict_known(ctx, stream_dict, "F", &filtered);
1828
19.3k
        if (code < 0)
1829
0
            goto exit;
1830
19.3k
    }
1831
1832
154k
retry:
1833
154k
    if (ToRead == 0) {
1834
146k
        if (filtered || ctx->encryption.is_encrypted) {
1835
131k
            code = pdfi_apply_SubFileDecode_filter(ctx, 0, "endstream", ctx->main_stream, &SubFileStream, false);
1836
131k
            if (code < 0)
1837
0
                goto exit;
1838
131k
            code = pdfi_filter(ctx, stream_obj, SubFileStream, &stream, false);
1839
131k
            if (code < 0) {
1840
726
                pdfi_close_file(ctx, SubFileStream);
1841
726
                goto exit;
1842
726
            }
1843
972k
            while (seofp(stream->s) != true && serrorp(stream->s) != true) {
1844
842k
                s_process_read_buf(stream->s);
1845
842k
                buflen += sbufavailable(stream->s);
1846
842k
                (void)sbufskip(stream->s, sbufavailable(stream->s));
1847
842k
            }
1848
130k
            pdfi_close_file(ctx, stream);
1849
130k
            pdfi_close_file(ctx, SubFileStream);
1850
130k
        } else {
1851
15.0k
            buflen = pdfi_stream_length(ctx, stream_obj);
1852
15.0k
        }
1853
146k
    } else
1854
8.75k
        buflen = *bufferlen;
1855
1856
    /* Alloc buffer */
1857
154k
    Buffer = gs_alloc_bytes(ctx->memory, buflen, "pdfi_stream_to_buffer (Buffer)");
1858
154k
    if (!Buffer) {
1859
5
        code = gs_note_error(gs_error_VMerror);
1860
5
        goto exit;
1861
5
    }
1862
1863
154k
    code = pdfi_seek(ctx, ctx->main_stream, pdfi_stream_offset(ctx, stream_obj), SEEK_SET);
1864
154k
    if (code < 0) {
1865
0
        buflen = 0;
1866
0
        goto exit;
1867
0
    }
1868
154k
    if (filtered || ctx->encryption.is_encrypted) {
1869
134k
        if (ToRead && stream_obj->length_valid)
1870
4.15k
            code = pdfi_apply_SubFileDecode_filter(ctx, stream_obj->Length, NULL, ctx->main_stream, &SubFileStream, false);
1871
130k
        else
1872
130k
            code = pdfi_apply_SubFileDecode_filter(ctx, 0, "endstream", ctx->main_stream, &SubFileStream, false);
1873
134k
        if (code < 0)
1874
0
            goto exit;
1875
1876
134k
        code = pdfi_filter(ctx, stream_obj, SubFileStream, &stream, false);
1877
134k
        if (code < 0) {
1878
            /* Because we opened the SubFileDecode separately to the filter chain, we need to close it separately too */
1879
117
            pdfi_close_file(ctx, SubFileStream);
1880
117
            goto exit;
1881
117
        }
1882
1883
134k
        code = sgets(stream->s, Buffer, buflen, (unsigned int *)&read);
1884
134k
        if (read < buflen) {
1885
2.76k
            memset(Buffer + read, 0x00, buflen - read);
1886
2.76k
        }
1887
1888
134k
        pdfi_close_file(ctx, stream);
1889
        /* Because we opened the SubFileDecode separately to the filter chain, we need to close it separately too */
1890
134k
        pdfi_close_file(ctx, SubFileStream);
1891
134k
        if (code == ERRC || code == EOFC) {
1892
2.98k
            code = 0;
1893
            /* Error reading the expected number of bytes. If we already calculated the number of
1894
             * bytes in the loop above, then ignore the error and carry on. If, however, we were
1895
             * told how many bytes to expect, and failed to read that many, go back and do this
1896
             * the slow way to determine how many bytes are *really* available.
1897
             */
1898
2.98k
            if(ToRead != 0) {
1899
662
                buflen = ToRead = 0;
1900
662
                code = pdfi_seek(ctx, ctx->main_stream, pdfi_stream_offset(ctx, stream_obj), SEEK_SET);
1901
662
                if (code < 0)
1902
0
                    goto exit;
1903
662
                gs_free_object(ctx->memory, Buffer, "pdfi_stream_to_buffer (Buffer)");
1904
662
                goto retry;
1905
662
            }
1906
2.98k
        }
1907
134k
    } else {
1908
19.2k
        if (ToRead && stream_obj->length_valid)
1909
4.20k
            code = pdfi_apply_SubFileDecode_filter(ctx, stream_obj->Length, NULL, ctx->main_stream, &SubFileStream, false);
1910
15.0k
        else
1911
15.0k
            code = pdfi_apply_SubFileDecode_filter(ctx, ToRead, "endstream", ctx->main_stream, &SubFileStream, false);
1912
19.2k
        if (code < 0)
1913
0
            goto exit;
1914
1915
19.2k
        code = sgets(SubFileStream->s, Buffer, buflen, (unsigned int *)&read);
1916
19.2k
        if (read < buflen) {
1917
103
            memset(Buffer + read, 0x00, buflen - read);
1918
103
        }
1919
1920
19.2k
        pdfi_close_file(ctx, SubFileStream);
1921
19.2k
        if (code == ERRC || code == EOFC) {
1922
3.59k
            code = 0;
1923
            /* Error reading the expected number of bytes. If we already calculated the number of
1924
             * bytes in the loop above, then ignore the error and carry on. If, however, we were
1925
             * told how many bytes to expect, and failed to read that many, go back and do this
1926
             * the slow way to determine how many bytes are *really* available.
1927
             */
1928
3.59k
            buflen = ToRead = 0;
1929
            /* Setting filtered to true is a lie, but it forces the code to go through the slow path and check the *real* number of bytes
1930
             * in the stream. This will be slow, but it should only happen when we get a file which is invalid.
1931
             */
1932
3.59k
            filtered = 1;
1933
3.59k
            code = pdfi_seek(ctx, ctx->main_stream, pdfi_stream_offset(ctx, stream_obj), SEEK_SET);
1934
3.59k
            if (code < 0)
1935
0
                goto exit;
1936
3.59k
            gs_free_object(ctx->memory, Buffer, "pdfi_stream_to_buffer (Buffer)");
1937
3.59k
            goto retry;
1938
3.59k
        }
1939
19.2k
    }
1940
1941
150k
 exit:
1942
150k
    pdfi_seek(ctx, ctx->main_stream, savedoffset, SEEK_SET);
1943
150k
    if (Buffer && code < 0)
1944
117
        gs_free_object(ctx->memory, Buffer, "pdfi_stream_to_buffer (Buffer)");
1945
150k
    else
1946
150k
        *buf = Buffer;
1947
150k
    *bufferlen = buflen;
1948
150k
    return code;
1949
154k
}
1950
1951
static int pdfi_open_resource_file_inner(pdf_context *ctx, const char *fname, const int fnamelen, stream **s)
1952
1.98M
{
1953
1.98M
    int code = 0;
1954
1.98M
    if (fname == NULL || fnamelen == 0 || fnamelen >= gp_file_name_sizeof)
1955
3
        *s = NULL;
1956
1.98M
    else if (gp_file_name_is_absolute(fname, fnamelen) || fname[0] == '%') {
1957
0
        char CFileName[gp_file_name_sizeof];
1958
1959
0
        if (fnamelen + 1 > gp_file_name_sizeof)
1960
0
            return_error(gs_error_ioerror);
1961
0
        memcpy(CFileName, fname, fnamelen);
1962
0
        CFileName[fnamelen] = 0x00;
1963
        /* If it's an absolute path or an explicit PS style device, just try to open it */
1964
0
        *s = sfopen(CFileName, "r", ctx->memory);
1965
0
    }
1966
1.98M
    else {
1967
1.98M
        char fnametotry[gp_file_name_sizeof];
1968
1.98M
        uint fnlen;
1969
1.98M
        gs_parsed_file_name_t pname;
1970
1.98M
        gp_file_name_combine_result r;
1971
1.98M
        int i, total;
1972
1973
1.98M
        *s = NULL;
1974
1.98M
        i = 0;
1975
1.98M
        total = ctx->search_paths.num_resource_paths - ctx->search_paths.num_init_resource_paths - 1;
1976
3.87M
retry:
1977
29.0M
        for (; i < total; i++) {
1978
25.2M
            gs_param_string *ss = &ctx->search_paths.resource_paths[i];
1979
1980
25.2M
            if (ss->data[0] == '%') {
1981
3.92M
                code = gs_parse_file_name(&pname, (char *)ss->data, ss->size, ctx->memory);
1982
3.92M
                if (code < 0 || (pname.len + fnamelen >= gp_file_name_sizeof)) {
1983
0
                    continue;
1984
0
                }
1985
3.92M
                memcpy(fnametotry, pname.fname, pname.len);
1986
3.92M
                memcpy(fnametotry + pname.len, fname, fnamelen);
1987
3.92M
                code = pname.iodev->procs.open_file(pname.iodev, fnametotry, pname.len + fnamelen, "r", s, ctx->memory);
1988
3.92M
                if (code < 0) {
1989
3.88M
                    continue;
1990
3.88M
                }
1991
46.1k
                break;
1992
3.92M
            }
1993
21.3M
            else {
1994
21.3M
                fnlen = gp_file_name_sizeof;
1995
21.3M
                r = gp_file_name_combine((char *)ss->data, ss->size, fname, fnamelen, false, fnametotry, &fnlen);
1996
21.3M
                if (r != gp_combine_success || fnlen > gp_file_name_sizeof - 1)
1997
0
                    continue;
1998
21.3M
                fnametotry[fnlen] = '\0';
1999
21.3M
                *s = sfopen(fnametotry, "r", ctx->memory);
2000
21.3M
                if (*s != NULL)
2001
0
                    break;
2002
21.3M
            }
2003
25.2M
        }
2004
3.87M
        if (*s == NULL && i < ctx->search_paths.num_resource_paths) {
2005
1.94M
            gs_param_string *ss = &ctx->search_paths.genericresourcedir;
2006
1.94M
            fnlen = gp_file_name_sizeof;
2007
1.94M
            r = gp_file_name_combine((char *)ss->data, ss->size, fname, fnamelen, false, fnametotry, &fnlen);
2008
1.94M
            if (r == gp_combine_success || fnlen < gp_file_name_sizeof) {
2009
1.94M
                fnametotry[fnlen] = '\0';
2010
1.94M
                *s = sfopen(fnametotry, "r", ctx->memory);
2011
1.94M
            }
2012
1.94M
        }
2013
3.87M
        if (*s == NULL && i < ctx->search_paths.num_resource_paths) {
2014
1.88M
            total = ctx->search_paths.num_resource_paths;
2015
1.88M
            goto retry;
2016
1.88M
        }
2017
3.87M
    }
2018
1.98M
    if (*s == NULL)
2019
1.88M
        return_error(gs_error_invalidfileaccess);
2020
2021
99.0k
    return 0;
2022
1.98M
}
2023
2024
int pdfi_open_resource_file(pdf_context *ctx, const char *fname, const int fnamelen, stream **s)
2025
114k
{
2026
114k
    return pdfi_open_resource_file_inner(ctx, fname, fnamelen, s);
2027
114k
}
2028
2029
bool pdfi_resource_file_exists(pdf_context *ctx, const char *fname, const int fnamelen)
2030
0
{
2031
0
    stream *s = NULL;
2032
0
    int code = pdfi_open_resource_file_inner(ctx, fname, fnamelen, &s);
2033
0
    if (s)
2034
0
        sfclose(s);
2035
2036
0
    return (code >= 0);
2037
0
}
2038
2039
static int pdfi_open_font_file_inner(pdf_context *ctx, const char *fname, const int fnamelen, stream **s)
2040
1.87M
{
2041
1.87M
    int code = 0;
2042
1.87M
    const char *fontdirstr = "Font/";
2043
1.87M
    const int fontdirstrlen = strlen(fontdirstr);
2044
1.87M
    uint fnlen;
2045
1.87M
    gp_file_name_combine_result r;
2046
1.87M
    char fnametotry[gp_file_name_sizeof];
2047
2048
1.87M
    if (fname == NULL || fnamelen == 0 || fnamelen >= (gp_file_name_sizeof - fontdirstrlen))
2049
3
        *s = NULL;
2050
1.87M
    else if (gp_file_name_is_absolute(fname, fnamelen) || fname[0] == '%') {
2051
0
        char CFileName[gp_file_name_sizeof];
2052
2053
0
        if (fnamelen + 1 > gp_file_name_sizeof)
2054
0
            return_error(gs_error_ioerror);
2055
0
        memcpy(CFileName, fname, fnamelen);
2056
0
        CFileName[fnamelen] = 0x00;
2057
        /* If it's an absolute path or an explicit PS style device, just try to open it */
2058
0
        *s = sfopen(CFileName, "r", ctx->memory);
2059
0
    }
2060
1.87M
    else {
2061
1.87M
        char fnametotry[gp_file_name_sizeof];
2062
1.87M
        gs_parsed_file_name_t pname;
2063
1.87M
        int i;
2064
2065
1.87M
        *s = NULL;
2066
1.87M
        for (i = 0; i < ctx->search_paths.num_font_paths; i++) {
2067
0
            gs_param_string *ss = &ctx->search_paths.font_paths[i];
2068
2069
0
            if (ss->data[0] == '%') {
2070
0
                code = gs_parse_file_name(&pname, (char *)ss->data, ss->size, ctx->memory);
2071
0
                if (code < 0 || (pname.len + fnamelen >= gp_file_name_sizeof)) {
2072
0
                    continue;
2073
0
                }
2074
0
                memcpy(fnametotry, pname.fname, pname.len);
2075
0
                memcpy(fnametotry + pname.len, fname, fnamelen);
2076
0
                code = pname.iodev->procs.open_file(pname.iodev, fnametotry, pname.len + fnamelen, "r", s, ctx->memory);
2077
0
                if (code < 0) {
2078
0
                    continue;
2079
0
                }
2080
0
                break;
2081
0
            }
2082
0
            else {
2083
0
                fnlen = gp_file_name_sizeof;
2084
0
                r = gp_file_name_combine((char *)ss->data, ss->size, fname, fnamelen, false, fnametotry, &fnlen);
2085
0
                if (r != gp_combine_success || fnlen > gp_file_name_sizeof - 1)
2086
0
                    continue;
2087
0
                fnametotry[fnlen] = '\0';
2088
0
                *s = sfopen(fnametotry, "r", ctx->memory);
2089
0
                if (*s != NULL)
2090
0
                    break;
2091
0
            }
2092
0
        }
2093
1.87M
    }
2094
2095
    /* If not in the font specific search path, try it as a resource */
2096
1.87M
    if (*s == NULL)
2097
1.87M
        code =  pdfi_open_resource_file_inner(ctx, fname, fnamelen, s);
2098
2099
1.87M
    if (*s == NULL) {
2100
1.87M
        gs_param_string *ss = &ctx->search_paths.genericresourcedir;
2101
1.87M
        char fstr[gp_file_name_sizeof];
2102
2103
1.87M
        fnlen = gp_file_name_sizeof;
2104
2105
1.87M
        if (fontdirstrlen + 1 > gp_file_name_sizeof)
2106
0
            return_error(gs_error_undefinedfilename);
2107
2108
1.87M
        memcpy(fstr, fontdirstr, fontdirstrlen);
2109
1.87M
        if (fname != NULL) {
2110
1.87M
            if (fontdirstrlen + fnamelen < gp_file_name_sizeof)
2111
1.87M
                memcpy(fstr + fontdirstrlen, fname, fnamelen);
2112
3
            else
2113
3
                return_error(gs_error_undefinedfilename);
2114
1.87M
        }
2115
2116
1.87M
        r = gp_file_name_combine((char *)ss->data, ss->size, fstr, fontdirstrlen + fnamelen, false, fnametotry, &fnlen);
2117
1.87M
        if (r == gp_combine_success || fnlen < gp_file_name_sizeof) {
2118
1.87M
            fnametotry[fnlen] = '\0';
2119
1.87M
            *s = sfopen(fnametotry, "r", ctx->memory);
2120
1.87M
        }
2121
1.87M
    }
2122
2123
1.87M
    return *s == NULL ? gs_error_undefinedfilename : 0;
2124
1.87M
}
2125
2126
int pdfi_open_font_file(pdf_context *ctx, const char *fname, const int fnamelen, stream **s)
2127
940k
{
2128
940k
    return pdfi_open_font_file_inner(ctx, fname, fnamelen, s);
2129
940k
}
2130
2131
bool pdfi_font_file_exists(pdf_context *ctx, const char *fname, const int fnamelen)
2132
932k
{
2133
932k
    stream *s = NULL;
2134
932k
    int code = pdfi_open_font_file_inner(ctx, fname, fnamelen, &s);
2135
932k
    if (s)
2136
0
        sfclose(s);
2137
2138
932k
    return (code >= 0);
2139
932k
}