Coverage Report

Created: 2026-10-28 08:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/pdf/pdf_func.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
/* function creation for the PDF interpreter */
17
18
#include "pdf_int.h"
19
#include "pdf_stack.h"
20
#include "pdf_func.h"
21
#include "pdf_dict.h"
22
#include "pdf_array.h"
23
#include "pdf_file.h"
24
#include "pdf_loop_detect.h"
25
26
#include "gsdsrc.h"
27
#include "gsfunc0.h"
28
#include "gsfunc3.h"
29
#include "gsfunc4.h"
30
#include "stream.h"
31
32
static int pdfi_build_sub_function(pdf_context *ctx, gs_function_t ** ppfn, const float *shading_domain, int num_inputs, pdf_obj *stream_obj, pdf_dict *page_dict);
33
34
672k
#define NUMBERTOKENSIZE 16
35
5.10M
#define OPTOKENSIZE 9
36
#define TOKENBUFFERSIZE NUMBERTOKENSIZE + 1
37
#define NUMOPS 42
38
39
typedef struct op_struct {
40
    unsigned char length;
41
    gs_PtCr_opcode_t code;
42
    unsigned char op[9];
43
}op_struct_t;
44
45
static const op_struct_t ops_table[] = {
46
    {(unsigned char)2, PtCr_eq, "eq"},
47
    {(unsigned char)2, PtCr_ge, "ge"},
48
    {(unsigned char)2, PtCr_gt, "gt"},
49
    {(unsigned char)2, PtCr_if, "if"},
50
    {(unsigned char)2, PtCr_le, "le"},
51
    {(unsigned char)2, PtCr_ln, "ln"},
52
    {(unsigned char)2, PtCr_lt, "lt"},
53
    {(unsigned char)2, PtCr_ne, "ne"},
54
    {(unsigned char)2, PtCr_or, "or"},
55
56
    {(unsigned char)3, PtCr_abs, "abs"},
57
    {(unsigned char)3, PtCr_add, "add"},
58
    {(unsigned char)3, PtCr_and, "and"},
59
    {(unsigned char)3, PtCr_cos, "cos"},
60
    {(unsigned char)3, PtCr_cvi, "cvi"},
61
    {(unsigned char)3, PtCr_cvr, "cvr"},
62
    {(unsigned char)3, PtCr_div, "div"},
63
    {(unsigned char)3, PtCr_dup, "dup"},
64
    {(unsigned char)3, PtCr_exp, "exp"},
65
    {(unsigned char)3, PtCr_log, "log"},
66
    {(unsigned char)3, PtCr_mul, "mul"},
67
    {(unsigned char)3, PtCr_mod, "mod"},
68
    {(unsigned char)3, PtCr_neg, "neg"},
69
    {(unsigned char)3, PtCr_not, "not"},
70
    {(unsigned char)3, PtCr_pop, "pop"},
71
    {(unsigned char)3, PtCr_sin, "sin"},
72
    {(unsigned char)3, PtCr_sub, "sub"},
73
    {(unsigned char)3, PtCr_xor, "xor"},
74
75
    {(unsigned char)4, PtCr_atan, "atan"},
76
    {(unsigned char)4, PtCr_copy, "copy"},
77
    {(unsigned char)4, PtCr_exch, "exch"},
78
    {(unsigned char)4, PtCr_idiv, "idiv"},
79
    {(unsigned char)4, PtCr_roll, "roll"},
80
    {(unsigned char)4, PtCr_sqrt, "sqrt"},
81
    {(unsigned char)4, PtCr_true, "true"},
82
83
    {(unsigned char)5, PtCr_false, "false"},
84
    {(unsigned char)5, PtCr_floor, "floor"},
85
    {(unsigned char)5, PtCr_index, "index"},
86
    {(unsigned char)5, PtCr_round, "round"},
87
88
    {(unsigned char)6, PtCr_else, "ifelse"},
89
90
    {(unsigned char)7, PtCr_ceiling, "ceiling"},
91
92
    {(unsigned char)8, PtCr_bitshift, "bitshift"},
93
    {(unsigned char)8, PtCr_truncate, "truncate"},
94
};
95
96
/* Fix up an if or ifelse forward reference. */
97
static int
98
psc_fixup(byte *p, byte *to)
99
75.3k
{
100
75.3k
    int skip = to - (p + 3);
101
102
75.3k
    if (skip > 0xFFFF)
103
0
        return_error(gs_error_rangecheck);
104
105
75.3k
    p[1] = (byte)(skip >> 8);
106
75.3k
    p[2] = (byte)skip;
107
75.3k
    return 0;
108
75.3k
}
109
static int
110
psc_fixup_ifelse(byte *p)
111
37.3k
{
112
37.3k
    int iflen = (p[0] << 8) + p[1];
113
114
37.3k
    iflen += 3;         /* To skip past the 'if' body and the 'else' header */
115
37.3k
    if (iflen > 0xFFFF)
116
0
        return_error(gs_error_rangecheck);
117
118
37.3k
    p[0] = (byte)(iflen >> 8);
119
37.3k
    p[1] = (byte)iflen;
120
37.3k
    return 0;
121
37.3k
}
122
123
/* Store an int in the  buffer */
124
static int
125
689k
put_int(byte **p, int n) {
126
689k
   if (n == (byte)n) {
127
638k
       if (*p) {
128
318k
          (*p)[0] = PtCr_byte;
129
318k
          (*p)[1] = (byte)n;
130
318k
          *p += 2;
131
318k
       }
132
638k
       return 2;
133
638k
   } else {
134
51.4k
       if (*p) {
135
25.6k
          **p = PtCr_int;
136
25.6k
          memcpy(*p + 1, &n, sizeof(int));
137
25.6k
          *p += sizeof(int) + 1;
138
25.6k
       }
139
51.4k
       return (sizeof(int) + 1);
140
51.4k
   }
141
689k
}
142
143
/* Store a float in the  buffer */
144
static int
145
142k
put_float(byte **p, float n) {
146
142k
   if (*p) {
147
70.9k
      **p = PtCr_float;
148
70.9k
      memcpy(*p + 1, &n, sizeof(float));
149
70.9k
      *p += sizeof(float) + 1;
150
70.9k
   }
151
142k
   return (sizeof(float) + 1);
152
142k
}
153
154
static int
155
pdfi_parse_type4_func_stream(pdf_context *ctx, pdf_c_stream *function_stream, int depth, byte *ops, unsigned int *size)
156
240k
{
157
240k
    int code;
158
240k
    int c;
159
240k
    char TokenBuffer[TOKENBUFFERSIZE];
160
240k
    unsigned int Size, IsReal;
161
240k
    byte *clause = NULL;
162
240k
    byte *p = (ops ? ops + *size : NULL);
163
164
7.34M
    while (1) {
165
7.34M
        if (*size > max_uint / 2)
166
0
            return gs_note_error(gs_error_VMerror);
167
168
7.34M
        c = pdfi_read_byte(ctx, function_stream);
169
7.34M
        if (c < 0)
170
116
            break;
171
7.34M
        switch(c) {
172
29
            case '%':
173
1.54k
                do {
174
1.54k
                    c = pdfi_read_byte(ctx, function_stream);
175
1.54k
                    if (c < 0)
176
12
                        break;
177
1.53k
                    if (c == 0x0a || c == 0x0d)
178
17
                        break;
179
1.53k
                }while (1);
180
29
                break;
181
3.83M
            case 0x20:
182
3.86M
            case 0x0a:
183
3.86M
            case 0x0d:
184
3.86M
            case 0x09:
185
3.86M
                continue;
186
240k
            case '{':
187
240k
                if (depth == 0) {
188
89.7k
                    depth++;
189
150k
                } else {
190
                    /* recursion, move on 3 bytes, and parse the sub level */
191
150k
                    if (depth == MAX_PSC_FUNCTION_NESTING)
192
0
                        return_error (gs_error_syntaxerror);
193
150k
                    *size += 3;
194
150k
                    code = pdfi_parse_type4_func_stream(ctx, function_stream, depth + 1, ops, size);
195
150k
                    if (code < 0)
196
139
                        return code;
197
150k
                    if (p) {
198
75.3k
                        if (clause == NULL) {
199
37.9k
                            clause = p;
200
37.9k
                            *p = (byte)PtCr_if;
201
37.9k
                            if ((code = psc_fixup(p, ops + *size)) < 0)
202
0
                                return code;
203
37.9k
                        } else {
204
37.3k
                            *p = (byte)PtCr_else;
205
37.3k
                            if ((code = psc_fixup(p, ops + *size)) < 0 ||
206
37.3k
                                (code = psc_fixup_ifelse(clause + 1) < 0))
207
0
                                return code;
208
37.3k
                            clause = NULL;
209
37.3k
                        }
210
75.3k
                        p = ops + *size;
211
75.3k
                    }
212
150k
                }
213
240k
                break;
214
240k
            case '}':
215
240k
                return *size;
216
0
                break;
217
3.00M
            default:
218
3.00M
                if (clause != NULL)
219
599
                    clause = NULL;
220
3.00M
                if ((c >= '0' && c <= '9') || c == '-' || c == '.') {
221
                    /* parse a number */
222
832k
                    Size = 1;
223
832k
                    if (c == '.')
224
223
                        IsReal = 1;
225
832k
                    else
226
832k
                        IsReal = 0;
227
832k
                    TokenBuffer[0] = (byte)c;
228
1.50M
                    while (1) {
229
1.50M
                        c = pdfi_read_byte(ctx, function_stream);
230
1.50M
                        if (c < 0)
231
0
                            return_error(gs_error_syntaxerror);
232
233
1.50M
                        if (c == '.'){
234
142k
                            if (IsReal == 1)
235
21
                                return_error(gs_error_syntaxerror);
236
142k
                            else {
237
142k
                                TokenBuffer[Size++] = (byte)c;
238
142k
                                IsReal = 1;
239
142k
                            }
240
1.36M
                        } else {
241
1.36M
                            if (c >= '0' && c <= '9') {
242
530k
                                TokenBuffer[Size++] = (byte)c;
243
530k
                            } else
244
832k
                                break;
245
1.36M
                        }
246
672k
                        if (Size > NUMBERTOKENSIZE) {
247
161
                            if (IsReal == 1)
248
                                /* Just discard decimal places beyond NUMBERTOKENSIZE .... */
249
161
                                Size--;
250
0
                            else
251
0
                                return_error(gs_error_syntaxerror);
252
161
                        }
253
672k
                    }
254
832k
                    TokenBuffer[Size] = 0x00;
255
832k
                    pdfi_unread_byte(ctx, function_stream, (byte)c);
256
832k
                    if (IsReal == 1) {
257
142k
                        *size += put_float(&p, atof(TokenBuffer));
258
689k
                    } else {
259
689k
                        *size += put_int(&p, atoi(TokenBuffer));
260
689k
                    }
261
2.16M
                } else {
262
2.16M
                    int i, NumOps = sizeof(ops_table) / sizeof(op_struct_t);
263
2.16M
                    op_struct_t *Op;
264
265
                    /* parse an operator */
266
2.16M
                    Size = 1;
267
2.16M
                    TokenBuffer[0] = (byte)c;
268
7.27M
                    while (1) {
269
7.27M
                        c = pdfi_read_byte(ctx, function_stream);
270
7.27M
                        if (c < 0)
271
61
                            return_error(gs_error_syntaxerror);
272
7.27M
                        if (c == 0x20 || c == 0x09 || c == 0x0a || c == 0x0d || c == '{' || c == '}')
273
2.16M
                            break;
274
5.10M
                        TokenBuffer[Size++] = (byte)c;
275
5.10M
                        if (Size > OPTOKENSIZE)
276
80
                            return_error(gs_error_syntaxerror);
277
5.10M
                    }
278
2.16M
                    TokenBuffer[Size] = 0x00;
279
2.16M
                    pdfi_unread_byte(ctx, function_stream, (byte)c);
280
47.6M
                    for (i=0;i < NumOps;i++) {
281
47.6M
                        Op = (op_struct_t *)&ops_table[i];
282
47.6M
                        if (Op->length < Size)
283
32.0M
                            continue;
284
285
15.5M
                        if (Op->length > Size)
286
182
                            return_error(gs_error_undefined);
287
288
15.5M
                        if (memcmp(Op->op, TokenBuffer, Size) == 0)
289
2.16M
                            break;
290
15.5M
                    }
291
2.16M
                    if (i > NumOps)
292
0
                        return_error(gs_error_syntaxerror);
293
2.16M
                    if (p == NULL)
294
1.08M
                        (*size)++;
295
1.08M
                    else {
296
1.08M
                        if (Op->code != PtCr_else && Op->code != PtCr_if) {
297
1.04M
                            (*size)++;
298
1.04M
                            *p++ = Op->code;
299
1.04M
                        }
300
1.08M
                    }
301
2.16M
                }
302
3.00M
                break;
303
7.34M
        }
304
7.34M
    }
305
306
116
    return 0;
307
240k
}
308
309
static int
310
pdfi_build_function_4(pdf_context *ctx, gs_function_params_t * mnDR,
311
                    pdf_stream *function_obj, int depth, gs_function_t ** ppfn)
312
7.79k
{
313
7.79k
    gs_function_PtCr_params_t params;
314
7.79k
    pdf_c_stream *function_stream = NULL;
315
7.79k
    int code;
316
7.79k
    byte *data_source_buffer;
317
7.79k
    byte *ops = NULL;
318
7.79k
    unsigned int size;
319
320
7.79k
    memset(&params, 0x00, sizeof(gs_function_PtCr_params_t));
321
7.79k
    *(gs_function_params_t *)&params = *mnDR;
322
7.79k
    params.ops.data = 0;  /* in case of failure */
323
7.79k
    params.ops.size = 0;  /* ditto */
324
325
7.79k
    if (pdfi_type_of(function_obj) != PDF_STREAM)
326
32
        return_error(gs_error_undefined);
327
328
7.76k
    code = pdfi_open_memory_stream_from_filtered_stream(ctx, function_obj, &data_source_buffer, &function_stream, false);
329
7.76k
    if (code < 0)
330
26
        goto function_4_error;
331
332
7.73k
    size = 0;
333
7.73k
    code = pdfi_parse_type4_func_stream(ctx, function_stream, 0, NULL, &size);
334
7.73k
    if (code < 0)
335
344
        goto function_4_error;
336
337
7.39k
    if (size > max_uint - 1) {
338
0
        code = gs_note_error(gs_error_VMerror);
339
0
        goto function_4_error;
340
0
    }
341
342
7.39k
    ops = gs_alloc_string(ctx->memory, size + 1, "pdfi_build_function_4(ops)");
343
7.39k
    if (ops == NULL) {
344
0
        code = gs_error_VMerror;
345
0
        goto function_4_error;
346
0
    }
347
348
7.39k
    code = pdfi_seek(ctx, function_stream, 0, SEEK_SET);
349
7.39k
    if (code < 0)
350
0
        goto function_4_error;
351
352
7.39k
    size = 0;
353
7.39k
    code = pdfi_parse_type4_func_stream(ctx, function_stream, 0, ops, &size);
354
7.39k
    if (code < 0)
355
0
        goto function_4_error;
356
7.39k
    ops[size] = PtCr_return;
357
358
7.39k
    code = pdfi_close_memory_stream(ctx, data_source_buffer, function_stream);
359
7.39k
    function_stream = NULL;
360
7.39k
    if (code < 0)
361
0
        goto function_4_error;
362
363
7.39k
    params.ops.data = (const byte *)ops;
364
    /* ops will now be freed with the function params, NULL ops now to avoid double free on error */
365
7.39k
    ops = NULL;
366
7.39k
    params.ops.size = size + 1;
367
7.39k
    code = gs_function_PtCr_init(ppfn, &params, ctx->memory);
368
7.39k
    if (code < 0)
369
28
        goto function_4_error;
370
371
7.36k
    return 0;
372
373
398
function_4_error:
374
398
    if (function_stream)
375
344
        (void)pdfi_close_memory_stream(ctx, data_source_buffer, function_stream);
376
377
398
    gs_function_PtCr_free_params(&params, ctx->memory);
378
398
    if (ops)
379
0
        gs_free_const_string(ctx->memory, ops, size, "pdfi_build_function_4(ops)");
380
398
    mnDR->Range = NULL;
381
398
    mnDR->Domain = NULL;
382
398
    return code;
383
7.39k
}
384
385
static int
386
pdfi_build_function_0(pdf_context *ctx, gs_function_params_t * mnDR,
387
                    pdf_stream *function_obj, int depth, gs_function_t ** ppfn)
388
22.2k
{
389
22.2k
    gs_function_Sd_params_t params;
390
22.2k
    pdf_c_stream *function_stream = NULL;
391
22.2k
    int code = 0;
392
22.2k
    int64_t Length, temp;
393
22.2k
    byte *data_source_buffer;
394
22.2k
    pdf_dict *function_dict = NULL;
395
396
22.2k
    memset(&params, 0x00, sizeof(gs_function_params_t));
397
22.2k
    *(gs_function_params_t *) & params = *mnDR;
398
22.2k
    params.Encode = params.Decode = NULL;
399
22.2k
    params.pole = NULL;
400
22.2k
    params.Size = params.array_step = params.stream_step = NULL;
401
22.2k
    params.Order = 0;
402
403
22.2k
    if (pdfi_type_of(function_obj) != PDF_STREAM)
404
12
        return_error(gs_error_undefined);
405
406
22.2k
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)function_obj, &function_dict);
407
22.2k
    if (code < 0)
408
0
        return code;
409
410
22.2k
    Length = pdfi_open_memory_stream_from_filtered_stream(ctx, function_obj, &data_source_buffer, &function_stream, false);
411
22.2k
    if (Length < 0) {
412
87
        return Length;
413
87
    }
414
415
22.1k
    data_source_init_stream(&params.DataSource, function_stream->s);
416
417
    /* We need to clear up the PDF stream, but leave the underlying stream alone, that's now
418
     * pointed to by the params.DataSource member.
419
     */
420
22.1k
    gs_free_object(ctx->memory, function_stream, "discard memory stream(pdf_stream)");
421
422
22.1k
    code = pdfi_dict_get_int(ctx, function_dict, "Order", &temp);
423
22.1k
    if (code < 0 &&  code != gs_error_undefined)
424
0
        goto function_0_error;
425
22.1k
    if (code == gs_error_undefined)
426
20.3k
        params.Order = 1;
427
1.81k
    else
428
1.81k
        params.Order = (int)temp;
429
430
22.1k
    code = pdfi_dict_get_int(ctx, function_dict, "BitsPerSample", &temp);
431
22.1k
    if (code < 0)
432
206
        goto function_0_error;
433
21.9k
    params.BitsPerSample = temp;
434
435
21.9k
    code = pdfi_make_float_array_from_dict(ctx, (float **)&params.Encode, function_dict, "Encode");
436
21.9k
    if (code < 0) {
437
8.86k
        if (code == gs_error_undefined)
438
8.86k
            code = 2 * params.m;
439
4
        else
440
4
            goto function_0_error;
441
8.86k
    }
442
21.9k
    if (code != 2 * params.m) {
443
0
        code = gs_error_rangecheck;
444
0
        goto function_0_error;
445
0
    }
446
447
21.9k
    code = pdfi_make_float_array_from_dict(ctx, (float **)&params.Decode, function_dict, "Decode");
448
21.9k
    if (code < 0) {
449
8.90k
        if (code == gs_error_undefined)
450
8.85k
            code = 2 * params.n;
451
49
        else
452
49
            goto function_0_error;
453
8.90k
    }
454
21.8k
    if (code != 2 * params.n) {
455
15
        code = gs_error_rangecheck;
456
15
        goto function_0_error;
457
15
    }
458
459
21.8k
    code = pdfi_make_int_array_from_dict(ctx, (int **)&params.Size, function_dict, "Size");
460
21.8k
    if (code != params.m) {
461
123
        if (code >= 0)
462
29
            code = gs_error_rangecheck;
463
123
        goto function_0_error;
464
123
    }
465
    /* check the stream has enough data */
466
21.7k
    {
467
21.7k
        unsigned int i;
468
21.7k
        uint64_t inputs = 1, samples = 0;
469
470
44.4k
        for (i=0;i<params.m;i++) {
471
22.6k
            inputs *= params.Size[i];
472
22.6k
        }
473
21.7k
        samples = params.n * (uint64_t)params.BitsPerSample;
474
21.7k
        samples *= inputs;
475
21.7k
        samples = samples >> 3;
476
21.7k
        if (samples > Length) {
477
285
            code = gs_error_rangecheck;
478
285
            goto function_0_error;
479
285
        }
480
21.7k
    }
481
482
21.4k
    code = gs_function_Sd_init(ppfn, &params, ctx->memory);
483
21.4k
    if (code < 0)
484
239
        goto function_0_error;
485
21.2k
    return 0;
486
487
921
function_0_error:
488
921
    s_close_filters(&params.DataSource.data.strm, params.DataSource.data.strm->strm);
489
921
    params.DataSource.data.strm = NULL;
490
921
    gs_function_Sd_free_params(&params, ctx->memory);
491
    /* These are freed by gs_function_Sd_free_params, since we copied
492
     * the poitners, we must NULL the originals, so that we don't double free.
493
     */
494
921
    mnDR->Range = NULL;
495
921
    mnDR->Domain = NULL;
496
921
    return code;
497
21.4k
}
498
499
static int
500
pdfi_build_function_2(pdf_context *ctx, gs_function_params_t * mnDR,
501
                    pdf_dict *function_dict, int depth, gs_function_t ** ppfn)
502
40.1k
{
503
40.1k
    gs_function_ElIn_params_t params;
504
40.1k
    int code, n0, n1;
505
40.1k
    double temp = 0.0;
506
507
40.1k
    memset(&params, 0x00, sizeof(gs_function_params_t));
508
40.1k
    *(gs_function_params_t *)&params = *mnDR;
509
40.1k
    params.C0 = 0;
510
40.1k
    params.C1 = 0;
511
512
40.1k
    code = pdfi_dict_get_number(ctx, function_dict, "N", &temp);
513
40.1k
    if (code < 0 &&  code != gs_error_undefined)
514
0
        return code;
515
40.1k
    params.N = (float)temp;
516
517
40.1k
    code = pdfi_make_float_array_from_dict(ctx, (float **)&params.C0, function_dict, "C0");
518
40.1k
    if (code < 0 && code != gs_error_undefined)
519
42
        return code;
520
40.0k
    n0 = code;
521
522
40.0k
    code = pdfi_make_float_array_from_dict(ctx, (float **)&params.C1, function_dict, "C1");
523
40.0k
    if (code < 0 && code != gs_error_undefined)
524
12
        goto function_2_error;
525
526
40.0k
    n1 = code;
527
40.0k
    if (params.C0 == NULL)
528
17
        n0 = 1;
529
40.0k
    if (params.C1 == NULL)
530
47
        n1 = 1;
531
40.0k
    if (params.Range == 0)
532
31.4k
        params.n = n0;   /* either one will do */
533
40.0k
    if (n0 != n1 || n0 != params.n) {
534
180
        code = gs_note_error(gs_error_rangecheck);
535
180
        goto function_2_error;
536
180
    }
537
538
39.8k
    code = gs_function_ElIn_init(ppfn, &params, ctx->memory);
539
39.8k
    if (code < 0)
540
320
        goto function_2_error;
541
542
39.5k
    return 0;
543
544
512
function_2_error:
545
512
    gs_function_ElIn_free_params(&params, ctx->memory);
546
512
    mnDR->Range = NULL;
547
512
    mnDR->Domain = NULL;
548
512
    return code;
549
39.8k
}
550
551
static int
552
pdfi_build_function_3(pdf_context *ctx, gs_function_params_t * mnDR,
553
                    pdf_dict *function_dict, const float *shading_domain, int num_inputs, pdf_dict *page_dict, int depth, gs_function_t ** ppfn)
554
8.67k
{
555
8.67k
    gs_function_1ItSg_params_t params;
556
8.67k
    int code, i;
557
8.67k
    pdf_array *Functions = NULL;
558
8.67k
    gs_function_t **ptr = NULL;
559
560
8.67k
    memset(&params, 0x00, sizeof(gs_function_params_t));
561
8.67k
    *(gs_function_params_t *) &params = *mnDR;
562
8.67k
    params.Functions = 0;
563
8.67k
    params.Bounds = 0;
564
8.67k
    params.Encode = 0;
565
566
8.67k
    code = pdfi_dict_get_type(ctx, function_dict, "Functions", PDF_ARRAY, (pdf_obj **)&Functions);
567
8.67k
    if (code < 0)
568
7
        return code;
569
570
8.67k
    params.k = pdfi_array_size(Functions);
571
8.67k
    code = alloc_function_array(params.k, &ptr, ctx->memory);
572
8.67k
    if (code < 0)
573
10
        goto function_3_error;
574
575
8.66k
    params.Functions = (const gs_function_t * const *)ptr;
576
577
8.66k
    code = pdfi_make_float_array_from_dict(ctx, (float **)&params.Bounds, function_dict, "Bounds");
578
8.66k
    if (code < 0)
579
15
        goto function_3_error;
580
581
8.64k
    if (code != params.k - 1) {
582
12
        code = gs_note_error(gs_error_rangecheck);
583
12
        goto function_3_error;
584
12
    }
585
586
8.63k
    code = pdfi_make_float_array_from_dict(ctx, (float **)&params.Encode, function_dict, "Encode");
587
8.63k
    if (code < 0)
588
48
        goto function_3_error;
589
590
8.58k
    if (code != 2 * params.k) {
591
0
        code = gs_note_error(gs_error_rangecheck);
592
0
        goto function_3_error;
593
0
    }
594
8.58k
    code = 0;
595
596
34.6k
    for (i = 0; i < params.k; ++i) {
597
27.3k
        pdf_obj * rsubfn = NULL;
598
599
        /* This is basically hacky. The test file /tests_private/pdf/pdf_1.7_ATS/WWTW61EC_file.pdf
600
         * has a number of shadings on page 2. Although there are numerous shadings, they each use one
601
         * of four functions. However, these functions are themselves type 3 functions with 255
602
         * sub-functions. Because our cache only has 200 entries (at this moment), this overfills
603
         * the cache, ejecting all the cached objects (and then some). Which means that we throw
604
         * out any previous shadings or functions, meaning that on every use we have to reread them. This is,
605
         * obviously, slow. So in the hope that reuse of *sub_functions* is unlikely, we choose to
606
         * read the subfunction without caching. This means the main shadings, and the functions,
607
         * remain cached so we can reuse them saving an enormous amount of time. If we ever find a file
608
         * which significantly reuses sub-functions we may need to revisit this.
609
         */
610
27.3k
        code = pdfi_array_get_nocache(ctx, (pdf_array *)Functions, (int64_t)i, &rsubfn);
611
27.3k
        if (code < 0)
612
1.03k
            goto function_3_error;
613
614
26.2k
        code = pdfi_build_sub_function(ctx, &ptr[i], &params.Encode[i * 2], num_inputs, rsubfn, page_dict);
615
26.2k
        pdfi_countdown(rsubfn);
616
26.2k
        if (code < 0)
617
157
            goto function_3_error;
618
26.2k
    }
619
620
7.39k
    if (params.Range == 0)
621
7.36k
        params.n = params.Functions[0]->params.n;
622
623
7.39k
    code = gs_function_1ItSg_init(ppfn, &params, ctx->memory);
624
7.39k
    if (code < 0)
625
5
        goto function_3_error;
626
627
7.38k
    pdfi_countdown(Functions);
628
7.38k
    return 0;
629
630
1.28k
function_3_error:
631
1.28k
    pdfi_countdown(Functions);
632
1.28k
    gs_function_1ItSg_free_params(&params, ctx->memory);
633
1.28k
    mnDR->Range = NULL;
634
1.28k
    mnDR->Domain = NULL;
635
1.28k
    return code;
636
7.39k
}
637
638
static int pdfi_build_sub_function(pdf_context *ctx, gs_function_t ** ppfn, const float *shading_domain, int num_inputs, pdf_obj *stream_obj, pdf_dict *page_dict)
639
80.1k
{
640
80.1k
    int code, i;
641
80.1k
    int64_t Type;
642
80.1k
    gs_function_params_t params;
643
80.1k
    pdf_dict *stream_dict;
644
80.1k
    int obj_num;
645
646
80.1k
    params.Range = params.Domain = NULL;
647
648
80.1k
    code = pdfi_loop_detector_mark(ctx);
649
80.1k
    if (code < 0)
650
0
        return code;
651
652
80.1k
    obj_num = pdf_object_num(stream_obj);
653
80.1k
    if (obj_num != 0) {
654
69.7k
        if (pdfi_loop_detector_check_object(ctx, obj_num))
655
0
            return gs_note_error(gs_error_circular_reference);
656
69.7k
        code = pdfi_loop_detector_add_object(ctx, obj_num);
657
69.7k
        if (code < 0)
658
0
            goto sub_function_error;
659
69.7k
    }
660
661
80.1k
    code = pdfi_dict_from_obj(ctx, stream_obj, &stream_dict);
662
80.1k
    if (code < 0)
663
103
        goto sub_function_error;
664
665
80.0k
    code = pdfi_dict_get_int(ctx, stream_dict, "FunctionType", &Type);
666
80.0k
    if (code < 0)
667
847
        goto sub_function_error;
668
669
79.1k
    if (Type < 0 || Type > 4 || Type == 1) {
670
20
        code = gs_note_error(gs_error_rangecheck);
671
20
        goto sub_function_error;
672
20
    }
673
674
79.1k
    memset(&params, 0x00, sizeof(gs_function_params_t));
675
676
    /* First gather all the entries common to all functions */
677
79.1k
    code = pdfi_make_float_array_from_dict(ctx, (float **)&params.Domain, stream_dict, "Domain");
678
79.1k
    if (code < 0)
679
235
        goto sub_function_error;
680
681
78.9k
    if (code & 1) {
682
17
        code = gs_error_rangecheck;
683
17
        goto sub_function_error;
684
17
    }
685
686
160k
    for (i=0;i<code;i+=2) {
687
81.8k
        if (params.Domain[i] > params.Domain[i+1]) {
688
16
            code = gs_error_rangecheck;
689
16
            goto sub_function_error;
690
16
        }
691
81.8k
    }
692
78.8k
    if (shading_domain) {
693
43.7k
        if (num_inputs != code >> 1) {
694
14
            code = gs_error_rangecheck;
695
14
            goto sub_function_error;
696
14
        }
697
698
87.3k
        for (i=0;i<2*num_inputs;i+=2) {
699
43.6k
            if (params.Domain[i] > shading_domain[i] || params.Domain[i+1] < shading_domain[i+1]) {
700
25
                code = gs_error_rangecheck;
701
25
                goto sub_function_error;
702
25
            }
703
43.6k
        }
704
43.6k
    }
705
706
78.8k
    params.m = code >> 1;
707
708
78.8k
    code = pdfi_make_float_array_from_dict(ctx, (float **)&params.Range, stream_dict, "Range");
709
78.8k
    if (code < 0 && code != gs_error_undefined)
710
27
        goto sub_function_error;
711
78.8k
    else {
712
78.8k
        if (code > 0)
713
38.7k
            params.n = code >> 1;
714
40.1k
        else
715
40.1k
            params.n = 0;
716
78.8k
    }
717
78.8k
    if (params.n > GS_CLIENT_COLOR_MAX_COMPONENTS) {
718
0
        code = gs_note_error(gs_error_limitcheck);
719
0
        goto sub_function_error;
720
0
    }
721
78.8k
    switch(Type) {
722
22.2k
        case 0:
723
22.2k
            code = pdfi_build_function_0(ctx, &params, (pdf_stream *)stream_obj, 0, ppfn);
724
22.2k
            if (code < 0)
725
1.02k
                goto sub_function_error;
726
21.2k
            break;
727
40.1k
        case 2:
728
40.1k
            code = pdfi_build_function_2(ctx, &params, stream_dict, 0, ppfn);
729
40.1k
            if (code < 0)
730
554
                goto sub_function_error;
731
39.5k
            break;
732
39.5k
        case 3:
733
8.67k
            code = pdfi_build_function_3(ctx, &params, stream_dict, shading_domain,  num_inputs, page_dict, 0, ppfn);
734
8.67k
            if (code < 0)
735
1.29k
                goto sub_function_error;
736
7.38k
            break;
737
7.79k
        case 4:
738
7.79k
            code = pdfi_build_function_4(ctx, &params, (pdf_stream *)stream_obj, 0, ppfn);
739
7.79k
            if (code < 0)
740
430
                goto sub_function_error;
741
7.36k
            break;
742
7.36k
        default:
743
0
            break;
744
78.8k
    }
745
75.5k
    pdfi_loop_detector_cleartomark(ctx);
746
75.5k
    return 0;
747
748
4.60k
sub_function_error:
749
4.60k
    gs_free_const_object(ctx->memory, params.Domain, "pdfi_build_sub_function (Domain) error exit\n");
750
4.60k
    gs_free_const_object(ctx->memory, params.Range, "pdfi_build_sub_function(Range) error exit\n");
751
4.60k
    pdfi_loop_detector_cleartomark(ctx);
752
4.60k
    return code;
753
78.8k
}
754
755
756
static int pdfi_free_function_special(pdf_context *ctx, gs_function_t *pfn);
757
758
#if 0
759
/* For type 0 functions, need to free up the data associated with the stream
760
 * that it was using.  This doesn't get freed in the gs_function_free() code.
761
 */
762
static int pdfi_free_function_0(pdf_context *ctx, gs_function_t *pfn)
763
{
764
    gs_function_Sd_params_t *params = (gs_function_Sd_params_t *)&pfn->params;
765
766
    s_close_filters(&params->DataSource.data.strm, params->DataSource.data.strm->strm);
767
    gs_free_object(ctx->memory, params->DataSource.data.strm, "pdfi_free_function");
768
    return 0;
769
}
770
#endif
771
772
/* For type 3 functions, it has an array of functions that might need special handling.
773
 */
774
static int pdfi_free_function_3(pdf_context *ctx, gs_function_t *pfn)
775
7.37k
{
776
7.37k
    gs_function_1ItSg_params_t *params = (gs_function_1ItSg_params_t *)&pfn->params;
777
7.37k
    int i;
778
779
33.3k
    for (i=0; i<params->k; i++) {
780
25.9k
        pdfi_free_function_special(ctx, (gs_function_t *)params->Functions[i]);
781
25.9k
    }
782
7.37k
    return 0;
783
7.37k
}
784
785
/* Free any special stuff associated with a function */
786
static int pdfi_free_function_special(pdf_context *ctx, gs_function_t *pfn)
787
112k
{
788
112k
    switch(pfn->head.type) {
789
#if 0
790
    /* Before commit 3f2408d5ac786ac1c0a837b600f4ef3be9be0332
791
     * https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=3f2408d5ac786ac1c0a837b600f4ef3be9be0332
792
     * we needed to close the data stream and free the memory. That is now
793
     * performed by the graphics library so we don't need to do this any more.
794
     */
795
    case 0:
796
        pdfi_free_function_0(ctx, pfn);
797
        break;
798
#endif
799
7.37k
    case 3:
800
7.37k
        pdfi_free_function_3(ctx, pfn);
801
7.37k
        break;
802
105k
    default:
803
105k
        break;
804
112k
    }
805
112k
    return 0;
806
112k
}
807
808
int pdfi_free_function(pdf_context *ctx, gs_function_t *pfn)
809
94.2k
{
810
94.2k
    if (pfn == NULL)
811
7.43k
        return 0;
812
813
    /* Free any special stuff for the function */
814
86.7k
    pdfi_free_function_special(ctx, pfn);
815
816
    /* Free the standard stuff handled by the gs library */
817
86.7k
    gs_function_free(pfn, true, ctx->memory);
818
86.7k
    return 0;
819
94.2k
}
820
821
int pdfi_build_function(pdf_context *ctx, gs_function_t ** ppfn, const float *shading_domain, int num_inputs, pdf_obj *stream_obj, pdf_dict *page_dict)
822
53.8k
{
823
53.8k
    return pdfi_build_sub_function(ctx, ppfn, shading_domain, num_inputs, stream_obj, page_dict);
824
53.8k
}
825
826
int pdfi_build_halftone_function(pdf_context *ctx, gs_function_t ** ppfn, byte *Buffer, int64_t Length)
827
37.3k
{
828
37.3k
    gs_function_PtCr_params_t params;
829
37.3k
    pdf_c_stream *function_stream = NULL;
830
37.3k
    int code=0;
831
37.3k
    byte *ops = NULL;
832
37.3k
    unsigned int size;
833
37.3k
    float *pfloat;
834
37.3k
    byte *stream_buffer = NULL;
835
836
37.3k
    memset(&params, 0x00, sizeof(gs_function_PtCr_params_t));
837
37.3k
    params.ops.data = 0;  /* in case of failure */
838
37.3k
    params.ops.size = 0;  /* ditto */
839
840
37.3k
    stream_buffer = gs_alloc_bytes(ctx->memory, Length, "pdfi_build_halftone_function(stream_buffer))");
841
37.3k
    if (stream_buffer == NULL)
842
0
        goto halftone_function_error;
843
844
37.3k
    memcpy(stream_buffer, Buffer, Length);
845
846
37.3k
    code = pdfi_open_memory_stream_from_memory(ctx, Length, stream_buffer, &function_stream, true);
847
37.3k
    if (code < 0)
848
0
        goto halftone_function_error;
849
850
37.3k
    size = 0;
851
37.3k
    code = pdfi_parse_type4_func_stream(ctx, function_stream, 0, NULL, &size);
852
37.3k
    if (code < 0)
853
0
        goto halftone_function_error;
854
855
37.3k
    if (size > max_uint - 1) {
856
0
        code = gs_note_error(gs_error_VMerror);
857
0
        goto halftone_function_error;
858
0
    }
859
860
37.3k
    ops = gs_alloc_string(ctx->memory, size + 1, "pdfi_build_halftone_function(ops)");
861
37.3k
    if (ops == NULL) {
862
0
        code = gs_error_VMerror;
863
0
        goto halftone_function_error;
864
0
    }
865
866
37.3k
    code = pdfi_seek(ctx, function_stream, 0, SEEK_SET);
867
37.3k
    if (code < 0)
868
0
        goto halftone_function_error;
869
870
37.3k
    size = 0;
871
37.3k
    code = pdfi_parse_type4_func_stream(ctx, function_stream, 0, ops, &size);
872
37.3k
    if (code < 0)
873
0
        goto halftone_function_error;
874
37.3k
    ops[size] = PtCr_return;
875
876
37.3k
    code = pdfi_close_memory_stream(ctx, stream_buffer, function_stream);
877
37.3k
    if (code < 0) {
878
0
        function_stream = NULL;
879
0
        goto halftone_function_error;
880
0
    }
881
882
37.3k
    params.ops.data = (const byte *)ops;
883
37.3k
    params.ops.size = size + 1;
884
37.3k
    params.m = 2;
885
37.3k
    params.n = 1;
886
37.3k
    pfloat = (float *)gs_alloc_byte_array(ctx->memory, 4, sizeof(float), "pdfi_build_halftone_function(Domain)");
887
37.3k
    if (pfloat == NULL) {
888
0
        code = gs_error_VMerror;
889
0
        goto halftone_function_error;
890
0
    }
891
37.3k
    pfloat[0] = -1;
892
37.3k
    pfloat[1] = 1;
893
37.3k
    pfloat[2] = -1;
894
37.3k
    pfloat[3] = 1;
895
37.3k
    params.Domain = (const float *)pfloat;
896
37.3k
    pfloat = (float *)gs_alloc_byte_array(ctx->memory, 2, sizeof(float), "pdfi_build_halftone_function(Domain)");
897
37.3k
    if (pfloat == NULL) {
898
0
        code = gs_error_VMerror;
899
0
        goto halftone_function_error;
900
0
    }
901
37.3k
    pfloat[0] = -1;
902
37.3k
    pfloat[1] = 1;
903
37.3k
    params.Range = (const float *)pfloat;
904
905
37.3k
    code = gs_function_PtCr_init(ppfn, &params, ctx->memory);
906
37.3k
    if (code < 0)
907
0
        goto halftone_function_error;
908
909
37.3k
    return 0;
910
911
0
halftone_function_error:
912
0
    if (function_stream)
913
0
        (void)pdfi_close_memory_stream(ctx, stream_buffer, function_stream);
914
915
0
    gs_function_PtCr_free_params(&params, ctx->memory);
916
0
    if (ops)
917
0
        gs_free_const_string(ctx->memory, ops, size, "pdfi_build_function_4(ops)");
918
0
    return code;
919
37.3k
}