Coverage Report

Created: 2026-02-14 07:09

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-2024 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
401k
#define NUMBERTOKENSIZE 16
35
4.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[8];
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 void
98
psc_fixup(byte *p, byte *to)
99
62.0k
{
100
62.0k
    int skip = to - (p + 3);
101
102
62.0k
    p[1] = (byte)(skip >> 8);
103
62.0k
    p[2] = (byte)skip;
104
62.0k
}
105
static void psc_fixup_ifelse(byte *p)
106
30.6k
{
107
30.6k
    int iflen = (p[0] << 8) + p[1];
108
109
30.6k
    iflen += 3;         /* To skip past the 'if' body and the 'else' header */
110
30.6k
    p[0] = (byte)(iflen >> 8);
111
30.6k
    p[1] = (byte)iflen;
112
30.6k
}
113
114
/* Store an int in the  buffer */
115
static int
116
539k
put_int(byte **p, int n) {
117
539k
   if (n == (byte)n) {
118
500k
       if (*p) {
119
249k
          (*p)[0] = PtCr_byte;
120
249k
          (*p)[1] = (byte)n;
121
249k
          *p += 2;
122
249k
       }
123
500k
       return 2;
124
500k
   } else {
125
38.3k
       if (*p) {
126
19.0k
          **p = PtCr_int;
127
19.0k
          memcpy(*p + 1, &n, sizeof(int));
128
19.0k
          *p += sizeof(int) + 1;
129
19.0k
       }
130
38.3k
       return (sizeof(int) + 1);
131
38.3k
   }
132
539k
}
133
134
/* Store a float in the  buffer */
135
static int
136
96.4k
put_float(byte **p, float n) {
137
96.4k
   if (*p) {
138
47.8k
      **p = PtCr_float;
139
47.8k
      memcpy(*p + 1, &n, sizeof(float));
140
47.8k
      *p += sizeof(float) + 1;
141
47.8k
   }
142
96.4k
   return (sizeof(float) + 1);
143
96.4k
}
144
145
static int
146
pdfi_parse_type4_func_stream(pdf_context *ctx, pdf_c_stream *function_stream, int depth, byte *ops, unsigned int *size)
147
198k
{
148
198k
    int code;
149
198k
    int c;
150
198k
    char TokenBuffer[TOKENBUFFERSIZE];
151
198k
    unsigned int Size, IsReal;
152
198k
    byte *clause = NULL;
153
198k
    byte *p = (ops ? ops + *size : NULL);
154
155
5.86M
    while (1) {
156
5.86M
        if (*size > max_uint / 2)
157
0
            return gs_note_error(gs_error_VMerror);
158
159
5.86M
        c = pdfi_read_byte(ctx, function_stream);
160
5.86M
        if (c < 0)
161
168
            break;
162
5.86M
        switch(c) {
163
32
            case '%':
164
1.07k
                do {
165
1.07k
                    c = pdfi_read_byte(ctx, function_stream);
166
1.07k
                    if (c < 0)
167
20
                        break;
168
1.05k
                    if (c == 0x0a || c == 0x0d)
169
12
                        break;
170
1.05k
                }while (1);
171
32
                break;
172
3.06M
            case 0x20:
173
3.08M
            case 0x0a:
174
3.08M
            case 0x0d:
175
3.08M
            case 0x09:
176
3.08M
                continue;
177
198k
            case '{':
178
198k
                if (depth == 0) {
179
73.5k
                    depth++;
180
124k
                } else {
181
                    /* recursion, move on 3 bytes, and parse the sub level */
182
124k
                    if (depth++ == MAX_PSC_FUNCTION_NESTING)
183
0
                        return_error (gs_error_syntaxerror);
184
124k
                    *size += 3;
185
124k
                    code = pdfi_parse_type4_func_stream(ctx, function_stream, depth + 1, ops, size);
186
124k
                    depth --;
187
124k
                    if (code < 0)
188
198
                        return code;
189
124k
                    if (p) {
190
62.0k
                        if (clause == NULL) {
191
31.4k
                            clause = p;
192
31.4k
                            *p = (byte)PtCr_if;
193
31.4k
                            psc_fixup(p, ops + *size);
194
31.4k
                        } else {
195
30.6k
                            *p = (byte)PtCr_else;
196
30.6k
                            psc_fixup(p, ops + *size);
197
30.6k
                            psc_fixup_ifelse(clause + 1);
198
30.6k
                            clause = NULL;
199
30.6k
                        }
200
62.0k
                        p = ops + *size;
201
62.0k
                    }
202
124k
                }
203
197k
                break;
204
197k
            case '}':
205
197k
                return *size;
206
0
                break;
207
2.38M
            default:
208
2.38M
                if (clause != NULL)
209
693
                    clause = NULL;
210
2.38M
                if ((c >= '0' && c <= '9') || c == '-' || c == '.') {
211
                    /* parse a number */
212
635k
                    Size = 1;
213
635k
                    if (c == '.')
214
251
                        IsReal = 1;
215
635k
                    else
216
635k
                        IsReal = 0;
217
635k
                    TokenBuffer[0] = (byte)c;
218
1.03M
                    while (1) {
219
1.03M
                        c = pdfi_read_byte(ctx, function_stream);
220
1.03M
                        if (c < 0)
221
0
                            return_error(gs_error_syntaxerror);
222
223
1.03M
                        if (c == '.'){
224
96.2k
                            if (IsReal == 1)
225
26
                                return_error(gs_error_syntaxerror);
226
96.2k
                            else {
227
96.2k
                                TokenBuffer[Size++] = (byte)c;
228
96.2k
                                IsReal = 1;
229
96.2k
                            }
230
940k
                        } else {
231
940k
                            if (c >= '0' && c <= '9') {
232
305k
                                TokenBuffer[Size++] = (byte)c;
233
305k
                            } else
234
635k
                                break;
235
940k
                        }
236
401k
                        if (Size > NUMBERTOKENSIZE) {
237
232
                            if (IsReal == 1)
238
                                /* Just discard decimal places beyond NUMBERTOKENSIZE .... */
239
232
                                Size--;
240
0
                            else
241
0
                                return_error(gs_error_syntaxerror);
242
232
                        }
243
401k
                    }
244
635k
                    TokenBuffer[Size] = 0x00;
245
635k
                    pdfi_unread_byte(ctx, function_stream, (byte)c);
246
635k
                    if (IsReal == 1) {
247
96.4k
                        *size += put_float(&p, atof(TokenBuffer));
248
539k
                    } else {
249
539k
                        *size += put_int(&p, atoi(TokenBuffer));
250
539k
                    }
251
1.74M
                } else {
252
1.74M
                    int i, NumOps = sizeof(ops_table) / sizeof(op_struct_t);
253
1.74M
                    op_struct_t *Op;
254
255
                    /* parse an operator */
256
1.74M
                    Size = 1;
257
1.74M
                    TokenBuffer[0] = (byte)c;
258
5.85M
                    while (1) {
259
5.85M
                        c = pdfi_read_byte(ctx, function_stream);
260
5.85M
                        if (c < 0)
261
61
                            return_error(gs_error_syntaxerror);
262
5.85M
                        if (c == 0x20 || c == 0x09 || c == 0x0a || c == 0x0d || c == '{' || c == '}')
263
1.74M
                            break;
264
4.10M
                        TokenBuffer[Size++] = (byte)c;
265
4.10M
                        if (Size > OPTOKENSIZE)
266
108
                            return_error(gs_error_syntaxerror);
267
4.10M
                    }
268
1.74M
                    TokenBuffer[Size] = 0x00;
269
1.74M
                    pdfi_unread_byte(ctx, function_stream, (byte)c);
270
38.2M
                    for (i=0;i < NumOps;i++) {
271
38.2M
                        Op = (op_struct_t *)&ops_table[i];
272
38.2M
                        if (Op->length < Size)
273
25.6M
                            continue;
274
275
12.5M
                        if (Op->length > Size)
276
233
                            return_error(gs_error_undefined);
277
278
12.5M
                        if (memcmp(Op->op, TokenBuffer, Size) == 0)
279
1.74M
                            break;
280
12.5M
                    }
281
1.74M
                    if (i > NumOps)
282
0
                        return_error(gs_error_syntaxerror);
283
1.74M
                    if (p == NULL)
284
876k
                        (*size)++;
285
873k
                    else {
286
873k
                        if (Op->code != PtCr_else && Op->code != PtCr_if) {
287
841k
                            (*size)++;
288
841k
                            *p++ = Op->code;
289
841k
                        }
290
873k
                    }
291
1.74M
                }
292
2.38M
                break;
293
5.86M
        }
294
5.86M
    }
295
296
168
    return 0;
297
198k
}
298
299
static int
300
pdfi_build_function_4(pdf_context *ctx, gs_function_params_t * mnDR,
301
                    pdf_stream *function_obj, int depth, gs_function_t ** ppfn)
302
6.43k
{
303
6.43k
    gs_function_PtCr_params_t params;
304
6.43k
    pdf_c_stream *function_stream = NULL;
305
6.43k
    int code;
306
6.43k
    byte *data_source_buffer;
307
6.43k
    byte *ops = NULL;
308
6.43k
    unsigned int size;
309
310
6.43k
    memset(&params, 0x00, sizeof(gs_function_PtCr_params_t));
311
6.43k
    *(gs_function_params_t *)&params = *mnDR;
312
6.43k
    params.ops.data = 0;  /* in case of failure */
313
6.43k
    params.ops.size = 0;  /* ditto */
314
315
6.43k
    if (pdfi_type_of(function_obj) != PDF_STREAM)
316
40
        return_error(gs_error_undefined);
317
318
6.39k
    code = pdfi_open_memory_stream_from_filtered_stream(ctx, function_obj, &data_source_buffer, &function_stream, false);
319
6.39k
    if (code < 0)
320
29
        goto function_4_error;
321
322
6.36k
    size = 0;
323
6.36k
    code = pdfi_parse_type4_func_stream(ctx, function_stream, 0, NULL, &size);
324
6.36k
    if (code < 0)
325
428
        goto function_4_error;
326
327
5.93k
    if (size > max_uint - 1) {
328
0
        code = gs_note_error(gs_error_VMerror);
329
0
        goto function_4_error;
330
0
    }
331
332
5.93k
    ops = gs_alloc_string(ctx->memory, size + 1, "pdfi_build_function_4(ops)");
333
5.93k
    if (ops == NULL) {
334
0
        code = gs_error_VMerror;
335
0
        goto function_4_error;
336
0
    }
337
338
5.93k
    code = pdfi_seek(ctx, function_stream, 0, SEEK_SET);
339
5.93k
    if (code < 0)
340
0
        goto function_4_error;
341
342
5.93k
    size = 0;
343
5.93k
    code = pdfi_parse_type4_func_stream(ctx, function_stream, 0, ops, &size);
344
5.93k
    if (code < 0)
345
0
        goto function_4_error;
346
5.93k
    ops[size] = PtCr_return;
347
348
5.93k
    code = pdfi_close_memory_stream(ctx, data_source_buffer, function_stream);
349
5.93k
    function_stream = NULL;
350
5.93k
    if (code < 0)
351
0
        goto function_4_error;
352
353
5.93k
    params.ops.data = (const byte *)ops;
354
    /* ops will now be freed with the function params, NULL ops now to avoid double free on error */
355
5.93k
    ops = NULL;
356
5.93k
    params.ops.size = size + 1;
357
5.93k
    code = gs_function_PtCr_init(ppfn, &params, ctx->memory);
358
5.93k
    if (code < 0)
359
46
        goto function_4_error;
360
361
5.89k
    return 0;
362
363
503
function_4_error:
364
503
    if (function_stream)
365
428
        (void)pdfi_close_memory_stream(ctx, data_source_buffer, function_stream);
366
367
503
    gs_function_PtCr_free_params(&params, ctx->memory);
368
503
    if (ops)
369
0
        gs_free_const_string(ctx->memory, ops, size, "pdfi_build_function_4(ops)");
370
503
    mnDR->Range = NULL;
371
503
    mnDR->Domain = NULL;
372
503
    return code;
373
5.93k
}
374
375
static int
376
pdfi_build_function_0(pdf_context *ctx, gs_function_params_t * mnDR,
377
                    pdf_stream *function_obj, int depth, gs_function_t ** ppfn)
378
21.9k
{
379
21.9k
    gs_function_Sd_params_t params;
380
21.9k
    pdf_c_stream *function_stream = NULL;
381
21.9k
    int code = 0;
382
21.9k
    int64_t Length, temp;
383
21.9k
    byte *data_source_buffer;
384
21.9k
    pdf_dict *function_dict = NULL;
385
386
21.9k
    memset(&params, 0x00, sizeof(gs_function_params_t));
387
21.9k
    *(gs_function_params_t *) & params = *mnDR;
388
21.9k
    params.Encode = params.Decode = NULL;
389
21.9k
    params.pole = NULL;
390
21.9k
    params.Size = params.array_step = params.stream_step = NULL;
391
21.9k
    params.Order = 0;
392
393
21.9k
    if (pdfi_type_of(function_obj) != PDF_STREAM)
394
13
        return_error(gs_error_undefined);
395
396
21.9k
    code = pdfi_dict_from_obj(ctx, (pdf_obj *)function_obj, &function_dict);
397
21.9k
    if (code < 0)
398
0
        return code;
399
400
21.9k
    Length = pdfi_open_memory_stream_from_filtered_stream(ctx, function_obj, &data_source_buffer, &function_stream, false);
401
21.9k
    if (Length < 0) {
402
135
        return Length;
403
135
    }
404
405
21.8k
    data_source_init_stream(&params.DataSource, function_stream->s);
406
407
    /* We need to clear up the PDF stream, but leave the underlying stream alone, that's now
408
     * pointed to by the params.DataSource member.
409
     */
410
21.8k
    gs_free_object(ctx->memory, function_stream, "discard memory stream(pdf_stream)");
411
412
21.8k
    code = pdfi_dict_get_int(ctx, function_dict, "Order", &temp);
413
21.8k
    if (code < 0 &&  code != gs_error_undefined)
414
0
        goto function_0_error;
415
21.8k
    if (code == gs_error_undefined)
416
20.7k
        params.Order = 1;
417
1.12k
    else
418
1.12k
        params.Order = (int)temp;
419
420
21.8k
    code = pdfi_dict_get_int(ctx, function_dict, "BitsPerSample", &temp);
421
21.8k
    if (code < 0)
422
221
        goto function_0_error;
423
21.6k
    params.BitsPerSample = temp;
424
425
21.6k
    code = pdfi_make_float_array_from_dict(ctx, (float **)&params.Encode, function_dict, "Encode");
426
21.6k
    if (code < 0) {
427
9.42k
        if (code == gs_error_undefined)
428
9.41k
            code = 2 * params.m;
429
4
        else
430
4
            goto function_0_error;
431
9.42k
    }
432
21.6k
    if (code != 2 * params.m) {
433
0
        code = gs_error_rangecheck;
434
0
        goto function_0_error;
435
0
    }
436
437
21.6k
    code = pdfi_make_float_array_from_dict(ctx, (float **)&params.Decode, function_dict, "Decode");
438
21.6k
    if (code < 0) {
439
9.46k
        if (code == gs_error_undefined)
440
9.41k
            code = 2 * params.n;
441
56
        else
442
56
            goto function_0_error;
443
9.46k
    }
444
21.5k
    if (code != 2 * params.n) {
445
21
        code = gs_error_rangecheck;
446
21
        goto function_0_error;
447
21
    }
448
449
21.5k
    code = pdfi_make_int_array_from_dict(ctx, (int **)&params.Size, function_dict, "Size");
450
21.5k
    if (code != params.m) {
451
154
        if (code >= 0)
452
38
            code = gs_error_rangecheck;
453
154
        goto function_0_error;
454
154
    }
455
    /* check the stream has enough data */
456
21.3k
    {
457
21.3k
        unsigned int i;
458
21.3k
        uint64_t inputs = 1, samples = 0;
459
460
43.9k
        for (i=0;i<params.m;i++) {
461
22.5k
            inputs *= params.Size[i];
462
22.5k
        }
463
21.3k
        samples = params.n * (uint64_t)params.BitsPerSample;
464
21.3k
        samples *= inputs;
465
21.3k
        samples = samples >> 3;
466
21.3k
        if (samples > Length) {
467
1.57k
            code = gs_error_rangecheck;
468
1.57k
            goto function_0_error;
469
1.57k
        }
470
21.3k
    }
471
472
19.8k
    code = gs_function_Sd_init(ppfn, &params, ctx->memory);
473
19.8k
    if (code < 0)
474
251
        goto function_0_error;
475
19.5k
    return 0;
476
477
2.28k
function_0_error:
478
2.28k
    s_close_filters(&params.DataSource.data.strm, params.DataSource.data.strm->strm);
479
2.28k
    params.DataSource.data.strm = NULL;
480
2.28k
    gs_function_Sd_free_params(&params, ctx->memory);
481
    /* These are freed by gs_function_Sd_free_params, since we copied
482
     * the poitners, we must NULL the originals, so that we don't double free.
483
     */
484
2.28k
    mnDR->Range = NULL;
485
2.28k
    mnDR->Domain = NULL;
486
2.28k
    return code;
487
19.8k
}
488
489
static int
490
pdfi_build_function_2(pdf_context *ctx, gs_function_params_t * mnDR,
491
                    pdf_dict *function_dict, int depth, gs_function_t ** ppfn)
492
27.0k
{
493
27.0k
    gs_function_ElIn_params_t params;
494
27.0k
    int code, n0, n1;
495
27.0k
    double temp = 0.0;
496
497
27.0k
    memset(&params, 0x00, sizeof(gs_function_params_t));
498
27.0k
    *(gs_function_params_t *)&params = *mnDR;
499
27.0k
    params.C0 = 0;
500
27.0k
    params.C1 = 0;
501
502
27.0k
    code = pdfi_dict_get_number(ctx, function_dict, "N", &temp);
503
27.0k
    if (code < 0 &&  code != gs_error_undefined)
504
0
        return code;
505
27.0k
    params.N = (float)temp;
506
507
27.0k
    code = pdfi_make_float_array_from_dict(ctx, (float **)&params.C0, function_dict, "C0");
508
27.0k
    if (code < 0 && code != gs_error_undefined)
509
64
        return code;
510
26.9k
    n0 = code;
511
512
26.9k
    code = pdfi_make_float_array_from_dict(ctx, (float **)&params.C1, function_dict, "C1");
513
26.9k
    if (code < 0 && code != gs_error_undefined)
514
41
        goto function_2_error;
515
516
26.9k
    n1 = code;
517
26.9k
    if (params.C0 == NULL)
518
25
        n0 = 1;
519
26.9k
    if (params.C1 == NULL)
520
55
        n1 = 1;
521
26.9k
    if (params.Range == 0)
522
18.6k
        params.n = n0;   /* either one will do */
523
26.9k
    if (n0 != n1 || n0 != params.n) {
524
206
        code = gs_note_error(gs_error_rangecheck);
525
206
        goto function_2_error;
526
206
    }
527
528
26.7k
    code = gs_function_ElIn_init(ppfn, &params, ctx->memory);
529
26.7k
    if (code < 0)
530
242
        goto function_2_error;
531
532
26.4k
    return 0;
533
534
489
function_2_error:
535
489
    gs_function_ElIn_free_params(&params, ctx->memory);
536
489
    mnDR->Range = NULL;
537
489
    mnDR->Domain = NULL;
538
489
    return code;
539
26.7k
}
540
541
static int
542
pdfi_build_function_3(pdf_context *ctx, gs_function_params_t * mnDR,
543
                    pdf_dict *function_dict, const float *shading_domain, int num_inputs, pdf_dict *page_dict, int depth, gs_function_t ** ppfn)
544
5.79k
{
545
5.79k
    gs_function_1ItSg_params_t params;
546
5.79k
    int code, i;
547
5.79k
    pdf_array *Functions = NULL;
548
5.79k
    gs_function_t **ptr = NULL;
549
550
5.79k
    memset(&params, 0x00, sizeof(gs_function_params_t));
551
5.79k
    *(gs_function_params_t *) &params = *mnDR;
552
5.79k
    params.Functions = 0;
553
5.79k
    params.Bounds = 0;
554
5.79k
    params.Encode = 0;
555
556
5.79k
    code = pdfi_dict_get_type(ctx, function_dict, "Functions", PDF_ARRAY, (pdf_obj **)&Functions);
557
5.79k
    if (code < 0)
558
16
        return code;
559
560
5.77k
    params.k = pdfi_array_size(Functions);
561
5.77k
    code = alloc_function_array(params.k, &ptr, ctx->memory);
562
5.77k
    if (code < 0)
563
11
        goto function_3_error;
564
565
5.76k
    params.Functions = (const gs_function_t * const *)ptr;
566
567
5.76k
    code = pdfi_make_float_array_from_dict(ctx, (float **)&params.Bounds, function_dict, "Bounds");
568
5.76k
    if (code < 0)
569
20
        goto function_3_error;
570
571
5.74k
    code = pdfi_make_float_array_from_dict(ctx, (float **)&params.Encode, function_dict, "Encode");
572
5.74k
    if (code < 0)
573
51
        goto function_3_error;
574
575
5.69k
    if (code != 2 * params.k) {
576
14
        code = gs_note_error(gs_error_rangecheck);
577
14
        goto function_3_error;
578
14
    }
579
5.67k
    code = 0;
580
581
19.6k
    for (i = 0; i < params.k; ++i) {
582
15.1k
        pdf_obj * rsubfn = NULL;
583
584
        /* This is basically hacky. The test file /tests_private/pdf/pdf_1.7_ATS/WWTW61EC_file.pdf
585
         * has a number of shadings on page 2. Although there are numerous shadings, they each use one
586
         * of four functions. However, these functions are themselves type 3 functions with 255
587
         * sub-functions. Because our cache only has 200 entries (at this moment), this overfills
588
         * the cache, ejecting all the cached objects (and then some). Which means that we throw
589
         * out any previous shadings or functions, meaning that on every use we have to reread them. This is,
590
         * obviously, slow. So in the hope that reuse of *sub_functions* is unlikely, we choose to
591
         * read the subfunction without caching. This means the main shadings, and the functions,
592
         * remain cached so we can reuse them saving an enormous amount of time. If we ever find a file
593
         * which significantly reuses sub-functions we may need to revisit this.
594
         */
595
15.1k
        code = pdfi_array_get_nocache(ctx, (pdf_array *)Functions, (int64_t)i, &rsubfn);
596
15.1k
        if (code < 0)
597
1.07k
            goto function_3_error;
598
599
14.1k
        code = pdfi_build_sub_function(ctx, &ptr[i], &params.Encode[i * 2], num_inputs, rsubfn, page_dict);
600
14.1k
        pdfi_countdown(rsubfn);
601
14.1k
        if (code < 0)
602
166
            goto function_3_error;
603
14.1k
    }
604
605
4.44k
    if (params.Range == 0)
606
4.41k
        params.n = params.Functions[0]->params.n;
607
608
4.44k
    code = gs_function_1ItSg_init(ppfn, &params, ctx->memory);
609
4.44k
    if (code < 0)
610
7
        goto function_3_error;
611
612
4.43k
    pdfi_countdown(Functions);
613
4.43k
    return 0;
614
615
1.34k
function_3_error:
616
1.34k
    pdfi_countdown(Functions);
617
1.34k
    gs_function_1ItSg_free_params(&params, ctx->memory);
618
1.34k
    mnDR->Range = NULL;
619
1.34k
    mnDR->Domain = NULL;
620
1.34k
    return code;
621
4.44k
}
622
623
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)
624
62.6k
{
625
62.6k
    int code, i;
626
62.6k
    int64_t Type;
627
62.6k
    gs_function_params_t params;
628
62.6k
    pdf_dict *stream_dict;
629
62.6k
    int obj_num;
630
631
62.6k
    params.Range = params.Domain = NULL;
632
633
62.6k
    code = pdfi_loop_detector_mark(ctx);
634
62.6k
    if (code < 0)
635
0
        return code;
636
637
62.6k
    obj_num = pdf_object_num(stream_obj);
638
62.6k
    if (obj_num != 0) {
639
52.2k
        if (pdfi_loop_detector_check_object(ctx, obj_num))
640
0
            return gs_note_error(gs_error_circular_reference);
641
52.2k
        code = pdfi_loop_detector_add_object(ctx, obj_num);
642
52.2k
        if (code < 0)
643
0
            goto sub_function_error;
644
52.2k
    }
645
646
62.6k
    code = pdfi_dict_from_obj(ctx, stream_obj, &stream_dict);
647
62.6k
    if (code < 0)
648
111
        goto sub_function_error;
649
650
62.5k
    code = pdfi_dict_get_int(ctx, stream_dict, "FunctionType", &Type);
651
62.5k
    if (code < 0)
652
851
        goto sub_function_error;
653
654
61.6k
    if (Type < 0 || Type > 4 || Type == 1) {
655
35
        code = gs_note_error(gs_error_rangecheck);
656
35
        goto sub_function_error;
657
35
    }
658
659
61.6k
    memset(&params, 0x00, sizeof(gs_function_params_t));
660
661
    /* First gather all the entries common to all functions */
662
61.6k
    code = pdfi_make_float_array_from_dict(ctx, (float **)&params.Domain, stream_dict, "Domain");
663
61.6k
    if (code < 0)
664
270
        goto sub_function_error;
665
666
61.3k
    if (code & 1) {
667
19
        code = gs_error_rangecheck;
668
19
        goto sub_function_error;
669
19
    }
670
671
125k
    for (i=0;i<code;i+=2) {
672
64.3k
        if (params.Domain[i] > params.Domain[i+1]) {
673
24
            code = gs_error_rangecheck;
674
24
            goto sub_function_error;
675
24
        }
676
64.3k
    }
677
61.3k
    if (shading_domain) {
678
27.6k
        if (num_inputs != code >> 1) {
679
16
            code = gs_error_rangecheck;
680
16
            goto sub_function_error;
681
16
        }
682
683
55.3k
        for (i=0;i<2*num_inputs;i+=2) {
684
27.6k
            if (params.Domain[i] > shading_domain[i] || params.Domain[i+1] < shading_domain[i+1]) {
685
27
                code = gs_error_rangecheck;
686
27
                goto sub_function_error;
687
27
            }
688
27.6k
        }
689
27.6k
    }
690
691
61.2k
    params.m = code >> 1;
692
693
61.2k
    code = pdfi_make_float_array_from_dict(ctx, (float **)&params.Range, stream_dict, "Range");
694
61.2k
    if (code < 0 && code != gs_error_undefined)
695
44
        goto sub_function_error;
696
61.2k
    else {
697
61.2k
        if (code > 0)
698
36.7k
            params.n = code >> 1;
699
24.4k
        else
700
24.4k
            params.n = 0;
701
61.2k
    }
702
61.2k
    switch(Type) {
703
21.9k
        case 0:
704
21.9k
            code = pdfi_build_function_0(ctx, &params, (pdf_stream *)stream_obj, 0, ppfn);
705
21.9k
            if (code < 0)
706
2.43k
                goto sub_function_error;
707
19.5k
            break;
708
27.0k
        case 2:
709
27.0k
            code = pdfi_build_function_2(ctx, &params, stream_dict, 0, ppfn);
710
27.0k
            if (code < 0)
711
553
                goto sub_function_error;
712
26.4k
            break;
713
26.4k
        case 3:
714
5.79k
            code = pdfi_build_function_3(ctx, &params, stream_dict, shading_domain,  num_inputs, page_dict, 0, ppfn);
715
5.79k
            if (code < 0)
716
1.35k
                goto sub_function_error;
717
4.43k
            break;
718
6.43k
        case 4:
719
6.43k
            code = pdfi_build_function_4(ctx, &params, (pdf_stream *)stream_obj, 0, ppfn);
720
6.43k
            if (code < 0)
721
543
                goto sub_function_error;
722
5.89k
            break;
723
5.89k
        default:
724
0
            break;
725
61.2k
    }
726
56.3k
    pdfi_loop_detector_cleartomark(ctx);
727
56.3k
    return 0;
728
729
6.28k
sub_function_error:
730
6.28k
    gs_free_const_object(ctx->memory, params.Domain, "pdfi_build_sub_function (Domain) error exit\n");
731
6.28k
    gs_free_const_object(ctx->memory, params.Range, "pdfi_build_sub_function(Range) error exit\n");
732
6.28k
    pdfi_loop_detector_cleartomark(ctx);
733
6.28k
    return code;
734
61.2k
}
735
736
737
static int pdfi_free_function_special(pdf_context *ctx, gs_function_t *pfn);
738
739
#if 0
740
/* For type 0 functions, need to free up the data associated with the stream
741
 * that it was using.  This doesn't get freed in the gs_function_free() code.
742
 */
743
static int pdfi_free_function_0(pdf_context *ctx, gs_function_t *pfn)
744
{
745
    gs_function_Sd_params_t *params = (gs_function_Sd_params_t *)&pfn->params;
746
747
    s_close_filters(&params->DataSource.data.strm, params->DataSource.data.strm->strm);
748
    gs_free_object(ctx->memory, params->DataSource.data.strm, "pdfi_free_function");
749
    return 0;
750
}
751
#endif
752
753
/* For type 3 functions, it has an array of functions that might need special handling.
754
 */
755
static int pdfi_free_function_3(pdf_context *ctx, gs_function_t *pfn)
756
4.42k
{
757
4.42k
    gs_function_1ItSg_params_t *params = (gs_function_1ItSg_params_t *)&pfn->params;
758
4.42k
    int i;
759
760
18.2k
    for (i=0; i<params->k; i++) {
761
13.7k
        pdfi_free_function_special(ctx, (gs_function_t *)params->Functions[i]);
762
13.7k
    }
763
4.42k
    return 0;
764
4.42k
}
765
766
/* Free any special stuff associated with a function */
767
static int pdfi_free_function_special(pdf_context *ctx, gs_function_t *pfn)
768
86.8k
{
769
86.8k
    switch(pfn->head.type) {
770
#if 0
771
    /* Before commit 3f2408d5ac786ac1c0a837b600f4ef3be9be0332
772
     * https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=3f2408d5ac786ac1c0a837b600f4ef3be9be0332
773
     * we needed to close the data stream and free the memory. That is now
774
     * performed by the graphics library so we don't need to do this any more.
775
     */
776
    case 0:
777
        pdfi_free_function_0(ctx, pfn);
778
        break;
779
#endif
780
4.42k
    case 3:
781
4.42k
        pdfi_free_function_3(ctx, pfn);
782
4.42k
        break;
783
82.4k
    default:
784
82.4k
        break;
785
86.8k
    }
786
86.8k
    return 0;
787
86.8k
}
788
789
int pdfi_free_function(pdf_context *ctx, gs_function_t *pfn)
790
81.1k
{
791
81.1k
    if (pfn == NULL)
792
8.02k
        return 0;
793
794
    /* Free any special stuff for the function */
795
73.1k
    pdfi_free_function_special(ctx, pfn);
796
797
    /* Free the standard stuff handled by the gs library */
798
73.1k
    gs_function_free(pfn, true, ctx->memory);
799
73.1k
    return 0;
800
81.1k
}
801
802
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)
803
48.5k
{
804
48.5k
    return pdfi_build_sub_function(ctx, ppfn, shading_domain, num_inputs, stream_obj, page_dict);
805
48.5k
}
806
807
int pdfi_build_halftone_function(pdf_context *ctx, gs_function_t ** ppfn, byte *Buffer, int64_t Length)
808
30.6k
{
809
30.6k
    gs_function_PtCr_params_t params;
810
30.6k
    pdf_c_stream *function_stream = NULL;
811
30.6k
    int code=0;
812
30.6k
    byte *ops = NULL;
813
30.6k
    unsigned int size;
814
30.6k
    float *pfloat;
815
30.6k
    byte *stream_buffer = NULL;
816
817
30.6k
    memset(&params, 0x00, sizeof(gs_function_PtCr_params_t));
818
30.6k
    params.ops.data = 0;  /* in case of failure */
819
30.6k
    params.ops.size = 0;  /* ditto */
820
821
30.6k
    stream_buffer = gs_alloc_bytes(ctx->memory, Length, "pdfi_build_halftone_function(stream_buffer))");
822
30.6k
    if (stream_buffer == NULL)
823
0
        goto halftone_function_error;
824
825
30.6k
    memcpy(stream_buffer, Buffer, Length);
826
827
30.6k
    code = pdfi_open_memory_stream_from_memory(ctx, Length, stream_buffer, &function_stream, true);
828
30.6k
    if (code < 0)
829
0
        goto halftone_function_error;
830
831
30.6k
    size = 0;
832
30.6k
    code = pdfi_parse_type4_func_stream(ctx, function_stream, 0, NULL, &size);
833
30.6k
    if (code < 0)
834
0
        goto halftone_function_error;
835
836
30.6k
    if (size > max_uint - 1) {
837
0
        code = gs_note_error(gs_error_VMerror);
838
0
        goto halftone_function_error;
839
0
    }
840
841
30.6k
    ops = gs_alloc_string(ctx->memory, size + 1, "pdfi_build_halftone_function(ops)");
842
30.6k
    if (ops == NULL) {
843
0
        code = gs_error_VMerror;
844
0
        goto halftone_function_error;
845
0
    }
846
847
30.6k
    code = pdfi_seek(ctx, function_stream, 0, SEEK_SET);
848
30.6k
    if (code < 0)
849
0
        goto halftone_function_error;
850
851
30.6k
    size = 0;
852
30.6k
    code = pdfi_parse_type4_func_stream(ctx, function_stream, 0, ops, &size);
853
30.6k
    if (code < 0)
854
0
        goto halftone_function_error;
855
30.6k
    ops[size] = PtCr_return;
856
857
30.6k
    code = pdfi_close_memory_stream(ctx, stream_buffer, function_stream);
858
30.6k
    if (code < 0) {
859
0
        function_stream = NULL;
860
0
        goto halftone_function_error;
861
0
    }
862
863
30.6k
    params.ops.data = (const byte *)ops;
864
30.6k
    params.ops.size = size + 1;
865
30.6k
    params.m = 2;
866
30.6k
    params.n = 1;
867
30.6k
    pfloat = (float *)gs_alloc_byte_array(ctx->memory, 4, sizeof(float), "pdfi_build_halftone_function(Domain)");
868
30.6k
    if (pfloat == NULL) {
869
0
        code = gs_error_VMerror;
870
0
        goto halftone_function_error;
871
0
    }
872
30.6k
    pfloat[0] = -1;
873
30.6k
    pfloat[1] = 1;
874
30.6k
    pfloat[2] = -1;
875
30.6k
    pfloat[3] = 1;
876
30.6k
    params.Domain = (const float *)pfloat;
877
30.6k
    pfloat = (float *)gs_alloc_byte_array(ctx->memory, 2, sizeof(float), "pdfi_build_halftone_function(Domain)");
878
30.6k
    if (pfloat == NULL) {
879
0
        code = gs_error_VMerror;
880
0
        goto halftone_function_error;
881
0
    }
882
30.6k
    pfloat[0] = -1;
883
30.6k
    pfloat[1] = 1;
884
30.6k
    params.Range = (const float *)pfloat;
885
886
30.6k
    code = gs_function_PtCr_init(ppfn, &params, ctx->memory);
887
30.6k
    if (code < 0)
888
0
        goto halftone_function_error;
889
890
30.6k
    return 0;
891
892
0
halftone_function_error:
893
0
    if (function_stream)
894
0
        (void)pdfi_close_memory_stream(ctx, stream_buffer, function_stream);
895
896
0
    gs_function_PtCr_free_params(&params, ctx->memory);
897
0
    if (ops)
898
0
        gs_free_const_string(ctx->memory, ops, size, "pdfi_build_function_4(ops)");
899
0
    return code;
900
30.6k
}