Coverage Report

Created: 2025-12-31 07:31

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