Coverage Report

Created: 2022-10-31 07:00

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