Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/psi/zfunc4.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2025 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* PostScript language support for FunctionType 4 (PS Calculator) Functions */
18
#include "memory_.h"
19
#include "ghost.h"
20
#include "oper.h"
21
#include "opextern.h"
22
#include "gsfunc.h"
23
#include "gsfunc4.h"
24
#include "gsutil.h"
25
#include "idict.h"
26
#include "ifunc.h"
27
#include "iname.h"
28
#include "dstack.h"
29
#include "ialloc.h"
30
#include "gzstate.h"      /* these are needed to check device parameters */
31
#include "gsparam.h"      /* these are needed to check device parameters */
32
#include "zfunc.h"
33
#include "zcolor.h"
34
#include "gxdevsop.h"
35
36
/*
37
 * FunctionType 4 functions are not defined in the PostScript language.  We
38
 * provide support for them because they are needed for PDF 1.3.  In
39
 * addition to the standard FunctionType, Domain, and Range keys, they have
40
 * a Function key whose value is a procedure in a restricted subset of the
41
 * PostScript language.  Specifically, the procedure must (recursively)
42
 * contain only integer, real, Boolean, and procedure constants (only as
43
 * literal operands of if and and ifelse), and operators chosen from the set
44
 * given below.  Note that names other than true and false are not allowed:
45
 * the procedure must be 'bound'.
46
 *
47
 * The following list is taken directly from the PDF 1.3 documentation.
48
 */
49
#define XOP(zfn) int zfn(i_ctx_t *)
50
XOP(zabs); XOP(zand); XOP(zatan); XOP(zbitshift);
51
XOP(zceiling); XOP(zcos); XOP(zcvi); XOP(zcvr);
52
XOP(zdiv); XOP(zexp); XOP(zfloor); XOP(zidiv);
53
XOP(zln); XOP(zlog); XOP(zmod); XOP(zmul);
54
XOP(zneg); XOP(znot); XOP(zor); XOP(zround);
55
XOP(zsin); XOP(zsqrt); XOP(ztruncate); XOP(zxor);
56
XOP(zeq); XOP(zge); XOP(zgt); XOP(zle); XOP(zlt); XOP(zne);
57
XOP(z2copy);
58
#undef XOP
59
typedef struct calc_op_s {
60
    op_proc_t proc;
61
    gs_PtCr_opcode_t opcode;
62
} calc_op_t;
63
static const calc_op_t calc_ops[] = {
64
65
    /* Arithmetic operators */
66
67
    {zabs, PtCr_abs},
68
    {zadd, PtCr_add},
69
    {zand, PtCr_and},
70
    {zatan, PtCr_atan},
71
    {zbitshift, PtCr_bitshift},
72
    {zceiling, PtCr_ceiling},
73
    {zcos, PtCr_cos},
74
    {zcvi, PtCr_cvi},
75
    {zcvr, PtCr_cvr},
76
    {zdiv, PtCr_div},
77
    {zexp, PtCr_exp},
78
    {zfloor, PtCr_floor},
79
    {zidiv, PtCr_idiv},
80
    {zln, PtCr_ln},
81
    {zlog, PtCr_log},
82
    {zmod, PtCr_mod},
83
    {zmul, PtCr_mul},
84
    {zneg, PtCr_neg},
85
    {znot, PtCr_not},
86
    {zor, PtCr_or},
87
    {zround, PtCr_round},
88
    {zsin, PtCr_sin},
89
    {zsqrt, PtCr_sqrt},
90
    {zsub, PtCr_sub},
91
    {ztruncate, PtCr_truncate},
92
    {zxor, PtCr_xor},
93
94
    /* Comparison operators */
95
96
    {zeq, PtCr_eq},
97
    {zge, PtCr_ge},
98
    {zgt, PtCr_gt},
99
    {zle, PtCr_le},
100
    {zlt, PtCr_lt},
101
    {zne, PtCr_ne},
102
103
    /* Stack operators */
104
105
    {zcopy, PtCr_copy},
106
    {z2copy, PtCr_copy},
107
    {zdup, PtCr_dup},
108
    {zexch, PtCr_exch},
109
    {zindex, PtCr_index},
110
    {zpop, PtCr_pop},
111
    {zroll, PtCr_roll}
112
113
    /* Special operators */
114
115
    /*{zif, PtCr_if},*/
116
    /*{zifelse, PtCr_ifelse},*/
117
    /*{ztrue, PtCr_true},*/
118
    /*{zfalse, PtCr_false}*/
119
};
120
121
/* Fix up an if or ifelse forward reference. */
122
static void
123
psc_fixup(byte *p, byte *to)
124
0
{
125
0
    int skip = to - (p + 3);
126
127
0
    p[1] = (byte)(skip >> 8);
128
0
    p[2] = (byte)skip;
129
0
}
130
131
/* Check whether the ref is a given operator or resolves to it */
132
static bool
133
resolves_to_oper(i_ctx_t *i_ctx_p, const ref *pref, const op_proc_t proc)
134
0
{
135
0
    if (!r_has_attr(pref, a_executable))
136
0
        return false;
137
0
    if (r_btype(pref) == t_operator) {
138
0
        return pref->value.opproc == proc;
139
0
    } else if (r_btype(pref) == t_name) {
140
0
        ref * val;
141
0
        if (dict_find(systemdict, pref, &val) <= 0)
142
0
            return false;
143
0
        if (r_btype(val) != t_operator)
144
0
            return false;
145
0
        if (!r_has_attr(val, a_executable))
146
0
            return false;
147
0
        return val->value.opproc == proc;
148
0
    }
149
0
   else
150
0
      return false;
151
0
}
152
153
/* Store an int in the  buffer */
154
static int
155
18.5k
put_int(byte **p, int n) {
156
18.5k
   if (n == (byte)n) {
157
16.6k
       if (*p) {
158
16.6k
          (*p)[0] = PtCr_byte;
159
16.6k
          (*p)[1] = (byte)n;
160
16.6k
          *p += 2;
161
16.6k
       }
162
16.6k
       return 2;
163
16.6k
   } else {
164
1.87k
       if (*p) {
165
1.87k
          **p = PtCr_int;
166
1.87k
          memcpy(*p + 1, &n, sizeof(int));
167
1.87k
          *p += sizeof(int) + 1;
168
1.87k
       }
169
1.87k
       return (sizeof(int) + 1);
170
1.87k
   }
171
18.5k
}
172
173
/* Store a float in the  buffer */
174
static int
175
38.7k
put_float(byte **p, float n) {
176
38.7k
   if (*p) {
177
38.7k
      **p = PtCr_float;
178
38.7k
      memcpy(*p + 1, &n, sizeof(float));
179
38.7k
      *p += sizeof(float) + 1;
180
38.7k
   }
181
38.7k
   return (sizeof(float) + 1);
182
38.7k
}
183
184
/* Store an op code in the  buffer */
185
static int
186
0
put_op(byte **p, byte op) {
187
0
   if (*p)
188
0
      *(*p)++ = op;
189
0
   return 1;
190
0
}
191
192
/*
193
 * Check a calculator function for validity, optionally storing its encoded
194
 * representation and add the size of the encoded representation to *psize.
195
 * Note that we arbitrarily limit the depth of procedure nesting.  pref is
196
 * known to be a procedure.
197
 */
198
static int
199
check_psc_function(i_ctx_t *i_ctx_p, const ref *pref, int depth, byte *ops, uint *psize, bool AllowRepeat)
200
11.5k
{
201
11.5k
    int code;
202
11.5k
    uint i, j;
203
11.5k
    uint size = r_size(pref);
204
11.5k
    byte *p;
205
206
11.5k
    if (size == 2 && depth == 0) {
207
        /* Bug 690986. Recognize and replace Corel tint transform function.
208
           { tint_params CorelTintTransformFunction }
209
210
           Where tint_params resolves to an arrey like:
211
             [ 1.0 0.0 0.0 0.0
212
               0.0 1.0 0.0 0.0
213
               0.0 0.0 1.0 0.0
214
               0.0 0.0 0.0 1.0
215
               0.2 0.81 0.76 0.61
216
            ]
217
           And CorelTintTransformFunction is:
218
            { /colorantSpecArray exch def
219
              /nColorants colorantSpecArray length 4 idiv def
220
              /inColor nColorants 1 add 1 roll nColorants array astore def
221
              /outColor 4 array def
222
              0 1 3 {
223
                /nOutInk exch def
224
                1
225
                0 1 nColorants 1 sub {
226
                  dup inColor exch get
227
                  exch 4 mul nOutInk add colorantSpecArray exch get mul
228
                  1 exch sub mul
229
                } for
230
                1 exch sub
231
                outColor nOutInk 3 -1 roll put
232
              } for
233
              outColor aload pop
234
            }
235
        */
236
13
        ref r_tp, r_cttf; /* original references */
237
13
        ref n_tp, n_cttf; /* names */
238
13
        ref *v_tp, *v_cttf; /* values */
239
13
        int sz;
240
241
13
        p = ops;
242
13
        sz = *psize;
243
13
        if(array_get(imemory, pref, 0, &r_tp) < 0)
244
0
            goto idiom_failed;
245
13
        if (array_get(imemory, pref, 1, &r_cttf) < 0)
246
0
            goto idiom_failed;
247
13
        if (r_has_type(&r_tp, t_name) && r_has_type(&r_cttf, t_name)) {
248
0
            if ((code = name_enter_string(imemory, "tint_params", &n_tp)) < 0)
249
0
                return code;
250
0
            if (r_tp.value.pname == n_tp.value.pname) {
251
0
                if ((code = name_enter_string(imemory, "CorelTintTransformFunction", &n_cttf)) < 0)
252
0
                    return code;
253
0
                if (r_cttf.value.pname == n_cttf.value.pname) {
254
0
                    v_tp   = dict_find_name(&n_tp);
255
0
                    v_cttf = dict_find_name(&n_cttf);
256
0
                    if (v_tp && v_cttf && r_is_array(v_tp) && r_is_array(v_cttf)) {
257
0
                        uint n_elem = r_size(v_tp);
258
259
0
                        if ((n_elem & 3) == 0 && r_size(v_cttf) == 31) {
260
                            /* Enough testing, idiom recognition tests less. */
261
0
                            uint n_col = n_elem/4;
262
263
0
                            for (i = 0; i < 4; i ++) {
264
0
                                ref v;
265
0
                                float fv;
266
0
                                bool first = true;
267
268
0
                                for (j = 0; j < n_col; j++) {
269
0
                                    if (array_get(imemory, v_tp, j*4 + i, &v) < 0)
270
0
                                        goto idiom_failed;
271
0
                                    if (r_type(&v) == t_integer)
272
0
                                        fv = (float)v.value.intval;
273
0
                                    else if (r_type(&v) == t_real)
274
0
                                        fv = v.value.realval;
275
0
                                    else
276
0
                                        goto idiom_failed;
277
278
0
                                    if (fv != 0.) {
279
                                        /* Ensure we can't overflow max_uint, Worst case is 3 x put_int + put_float + 4 x put_op */
280
0
                                        if (sz > max_uint - ((3 * (sizeof(int) + 1)) + (sizeof(float) + 1) + 4))
281
0
                                            return_error(gs_error_VMerror);
282
283
0
                                        if (first)
284
0
                                            sz += put_int(&p, 1);
285
0
                                        sz += put_int(&p, 1);
286
0
                                        sz += put_int(&p, n_col + 1 - j + i + !first);
287
0
                                        sz += put_op(&p, PtCr_index);
288
0
                                        if (fv != 1.) {
289
0
                                            sz += put_float(&p, fv);
290
0
                                            sz += put_op(&p, PtCr_mul);
291
0
                                        }
292
0
                                        sz += put_op(&p, PtCr_sub);
293
0
                                        if (first)
294
0
                                            first = false;
295
0
                                        else
296
0
                                            sz += put_op(&p, PtCr_mul);
297
0
                                    }
298
0
                                }
299
                                /* Ensure we can't overflow max_uint */
300
0
                                if (sz > max_uint - (sizeof(int) + 1))
301
0
                                    return_error(gs_error_VMerror);
302
0
                                if (first)
303
0
                                    sz += put_int(&p, 0);
304
0
                                else
305
0
                                    sz += put_op(&p, PtCr_sub);
306
0
                            }
307
                            /* Ensure we can't overflow max_uint; required size is 2 x put_int + put_op + n_col x put_op */
308
0
                            if (sz > max_uint - ((2 * (sizeof(int) + 1)) + n_col + 1))
309
0
                                return_error(gs_error_VMerror);
310
                            /* n_col+4 4 roll pop ... pop  */
311
0
                            sz += put_int(&p, n_col + 4);
312
0
                            sz += put_int(&p, 4);
313
0
                            sz += put_op(&p, PtCr_roll);
314
0
                            for (j = 0; j < n_col; j++)
315
0
                                sz += put_op(&p, PtCr_pop);
316
0
                            *psize = sz;
317
0
                            return 0;
318
0
                        }
319
0
                    }
320
0
                }
321
0
            }
322
0
        }
323
13
    }
324
11.5k
  idiom_failed:;
325
81.2k
    for (i = 0; i < size; ++i) {
326
69.9k
        byte no_ops[1 + max(sizeof(int), sizeof(float))];
327
69.9k
        ref elt, elt2, elt3;
328
69.9k
        ref * delp;
329
330
69.9k
        p = (ops ? ops + *psize : no_ops);
331
69.9k
        array_get(imemory, pref, i, &elt);
332
69.9k
        switch (r_btype(&elt)) {
333
18.5k
        case t_integer:
334
            /* Ensure we can't overflow max_uint */
335
18.5k
            if (*psize > max_uint - (sizeof(int) + 1))
336
0
                return_error(gs_error_VMerror);
337
18.5k
            *psize += put_int(&p, elt.value.intval);
338
18.5k
            break;
339
38.7k
        case t_real:
340
            /* Ensure we can't overflow max_uint */
341
38.7k
            if (*psize > max_uint - (sizeof(float) + 1))
342
0
                return_error(gs_error_VMerror);
343
38.7k
            *psize += put_float(&p, elt.value.realval);
344
38.7k
            break;
345
0
        case t_boolean:
346
            /* Ensure we can't overflow max_uint */
347
0
            if (*psize > max_uint - 1)
348
0
                return_error(gs_error_VMerror);
349
0
            *p = (elt.value.boolval ? PtCr_true : PtCr_false);
350
0
            ++*psize;
351
0
            break;
352
12.6k
        case t_name:
353
12.6k
            if (!r_has_attr(&elt, a_executable))
354
18
                return_error(gs_error_rangecheck);
355
            /* Ensure we can't overflow max_uint, initially check the quick cases */
356
12.6k
            if (*psize > max_uint - 1)
357
0
                return_error(gs_error_VMerror);
358
12.6k
            name_string_ref(imemory, &elt, &elt);
359
12.6k
            if (!bytes_compare(elt.value.bytes, r_size(&elt),
360
12.6k
                               (const byte *)"true", 4)) {
361
0
                *p = PtCr_true;
362
0
                ++*psize;
363
0
                break;
364
0
            }
365
12.6k
            if (!bytes_compare(elt.value.bytes, r_size(&elt),
366
12.6k
                                      (const byte *)"false", 5)) {
367
0
                *p = PtCr_false;
368
0
                ++*psize;
369
0
                break;
370
0
            }
371
            /* Check if the name is a valid operator in systemdict */
372
12.6k
            if (dict_find(systemdict, &elt, &delp) <= 0)
373
29
                return_error(gs_error_undefined);
374
12.5k
            if (r_btype(delp) != t_operator)
375
183
                return_error(gs_error_typecheck);
376
12.3k
            if (!r_has_attr(delp, a_executable))
377
0
                return_error(gs_error_rangecheck);
378
12.3k
            elt = *delp;
379
            /* Fall into the operator case */
380
12.3k
        case t_operator: {
381
12.3k
            int j;
382
383
            /* Ensure we can't overflow max_uint, all operators are a single byte */
384
12.3k
            if (*psize > max_uint - 1)
385
0
                return_error(gs_error_VMerror);
386
446k
            for (j = 0; j < countof(calc_ops); ++j)
387
446k
                if (elt.value.opproc == calc_ops[j].proc) {
388
12.3k
                    *p = calc_ops[j].opcode;
389
12.3k
                    ++*psize;
390
12.3k
                    goto next;
391
12.3k
                }
392
12.3k
            return_error(gs_error_rangecheck);
393
12.3k
        }
394
0
        default: {
395
0
            if (!r_is_proc(&elt))
396
0
                return_error(gs_error_typecheck);
397
0
            if (depth == MAX_PSC_FUNCTION_NESTING)
398
0
                return_error(gs_error_limitcheck);
399
0
            if ((code = array_get(imemory, pref, ++i, &elt2)) < 0)
400
0
                return code;
401
            /* Ensure we can't overflow max_uint */
402
0
            if (*psize > max_uint - 3)
403
0
                return_error(gs_error_VMerror);
404
0
            *psize += 3;
405
0
            code = check_psc_function(i_ctx_p, &elt, depth + 1, ops, psize, AllowRepeat);
406
0
            if (code < 0)
407
0
                return code;
408
            /* Check for { proc } repeat | {proc} if | {proc1} {proc2} ifelse */
409
0
            if (resolves_to_oper(i_ctx_p, &elt2, zrepeat)) {
410
0
                if (!AllowRepeat)
411
0
                    return_error(gs_error_rangecheck);
412
                /* We need a byte to add the repeat end below */
413
0
                if (*psize > max_uint - 1)
414
0
                    return_error(gs_error_VMerror);
415
0
                if (ops) {
416
0
                    *p = PtCr_repeat;
417
0
                    psc_fixup(p, ops + *psize);
418
0
                    p = ops + *psize;
419
0
                    *p++ = PtCr_repeat_end;
420
0
                }
421
0
                *psize += 1;  /* extra room for repeat_end */
422
0
            } else if (resolves_to_oper(i_ctx_p, &elt2, zif)) {
423
0
                if (ops) {
424
0
                    *p = PtCr_if;
425
0
                    psc_fixup(p, ops + *psize);
426
0
                }
427
0
            } else if (!r_is_proc(&elt2))
428
0
                return_error(gs_error_rangecheck);
429
0
            else if ((code = array_get(imemory, pref, ++i, &elt3)) < 0)
430
0
                return code;
431
0
            else if (resolves_to_oper(i_ctx_p, &elt3, zifelse)) {
432
0
                if (ops) {
433
0
                    *p = PtCr_if;
434
0
                    psc_fixup(p, ops + *psize + 3);
435
0
                    p = ops + *psize;
436
0
                    *p = PtCr_else;
437
0
                }
438
                /* Ensure we can't overflow max_uint */
439
0
                if (*psize > max_uint - 3)
440
0
                    return_error(gs_error_VMerror);
441
0
                *psize += 3;
442
0
                code = check_psc_function(i_ctx_p, &elt2, depth + 1, ops, psize, AllowRepeat);
443
0
                if (code < 0)
444
0
                    return code;
445
0
                if (ops)
446
0
                    psc_fixup(p, ops + *psize);
447
0
            } else
448
0
                return_error(gs_error_rangecheck);
449
0
            }   /* end 'default' */
450
69.9k
        }
451
69.7k
    next:
452
69.7k
        DO_NOTHING;
453
69.7k
    }
454
11.2k
    return 0;
455
11.5k
}
456
#undef MAX_PSC_FUNCTION_NESTING
457
458
/* Check prototype */
459
build_function_proc(gs_build_function_4);
460
461
/* Finish building a FunctionType 4 (PostScript Calculator) function. */
462
int
463
gs_build_function_4(i_ctx_t *i_ctx_p, const ref *op, const gs_function_params_t * mnDR,
464
                    int depth, gs_function_t ** ppfn, gs_memory_t *mem)
465
0
{
466
0
    gs_function_PtCr_params_t params;
467
0
    ref *proc;
468
0
    int code;
469
0
    byte *ops;
470
0
    uint size;
471
0
    bool AllowRepeat = true; /* Default to permitting Repeat, devices which can't handle it implement the spec_op */
472
473
0
    *(gs_function_params_t *)&params = *mnDR;
474
0
    params.ops.data = 0;  /* in case of failure */
475
0
    params.ops.size = 0;  /* ditto */
476
0
    if (dict_find_string(op, "Function", &proc) <= 0) {
477
0
        code = gs_note_error(gs_error_rangecheck);
478
0
        goto fail;
479
0
    }
480
0
    if (!r_is_proc(proc)) {
481
0
        code = gs_note_error(gs_error_typecheck);
482
0
        goto fail;
483
0
    }
484
0
    size = 0;
485
486
    /* Check if the device allows the use of repeat in functions */
487
    /* We can't handle 'repeat' with pdfwrite since it emits FunctionType 4 */
488
0
    {
489
0
        char data[] = {"AllowPSRepeatFunctions"};
490
0
        dev_param_req_t request;
491
0
        gs_c_param_list list;
492
493
0
        gs_c_param_list_write(&list, i_ctx_p->pgs->device->memory);
494
        /* Stuff the data into a structure for passing to the spec_op */
495
0
        request.Param = data;
496
0
        request.list = &list;
497
0
        code = dev_proc(i_ctx_p->pgs->device, dev_spec_op)(i_ctx_p->pgs->device, gxdso_get_dev_param, &request, sizeof(dev_param_req_t));
498
0
        if (code < 0 && code != gs_error_undefined) {
499
0
            gs_c_param_list_release(&list);
500
0
            return code;
501
0
        }
502
0
        gs_c_param_list_read(&list);
503
0
        code = param_read_bool((gs_param_list *)&list,
504
0
            "AllowPSRepeatFunctions",
505
0
            &AllowRepeat);
506
0
        gs_c_param_list_release(&list);
507
0
        if (code < 0)
508
0
            return code;
509
0
    }
510
511
0
    code = check_psc_function(i_ctx_p, proc, 0, NULL, &size, AllowRepeat);
512
0
    if (code < 0)
513
0
        goto fail;
514
515
    /* We need an extra byte for the function return (see below)
516
     * strings are limited to max_uint size so make sure we won't overflow.
517
     */
518
0
    if (size == max_uint) {
519
0
        code = gs_note_error(gs_error_VMerror);
520
0
        goto fail;
521
0
    }
522
523
0
    ops = gs_alloc_string(mem, size + 1, "gs_build_function_4(ops)");
524
0
    if (ops == 0) {
525
0
        code = gs_note_error(gs_error_VMerror);
526
0
        goto fail;
527
0
    }
528
0
    size = 0;
529
0
    check_psc_function(i_ctx_p, proc, 0, ops, &size, AllowRepeat); /* can't fail */
530
0
    ops[size] = PtCr_return;
531
0
    params.ops.data = ops;
532
0
    params.ops.size = size + 1;
533
0
    code = gs_function_PtCr_init(ppfn, &params, mem);
534
0
    if (code >= 0)
535
0
        return 0;
536
    /* free_params will free the ops string */
537
0
fail:
538
0
    gs_function_PtCr_free_params(&params, mem);
539
0
    return code;
540
0
}
541
542
int make_type4_function(i_ctx_t * i_ctx_p, ref *arr, ref *pproc, gs_function_t **func)
543
5.88k
{
544
5.88k
    int code, num_components, CIESubst;
545
5.88k
    uint size;
546
5.88k
    byte *ops = NULL;
547
5.88k
    gs_function_PtCr_params_t params;
548
5.88k
    float *ptr;
549
5.88k
    ref alternatespace, *palternatespace = &alternatespace;
550
5.88k
    PS_colour_space_t *space, *altspace;
551
5.88k
    bool AllowRepeat = true; /* Default to permitting Repeat, devices which can't handle it implement the spec_op */
552
553
5.88k
    code = get_space_object(i_ctx_p, arr, &space);
554
5.88k
    if (code < 0)
555
0
        return code;
556
5.88k
    if (!space->alternateproc)
557
0
        return gs_error_typecheck;
558
5.88k
    code = space->alternateproc(i_ctx_p, arr, &palternatespace, &CIESubst);
559
5.88k
    if (code < 0)
560
0
        return code;
561
5.88k
    code = get_space_object(i_ctx_p, palternatespace, &altspace);
562
5.88k
    if (code < 0)
563
0
        return code;
564
565
5.88k
    code = space->numcomponents(i_ctx_p, arr, &num_components);
566
5.88k
    if (code < 0)
567
0
        return code;
568
5.88k
    ptr = (float *)gs_alloc_byte_array(imemory, num_components * 2, sizeof(float), "make_type4_function(Domain)");
569
5.88k
    if (!ptr)
570
0
        return gs_error_VMerror;
571
5.88k
    code = space->domain(i_ctx_p, arr, ptr);
572
5.88k
    if (code < 0) {
573
0
        gs_free_const_object(imemory, ptr, "make_type4_function(Domain)");
574
0
        return code;
575
0
    }
576
5.88k
    params.Domain = ptr;
577
5.88k
    params.m = num_components;
578
579
5.88k
    code = altspace->numcomponents(i_ctx_p, &alternatespace, &num_components);
580
5.88k
    if (code < 0) {
581
0
        gs_free_const_object(imemory, params.Domain, "make_type4_function(Domain)");
582
0
        return code;
583
0
    }
584
5.88k
    ptr = (float *)gs_alloc_byte_array(imemory, num_components * 2, sizeof(float), "make_type4_function(Range)");
585
5.88k
    if (!ptr) {
586
0
        gs_free_const_object(imemory, params.Domain, "make_type4_function(Domain)");
587
0
        return gs_error_VMerror;
588
0
    }
589
5.88k
    code = altspace->range(i_ctx_p, &alternatespace, ptr);
590
5.88k
    if (code < 0) {
591
0
        gs_free_const_object(imemory, ptr, "make_type4_function(Domain)");
592
0
        gs_free_const_object(imemory, params.Domain, "make_type4_function(Range)");
593
0
        return code;
594
0
    }
595
5.88k
    params.Range = ptr;
596
5.88k
    params.n = num_components;
597
598
5.88k
    params.ops.data = 0;  /* in case of failure, see gs_function_PtCr_free_params */
599
5.88k
    params.ops.size = 0;  /* ditto */
600
5.88k
    size = 0;
601
602
    /* Check if the device allows the use of repeat in functions */
603
    /* We can't handle 'repeat' with pdfwrite since it emits FunctionType 4 */
604
5.88k
    {
605
5.88k
        char data[] = {"AllowPSRepeatFunctions"};
606
5.88k
        dev_param_req_t request;
607
5.88k
        gs_c_param_list list;
608
609
5.88k
        gs_c_param_list_write(&list, i_ctx_p->pgs->device->memory);
610
        /* Stuff the data into a structure for passing to the spec_op */
611
5.88k
        request.Param = data;
612
5.88k
        request.list = &list;
613
5.88k
        code = dev_proc(i_ctx_p->pgs->device, dev_spec_op)(i_ctx_p->pgs->device, gxdso_get_dev_param, &request, sizeof(dev_param_req_t));
614
5.88k
        if (code < 0 && code != gs_error_undefined) {
615
0
            gs_c_param_list_release(&list);
616
0
            return code;
617
0
        }
618
5.88k
        gs_c_param_list_read(&list);
619
5.88k
        code = param_read_bool((gs_param_list *)&list,
620
5.88k
            "AllowPSRepeatFunctions",
621
5.88k
            &AllowRepeat);
622
5.88k
        gs_c_param_list_release(&list);
623
5.88k
        if (code < 0)
624
0
            return code;
625
5.88k
    }
626
627
5.88k
    code = check_psc_function(i_ctx_p, (const ref *)pproc, 0, NULL, &size, AllowRepeat);
628
5.88k
    if (code < 0)
629
245
        goto error;
630
631
    /* We need an extra byte for the function return (see below)
632
     * strings are limited to max_uint size so make sure we won't overflow.
633
     */
634
5.63k
    if (size == max_uint) {
635
0
        code = gs_note_error(gs_error_VMerror);
636
0
        goto error;
637
0
    }
638
639
5.63k
    ops = gs_alloc_string(imemory, size + 1, "make_type4_function(ops)");
640
5.63k
    if (ops == NULL) {
641
0
        code = gs_note_error(gs_error_VMerror);
642
0
        goto error;
643
0
    }
644
5.63k
    size = 0;
645
5.63k
    check_psc_function(i_ctx_p, (const ref *)pproc, 0, ops, &size, AllowRepeat); /* can't fail */
646
5.63k
    ops[size] = PtCr_return;
647
5.63k
    params.ops.data = ops;
648
5.63k
    params.ops.size = size + 1;
649
5.63k
    code = gs_function_PtCr_init(func, &params, imemory);
650
5.63k
    if (code < 0)
651
0
        goto error;
652
653
5.63k
    return code;
654
655
245
error:
656
    /* free_params will free the ops string */
657
245
    gs_function_PtCr_free_params(&params, imemory);
658
245
    return code;
659
5.63k
}