Coverage Report

Created: 2025-08-28 07:06

/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
109M
#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
52.8M
{
67
52.8M
    vsp->value.f = f;
68
52.8M
    vsp->type = CVT_FLOAT;
69
52.8M
}
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
10.3M
{
109
10.3M
    const gs_function_PtCr_t *pfn = (const gs_function_PtCr_t *)pfn_common;
110
10.3M
    calc_value_t vstack_buf[2 + MAX_VSTACK + 1];
111
10.3M
    calc_value_t *vstack = &vstack_buf[1];
112
10.3M
    calc_value_t *vsp = vstack + pfn->params.m;
113
10.3M
    const byte *p = pfn->params.ops.data;
114
10.3M
    int repeat_count[MAX_PSC_FUNCTION_NESTING];
115
10.3M
    int repeat_proc_size[MAX_PSC_FUNCTION_NESTING];
116
10.3M
    int repeat_nesting_level = -1;
117
10.3M
    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
10.3M
    static const struct op_defn_s {
125
10.3M
        byte opcode[16];  /* 4 * type[-1] + type[0] */
126
10.3M
    } op_defn_table[] = {
127
        /* Keep this consistent with opcodes in gsfunc4.h! */
128
129
758M
#define O4(op) op,op,op,op
130
1.67G
#define E PtCr_typecheck
131
426M
#define E4 O4(E)
132
10.3M
#define N PtCr_no_op
133
        /* 0-operand operators */
134
10.3M
#define OP_NONE(op)\
135
83.1M
  {{O4(op), O4(op), O4(op), O4(op)}}
136
        /* 1-operand operators */
137
10.3M
#define OP1(b, i, f)\
138
207M
  {{E,b,i,f, E,b,i,f, E,b,i,f, E,b,i,f}}
139
10.3M
#define OP_NUM1(i, f)\
140
83.1M
  OP1(E, i, f)
141
10.3M
#define OP_MATH1(f)\
142
51.9M
  OP1(E, PtCr_int_to_float, f)
143
10.3M
#define OP_ANY1(op)\
144
20.7M
  OP1(op, op, op)
145
        /* 2-operand operators */
146
10.3M
#define OP_NUM2(i, f)\
147
72.7M
  {{E4, E4, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
148
10.3M
#define OP_INT_BOOL2(i)\
149
31.1M
  {{E4, E,i,i,E, E,i,i,E, E4}}
150
10.3M
#define OP_MATH2(f)\
151
31.1M
  {{E4, E4, E,E,PtCr_int2_to_float,PtCr_2nd_int_to_float,\
152
31.1M
    E,E,PtCr_int_to_float,f}}
153
10.3M
#define OP_INT2(i)\
154
41.5M
  {{E4, E4, E,E,i,E, E4}}
155
10.3M
#define OP_REL2(i, f)\
156
20.7M
  {{E4, E,i,E,E, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
157
10.3M
#define OP_ANY2(op)\
158
10.3M
  {{E4, E,op,op,op, E,op,op,op, E,op,op,op}}
159
160
    /* Arithmetic operators */
161
162
10.3M
        OP_NUM1(PtCr_abs_int, PtCr_abs), /* abs */
163
10.3M
        OP_NUM2(PtCr_add_int, PtCr_add), /* add */
164
10.3M
        OP_INT_BOOL2(PtCr_and),  /* and */
165
10.3M
        OP_MATH2(PtCr_atan),  /* atan */
166
10.3M
        OP_INT2(PtCr_bitshift),  /* bitshift */
167
10.3M
        OP_NUM1(N, PtCr_ceiling),  /* ceiling */
168
10.3M
        OP_MATH1(PtCr_cos), /* cos */
169
10.3M
        OP_NUM1(N, PtCr_cvi),  /* cvi */
170
10.3M
        OP_NUM1(PtCr_int_to_float, N), /* cvr */
171
10.3M
        OP_MATH2(PtCr_div), /* div */
172
10.3M
        OP_MATH2(PtCr_exp), /* exp */
173
10.3M
        OP_NUM1(N, PtCr_floor),  /* floor */
174
10.3M
        OP_INT2(PtCr_idiv),  /* idiv */
175
10.3M
        OP_MATH1(PtCr_ln),  /* ln */
176
10.3M
        OP_MATH1(PtCr_log), /* log */
177
10.3M
        OP_INT2(PtCr_mod), /* mod */
178
10.3M
        OP_NUM2(PtCr_mul_int, PtCr_mul), /* mul */
179
10.3M
        OP_NUM1(PtCr_neg_int, PtCr_neg), /* neg */
180
10.3M
        OP1(PtCr_not, PtCr_not, E),  /* not */
181
10.3M
        OP_INT_BOOL2(PtCr_or),  /* or */
182
10.3M
        OP_NUM1(N, PtCr_round),  /* round */
183
10.3M
        OP_MATH1(PtCr_sin), /* sin */
184
10.3M
        OP_MATH1(PtCr_sqrt),  /* sqrt */
185
10.3M
        OP_NUM2(PtCr_sub_int, PtCr_sub), /* sub */
186
10.3M
        OP_NUM1(N, PtCr_truncate), /* truncate */
187
10.3M
        OP_INT_BOOL2(PtCr_xor),  /* xor */
188
189
    /* Comparison operators */
190
191
10.3M
        OP_REL2(PtCr_eq_int, PtCr_eq), /* eq */
192
10.3M
        OP_NUM2(PtCr_ge_int, PtCr_ge), /* ge */
193
10.3M
        OP_NUM2(PtCr_gt_int, PtCr_gt), /* gt */
194
10.3M
        OP_NUM2(PtCr_le_int, PtCr_le), /* le */
195
10.3M
        OP_NUM2(PtCr_lt_int, PtCr_lt), /* lt */
196
10.3M
        OP_REL2(PtCr_ne_int, PtCr_ne), /* ne */
197
198
    /* Stack operators */
199
200
10.3M
        OP1(E, PtCr_copy, E),  /* copy */
201
10.3M
        OP_ANY1(PtCr_dup), /* dup */
202
10.3M
        OP_ANY2(PtCr_exch),  /* exch */
203
10.3M
        OP1(E, PtCr_index, E), /* index */
204
10.3M
        OP_ANY1(PtCr_pop), /* pop */
205
10.3M
        OP_INT2(PtCr_roll),  /* roll */
206
207
    /* Constants */
208
209
10.3M
        OP_NONE(PtCr_byte),    /* byte */
210
10.3M
        OP_NONE(PtCr_int),   /* int */
211
10.3M
        OP_NONE(PtCr_float),   /* float */
212
10.3M
        OP_NONE(PtCr_true),    /* true */
213
10.3M
        OP_NONE(PtCr_false),   /* false */
214
215
    /* Special */
216
217
10.3M
        OP1(PtCr_if, E, E),    /* if */
218
10.3M
        OP_NONE(PtCr_else),    /* else */
219
10.3M
        OP_NONE(PtCr_return),    /* return */
220
10.3M
        OP1(E, PtCr_repeat, E),    /* repeat */
221
10.3M
        OP_NONE(PtCr_repeat_end) /* repeat_end */
222
10.3M
    };
223
224
10.3M
    memset(repeat_count, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
225
10.3M
    memset(repeat_proc_size, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
226
227
10.3M
    vstack[-1].type = CVT_NONE;  /* for type dispatch in empty stack case */
228
10.3M
    vstack[0].type = CVT_NONE;  /* catch underflow */
229
45.7M
    for (i = 0; i < pfn->params.m; ++i)
230
35.3M
        store_float(&vstack[i + 1], in[i]);
231
232
200M
    for (; ; ) {
233
200M
        int code, n;
234
235
200M
        switch (op_defn_table[*p++].opcode[(vsp[-1].type << 2) + vsp->type]) {
236
237
            /* Miscellaneous */
238
239
2.49M
        case PtCr_no_op:
240
2.49M
            continue;
241
40
        case PtCr_typecheck:
242
40
            return_error(gs_error_typecheck);
243
244
            /* Coerce and re-dispatch */
245
246
13.4M
        case PtCr_int_to_float:
247
13.4M
            store_float(vsp, (double)vsp->value.i);
248
13.4M
            --p; continue;
249
127k
        case PtCr_int2_to_float:
250
127k
            store_float(vsp, (double)vsp->value.i);
251
            /* fall through */
252
3.90M
        case PtCr_2nd_int_to_float:
253
3.90M
            store_float(vsp - 1, (double)vsp[-1].value.i);
254
3.90M
            --p; continue;
255
256
            /* Arithmetic operators */
257
258
3.87M
        case PtCr_abs:
259
3.87M
            vsp->value.f = fabs(vsp->value.f);
260
3.87M
            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
1.92M
        case PtCr_add:
271
1.92M
            vsp[-1].value.f += vsp->value.f;
272
1.92M
            --vsp; continue;
273
0
        case PtCr_and:
274
0
            vsp[-1].value.i &= vsp->value.i;
275
0
            --vsp; continue;
276
2.77M
        case PtCr_atan: {
277
2.77M
            double result;
278
279
2.77M
            code = gs_atan2_degrees(vsp[-1].value.f, vsp->value.f,
280
2.77M
                                    &result);
281
2.77M
            if (code < 0)
282
0
                return code;
283
2.77M
            vsp[-1].value.f = result;
284
2.77M
            --vsp; continue;
285
2.77M
        }
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.77M
        case PtCr_cos:
300
2.77M
            vsp->value.f = gs_cos_degrees(vsp->value.f);
301
2.77M
            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.77M
        }
313
0
        case PtCr_cvr:
314
0
            continue;  /* prepare handled it */
315
3.18M
        case PtCr_div:
316
3.18M
            if (vsp->value.f == 0)
317
0
                return_error(gs_error_undefinedresult);
318
3.18M
            vsp[-1].value.f /= vsp->value.f;
319
3.18M
            --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.81M
        case PtCr_mul_int: {
347
            /* We don't bother to optimize this. */
348
2.81M
            double prod = (double)vsp[-1].value.i * vsp->value.i;
349
350
2.81M
            if (prod < min_int || prod > max_int)
351
0
                store_float(vsp - 1, prod);
352
2.81M
            else
353
2.81M
                vsp[-1].value.i = (int)prod;
354
2.81M
            --vsp; continue;
355
0
        }
356
5.92M
        case PtCr_mul:
357
5.92M
            vsp[-1].value.f *= vsp->value.f;
358
5.92M
            --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.18M
        case PtCr_sin:
385
3.18M
            vsp->value.f = gs_sin_degrees(vsp->value.f);
386
3.18M
            continue;
387
3.18M
        case PtCr_sqrt:
388
3.18M
            vsp->value.f = sqrt(vsp->value.f);
389
3.18M
            continue;
390
481k
        case PtCr_sub_int: {
391
481k
            int int1 = vsp[-1].value.i, int2 = vsp->value.i;
392
393
481k
            if ((int1 ^ int2) < 0 && ((int1 - int2) ^ int1) >= 0)
394
0
                store_float(vsp - 1, (double)int1 - int2);
395
481k
            else
396
481k
                vsp[-1].value.i = int1 - int2;
397
481k
            --vsp; continue;
398
127k
        }
399
13.3M
        case PtCr_sub:
400
13.3M
            vsp[-1].value.f -= vsp->value.f;
401
13.3M
            --vsp; continue;
402
17
        case PtCr_truncate:
403
17
            vsp->value.f = (vsp->value.f < 0 ? ceil(vsp->value.f) :
404
17
                            floor(vsp->value.f));
405
17
            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.53M
  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
22
        case PtCr_ge_int:
419
22
            DO_REL(>=, i);
420
22
            goto rel;
421
48
        case PtCr_ge:
422
48
            DO_REL(>=, f);
423
48
            goto rel;
424
333
        case PtCr_gt_int:
425
333
            DO_REL(>, i);
426
333
            goto rel;
427
111
        case PtCr_gt:
428
111
            DO_REL(>, f);
429
111
            goto rel;
430
0
        case PtCr_le_int:
431
0
            DO_REL(<=, i);
432
0
            goto rel;
433
343k
        case PtCr_le:
434
343k
            DO_REL(<=, f);
435
343k
            goto rel;
436
0
        case PtCr_lt_int:
437
0
            DO_REL(<, i);
438
0
            goto rel;
439
3.18M
        case PtCr_lt:
440
3.18M
            DO_REL(<, f);
441
3.18M
            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.53M
        rel:
451
3.53M
            vsp[-1].type = CVT_BOOL;
452
3.53M
            --vsp; continue;
453
454
0
#undef DO_REL
455
456
            /* Stack operators */
457
458
343k
        case PtCr_copy:
459
343k
            i = vsp->value.i;
460
343k
            n = vsp - vstack;
461
343k
            if (i < 0 || i >= n)
462
0
                return_error(gs_error_rangecheck);
463
343k
            if (i > MAX_VSTACK - (n - 1))
464
0
                return_error(gs_error_limitcheck);
465
343k
            memcpy(vsp, vsp - i, i * sizeof(*vsp));
466
343k
            vsp += i - 1;
467
343k
            continue;
468
13.6M
        case PtCr_dup:
469
13.6M
            vsp[1] = *vsp;
470
13.6M
            goto push;
471
18.2M
        case PtCr_exch:
472
18.2M
            vstack[MAX_VSTACK] = *vsp;
473
18.2M
            *vsp = vsp[-1];
474
18.2M
            vsp[-1] = vstack[MAX_VSTACK];
475
18.2M
            continue;
476
1.97M
        case PtCr_index:
477
1.97M
            i = vsp->value.i;
478
1.97M
            if (i < 0 || i >= vsp - vstack - 1)
479
0
                return_error(gs_error_rangecheck);
480
1.97M
            *vsp = vsp[-i - 1];
481
1.97M
            continue;
482
13.1M
        case PtCr_pop:
483
13.1M
            --vsp;
484
13.1M
            continue;
485
13.1M
        case PtCr_roll:
486
13.1M
            n = vsp[-1].value.i;
487
13.1M
            i = vsp->value.i;
488
13.1M
            if (n < 0 || n > vsp - vstack - 2)
489
0
                return_error(gs_error_rangecheck);
490
            /* We don't bother to do this efficiently. */
491
36.1M
            for (; i > 0; i--) {
492
22.9M
                memmove(vsp - n, vsp - (n + 1), n * sizeof(*vsp));
493
22.9M
                vsp[-(n + 1)] = vsp[-1];
494
22.9M
            }
495
15.7M
            for (; i < 0; i++) {
496
2.60M
                vsp[-1] = vsp[-(n + 1)];
497
2.60M
                memmove(vsp - (n + 1), vsp - n, n * sizeof(*vsp));
498
2.60M
            }
499
13.1M
            vsp -= 2;
500
13.1M
            continue;
501
502
            /* Constants */
503
504
41.4M
        case PtCr_byte:
505
41.4M
            vsp[1].value.i = *p++, vsp[1].type = CVT_INT;
506
41.4M
            goto push;
507
8.56M
        case PtCr_int /* native */:
508
8.56M
            memcpy(&vsp[1].value.i, p, sizeof(int));
509
8.56M
            vsp[1].type = CVT_INT;
510
8.56M
            p += sizeof(int);
511
8.56M
            goto push;
512
8.82M
        case PtCr_float /* native */:
513
8.82M
            memcpy(&vsp[1].value.f, p, sizeof(float));
514
8.82M
            vsp[1].type = CVT_FLOAT;
515
8.82M
            p += sizeof(float);
516
8.82M
            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
72.4M
        push:
523
72.4M
            if (vsp == &vstack[MAX_VSTACK])
524
1
                return_error(gs_error_limitcheck);
525
72.4M
            ++vsp;
526
72.4M
            continue;
527
528
            /* Special */
529
530
3.53M
        case PtCr_if:
531
3.53M
            if ((vsp--)->value.i) { /* value is true, execute body */
532
2.98M
                p += 2;
533
2.98M
                continue;
534
2.98M
            }
535
            /* falls through */
536
723k
        case PtCr_else:
537
723k
            p += 2 + (p[0] << 8) + p[1];  /* skip the past body */
538
723k
            continue;
539
10.3M
        case PtCr_return:
540
10.3M
            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
200M
        }
558
200M
    }
559
10.3M
 fin:
560
10.3M
    {   /* Following Acrobat, take the desired number of parameters */
561
        /* from the top of stack and ignore the rest. Bug 702950. */
562
10.3M
        int extra_ops = vsp - vstack - pfn->params.n;
563
10.3M
        if (extra_ops < 0)
564
78
            return_error(gs_error_rangecheck);
565
41.3M
        for (i = 0; i < pfn->params.n; ++i) {
566
30.9M
            switch (vstack[i + 1 + extra_ops].type) {
567
495k
            case CVT_INT:
568
495k
                out[i] = (float)vstack[i + 1 + extra_ops].value.i;
569
495k
                break;
570
30.4M
            case CVT_FLOAT:
571
30.4M
                out[i] = vstack[i + 1 + extra_ops].value.f;
572
30.4M
                break;
573
0
            default:
574
0
                return_error(gs_error_typecheck);
575
30.9M
            }
576
30.9M
        }
577
10.3M
    }
578
10.3M
    return 0;
579
10.3M
}
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
2.30k
{
600
2.30k
    const byte *p;
601
602
2.30k
    spputc(s, '{');
603
27.7k
    for (p = ops; p < ops + size; )
604
25.4k
        switch (*p++) {
605
7.86k
        case PtCr_byte:
606
7.86k
            pprintd1(s, "%d ", *p++);
607
7.86k
            break;
608
1.18k
        case PtCr_int: {
609
1.18k
            int i;
610
611
1.18k
            memcpy(&i, p, sizeof(int));
612
1.18k
            pprintd1(s, "%d ", i);
613
1.18k
            p += sizeof(int);
614
1.18k
            break;
615
0
        }
616
5.03k
        case PtCr_float: {
617
5.03k
            float f;
618
619
5.03k
            memcpy(&f, p, sizeof(float));
620
5.03k
            pprintg1(s, "%g ", f);
621
5.03k
            p += sizeof(float);
622
5.03k
            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
269
        case PtCr_if: {
631
269
            int skip = (p[0] << 8) + p[1];
632
269
            int code;
633
634
269
            code = calc_put_ops(s, p += 2, skip);
635
269
            p += skip;
636
269
            if (code < 0)
637
0
                return code;
638
269
            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
269
                stream_puts(s, " if ");
647
269
            break;
648
269
        }
649
269
        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
11.0k
        default: {    /* must be < PtCr_NUM_OPS */
659
11.0k
                static const char *const op_names[] = {
660
                    /* Keep this consistent with opcodes in gsfunc4.h! */
661
11.0k
                    "abs", "add", "and", "atan", "bitshift",
662
11.0k
                    "ceiling", "cos", "cvi", "cvr", "div", "exp",
663
11.0k
                    "floor", "idiv", "ln", "log", "mod", "mul",
664
11.0k
                    "neg", "not", "or", "round", "sin", "sqrt", "sub",
665
11.0k
                    "truncate", "xor",
666
11.0k
                    "eq", "ge", "gt", "le", "lt", "ne",
667
11.0k
                    "copy", "dup", "exch", "index", "pop", "roll"
668
11.0k
                };
669
670
11.0k
                pprints1(s, "%s ", op_names[p[-1]]);
671
11.0k
            }
672
25.4k
        }
673
2.30k
    spputc(s, '}');
674
2.30k
    return 0;
675
2.30k
}
676
static int
677
calc_put(stream *s, const gs_function_PtCr_t *pfn)
678
2.03k
{
679
2.03k
    calc_put_ops(s, pfn->params.ops.data, pfn->params.ops.size - 1);
680
2.03k
    return 0;
681
2.03k
}
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
1.08k
{
688
1.08k
    const gs_function_PtCr_t *const pfn =
689
1.08k
        (const gs_function_PtCr_t *)
690
1.08k
          ((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
1.08k
    stream_SFD_state st;
700
1.08k
    stream ds, bs;
701
1.08k
    byte dbuf[200];   /* arbitrary */
702
1.08k
    const stream_template *const templat = &s_SFD_template;
703
704
    /* Set up the stream that writes into the buffer. */
705
1.08k
    s_init(&bs, NULL);
706
1.08k
    swrite_string(&bs, buf, length);
707
    /* Set up the SubFileDecode stream. */
708
1.08k
    s_init(&ds, NULL);
709
1.08k
    s_init_state((stream_state *)&st, templat, NULL);
710
1.08k
    templat->set_defaults((stream_state *)&st);
711
1.08k
    st.skip_count = start;
712
1.08k
    s_init_filter(&ds, (stream_state *)&st, dbuf, sizeof(dbuf), &bs);
713
1.08k
    calc_put(&ds, pfn);
714
1.08k
    sclose(&ds);
715
1.08k
    if (ptr)
716
1.08k
        *ptr = buf;
717
1.08k
    return 0;
718
1.08k
}
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
952
{
724
952
    const gs_function_PtCr_t *const pfn =
725
952
        (const gs_function_PtCr_t *)pfn_common;
726
727
952
    gs_function_get_info_default(pfn_common, pfi);
728
952
    pfi->DataSource = &pfn->data_source;
729
952
    {
730
952
        stream s;
731
732
952
        s_init(&s, NULL);
733
952
        swrite_position_only(&s);
734
952
        calc_put(&s, pfn);
735
952
        pfi->data_size = stell(&s);
736
952
    }
737
952
}
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
84.0k
{
805
84.0k
    gs_free_const_string(mem, params->ops.data, params->ops.size, "ops");
806
84.0k
    params->ops.data = NULL;
807
84.0k
    params->ops.size = 0;
808
84.0k
    fn_common_free_params((gs_function_params_t *) params, mem);
809
84.0k
}
810
811
/* Serialize. */
812
static int
813
gs_function_PtCr_serialize(const gs_function_t * pfn, stream *s)
814
23.0k
{
815
23.0k
    uint n;
816
23.0k
    const gs_function_PtCr_params_t * p = (const gs_function_PtCr_params_t *)&pfn->params;
817
23.0k
    int code = fn_common_serialize(pfn, s);
818
819
23.0k
    if (code < 0)
820
0
        return code;
821
23.0k
    code = sputs(s, (const byte *)&p->ops.size, sizeof(p->ops.size), &n);
822
23.0k
    if (code < 0)
823
0
        return code;
824
23.0k
    return sputs(s, p->ops.data, p->ops.size, &n);
825
23.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
87.8k
{
832
87.8k
    static const gs_function_head_t function_PtCr_head = {
833
87.8k
        function_type_PostScript_Calculator,
834
87.8k
        {
835
87.8k
            (fn_evaluate_proc_t) fn_PtCr_evaluate,
836
87.8k
            (fn_is_monotonic_proc_t) fn_PtCr_is_monotonic,
837
87.8k
            (fn_get_info_proc_t) fn_PtCr_get_info,
838
87.8k
            fn_common_get_params,
839
87.8k
            (fn_make_scaled_proc_t) fn_PtCr_make_scaled,
840
87.8k
            (fn_free_params_proc_t) gs_function_PtCr_free_params,
841
87.8k
            fn_common_free,
842
87.8k
            (fn_serialize_proc_t) gs_function_PtCr_serialize,
843
87.8k
        }
844
87.8k
    };
845
87.8k
    int code;
846
847
87.8k
    *ppfn = 0;      /* in case of error */
848
87.8k
    code = fn_check_mnDR((const gs_function_params_t *)params,
849
87.8k
                         params->m, params->n);
850
87.8k
    if (code < 0)
851
45
        return code;
852
87.8k
    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
87.8k
    {
858
87.8k
        const byte *p = params->ops.data;
859
860
3.54M
        for (; *p != PtCr_return; ++p)
861
3.45M
            switch ((gs_PtCr_opcode_t)*p) {
862
965k
            case PtCr_byte:
863
965k
                ++p; break;
864
149k
            case PtCr_int:
865
149k
                p += sizeof(int); break;
866
228k
            case PtCr_float:
867
228k
                p += sizeof(float); break;
868
0
            case PtCr_repeat:
869
43.5k
            case PtCr_if:
870
86.5k
            case PtCr_else:
871
86.5k
                p += 2;
872
86.5k
            case PtCr_repeat_end:
873
86.5k
            case PtCr_true:
874
86.5k
            case PtCr_false:
875
86.5k
                break;
876
2.02M
            default:
877
2.02M
                if (*p >= PtCr_NUM_OPS)
878
0
                    return_error(gs_error_rangecheck);
879
3.45M
            }
880
87.8k
        if (p != params->ops.data + params->ops.size - 1)
881
0
            return_error(gs_error_rangecheck);
882
87.8k
    }
883
87.8k
    {
884
87.8k
        gs_function_PtCr_t *pfn =
885
87.8k
            gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
886
87.8k
                            "gs_function_PtCr_init");
887
888
87.8k
        if (pfn == 0)
889
0
            return_error(gs_error_VMerror);
890
87.8k
        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
87.8k
        data_source_init_string2(&pfn->data_source, NULL, 0);
897
87.8k
        pfn->data_source.access = calc_access;
898
87.8k
        pfn->head = function_PtCr_head;
899
87.8k
        *ppfn = (gs_function_t *) pfn;
900
87.8k
    }
901
0
    return 0;
902
87.8k
}