Coverage Report

Created: 2025-06-10 07:27

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