Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gsfunc4.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 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
/* Implementation of FunctionType 4 (PostScript Calculator) Functions */
18
#include "math_.h"
19
#include "memory_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsdsrc.h"
23
#include "gsfunc4.h"
24
#include "gxfarith.h"
25
#include "gxfunc.h"
26
#include "stream.h"
27
#include "strimpl.h"
28
#include "sfilter.h"    /* for SubFileDecode */
29
#include "spprint.h"
30
#include "stream.h"
31
32
typedef struct gs_function_PtCr_s {
33
    gs_function_head_t head;
34
    gs_function_PtCr_params_t params;
35
    /* Define a bogus DataSource for get_function_info. */
36
    gs_data_source_t data_source;
37
} gs_function_PtCr_t;
38
39
/* GC descriptor */
40
private_st_function_PtCr();
41
42
/* Define the maximum stack depth. */
43
116M
#define MAX_VSTACK 256    /* Max 100 is enough per PDF spec, but we use this
44
                                 * for DeviceN handling. Must be at least as large
45
                                 * as the number of components
46
                                 */
47
48
/* Define the structure of values on the stack. */
49
typedef enum {
50
    CVT_NONE = 0, /* empty stack slot */
51
    CVT_BOOL,
52
    CVT_INT,
53
    CVT_FLOAT
54
} calc_value_type_t;
55
typedef struct calc_value_s {
56
    calc_value_type_t type;
57
    union {
58
        int i;      /* also used for Boolean */
59
        float f;
60
    } value;
61
} calc_value_t;
62
63
/* Store a float. */
64
static inline void
65
store_float(calc_value_t *vsp, double f)
66
58.2M
{
67
58.2M
    vsp->value.f = f;
68
58.2M
    vsp->type = CVT_FLOAT;
69
58.2M
}
70
71
/*
72
 * Define extended opcodes with typed operands.  We use the original
73
 * opcodes for the floating-point case.
74
 */
75
typedef enum {
76
77
        /* Typed variants */
78
79
    PtCr_abs_int = PtCr_NUM_OPCODES,
80
    PtCr_add_int,
81
    PtCr_mul_int,
82
    PtCr_neg_int,
83
    PtCr_not_bool,    /* default is int */
84
    PtCr_sub_int,
85
    PtCr_eq_int,
86
    PtCr_ge_int,
87
    PtCr_gt_int,
88
    PtCr_le_int,
89
    PtCr_lt_int,
90
    PtCr_ne_int,
91
92
        /* Coerce and re-dispatch */
93
94
    PtCr_int_to_float,
95
    PtCr_2nd_int_to_float,
96
    PtCr_int2_to_float,
97
98
        /* Miscellaneous */
99
100
    PtCr_no_op,
101
    PtCr_typecheck
102
103
} gs_PtCr_typed_opcode_t;
104
105
/* Evaluate a PostScript Calculator function. */
106
static int
107
fn_PtCr_evaluate(const gs_function_t *pfn_common, const float *in, float *out)
108
11.6M
{
109
11.6M
    const gs_function_PtCr_t *pfn = (const gs_function_PtCr_t *)pfn_common;
110
11.6M
    calc_value_t vstack_buf[2 + MAX_VSTACK + 1];
111
11.6M
    calc_value_t *vstack = &vstack_buf[1];
112
11.6M
    calc_value_t *vsp = vstack + pfn->params.m;
113
11.6M
    const byte *p = pfn->params.ops.data;
114
11.6M
    int repeat_count[MAX_PSC_FUNCTION_NESTING];
115
11.6M
    int repeat_proc_size[MAX_PSC_FUNCTION_NESTING];
116
11.6M
    int repeat_nesting_level = -1;
117
11.6M
    int i;
118
119
    /*
120
     * Define the table for mapping explicit opcodes to typed opcodes.
121
     * We index this table with the opcode and the types of the top 2
122
     * values on the stack.
123
     */
124
11.6M
    static const struct op_defn_s {
125
11.6M
        byte opcode[16];  /* 4 * type[-1] + type[0] */
126
11.6M
    } op_defn_table[] = {
127
        /* Keep this consistent with opcodes in gsfunc4.h! */
128
129
848M
#define O4(op) op,op,op,op
130
1.87G
#define E PtCr_typecheck
131
476M
#define E4 O4(E)
132
11.6M
#define N PtCr_no_op
133
        /* 0-operand operators */
134
11.6M
#define OP_NONE(op)\
135
93.0M
  {{O4(op), O4(op), O4(op), O4(op)}}
136
        /* 1-operand operators */
137
11.6M
#define OP1(b, i, f)\
138
232M
  {{E,b,i,f, E,b,i,f, E,b,i,f, E,b,i,f}}
139
11.6M
#define OP_NUM1(i, f)\
140
93.0M
  OP1(E, i, f)
141
11.6M
#define OP_MATH1(f)\
142
58.1M
  OP1(E, PtCr_int_to_float, f)
143
11.6M
#define OP_ANY1(op)\
144
23.2M
  OP1(op, op, op)
145
        /* 2-operand operators */
146
11.6M
#define OP_NUM2(i, f)\
147
81.3M
  {{E4, E4, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
148
11.6M
#define OP_INT_BOOL2(i)\
149
34.8M
  {{E4, E,i,i,E, E,i,i,E, E4}}
150
11.6M
#define OP_MATH2(f)\
151
34.8M
  {{E4, E4, E,E,PtCr_int2_to_float,PtCr_2nd_int_to_float,\
152
34.8M
    E,E,PtCr_int_to_float,f}}
153
11.6M
#define OP_INT2(i)\
154
46.5M
  {{E4, E4, E,E,i,E, E4}}
155
11.6M
#define OP_REL2(i, f)\
156
23.2M
  {{E4, E,i,E,E, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
157
11.6M
#define OP_ANY2(op)\
158
11.6M
  {{E4, E,op,op,op, E,op,op,op, E,op,op,op}}
159
160
    /* Arithmetic operators */
161
162
11.6M
        OP_NUM1(PtCr_abs_int, PtCr_abs), /* abs */
163
11.6M
        OP_NUM2(PtCr_add_int, PtCr_add), /* add */
164
11.6M
        OP_INT_BOOL2(PtCr_and),  /* and */
165
11.6M
        OP_MATH2(PtCr_atan),  /* atan */
166
11.6M
        OP_INT2(PtCr_bitshift),  /* bitshift */
167
11.6M
        OP_NUM1(N, PtCr_ceiling),  /* ceiling */
168
11.6M
        OP_MATH1(PtCr_cos), /* cos */
169
11.6M
        OP_NUM1(N, PtCr_cvi),  /* cvi */
170
11.6M
        OP_NUM1(PtCr_int_to_float, N), /* cvr */
171
11.6M
        OP_MATH2(PtCr_div), /* div */
172
11.6M
        OP_MATH2(PtCr_exp), /* exp */
173
11.6M
        OP_NUM1(N, PtCr_floor),  /* floor */
174
11.6M
        OP_INT2(PtCr_idiv),  /* idiv */
175
11.6M
        OP_MATH1(PtCr_ln),  /* ln */
176
11.6M
        OP_MATH1(PtCr_log), /* log */
177
11.6M
        OP_INT2(PtCr_mod), /* mod */
178
11.6M
        OP_NUM2(PtCr_mul_int, PtCr_mul), /* mul */
179
11.6M
        OP_NUM1(PtCr_neg_int, PtCr_neg), /* neg */
180
11.6M
        OP1(PtCr_not, PtCr_not, E),  /* not */
181
11.6M
        OP_INT_BOOL2(PtCr_or),  /* or */
182
11.6M
        OP_NUM1(N, PtCr_round),  /* round */
183
11.6M
        OP_MATH1(PtCr_sin), /* sin */
184
11.6M
        OP_MATH1(PtCr_sqrt),  /* sqrt */
185
11.6M
        OP_NUM2(PtCr_sub_int, PtCr_sub), /* sub */
186
11.6M
        OP_NUM1(N, PtCr_truncate), /* truncate */
187
11.6M
        OP_INT_BOOL2(PtCr_xor),  /* xor */
188
189
    /* Comparison operators */
190
191
11.6M
        OP_REL2(PtCr_eq_int, PtCr_eq), /* eq */
192
11.6M
        OP_NUM2(PtCr_ge_int, PtCr_ge), /* ge */
193
11.6M
        OP_NUM2(PtCr_gt_int, PtCr_gt), /* gt */
194
11.6M
        OP_NUM2(PtCr_le_int, PtCr_le), /* le */
195
11.6M
        OP_NUM2(PtCr_lt_int, PtCr_lt), /* lt */
196
11.6M
        OP_REL2(PtCr_ne_int, PtCr_ne), /* ne */
197
198
    /* Stack operators */
199
200
11.6M
        OP1(E, PtCr_copy, E),  /* copy */
201
11.6M
        OP_ANY1(PtCr_dup), /* dup */
202
11.6M
        OP_ANY2(PtCr_exch),  /* exch */
203
11.6M
        OP1(E, PtCr_index, E), /* index */
204
11.6M
        OP_ANY1(PtCr_pop), /* pop */
205
11.6M
        OP_INT2(PtCr_roll),  /* roll */
206
207
    /* Constants */
208
209
11.6M
        OP_NONE(PtCr_byte),    /* byte */
210
11.6M
        OP_NONE(PtCr_int),   /* int */
211
11.6M
        OP_NONE(PtCr_float),   /* float */
212
11.6M
        OP_NONE(PtCr_true),    /* true */
213
11.6M
        OP_NONE(PtCr_false),   /* false */
214
215
    /* Special */
216
217
11.6M
        OP1(PtCr_if, E, E),    /* if */
218
11.6M
        OP_NONE(PtCr_else),    /* else */
219
11.6M
        OP_NONE(PtCr_return),    /* return */
220
11.6M
        OP1(E, PtCr_repeat, E),    /* repeat */
221
11.6M
        OP_NONE(PtCr_repeat_end) /* repeat_end */
222
11.6M
    };
223
224
11.6M
    memset(repeat_count, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
225
11.6M
    memset(repeat_proc_size, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
226
227
11.6M
    vstack[-1].type = CVT_NONE;  /* for type dispatch in empty stack case */
228
11.6M
    vstack[0].type = CVT_NONE;  /* catch underflow */
229
52.0M
    for (i = 0; i < pfn->params.m; ++i)
230
40.4M
        store_float(&vstack[i + 1], in[i]);
231
232
212M
    for (; ; ) {
233
212M
        int code, n;
234
235
212M
        switch (op_defn_table[*p++].opcode[(vsp[-1].type << 2) + vsp->type]) {
236
237
            /* Miscellaneous */
238
239
2.60M
        case PtCr_no_op:
240
2.60M
            continue;
241
26
        case PtCr_typecheck:
242
26
            return_error(gs_error_typecheck);
243
244
            /* Coerce and re-dispatch */
245
246
13.7M
        case PtCr_int_to_float:
247
13.7M
            store_float(vsp, (double)vsp->value.i);
248
13.7M
            --p; continue;
249
127k
        case PtCr_int2_to_float:
250
127k
            store_float(vsp, (double)vsp->value.i);
251
            /* fall through */
252
3.99M
        case PtCr_2nd_int_to_float:
253
3.99M
            store_float(vsp - 1, (double)vsp[-1].value.i);
254
3.99M
            --p; continue;
255
256
            /* Arithmetic operators */
257
258
3.57M
        case PtCr_abs:
259
3.57M
            vsp->value.f = fabs(vsp->value.f);
260
3.57M
            continue;
261
0
        case PtCr_add_int: {
262
0
            int int1 = vsp[-1].value.i, int2 = vsp->value.i;
263
264
0
            if ((int1 ^ int2) >= 0 && ((int1 + int2) ^ int1) < 0)
265
0
                store_float(vsp - 1, (double)int1 + int2);
266
0
            else
267
0
                vsp[-1].value.i = int1 + int2;
268
0
            --vsp; continue;
269
127k
        }
270
2.21M
        case PtCr_add:
271
2.21M
            vsp[-1].value.f += vsp->value.f;
272
2.21M
            --vsp; continue;
273
0
        case PtCr_and:
274
0
            vsp[-1].value.i &= vsp->value.i;
275
0
            --vsp; continue;
276
2.58M
        case PtCr_atan: {
277
2.58M
            double result;
278
279
2.58M
            code = gs_atan2_degrees(vsp[-1].value.f, vsp->value.f,
280
2.58M
                                    &result);
281
2.58M
            if (code < 0)
282
0
                return code;
283
2.58M
            vsp[-1].value.f = result;
284
2.58M
            --vsp; continue;
285
2.58M
        }
286
0
        case PtCr_bitshift:
287
0
#define MAX_SHIFT (ARCH_SIZEOF_INT * 8 - 1)
288
0
            if (vsp->value.i < -MAX_SHIFT || vsp->value.i > MAX_SHIFT)
289
0
                vsp[-1].value.i = 0;
290
0
#undef MAX_SHIFT
291
0
            else if ((n = vsp->value.i) < 0)
292
0
                vsp[-1].value.i = ((uint)(vsp[-1].value.i)) >> -n;
293
0
            else
294
0
                vsp[-1].value.i <<= n;
295
0
            --vsp; continue;
296
0
        case PtCr_ceiling:
297
0
            vsp->value.f = ceil(vsp->value.f);
298
0
            continue;
299
2.58M
        case PtCr_cos:
300
2.58M
            vsp->value.f = gs_cos_degrees(vsp->value.f);
301
2.58M
            continue;
302
0
        case PtCr_cvi:
303
0
        {
304
           /* Strictly speaking assigning one element of union
305
            * to another, overlapping element of a different size is
306
            * undefined behavior, hence assign to an intermediate variable
307
            */
308
0
            int int1 = (int)(vsp->value.f);
309
0
            vsp->value.i = int1;
310
0
            vsp->type = CVT_INT;
311
0
            continue;
312
2.58M
        }
313
0
        case PtCr_cvr:
314
0
            continue;  /* prepare handled it */
315
3.26M
        case PtCr_div:
316
3.26M
            if (vsp->value.f == 0)
317
0
                return_error(gs_error_undefinedresult);
318
3.26M
            vsp[-1].value.f /= vsp->value.f;
319
3.26M
            --vsp; continue;
320
0
        case PtCr_exp:
321
0
            vsp[-1].value.f = pow(vsp[-1].value.f, vsp->value.f);
322
0
            --vsp; continue;
323
0
        case PtCr_floor:
324
0
            vsp->value.f = floor(vsp->value.f);
325
0
            continue;
326
0
        case PtCr_idiv:
327
0
            if (vsp->value.i == 0)
328
0
                return_error(gs_error_undefinedresult);
329
0
            if (vsp[-1].value.i == min_int &&
330
0
                vsp->value.i == -1)  /* anomalous boundary case, fail */
331
0
                return_error(gs_error_rangecheck);
332
0
            else
333
0
                vsp[-1].value.i /= vsp->value.i;
334
0
            --vsp; continue;
335
0
        case PtCr_ln:
336
0
            vsp->value.f = log(vsp->value.f);
337
0
            continue;
338
0
        case PtCr_log:
339
0
            vsp->value.f = log10(vsp->value.f);
340
0
            continue;
341
0
        case PtCr_mod:
342
0
            if (vsp->value.i == 0)
343
0
                return_error(gs_error_undefinedresult);
344
0
            vsp[-1].value.i %= vsp->value.i;
345
0
            --vsp; continue;
346
2.88M
        case PtCr_mul_int: {
347
            /* We don't bother to optimize this. */
348
2.88M
            double prod = (double)vsp[-1].value.i * vsp->value.i;
349
350
2.88M
            if (prod < min_int || prod > max_int)
351
0
                store_float(vsp - 1, prod);
352
2.88M
            else
353
2.88M
                vsp[-1].value.i = (int)prod;
354
2.88M
            --vsp; continue;
355
0
        }
356
6.33M
        case PtCr_mul:
357
6.33M
            vsp[-1].value.f *= vsp->value.f;
358
6.33M
            --vsp; continue;
359
127k
        case PtCr_abs_int:
360
127k
            if (vsp->value.i >= 0)
361
127k
                continue;
362
            /* fallthrough */
363
0
        case PtCr_neg_int:
364
0
            if (vsp->value.i == min_int)
365
0
                store_float(vsp, (double)vsp->value.i); /* =self negated */
366
0
            else
367
0
                vsp->value.i = -vsp->value.i;
368
0
            continue;
369
0
        case PtCr_neg:
370
0
            vsp->value.f = -vsp->value.f;
371
0
            continue;
372
0
        case PtCr_not_bool:
373
0
            vsp->value.i = !vsp->value.i;
374
0
            continue;
375
0
        case PtCr_not:
376
0
            vsp->value.i = ~vsp->value.i;
377
0
            continue;
378
0
        case PtCr_or:
379
0
            vsp[-1].value.i |= vsp->value.i;
380
0
            --vsp; continue;
381
0
        case PtCr_round:
382
0
            vsp->value.f = floor(vsp->value.f + 0.5);
383
0
            continue;
384
3.26M
        case PtCr_sin:
385
3.26M
            vsp->value.f = gs_sin_degrees(vsp->value.f);
386
3.26M
            continue;
387
3.26M
        case PtCr_sqrt:
388
3.26M
            vsp->value.f = sqrt(vsp->value.f);
389
3.26M
            continue;
390
642k
        case PtCr_sub_int: {
391
642k
            int int1 = vsp[-1].value.i, int2 = vsp->value.i;
392
393
642k
            if ((int1 ^ int2) < 0 && ((int1 - int2) ^ int1) >= 0)
394
0
                store_float(vsp - 1, (double)int1 - int2);
395
642k
            else
396
642k
                vsp[-1].value.i = int1 - int2;
397
642k
            --vsp; continue;
398
127k
        }
399
13.4M
        case PtCr_sub:
400
13.4M
            vsp[-1].value.f -= vsp->value.f;
401
13.4M
            --vsp; continue;
402
0
        case PtCr_truncate:
403
0
            vsp->value.f = (vsp->value.f < 0 ? ceil(vsp->value.f) :
404
0
                            floor(vsp->value.f));
405
0
            continue;
406
0
        case PtCr_xor:
407
0
            vsp[-1].value.i ^= vsp->value.i;
408
0
            --vsp; continue;
409
410
            /* Boolean operators */
411
412
0
#define DO_REL(rel, m)\
413
3.41M
  vsp[-1].value.i = vsp[-1].value.m rel vsp->value.m
414
415
0
        case PtCr_eq_int:
416
0
            DO_REL(==, i);
417
0
            goto rel;
418
18
        case PtCr_ge_int:
419
18
            DO_REL(>=, i);
420
18
            goto rel;
421
46
        case PtCr_ge:
422
46
            DO_REL(>=, f);
423
46
            goto rel;
424
312
        case PtCr_gt_int:
425
312
            DO_REL(>, i);
426
312
            goto rel;
427
104
        case PtCr_gt:
428
104
            DO_REL(>, f);
429
104
            goto rel;
430
0
        case PtCr_le_int:
431
0
            DO_REL(<=, i);
432
0
            goto rel;
433
154k
        case PtCr_le:
434
154k
            DO_REL(<=, f);
435
154k
            goto rel;
436
0
        case PtCr_lt_int:
437
0
            DO_REL(<, i);
438
0
            goto rel;
439
3.26M
        case PtCr_lt:
440
3.26M
            DO_REL(<, f);
441
3.26M
            goto rel;
442
0
        case PtCr_ne_int:
443
0
            DO_REL(!=, i);
444
0
            goto rel;
445
0
        case PtCr_ne:
446
0
            DO_REL(!=, f);
447
0
            goto rel;
448
0
        case PtCr_eq:
449
0
            DO_REL(==, f);
450
3.41M
        rel:
451
3.41M
            vsp[-1].type = CVT_BOOL;
452
3.41M
            --vsp; continue;
453
454
0
#undef DO_REL
455
456
            /* Stack operators */
457
458
154k
        case PtCr_copy:
459
154k
            i = vsp->value.i;
460
154k
            n = vsp - vstack;
461
154k
            if (i < 0 || i >= n)
462
0
                return_error(gs_error_rangecheck);
463
154k
            if (i > MAX_VSTACK - (n - 1))
464
0
                return_error(gs_error_limitcheck);
465
154k
            memcpy(vsp, vsp - i, i * sizeof(*vsp));
466
154k
            vsp += i - 1;
467
154k
            continue;
468
13.5M
        case PtCr_dup:
469
13.5M
            vsp[1] = *vsp;
470
13.5M
            goto push;
471
18.8M
        case PtCr_exch:
472
18.8M
            vstack[MAX_VSTACK] = *vsp;
473
18.8M
            *vsp = vsp[-1];
474
18.8M
            vsp[-1] = vstack[MAX_VSTACK];
475
18.8M
            continue;
476
2.63M
        case PtCr_index:
477
2.63M
            i = vsp->value.i;
478
2.63M
            if (i < 0 || i >= vsp - vstack - 1)
479
0
                return_error(gs_error_rangecheck);
480
2.63M
            *vsp = vsp[-i - 1];
481
2.63M
            continue;
482
14.8M
        case PtCr_pop:
483
14.8M
            --vsp;
484
14.8M
            continue;
485
15.0M
        case PtCr_roll:
486
15.0M
            n = vsp[-1].value.i;
487
15.0M
            i = vsp->value.i;
488
15.0M
            if (n < 0 || n > vsp - vstack - 2)
489
0
                return_error(gs_error_rangecheck);
490
            /* We don't bother to do this efficiently. */
491
42.2M
            for (; i > 0; i--) {
492
27.1M
                memmove(vsp - n, vsp - (n + 1), n * sizeof(*vsp));
493
27.1M
                vsp[-(n + 1)] = vsp[-1];
494
27.1M
            }
495
17.9M
            for (; i < 0; i++) {
496
2.88M
                vsp[-1] = vsp[-(n + 1)];
497
2.88M
                memmove(vsp - (n + 1), vsp - n, n * sizeof(*vsp));
498
2.88M
            }
499
15.0M
            vsp -= 2;
500
15.0M
            continue;
501
502
            /* Constants */
503
504
46.2M
        case PtCr_byte:
505
46.2M
            vsp[1].value.i = *p++, vsp[1].type = CVT_INT;
506
46.2M
            goto push;
507
8.73M
        case PtCr_int /* native */:
508
8.73M
            memcpy(&vsp[1].value.i, p, sizeof(int));
509
8.73M
            vsp[1].type = CVT_INT;
510
8.73M
            p += sizeof(int);
511
8.73M
            goto push;
512
9.41M
        case PtCr_float /* native */:
513
9.41M
            memcpy(&vsp[1].value.f, p, sizeof(float));
514
9.41M
            vsp[1].type = CVT_FLOAT;
515
9.41M
            p += sizeof(float);
516
9.41M
            goto push;
517
0
        case PtCr_true:
518
0
            vsp[1].value.i = true, vsp[1].type = CVT_BOOL;
519
0
            goto push;
520
0
        case PtCr_false:
521
0
            vsp[1].value.i = false, vsp[1].type = CVT_BOOL;
522
77.9M
        push:
523
77.9M
            if (vsp == &vstack[MAX_VSTACK])
524
1
                return_error(gs_error_limitcheck);
525
77.9M
            ++vsp;
526
77.9M
            continue;
527
528
            /* Special */
529
530
3.41M
        case PtCr_if:
531
3.41M
            if ((vsp--)->value.i) { /* value is true, execute body */
532
2.95M
                p += 2;
533
2.95M
                continue;
534
2.95M
            }
535
            /* falls through */
536
538k
        case PtCr_else:
537
538k
            p += 2 + (p[0] << 8) + p[1];  /* skip the past body */
538
538k
            continue;
539
11.6M
        case PtCr_return:
540
11.6M
            goto fin;
541
0
        case PtCr_repeat:
542
0
            repeat_nesting_level++;
543
0
            repeat_count[repeat_nesting_level] = vsp->value.i;
544
0
            repeat_proc_size[repeat_nesting_level] = 1 + (p[0] << 8) + p[1];  /* body size */
545
0
            --vsp;    /* pop the counter */
546
0
            p += 3 + (p[0] <<8) + p[1];       /* advance just past the repeat_end */
547
            /* falls through */
548
0
        case PtCr_repeat_end:
549
0
            if (repeat_nesting_level < 0)
550
0
                return_error(gs_error_rangecheck);
551
552
0
            if ((repeat_count[repeat_nesting_level])-- <= 0)
553
0
                repeat_nesting_level--;
554
0
            else
555
0
                p -= repeat_proc_size[repeat_nesting_level];
556
0
            continue;
557
212M
        }
558
212M
    }
559
11.6M
 fin:
560
11.6M
    {   /* Following Acrobat, take the desired number of parameters */
561
        /* from the top of stack and ignore the rest. Bug 702950. */
562
11.6M
        int extra_ops = vsp - vstack - pfn->params.n;
563
11.6M
        if (extra_ops < 0)
564
24
            return_error(gs_error_rangecheck);
565
46.7M
        for (i = 0; i < pfn->params.n; ++i) {
566
35.1M
            switch (vstack[i + 1 + extra_ops].type) {
567
654k
            case CVT_INT:
568
654k
                out[i] = (float)vstack[i + 1 + extra_ops].value.i;
569
654k
                break;
570
34.4M
            case CVT_FLOAT:
571
34.4M
                out[i] = vstack[i + 1 + extra_ops].value.f;
572
34.4M
                break;
573
0
            default:
574
0
                return_error(gs_error_typecheck);
575
35.1M
            }
576
35.1M
        }
577
11.6M
    }
578
11.6M
    return 0;
579
11.6M
}
580
581
/* Test whether a PostScript Calculator function is monotonic. */
582
static int
583
fn_PtCr_is_monotonic(const gs_function_t * pfn_common,
584
                     const float *lower, const float *upper, uint *mask)
585
0
{
586
    /*
587
     * No reasonable way to tell.  Eventually we should check for
588
     * functions consisting of only stack-manipulating operations,
589
     * since these may be common for DeviceN color spaces and *are*
590
     * monotonic.
591
     */
592
0
    *mask = 0x49249249;
593
0
    return 0;
594
0
}
595
596
/* Write the function definition in symbolic form on a stream. */
597
static int
598
calc_put_ops(stream *s, const byte *ops, uint size)
599
1.43k
{
600
1.43k
    const byte *p;
601
602
1.43k
    spputc(s, '{');
603
9.49k
    for (p = ops; p < ops + size; )
604
8.05k
        switch (*p++) {
605
2.30k
        case PtCr_byte:
606
2.30k
            pprintd1(s, "%d ", *p++);
607
2.30k
            break;
608
443
        case PtCr_int: {
609
443
            int i;
610
611
443
            memcpy(&i, p, sizeof(int));
612
443
            pprintd1(s, "%d ", i);
613
443
            p += sizeof(int);
614
443
            break;
615
0
        }
616
2.33k
        case PtCr_float: {
617
2.33k
            float f;
618
619
2.33k
            memcpy(&f, p, sizeof(float));
620
2.33k
            pprintg1(s, "%g ", f);
621
2.33k
            p += sizeof(float);
622
2.33k
            break;
623
0
        }
624
0
        case PtCr_true:
625
0
            stream_puts(s, "true ");
626
0
            break;
627
0
        case PtCr_false:
628
0
            stream_puts(s, "false ");
629
0
            break;
630
176
        case PtCr_if: {
631
176
            int skip = (p[0] << 8) + p[1];
632
176
            int code;
633
634
176
            code = calc_put_ops(s, p += 2, skip);
635
176
            p += skip;
636
176
            if (code < 0)
637
0
                return code;
638
176
            if (code > 0) { /* else */
639
0
                skip = (p[-2] << 8) + p[-1];
640
0
                code = calc_put_ops(s, p, skip);
641
0
                p += skip;
642
0
                if (code < 0)
643
0
                    return code;
644
0
                stream_puts(s, " ifelse ");
645
0
            } else
646
176
                stream_puts(s, " if ");
647
176
            break;
648
176
        }
649
176
        case PtCr_else:
650
0
            if (p != ops + size - 2)
651
0
                return_error(gs_error_rangecheck);
652
0
            spputc(s, '}');
653
0
            return 1;
654
        /*case PtCr_return:*/ /* not possible */
655
0
        case PtCr_repeat:   /* We shouldn't encounter this, but just in case */
656
0
        case PtCr_repeat_end:
657
0
            return_error(gs_error_rangecheck);
658
2.79k
        default: {    /* must be < PtCr_NUM_OPS */
659
2.79k
                static const char *const op_names[] = {
660
                    /* Keep this consistent with opcodes in gsfunc4.h! */
661
2.79k
                    "abs", "add", "and", "atan", "bitshift",
662
2.79k
                    "ceiling", "cos", "cvi", "cvr", "div", "exp",
663
2.79k
                    "floor", "idiv", "ln", "log", "mod", "mul",
664
2.79k
                    "neg", "not", "or", "round", "sin", "sqrt", "sub",
665
2.79k
                    "truncate", "xor",
666
2.79k
                    "eq", "ge", "gt", "le", "lt", "ne",
667
2.79k
                    "copy", "dup", "exch", "index", "pop", "roll"
668
2.79k
                };
669
670
2.79k
                pprints1(s, "%s ", op_names[p[-1]]);
671
2.79k
            }
672
8.05k
        }
673
1.43k
    spputc(s, '}');
674
1.43k
    return 0;
675
1.43k
}
676
static int
677
calc_put(stream *s, const gs_function_PtCr_t *pfn)
678
1.26k
{
679
1.26k
    calc_put_ops(s, pfn->params.ops.data, pfn->params.ops.size - 1);
680
1.26k
    return 0;
681
1.26k
}
682
683
/* Access the symbolic definition as a DataSource. */
684
static int
685
calc_access(const gs_data_source_t *psrc, ulong start, uint length,
686
            byte *buf, const byte **ptr)
687
642
{
688
642
    const gs_function_PtCr_t *const pfn =
689
642
        (const gs_function_PtCr_t *)
690
642
          ((const char *)psrc - offset_of(gs_function_PtCr_t, data_source));
691
    /*
692
     * The caller wants a specific substring of the symbolic definition.
693
     * Generate the entire definition, using a SubFileDecode filter (in an
694
     * output pipeline!) to extract the substring.  This is very
695
     * inefficient, but this code is rarely used, and almost never actually
696
     * has to break up the definition into pieces to fit in the caller's
697
     * buffer.
698
     */
699
642
    stream_SFD_state st;
700
642
    stream ds, bs;
701
642
    byte dbuf[200];   /* arbitrary */
702
642
    const stream_template *const templat = &s_SFD_template;
703
704
    /* Set up the stream that writes into the buffer. */
705
642
    s_init(&bs, NULL);
706
642
    swrite_string(&bs, buf, length);
707
    /* Set up the SubFileDecode stream. */
708
642
    s_init(&ds, NULL);
709
642
    s_init_state((stream_state *)&st, templat, NULL);
710
642
    templat->set_defaults((stream_state *)&st);
711
642
    st.skip_count = start;
712
642
    s_init_filter(&ds, (stream_state *)&st, dbuf, sizeof(dbuf), &bs);
713
642
    calc_put(&ds, pfn);
714
642
    sclose(&ds);
715
642
    if (ptr)
716
642
        *ptr = buf;
717
642
    return 0;
718
642
}
719
720
/* Return PostScript Calculator function information. */
721
static void
722
fn_PtCr_get_info(const gs_function_t *pfn_common, gs_function_info_t *pfi)
723
621
{
724
621
    const gs_function_PtCr_t *const pfn =
725
621
        (const gs_function_PtCr_t *)pfn_common;
726
727
621
    gs_function_get_info_default(pfn_common, pfi);
728
621
    pfi->DataSource = &pfn->data_source;
729
621
    {
730
621
        stream s;
731
732
621
        s_init(&s, NULL);
733
621
        swrite_position_only(&s);
734
621
        calc_put(&s, pfn);
735
621
        pfi->data_size = stell(&s);
736
621
    }
737
621
}
738
739
/* Make a scaled copy of a PostScript Calculator function. */
740
static int
741
fn_PtCr_make_scaled(const gs_function_PtCr_t *pfn, gs_function_PtCr_t **ppsfn,
742
                    const gs_range_t *pranges, gs_memory_t *mem)
743
0
{
744
0
    gs_function_PtCr_t *psfn =
745
0
        gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
746
0
                        "fn_PtCr_make_scaled");
747
    /* We are adding {<int> 1 roll <float> mul <float> add} for each output. */
748
0
    int n = pfn->params.n;
749
0
    uint opsize = pfn->params.ops.size + (9 + 2 * sizeof(float)) * n;
750
0
    byte *ops = gs_alloc_string(mem, opsize, "fn_PtCr_make_scaled(ops)");
751
0
    byte *p;
752
0
    int code, i;
753
754
0
    if (psfn == 0 || ops == 0) {
755
0
        gs_free_string(mem, ops, opsize, "fn_PtCr_make_scaled(ops)");
756
0
        gs_free_object(mem, psfn, "fn_PtCr_make_scaled");
757
0
        return_error(gs_error_VMerror);
758
0
    }
759
0
    psfn->params = pfn->params;
760
0
    psfn->params.ops.data = ops;
761
0
    psfn->params.ops.size = opsize;
762
0
    psfn->data_source = pfn->data_source;
763
0
    code = fn_common_scale((gs_function_t *)psfn, (const gs_function_t *)pfn,
764
0
                           pranges, mem);
765
0
    if (code < 0) {
766
0
        gs_function_free((gs_function_t *)psfn, true, mem);
767
0
        return code;
768
0
    }
769
0
    memcpy(ops, pfn->params.ops.data, pfn->params.ops.size - 1); /* minus return */
770
0
    p = ops + pfn->params.ops.size - 1;
771
0
    for (i = n; --i >= 0; ) {
772
0
        float base = pranges[i].rmin;
773
0
        float factor = pranges[i].rmax - base;
774
775
0
        if (factor != 1) {
776
0
            p[0] = PtCr_float; memcpy(p + 1, &factor, sizeof(float));
777
0
            p += 1 + sizeof(float);
778
0
            *p++ = PtCr_mul;
779
0
        }
780
0
        if (base != 0) {
781
0
            p[0] = PtCr_float; memcpy(p + 1, &base, sizeof(float));
782
0
            p += 1 + sizeof(float);
783
0
            *p++ = PtCr_add;
784
0
        }
785
0
        if (n != 1) {
786
0
            p[0] = PtCr_byte; p[1] = (byte)n;
787
0
            p[2] = PtCr_byte; p[3] = 1;
788
0
            p[4] = PtCr_roll;
789
0
            p += 5;
790
0
        }
791
0
    }
792
0
    *p++ = PtCr_return;
793
0
    psfn->params.ops.size = p - ops;
794
0
    psfn->params.ops.data =
795
0
        gs_resize_string(mem, ops, opsize, psfn->params.ops.size,
796
0
                         "fn_PtCr_make_scaled");
797
0
    *ppsfn = psfn;
798
0
    return 0;
799
0
}
800
801
/* Free the parameters of a PostScript Calculator function. */
802
void
803
gs_function_PtCr_free_params(gs_function_PtCr_params_t * params, gs_memory_t * mem)
804
57.5k
{
805
57.5k
    gs_free_const_string(mem, params->ops.data, params->ops.size, "ops");
806
57.5k
    params->ops.data = NULL;
807
57.5k
    params->ops.size = 0;
808
57.5k
    fn_common_free_params((gs_function_params_t *) params, mem);
809
57.5k
}
810
811
/* Serialize. */
812
static int
813
gs_function_PtCr_serialize(const gs_function_t * pfn, stream *s)
814
20.0k
{
815
20.0k
    uint n;
816
20.0k
    const gs_function_PtCr_params_t * p = (const gs_function_PtCr_params_t *)&pfn->params;
817
20.0k
    int code = fn_common_serialize(pfn, s);
818
819
20.0k
    if (code < 0)
820
0
        return code;
821
20.0k
    code = sputs(s, (const byte *)&p->ops.size, sizeof(p->ops.size), &n);
822
20.0k
    if (code < 0)
823
0
        return code;
824
20.0k
    return sputs(s, p->ops.data, p->ops.size, &n);
825
20.0k
}
826
827
/* Allocate and initialize a PostScript Calculator function. */
828
int
829
gs_function_PtCr_init(gs_function_t ** ppfn,
830
                  const gs_function_PtCr_params_t * params, gs_memory_t * mem)
831
60.7k
{
832
60.7k
    static const gs_function_head_t function_PtCr_head = {
833
60.7k
        function_type_PostScript_Calculator,
834
60.7k
        {
835
60.7k
            (fn_evaluate_proc_t) fn_PtCr_evaluate,
836
60.7k
            (fn_is_monotonic_proc_t) fn_PtCr_is_monotonic,
837
60.7k
            (fn_get_info_proc_t) fn_PtCr_get_info,
838
60.7k
            fn_common_get_params,
839
60.7k
            (fn_make_scaled_proc_t) fn_PtCr_make_scaled,
840
60.7k
            (fn_free_params_proc_t) gs_function_PtCr_free_params,
841
60.7k
            fn_common_free,
842
60.7k
            (fn_serialize_proc_t) gs_function_PtCr_serialize,
843
60.7k
        }
844
60.7k
    };
845
60.7k
    int code;
846
847
60.7k
    *ppfn = 0;      /* in case of error */
848
60.7k
    code = fn_check_mnDR((const gs_function_params_t *)params,
849
60.7k
                         params->m, params->n);
850
60.7k
    if (code < 0)
851
15
        return code;
852
60.7k
    if (params->m > MAX_VSTACK || params->n > MAX_VSTACK)
853
0
        return_error(gs_error_limitcheck);
854
    /*
855
     * Pre-validate the operation string to reduce evaluation overhead.
856
     */
857
60.7k
    {
858
60.7k
        const byte *p = params->ops.data;
859
860
2.64M
        for (; *p != PtCr_return; ++p)
861
2.58M
            switch ((gs_PtCr_opcode_t)*p) {
862
801k
            case PtCr_byte:
863
801k
                ++p; break;
864
141k
            case PtCr_int:
865
141k
                p += sizeof(int); break;
866
181k
            case PtCr_float:
867
181k
                p += sizeof(float); break;
868
0
            case PtCr_repeat:
869
19.8k
            case PtCr_if:
870
39.1k
            case PtCr_else:
871
39.1k
                p += 2;
872
39.1k
            case PtCr_repeat_end:
873
39.1k
            case PtCr_true:
874
39.1k
            case PtCr_false:
875
39.1k
                break;
876
1.41M
            default:
877
1.41M
                if (*p >= PtCr_NUM_OPS)
878
0
                    return_error(gs_error_rangecheck);
879
2.58M
            }
880
60.7k
        if (p != params->ops.data + params->ops.size - 1)
881
0
            return_error(gs_error_rangecheck);
882
60.7k
    }
883
60.7k
    {
884
60.7k
        gs_function_PtCr_t *pfn =
885
60.7k
            gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
886
60.7k
                            "gs_function_PtCr_init");
887
888
60.7k
        if (pfn == 0)
889
0
            return_error(gs_error_VMerror);
890
60.7k
        pfn->params = *params;
891
        /*
892
         * We claim to have a DataSource, in order to write the function
893
         * definition in symbolic form for embedding in PDF files.
894
         * ****** THIS IS A HACK. ******
895
         */
896
60.7k
        data_source_init_string2(&pfn->data_source, NULL, 0);
897
60.7k
        pfn->data_source.access = calc_access;
898
60.7k
        pfn->head = function_PtCr_head;
899
60.7k
        *ppfn = (gs_function_t *) pfn;
900
60.7k
    }
901
0
    return 0;
902
60.7k
}